5417 lines
147 KiB
JavaScript
5417 lines
147 KiB
JavaScript
|
|
'use strict';
|
|||
|
|
|
|||
|
|
const path = require('node:path');
|
|||
|
|
const process$1 = require('node:process');
|
|||
|
|
const require$$0 = require('readline');
|
|||
|
|
const require$$2 = require('events');
|
|||
|
|
const node_module = require('node:module');
|
|||
|
|
const child_process = require('child_process');
|
|||
|
|
const require$$1$1 = require('path');
|
|||
|
|
const process$2 = require('process');
|
|||
|
|
const stream = require('stream');
|
|||
|
|
const fs = require('node:fs');
|
|||
|
|
const require$$0$1 = require('os');
|
|||
|
|
const require$$1 = require('tty');
|
|||
|
|
const os = require('node:os');
|
|||
|
|
const require$$0$2 = require('fs');
|
|||
|
|
const require$$1$2 = require('fs/promises');
|
|||
|
|
const fsPromises = require('node:fs/promises');
|
|||
|
|
|
|||
|
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|||
|
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|||
|
|
|
|||
|
|
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|||
|
|
const process__default = /*#__PURE__*/_interopDefaultCompat(process$1);
|
|||
|
|
const require$$0__default = /*#__PURE__*/_interopDefaultCompat(require$$0);
|
|||
|
|
const require$$2__default = /*#__PURE__*/_interopDefaultCompat(require$$2);
|
|||
|
|
const require$$1__default$2 = /*#__PURE__*/_interopDefaultCompat(require$$1$1);
|
|||
|
|
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|||
|
|
const require$$0__default$1 = /*#__PURE__*/_interopDefaultCompat(require$$0$1);
|
|||
|
|
const require$$1__default = /*#__PURE__*/_interopDefaultCompat(require$$1);
|
|||
|
|
const os__default = /*#__PURE__*/_interopDefaultCompat(os);
|
|||
|
|
const require$$0__default$2 = /*#__PURE__*/_interopDefaultCompat(require$$0$2);
|
|||
|
|
const require$$1__default$1 = /*#__PURE__*/_interopDefaultCompat(require$$1$2);
|
|||
|
|
const fsPromises__default = /*#__PURE__*/_interopDefaultCompat(fsPromises);
|
|||
|
|
|
|||
|
|
function getDefaultExportFromCjs (x) {
|
|||
|
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var ini$1;
|
|||
|
|
var hasRequiredIni;
|
|||
|
|
|
|||
|
|
function requireIni () {
|
|||
|
|
if (hasRequiredIni) return ini$1;
|
|||
|
|
hasRequiredIni = 1;
|
|||
|
|
const { hasOwnProperty } = Object.prototype;
|
|||
|
|
|
|||
|
|
const encode = (obj, opt = {}) => {
|
|||
|
|
if (typeof opt === 'string') {
|
|||
|
|
opt = { section: opt };
|
|||
|
|
}
|
|||
|
|
opt.align = opt.align === true;
|
|||
|
|
opt.newline = opt.newline === true;
|
|||
|
|
opt.sort = opt.sort === true;
|
|||
|
|
opt.whitespace = opt.whitespace === true || opt.align === true;
|
|||
|
|
// The `typeof` check is required because accessing the `process` directly fails on browsers.
|
|||
|
|
/* istanbul ignore next */
|
|||
|
|
opt.platform = opt.platform || (typeof process !== 'undefined' && process.platform);
|
|||
|
|
opt.bracketedArray = opt.bracketedArray !== false;
|
|||
|
|
|
|||
|
|
/* istanbul ignore next */
|
|||
|
|
const eol = opt.platform === 'win32' ? '\r\n' : '\n';
|
|||
|
|
const separator = opt.whitespace ? ' = ' : '=';
|
|||
|
|
const children = [];
|
|||
|
|
|
|||
|
|
const keys = opt.sort ? Object.keys(obj).sort() : Object.keys(obj);
|
|||
|
|
|
|||
|
|
let padToChars = 0;
|
|||
|
|
// If aligning on the separator, then padToChars is determined as follows:
|
|||
|
|
// 1. Get the keys
|
|||
|
|
// 2. Exclude keys pointing to objects unless the value is null or an array
|
|||
|
|
// 3. Add `[]` to array keys
|
|||
|
|
// 4. Ensure non empty set of keys
|
|||
|
|
// 5. Reduce the set to the longest `safe` key
|
|||
|
|
// 6. Get the `safe` length
|
|||
|
|
if (opt.align) {
|
|||
|
|
padToChars = safe(
|
|||
|
|
(
|
|||
|
|
keys
|
|||
|
|
.filter(k => obj[k] === null || Array.isArray(obj[k]) || typeof obj[k] !== 'object')
|
|||
|
|
.map(k => Array.isArray(obj[k]) ? `${k}[]` : k)
|
|||
|
|
)
|
|||
|
|
.concat([''])
|
|||
|
|
.reduce((a, b) => safe(a).length >= safe(b).length ? a : b)
|
|||
|
|
).length;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let out = '';
|
|||
|
|
const arraySuffix = opt.bracketedArray ? '[]' : '';
|
|||
|
|
|
|||
|
|
for (const k of keys) {
|
|||
|
|
const val = obj[k];
|
|||
|
|
if (val && Array.isArray(val)) {
|
|||
|
|
for (const item of val) {
|
|||
|
|
out += safe(`${k}${arraySuffix}`).padEnd(padToChars, ' ') + separator + safe(item) + eol;
|
|||
|
|
}
|
|||
|
|
} else if (val && typeof val === 'object') {
|
|||
|
|
children.push(k);
|
|||
|
|
} else {
|
|||
|
|
out += safe(k).padEnd(padToChars, ' ') + separator + safe(val) + eol;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (opt.section && out.length) {
|
|||
|
|
out = '[' + safe(opt.section) + ']' + (opt.newline ? eol + eol : eol) + out;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (const k of children) {
|
|||
|
|
const nk = splitSections(k, '.').join('\\.');
|
|||
|
|
const section = (opt.section ? opt.section + '.' : '') + nk;
|
|||
|
|
const child = encode(obj[k], {
|
|||
|
|
...opt,
|
|||
|
|
section,
|
|||
|
|
});
|
|||
|
|
if (out.length && child.length) {
|
|||
|
|
out += eol;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
out += child;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return out
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function splitSections (str, separator) {
|
|||
|
|
var lastMatchIndex = 0;
|
|||
|
|
var lastSeparatorIndex = 0;
|
|||
|
|
var nextIndex = 0;
|
|||
|
|
var sections = [];
|
|||
|
|
|
|||
|
|
do {
|
|||
|
|
nextIndex = str.indexOf(separator, lastMatchIndex);
|
|||
|
|
|
|||
|
|
if (nextIndex !== -1) {
|
|||
|
|
lastMatchIndex = nextIndex + separator.length;
|
|||
|
|
|
|||
|
|
if (nextIndex > 0 && str[nextIndex - 1] === '\\') {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sections.push(str.slice(lastSeparatorIndex, nextIndex));
|
|||
|
|
lastSeparatorIndex = nextIndex + separator.length;
|
|||
|
|
}
|
|||
|
|
} while (nextIndex !== -1)
|
|||
|
|
|
|||
|
|
sections.push(str.slice(lastSeparatorIndex));
|
|||
|
|
|
|||
|
|
return sections
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const decode = (str, opt = {}) => {
|
|||
|
|
opt.bracketedArray = opt.bracketedArray !== false;
|
|||
|
|
const out = Object.create(null);
|
|||
|
|
let p = out;
|
|||
|
|
let section = null;
|
|||
|
|
// section |key = value
|
|||
|
|
const re = /^\[([^\]]*)\]\s*$|^([^=]+)(=(.*))?$/i;
|
|||
|
|
const lines = str.split(/[\r\n]+/g);
|
|||
|
|
const duplicates = {};
|
|||
|
|
|
|||
|
|
for (const line of lines) {
|
|||
|
|
if (!line || line.match(/^\s*[;#]/) || line.match(/^\s*$/)) {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
const match = line.match(re);
|
|||
|
|
if (!match) {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
if (match[1] !== undefined) {
|
|||
|
|
section = unsafe(match[1]);
|
|||
|
|
if (section === '__proto__') {
|
|||
|
|
// not allowed
|
|||
|
|
// keep parsing the section, but don't attach it.
|
|||
|
|
p = Object.create(null);
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
p = out[section] = out[section] || Object.create(null);
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
const keyRaw = unsafe(match[2]);
|
|||
|
|
let isArray;
|
|||
|
|
if (opt.bracketedArray) {
|
|||
|
|
isArray = keyRaw.length > 2 && keyRaw.slice(-2) === '[]';
|
|||
|
|
} else {
|
|||
|
|
duplicates[keyRaw] = (duplicates?.[keyRaw] || 0) + 1;
|
|||
|
|
isArray = duplicates[keyRaw] > 1;
|
|||
|
|
}
|
|||
|
|
const key = isArray && keyRaw.endsWith('[]')
|
|||
|
|
? keyRaw.slice(0, -2) : keyRaw;
|
|||
|
|
|
|||
|
|
if (key === '__proto__') {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
const valueRaw = match[3] ? unsafe(match[4]) : true;
|
|||
|
|
const value = valueRaw === 'true' ||
|
|||
|
|
valueRaw === 'false' ||
|
|||
|
|
valueRaw === 'null' ? JSON.parse(valueRaw)
|
|||
|
|
: valueRaw;
|
|||
|
|
|
|||
|
|
// Convert keys with '[]' suffix to an array
|
|||
|
|
if (isArray) {
|
|||
|
|
if (!hasOwnProperty.call(p, key)) {
|
|||
|
|
p[key] = [];
|
|||
|
|
} else if (!Array.isArray(p[key])) {
|
|||
|
|
p[key] = [p[key]];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// safeguard against resetting a previously defined
|
|||
|
|
// array by accidentally forgetting the brackets
|
|||
|
|
if (Array.isArray(p[key])) {
|
|||
|
|
p[key].push(value);
|
|||
|
|
} else {
|
|||
|
|
p[key] = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
|
|||
|
|
// use a filter to return the keys that have to be deleted.
|
|||
|
|
const remove = [];
|
|||
|
|
for (const k of Object.keys(out)) {
|
|||
|
|
if (!hasOwnProperty.call(out, k) ||
|
|||
|
|
typeof out[k] !== 'object' ||
|
|||
|
|
Array.isArray(out[k])) {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// see if the parent section is also an object.
|
|||
|
|
// if so, add it to that, and mark this one for deletion
|
|||
|
|
const parts = splitSections(k, '.');
|
|||
|
|
p = out;
|
|||
|
|
const l = parts.pop();
|
|||
|
|
const nl = l.replace(/\\\./g, '.');
|
|||
|
|
for (const part of parts) {
|
|||
|
|
if (part === '__proto__') {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
if (!hasOwnProperty.call(p, part) || typeof p[part] !== 'object') {
|
|||
|
|
p[part] = Object.create(null);
|
|||
|
|
}
|
|||
|
|
p = p[part];
|
|||
|
|
}
|
|||
|
|
if (p === out && nl === l) {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
p[nl] = out[k];
|
|||
|
|
remove.push(k);
|
|||
|
|
}
|
|||
|
|
for (const del of remove) {
|
|||
|
|
delete out[del];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return out
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const isQuoted = val => {
|
|||
|
|
return (val.startsWith('"') && val.endsWith('"')) ||
|
|||
|
|
(val.startsWith("'") && val.endsWith("'"))
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const safe = val => {
|
|||
|
|
if (
|
|||
|
|
typeof val !== 'string' ||
|
|||
|
|
val.match(/[=\r\n]/) ||
|
|||
|
|
val.match(/^\[/) ||
|
|||
|
|
(val.length > 1 && isQuoted(val)) ||
|
|||
|
|
val !== val.trim()
|
|||
|
|
) {
|
|||
|
|
return JSON.stringify(val)
|
|||
|
|
}
|
|||
|
|
return val.split(';').join('\\;').split('#').join('\\#')
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const unsafe = val => {
|
|||
|
|
val = (val || '').trim();
|
|||
|
|
if (isQuoted(val)) {
|
|||
|
|
// remove the single quotes before calling JSON.parse
|
|||
|
|
if (val.charAt(0) === "'") {
|
|||
|
|
val = val.slice(1, -1);
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
val = JSON.parse(val);
|
|||
|
|
} catch {
|
|||
|
|
// ignore errors
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// walk the val to find the first not-escaped ; character
|
|||
|
|
let esc = false;
|
|||
|
|
let unesc = '';
|
|||
|
|
for (let i = 0, l = val.length; i < l; i++) {
|
|||
|
|
const c = val.charAt(i);
|
|||
|
|
if (esc) {
|
|||
|
|
if ('\\;#'.indexOf(c) !== -1) {
|
|||
|
|
unesc += c;
|
|||
|
|
} else {
|
|||
|
|
unesc += '\\' + c;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
esc = false;
|
|||
|
|
} else if (';#'.indexOf(c) !== -1) {
|
|||
|
|
break
|
|||
|
|
} else if (c === '\\') {
|
|||
|
|
esc = true;
|
|||
|
|
} else {
|
|||
|
|
unesc += c;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (esc) {
|
|||
|
|
unesc += '\\';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return unesc.trim()
|
|||
|
|
}
|
|||
|
|
return val
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
ini$1 = {
|
|||
|
|
parse: decode,
|
|||
|
|
decode,
|
|||
|
|
stringify: encode,
|
|||
|
|
encode,
|
|||
|
|
safe,
|
|||
|
|
unsafe,
|
|||
|
|
};
|
|||
|
|
return ini$1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var iniExports = requireIni();
|
|||
|
|
const ini = /*@__PURE__*/getDefaultExportFromCjs(iniExports);
|
|||
|
|
|
|||
|
|
var prompts$2 = {};
|
|||
|
|
|
|||
|
|
var kleur;
|
|||
|
|
var hasRequiredKleur;
|
|||
|
|
|
|||
|
|
function requireKleur () {
|
|||
|
|
if (hasRequiredKleur) return kleur;
|
|||
|
|
hasRequiredKleur = 1;
|
|||
|
|
|
|||
|
|
let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;
|
|||
|
|
if (typeof process !== 'undefined') {
|
|||
|
|
({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});
|
|||
|
|
isTTY = process.stdout && process.stdout.isTTY;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const $ = {
|
|||
|
|
enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (
|
|||
|
|
FORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY
|
|||
|
|
),
|
|||
|
|
|
|||
|
|
// modifiers
|
|||
|
|
reset: init(0, 0),
|
|||
|
|
bold: init(1, 22),
|
|||
|
|
dim: init(2, 22),
|
|||
|
|
italic: init(3, 23),
|
|||
|
|
underline: init(4, 24),
|
|||
|
|
inverse: init(7, 27),
|
|||
|
|
hidden: init(8, 28),
|
|||
|
|
strikethrough: init(9, 29),
|
|||
|
|
|
|||
|
|
// colors
|
|||
|
|
black: init(30, 39),
|
|||
|
|
red: init(31, 39),
|
|||
|
|
green: init(32, 39),
|
|||
|
|
yellow: init(33, 39),
|
|||
|
|
blue: init(34, 39),
|
|||
|
|
magenta: init(35, 39),
|
|||
|
|
cyan: init(36, 39),
|
|||
|
|
white: init(37, 39),
|
|||
|
|
gray: init(90, 39),
|
|||
|
|
grey: init(90, 39),
|
|||
|
|
|
|||
|
|
// background colors
|
|||
|
|
bgBlack: init(40, 49),
|
|||
|
|
bgRed: init(41, 49),
|
|||
|
|
bgGreen: init(42, 49),
|
|||
|
|
bgYellow: init(43, 49),
|
|||
|
|
bgBlue: init(44, 49),
|
|||
|
|
bgMagenta: init(45, 49),
|
|||
|
|
bgCyan: init(46, 49),
|
|||
|
|
bgWhite: init(47, 49)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function run(arr, str) {
|
|||
|
|
let i=0, tmp, beg='', end='';
|
|||
|
|
for (; i < arr.length; i++) {
|
|||
|
|
tmp = arr[i];
|
|||
|
|
beg += tmp.open;
|
|||
|
|
end += tmp.close;
|
|||
|
|
if (!!~str.indexOf(tmp.close)) {
|
|||
|
|
str = str.replace(tmp.rgx, tmp.close + tmp.open);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return beg + str + end;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function chain(has, keys) {
|
|||
|
|
let ctx = { has, keys };
|
|||
|
|
|
|||
|
|
ctx.reset = $.reset.bind(ctx);
|
|||
|
|
ctx.bold = $.bold.bind(ctx);
|
|||
|
|
ctx.dim = $.dim.bind(ctx);
|
|||
|
|
ctx.italic = $.italic.bind(ctx);
|
|||
|
|
ctx.underline = $.underline.bind(ctx);
|
|||
|
|
ctx.inverse = $.inverse.bind(ctx);
|
|||
|
|
ctx.hidden = $.hidden.bind(ctx);
|
|||
|
|
ctx.strikethrough = $.strikethrough.bind(ctx);
|
|||
|
|
|
|||
|
|
ctx.black = $.black.bind(ctx);
|
|||
|
|
ctx.red = $.red.bind(ctx);
|
|||
|
|
ctx.green = $.green.bind(ctx);
|
|||
|
|
ctx.yellow = $.yellow.bind(ctx);
|
|||
|
|
ctx.blue = $.blue.bind(ctx);
|
|||
|
|
ctx.magenta = $.magenta.bind(ctx);
|
|||
|
|
ctx.cyan = $.cyan.bind(ctx);
|
|||
|
|
ctx.white = $.white.bind(ctx);
|
|||
|
|
ctx.gray = $.gray.bind(ctx);
|
|||
|
|
ctx.grey = $.grey.bind(ctx);
|
|||
|
|
|
|||
|
|
ctx.bgBlack = $.bgBlack.bind(ctx);
|
|||
|
|
ctx.bgRed = $.bgRed.bind(ctx);
|
|||
|
|
ctx.bgGreen = $.bgGreen.bind(ctx);
|
|||
|
|
ctx.bgYellow = $.bgYellow.bind(ctx);
|
|||
|
|
ctx.bgBlue = $.bgBlue.bind(ctx);
|
|||
|
|
ctx.bgMagenta = $.bgMagenta.bind(ctx);
|
|||
|
|
ctx.bgCyan = $.bgCyan.bind(ctx);
|
|||
|
|
ctx.bgWhite = $.bgWhite.bind(ctx);
|
|||
|
|
|
|||
|
|
return ctx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function init(open, close) {
|
|||
|
|
let blk = {
|
|||
|
|
open: `\x1b[${open}m`,
|
|||
|
|
close: `\x1b[${close}m`,
|
|||
|
|
rgx: new RegExp(`\\x1b\\[${close}m`, 'g')
|
|||
|
|
};
|
|||
|
|
return function (txt) {
|
|||
|
|
if (this !== void 0 && this.has !== void 0) {
|
|||
|
|
!!~this.has.indexOf(open) || (this.has.push(open),this.keys.push(blk));
|
|||
|
|
return txt === void 0 ? this : $.enabled ? run(this.keys, txt+'') : txt+'';
|
|||
|
|
}
|
|||
|
|
return txt === void 0 ? chain([open], [blk]) : $.enabled ? run([blk], txt+'') : txt+'';
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
kleur = $;
|
|||
|
|
return kleur;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var action;
|
|||
|
|
var hasRequiredAction;
|
|||
|
|
|
|||
|
|
function requireAction () {
|
|||
|
|
if (hasRequiredAction) return action;
|
|||
|
|
hasRequiredAction = 1;
|
|||
|
|
|
|||
|
|
action = (key, isSelect) => {
|
|||
|
|
if (key.meta && key.name !== 'escape') return;
|
|||
|
|
|
|||
|
|
if (key.ctrl) {
|
|||
|
|
if (key.name === 'a') return 'first';
|
|||
|
|
if (key.name === 'c') return 'abort';
|
|||
|
|
if (key.name === 'd') return 'abort';
|
|||
|
|
if (key.name === 'e') return 'last';
|
|||
|
|
if (key.name === 'g') return 'reset';
|
|||
|
|
if (key.name === 'n') return 'down';
|
|||
|
|
if (key.name === 'p') return 'up';
|
|||
|
|
// avoid any non-ascii characters
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isSelect) {
|
|||
|
|
if (key.name === 'j') return 'down';
|
|||
|
|
if (key.name === 'k') return 'up';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (key.name === 'return') return 'submit';
|
|||
|
|
if (key.name === 'enter') return 'submit'; // ctrl + J
|
|||
|
|
if (key.name === 'backspace') return 'delete';
|
|||
|
|
if (key.name === 'delete') return 'deleteForward';
|
|||
|
|
if (key.name === 'abort') return 'abort';
|
|||
|
|
if (key.name === 'escape') return 'exit';
|
|||
|
|
// TODO: shift tab for prev
|
|||
|
|
if (key.name === 'tab') return 'next';
|
|||
|
|
if (key.name === 'pagedown') return 'nextPage';
|
|||
|
|
if (key.name === 'pageup') return 'prevPage';
|
|||
|
|
// TODO create home() in prompt types (e.g. TextPrompt)
|
|||
|
|
if (key.name === 'home') return 'home';
|
|||
|
|
// TODO create end() in prompt types (e.g. TextPrompt)
|
|||
|
|
if (key.name === 'end') return 'end';
|
|||
|
|
|
|||
|
|
if (key.name === 'up') return 'up';
|
|||
|
|
if (key.name === 'down') return 'down';
|
|||
|
|
if (key.name === 'right') return 'right';
|
|||
|
|
if (key.name === 'left') return 'left';
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
};
|
|||
|
|
return action;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var strip;
|
|||
|
|
var hasRequiredStrip;
|
|||
|
|
|
|||
|
|
function requireStrip () {
|
|||
|
|
if (hasRequiredStrip) return strip;
|
|||
|
|
hasRequiredStrip = 1;
|
|||
|
|
|
|||
|
|
strip = str => {
|
|||
|
|
const pattern = [
|
|||
|
|
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|||
|
|
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))'
|
|||
|
|
].join('|');
|
|||
|
|
|
|||
|
|
const RGX = new RegExp(pattern, 'g');
|
|||
|
|
return typeof str === 'string' ? str.replace(RGX, '') : str;
|
|||
|
|
};
|
|||
|
|
return strip;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var src;
|
|||
|
|
var hasRequiredSrc;
|
|||
|
|
|
|||
|
|
function requireSrc () {
|
|||
|
|
if (hasRequiredSrc) return src;
|
|||
|
|
hasRequiredSrc = 1;
|
|||
|
|
|
|||
|
|
const ESC = '\x1B';
|
|||
|
|
const CSI = `${ESC}[`;
|
|||
|
|
const beep = '\u0007';
|
|||
|
|
|
|||
|
|
const cursor = {
|
|||
|
|
to(x, y) {
|
|||
|
|
if (!y) return `${CSI}${x + 1}G`;
|
|||
|
|
return `${CSI}${y + 1};${x + 1}H`;
|
|||
|
|
},
|
|||
|
|
move(x, y) {
|
|||
|
|
let ret = '';
|
|||
|
|
|
|||
|
|
if (x < 0) ret += `${CSI}${-x}D`;
|
|||
|
|
else if (x > 0) ret += `${CSI}${x}C`;
|
|||
|
|
|
|||
|
|
if (y < 0) ret += `${CSI}${-y}A`;
|
|||
|
|
else if (y > 0) ret += `${CSI}${y}B`;
|
|||
|
|
|
|||
|
|
return ret;
|
|||
|
|
},
|
|||
|
|
up: (count = 1) => `${CSI}${count}A`,
|
|||
|
|
down: (count = 1) => `${CSI}${count}B`,
|
|||
|
|
forward: (count = 1) => `${CSI}${count}C`,
|
|||
|
|
backward: (count = 1) => `${CSI}${count}D`,
|
|||
|
|
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|||
|
|
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|||
|
|
left: `${CSI}G`,
|
|||
|
|
hide: `${CSI}?25l`,
|
|||
|
|
show: `${CSI}?25h`,
|
|||
|
|
save: `${ESC}7`,
|
|||
|
|
restore: `${ESC}8`
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const scroll = {
|
|||
|
|
up: (count = 1) => `${CSI}S`.repeat(count),
|
|||
|
|
down: (count = 1) => `${CSI}T`.repeat(count)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const erase = {
|
|||
|
|
screen: `${CSI}2J`,
|
|||
|
|
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|||
|
|
down: (count = 1) => `${CSI}J`.repeat(count),
|
|||
|
|
line: `${CSI}2K`,
|
|||
|
|
lineEnd: `${CSI}K`,
|
|||
|
|
lineStart: `${CSI}1K`,
|
|||
|
|
lines(count) {
|
|||
|
|
let clear = '';
|
|||
|
|
for (let i = 0; i < count; i++)
|
|||
|
|
clear += this.line + (i < count - 1 ? cursor.up() : '');
|
|||
|
|
if (count)
|
|||
|
|
clear += cursor.left;
|
|||
|
|
return clear;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
src = { cursor, scroll, erase, beep };
|
|||
|
|
return src;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var clear;
|
|||
|
|
var hasRequiredClear;
|
|||
|
|
|
|||
|
|
function requireClear () {
|
|||
|
|
if (hasRequiredClear) return clear;
|
|||
|
|
hasRequiredClear = 1;
|
|||
|
|
|
|||
|
|
const strip = requireStrip();
|
|||
|
|
const { erase, cursor } = requireSrc();
|
|||
|
|
|
|||
|
|
const width = str => [...strip(str)].length;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @param {string} prompt
|
|||
|
|
* @param {number} perLine
|
|||
|
|
*/
|
|||
|
|
clear = function(prompt, perLine) {
|
|||
|
|
if (!perLine) return erase.line + cursor.to(0);
|
|||
|
|
|
|||
|
|
let rows = 0;
|
|||
|
|
const lines = prompt.split(/\r?\n/);
|
|||
|
|
for (let line of lines) {
|
|||
|
|
rows += 1 + Math.floor(Math.max(width(line) - 1, 0) / perLine);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return erase.lines(rows);
|
|||
|
|
};
|
|||
|
|
return clear;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var figures_1;
|
|||
|
|
var hasRequiredFigures;
|
|||
|
|
|
|||
|
|
function requireFigures () {
|
|||
|
|
if (hasRequiredFigures) return figures_1;
|
|||
|
|
hasRequiredFigures = 1;
|
|||
|
|
|
|||
|
|
const main = {
|
|||
|
|
arrowUp: '↑',
|
|||
|
|
arrowDown: '↓',
|
|||
|
|
arrowLeft: '←',
|
|||
|
|
arrowRight: '→',
|
|||
|
|
radioOn: '◉',
|
|||
|
|
radioOff: '◯',
|
|||
|
|
tick: '✔',
|
|||
|
|
cross: '✖',
|
|||
|
|
ellipsis: '…',
|
|||
|
|
pointerSmall: '›',
|
|||
|
|
line: '─',
|
|||
|
|
pointer: '❯'
|
|||
|
|
};
|
|||
|
|
const win = {
|
|||
|
|
arrowUp: main.arrowUp,
|
|||
|
|
arrowDown: main.arrowDown,
|
|||
|
|
arrowLeft: main.arrowLeft,
|
|||
|
|
arrowRight: main.arrowRight,
|
|||
|
|
radioOn: '(*)',
|
|||
|
|
radioOff: '( )',
|
|||
|
|
tick: '√',
|
|||
|
|
cross: '×',
|
|||
|
|
ellipsis: '...',
|
|||
|
|
pointerSmall: '»',
|
|||
|
|
line: '─',
|
|||
|
|
pointer: '>'
|
|||
|
|
};
|
|||
|
|
const figures = process.platform === 'win32' ? win : main;
|
|||
|
|
|
|||
|
|
figures_1 = figures;
|
|||
|
|
return figures_1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var style;
|
|||
|
|
var hasRequiredStyle;
|
|||
|
|
|
|||
|
|
function requireStyle () {
|
|||
|
|
if (hasRequiredStyle) return style;
|
|||
|
|
hasRequiredStyle = 1;
|
|||
|
|
|
|||
|
|
const c = requireKleur();
|
|||
|
|
const figures = requireFigures();
|
|||
|
|
|
|||
|
|
// rendering user input.
|
|||
|
|
const styles = Object.freeze({
|
|||
|
|
password: { scale: 1, render: input => '*'.repeat(input.length) },
|
|||
|
|
emoji: { scale: 2, render: input => '😃'.repeat(input.length) },
|
|||
|
|
invisible: { scale: 0, render: input => '' },
|
|||
|
|
default: { scale: 1, render: input => `${input}` }
|
|||
|
|
});
|
|||
|
|
const render = type => styles[type] || styles.default;
|
|||
|
|
|
|||
|
|
// icon to signalize a prompt.
|
|||
|
|
const symbols = Object.freeze({
|
|||
|
|
aborted: c.red(figures.cross),
|
|||
|
|
done: c.green(figures.tick),
|
|||
|
|
exited: c.yellow(figures.cross),
|
|||
|
|
default: c.cyan('?')
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const symbol = (done, aborted, exited) =>
|
|||
|
|
aborted ? symbols.aborted : exited ? symbols.exited : done ? symbols.done : symbols.default;
|
|||
|
|
|
|||
|
|
// between the question and the user's input.
|
|||
|
|
const delimiter = completing =>
|
|||
|
|
c.gray(completing ? figures.ellipsis : figures.pointerSmall);
|
|||
|
|
|
|||
|
|
const item = (expandable, expanded) =>
|
|||
|
|
c.gray(expandable ? (expanded ? figures.pointerSmall : '+') : figures.line);
|
|||
|
|
|
|||
|
|
style = {
|
|||
|
|
styles,
|
|||
|
|
render,
|
|||
|
|
symbols,
|
|||
|
|
symbol,
|
|||
|
|
delimiter,
|
|||
|
|
item
|
|||
|
|
};
|
|||
|
|
return style;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var lines;
|
|||
|
|
var hasRequiredLines;
|
|||
|
|
|
|||
|
|
function requireLines () {
|
|||
|
|
if (hasRequiredLines) return lines;
|
|||
|
|
hasRequiredLines = 1;
|
|||
|
|
|
|||
|
|
const strip = requireStrip();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @param {string} msg
|
|||
|
|
* @param {number} perLine
|
|||
|
|
*/
|
|||
|
|
lines = function (msg, perLine) {
|
|||
|
|
let lines = String(strip(msg) || '').split(/\r?\n/);
|
|||
|
|
|
|||
|
|
if (!perLine) return lines.length;
|
|||
|
|
return lines.map(l => Math.ceil(l.length / perLine))
|
|||
|
|
.reduce((a, b) => a + b);
|
|||
|
|
};
|
|||
|
|
return lines;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var wrap;
|
|||
|
|
var hasRequiredWrap;
|
|||
|
|
|
|||
|
|
function requireWrap () {
|
|||
|
|
if (hasRequiredWrap) return wrap;
|
|||
|
|
hasRequiredWrap = 1;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @param {string} msg The message to wrap
|
|||
|
|
* @param {object} opts
|
|||
|
|
* @param {number|string} [opts.margin] Left margin
|
|||
|
|
* @param {number} opts.width Maximum characters per line including the margin
|
|||
|
|
*/
|
|||
|
|
wrap = (msg, opts = {}) => {
|
|||
|
|
const tab = Number.isSafeInteger(parseInt(opts.margin))
|
|||
|
|
? new Array(parseInt(opts.margin)).fill(' ').join('')
|
|||
|
|
: (opts.margin || '');
|
|||
|
|
|
|||
|
|
const width = opts.width;
|
|||
|
|
|
|||
|
|
return (msg || '').split(/\r?\n/g)
|
|||
|
|
.map(line => line
|
|||
|
|
.split(/\s+/g)
|
|||
|
|
.reduce((arr, w) => {
|
|||
|
|
if (w.length + tab.length >= width || arr[arr.length - 1].length + w.length + 1 < width)
|
|||
|
|
arr[arr.length - 1] += ` ${w}`;
|
|||
|
|
else arr.push(`${tab}${w}`);
|
|||
|
|
return arr;
|
|||
|
|
}, [ tab ])
|
|||
|
|
.join('\n'))
|
|||
|
|
.join('\n');
|
|||
|
|
};
|
|||
|
|
return wrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var entriesToDisplay;
|
|||
|
|
var hasRequiredEntriesToDisplay;
|
|||
|
|
|
|||
|
|
function requireEntriesToDisplay () {
|
|||
|
|
if (hasRequiredEntriesToDisplay) return entriesToDisplay;
|
|||
|
|
hasRequiredEntriesToDisplay = 1;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Determine what entries should be displayed on the screen, based on the
|
|||
|
|
* currently selected index and the maximum visible. Used in list-based
|
|||
|
|
* prompts like `select` and `multiselect`.
|
|||
|
|
*
|
|||
|
|
* @param {number} cursor the currently selected entry
|
|||
|
|
* @param {number} total the total entries available to display
|
|||
|
|
* @param {number} [maxVisible] the number of entries that can be displayed
|
|||
|
|
*/
|
|||
|
|
entriesToDisplay = (cursor, total, maxVisible) => {
|
|||
|
|
maxVisible = maxVisible || total;
|
|||
|
|
|
|||
|
|
let startIndex = Math.min(total- maxVisible, cursor - Math.floor(maxVisible / 2));
|
|||
|
|
if (startIndex < 0) startIndex = 0;
|
|||
|
|
|
|||
|
|
let endIndex = Math.min(startIndex + maxVisible, total);
|
|||
|
|
|
|||
|
|
return { startIndex, endIndex };
|
|||
|
|
};
|
|||
|
|
return entriesToDisplay;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var util;
|
|||
|
|
var hasRequiredUtil;
|
|||
|
|
|
|||
|
|
function requireUtil () {
|
|||
|
|
if (hasRequiredUtil) return util;
|
|||
|
|
hasRequiredUtil = 1;
|
|||
|
|
|
|||
|
|
util = {
|
|||
|
|
action: requireAction(),
|
|||
|
|
clear: requireClear(),
|
|||
|
|
style: requireStyle(),
|
|||
|
|
strip: requireStrip(),
|
|||
|
|
figures: requireFigures(),
|
|||
|
|
lines: requireLines(),
|
|||
|
|
wrap: requireWrap(),
|
|||
|
|
entriesToDisplay: requireEntriesToDisplay()
|
|||
|
|
};
|
|||
|
|
return util;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var prompt;
|
|||
|
|
var hasRequiredPrompt;
|
|||
|
|
|
|||
|
|
function requirePrompt () {
|
|||
|
|
if (hasRequiredPrompt) return prompt;
|
|||
|
|
hasRequiredPrompt = 1;
|
|||
|
|
|
|||
|
|
const readline = require$$0__default;
|
|||
|
|
const { action } = requireUtil();
|
|||
|
|
const EventEmitter = require$$2__default;
|
|||
|
|
const { beep, cursor } = requireSrc();
|
|||
|
|
const color = requireKleur();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Base prompt skeleton
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
*/
|
|||
|
|
class Prompt extends EventEmitter {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super();
|
|||
|
|
|
|||
|
|
this.firstRender = true;
|
|||
|
|
this.in = opts.stdin || process.stdin;
|
|||
|
|
this.out = opts.stdout || process.stdout;
|
|||
|
|
this.onRender = (opts.onRender || (() => void 0)).bind(this);
|
|||
|
|
const rl = readline.createInterface({ input:this.in, escapeCodeTimeout:50 });
|
|||
|
|
readline.emitKeypressEvents(this.in, rl);
|
|||
|
|
|
|||
|
|
if (this.in.isTTY) this.in.setRawMode(true);
|
|||
|
|
const isSelect = [ 'SelectPrompt', 'MultiselectPrompt' ].indexOf(this.constructor.name) > -1;
|
|||
|
|
const keypress = (str, key) => {
|
|||
|
|
let a = action(key, isSelect);
|
|||
|
|
if (a === false) {
|
|||
|
|
this._ && this._(str, key);
|
|||
|
|
} else if (typeof this[a] === 'function') {
|
|||
|
|
this[a](key);
|
|||
|
|
} else {
|
|||
|
|
this.bell();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.close = () => {
|
|||
|
|
this.out.write(cursor.show);
|
|||
|
|
this.in.removeListener('keypress', keypress);
|
|||
|
|
if (this.in.isTTY) this.in.setRawMode(false);
|
|||
|
|
rl.close();
|
|||
|
|
this.emit(this.aborted ? 'abort' : this.exited ? 'exit' : 'submit', this.value);
|
|||
|
|
this.closed = true;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.in.on('keypress', keypress);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fire() {
|
|||
|
|
this.emit('state', {
|
|||
|
|
value: this.value,
|
|||
|
|
aborted: !!this.aborted,
|
|||
|
|
exited: !!this.exited
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bell() {
|
|||
|
|
this.out.write(beep);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
this.onRender(color);
|
|||
|
|
if (this.firstRender) this.firstRender = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
prompt = Prompt;
|
|||
|
|
return prompt;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var text;
|
|||
|
|
var hasRequiredText;
|
|||
|
|
|
|||
|
|
function requireText () {
|
|||
|
|
if (hasRequiredText) return text;
|
|||
|
|
hasRequiredText = 1;
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { erase, cursor } = requireSrc();
|
|||
|
|
const { style, clear, lines, figures } = requireUtil();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* TextPrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {String} [opts.style='default'] Render style
|
|||
|
|
* @param {String} [opts.initial] Default value
|
|||
|
|
* @param {Function} [opts.validate] Validate function
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
* @param {String} [opts.error] The invalid error label
|
|||
|
|
*/
|
|||
|
|
class TextPrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.transform = style.render(opts.style);
|
|||
|
|
this.scale = this.transform.scale;
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.initial = opts.initial || ``;
|
|||
|
|
this.validator = opts.validate || (() => true);
|
|||
|
|
this.value = ``;
|
|||
|
|
this.errorMsg = opts.error || `Please Enter A Valid Value`;
|
|||
|
|
this.cursor = Number(!!this.initial);
|
|||
|
|
this.cursorOffset = 0;
|
|||
|
|
this.clear = clear(``, this.out.columns);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set value(v) {
|
|||
|
|
if (!v && this.initial) {
|
|||
|
|
this.placeholder = true;
|
|||
|
|
this.rendered = color.gray(this.transform.render(this.initial));
|
|||
|
|
} else {
|
|||
|
|
this.placeholder = false;
|
|||
|
|
this.rendered = this.transform.render(v);
|
|||
|
|
}
|
|||
|
|
this._value = v;
|
|||
|
|
this.fire();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get value() {
|
|||
|
|
return this._value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.value = ``;
|
|||
|
|
this.cursor = Number(!!this.initial);
|
|||
|
|
this.cursorOffset = 0;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
this.abort();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
this.value = this.value || this.initial;
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.error = false;
|
|||
|
|
this.red = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async validate() {
|
|||
|
|
let valid = await this.validator(this.value);
|
|||
|
|
if (typeof valid === `string`) {
|
|||
|
|
this.errorMsg = valid;
|
|||
|
|
valid = false;
|
|||
|
|
}
|
|||
|
|
this.error = !valid;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async submit() {
|
|||
|
|
this.value = this.value || this.initial;
|
|||
|
|
this.cursorOffset = 0;
|
|||
|
|
this.cursor = this.rendered.length;
|
|||
|
|
await this.validate();
|
|||
|
|
if (this.error) {
|
|||
|
|
this.red = true;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next() {
|
|||
|
|
if (!this.placeholder) return this.bell();
|
|||
|
|
this.value = this.initial;
|
|||
|
|
this.cursor = this.rendered.length;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
moveCursor(n) {
|
|||
|
|
if (this.placeholder) return;
|
|||
|
|
this.cursor = this.cursor+n;
|
|||
|
|
this.cursorOffset += n;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
let s1 = this.value.slice(0, this.cursor);
|
|||
|
|
let s2 = this.value.slice(this.cursor);
|
|||
|
|
this.value = `${s1}${c}${s2}`;
|
|||
|
|
this.red = false;
|
|||
|
|
this.cursor = this.placeholder ? 0 : s1.length+1;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
delete() {
|
|||
|
|
if (this.isCursorAtStart()) return this.bell();
|
|||
|
|
let s1 = this.value.slice(0, this.cursor-1);
|
|||
|
|
let s2 = this.value.slice(this.cursor);
|
|||
|
|
this.value = `${s1}${s2}`;
|
|||
|
|
this.red = false;
|
|||
|
|
if (this.isCursorAtStart()) {
|
|||
|
|
this.cursorOffset = 0;
|
|||
|
|
} else {
|
|||
|
|
this.cursorOffset++;
|
|||
|
|
this.moveCursor(-1);
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
deleteForward() {
|
|||
|
|
if(this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();
|
|||
|
|
let s1 = this.value.slice(0, this.cursor);
|
|||
|
|
let s2 = this.value.slice(this.cursor+1);
|
|||
|
|
this.value = `${s1}${s2}`;
|
|||
|
|
this.red = false;
|
|||
|
|
if (this.isCursorAtEnd()) {
|
|||
|
|
this.cursorOffset = 0;
|
|||
|
|
} else {
|
|||
|
|
this.cursorOffset++;
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
first() {
|
|||
|
|
this.cursor = 0;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
last() {
|
|||
|
|
this.cursor = this.value.length;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
left() {
|
|||
|
|
if (this.cursor <= 0 || this.placeholder) return this.bell();
|
|||
|
|
this.moveCursor(-1);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
right() {
|
|||
|
|
if (this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();
|
|||
|
|
this.moveCursor(1);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
isCursorAtStart() {
|
|||
|
|
return this.cursor === 0 || (this.placeholder && this.cursor === 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
isCursorAtEnd() {
|
|||
|
|
return this.cursor === this.rendered.length || (this.placeholder && this.cursor === this.rendered.length + 1)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (!this.firstRender) {
|
|||
|
|
if (this.outputError)
|
|||
|
|
this.out.write(cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns));
|
|||
|
|
this.out.write(clear(this.outputText, this.out.columns));
|
|||
|
|
}
|
|||
|
|
super.render();
|
|||
|
|
this.outputError = '';
|
|||
|
|
|
|||
|
|
this.outputText = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(this.done),
|
|||
|
|
this.red ? color.red(this.rendered) : this.rendered
|
|||
|
|
].join(` `);
|
|||
|
|
|
|||
|
|
if (this.error) {
|
|||
|
|
this.outputError += this.errorMsg.split(`\n`)
|
|||
|
|
.reduce((a, l, i) => a + `\n${i ? ' ' : figures.pointerSmall} ${color.red().italic(l)}`, ``);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.out.write(erase.line + cursor.to(0) + this.outputText + cursor.save + this.outputError + cursor.restore + cursor.move(this.cursorOffset, 0));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
text = TextPrompt;
|
|||
|
|
return text;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var select;
|
|||
|
|
var hasRequiredSelect;
|
|||
|
|
|
|||
|
|
function requireSelect () {
|
|||
|
|
if (hasRequiredSelect) return select;
|
|||
|
|
hasRequiredSelect = 1;
|
|||
|
|
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { style, clear, figures, wrap, entriesToDisplay } = requireUtil();
|
|||
|
|
const { cursor } = requireSrc();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* SelectPrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {Array} opts.choices Array of choice objects
|
|||
|
|
* @param {String} [opts.hint] Hint to display
|
|||
|
|
* @param {Number} [opts.initial] Index of default value
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
* @param {Number} [opts.optionsPerPage=10] Max options to display at once
|
|||
|
|
*/
|
|||
|
|
class SelectPrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.hint = opts.hint || '- Use arrow-keys. Return to submit.';
|
|||
|
|
this.warn = opts.warn || '- This option is disabled';
|
|||
|
|
this.cursor = opts.initial || 0;
|
|||
|
|
this.choices = opts.choices.map((ch, idx) => {
|
|||
|
|
if (typeof ch === 'string')
|
|||
|
|
ch = {title: ch, value: idx};
|
|||
|
|
return {
|
|||
|
|
title: ch && (ch.title || ch.value || ch),
|
|||
|
|
value: ch && (ch.value === undefined ? idx : ch.value),
|
|||
|
|
description: ch && ch.description,
|
|||
|
|
selected: ch && ch.selected,
|
|||
|
|
disabled: ch && ch.disabled
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
this.optionsPerPage = opts.optionsPerPage || 10;
|
|||
|
|
this.value = (this.choices[this.cursor] || {}).value;
|
|||
|
|
this.clear = clear('', this.out.columns);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
moveCursor(n) {
|
|||
|
|
this.cursor = n;
|
|||
|
|
this.value = this.choices[n].value;
|
|||
|
|
this.fire();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.moveCursor(0);
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
this.abort();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
submit() {
|
|||
|
|
if (!this.selection.disabled) {
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
} else
|
|||
|
|
this.bell();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
first() {
|
|||
|
|
this.moveCursor(0);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
last() {
|
|||
|
|
this.moveCursor(this.choices.length - 1);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
if (this.cursor === 0) {
|
|||
|
|
this.moveCursor(this.choices.length - 1);
|
|||
|
|
} else {
|
|||
|
|
this.moveCursor(this.cursor - 1);
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
if (this.cursor === this.choices.length - 1) {
|
|||
|
|
this.moveCursor(0);
|
|||
|
|
} else {
|
|||
|
|
this.moveCursor(this.cursor + 1);
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next() {
|
|||
|
|
this.moveCursor((this.cursor + 1) % this.choices.length);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
if (c === ' ') return this.submit();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get selection() {
|
|||
|
|
return this.choices[this.cursor];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|||
|
|
else this.out.write(clear(this.outputText, this.out.columns));
|
|||
|
|
super.render();
|
|||
|
|
|
|||
|
|
let { startIndex, endIndex } = entriesToDisplay(this.cursor, this.choices.length, this.optionsPerPage);
|
|||
|
|
|
|||
|
|
// Print prompt
|
|||
|
|
this.outputText = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(false),
|
|||
|
|
this.done ? this.selection.title : this.selection.disabled
|
|||
|
|
? color.yellow(this.warn) : color.gray(this.hint)
|
|||
|
|
].join(' ');
|
|||
|
|
|
|||
|
|
// Print choices
|
|||
|
|
if (!this.done) {
|
|||
|
|
this.outputText += '\n';
|
|||
|
|
for (let i = startIndex; i < endIndex; i++) {
|
|||
|
|
let title, prefix, desc = '', v = this.choices[i];
|
|||
|
|
|
|||
|
|
// Determine whether to display "more choices" indicators
|
|||
|
|
if (i === startIndex && startIndex > 0) {
|
|||
|
|
prefix = figures.arrowUp;
|
|||
|
|
} else if (i === endIndex - 1 && endIndex < this.choices.length) {
|
|||
|
|
prefix = figures.arrowDown;
|
|||
|
|
} else {
|
|||
|
|
prefix = ' ';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (v.disabled) {
|
|||
|
|
title = this.cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title);
|
|||
|
|
prefix = (this.cursor === i ? color.bold().gray(figures.pointer) + ' ' : ' ') + prefix;
|
|||
|
|
} else {
|
|||
|
|
title = this.cursor === i ? color.cyan().underline(v.title) : v.title;
|
|||
|
|
prefix = (this.cursor === i ? color.cyan(figures.pointer) + ' ' : ' ') + prefix;
|
|||
|
|
if (v.description && this.cursor === i) {
|
|||
|
|
desc = ` - ${v.description}`;
|
|||
|
|
if (prefix.length + title.length + desc.length >= this.out.columns
|
|||
|
|
|| v.description.split(/\r?\n/).length > 1) {
|
|||
|
|
desc = '\n' + wrap(v.description, { margin: 3, width: this.out.columns });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.outputText += `${prefix} ${title}${color.gray(desc)}\n`;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.out.write(this.outputText);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
select = SelectPrompt;
|
|||
|
|
return select;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var toggle;
|
|||
|
|
var hasRequiredToggle;
|
|||
|
|
|
|||
|
|
function requireToggle () {
|
|||
|
|
if (hasRequiredToggle) return toggle;
|
|||
|
|
hasRequiredToggle = 1;
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { style, clear } = requireUtil();
|
|||
|
|
const { cursor, erase } = requireSrc();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* TogglePrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {Boolean} [opts.initial=false] Default value
|
|||
|
|
* @param {String} [opts.active='no'] Active label
|
|||
|
|
* @param {String} [opts.inactive='off'] Inactive label
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
*/
|
|||
|
|
class TogglePrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.value = !!opts.initial;
|
|||
|
|
this.active = opts.active || 'on';
|
|||
|
|
this.inactive = opts.inactive || 'off';
|
|||
|
|
this.initialValue = this.value;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.value = this.initialValue;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
this.abort();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
submit() {
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
deactivate() {
|
|||
|
|
if (this.value === false) return this.bell();
|
|||
|
|
this.value = false;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
activate() {
|
|||
|
|
if (this.value === true) return this.bell();
|
|||
|
|
this.value = true;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
delete() {
|
|||
|
|
this.deactivate();
|
|||
|
|
}
|
|||
|
|
left() {
|
|||
|
|
this.deactivate();
|
|||
|
|
}
|
|||
|
|
right() {
|
|||
|
|
this.activate();
|
|||
|
|
}
|
|||
|
|
down() {
|
|||
|
|
this.deactivate();
|
|||
|
|
}
|
|||
|
|
up() {
|
|||
|
|
this.activate();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next() {
|
|||
|
|
this.value = !this.value;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
if (c === ' ') {
|
|||
|
|
this.value = !this.value;
|
|||
|
|
} else if (c === '1') {
|
|||
|
|
this.value = true;
|
|||
|
|
} else if (c === '0') {
|
|||
|
|
this.value = false;
|
|||
|
|
} else return this.bell();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|||
|
|
else this.out.write(clear(this.outputText, this.out.columns));
|
|||
|
|
super.render();
|
|||
|
|
|
|||
|
|
this.outputText = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(this.done),
|
|||
|
|
this.value ? this.inactive : color.cyan().underline(this.inactive),
|
|||
|
|
color.gray('/'),
|
|||
|
|
this.value ? color.cyan().underline(this.active) : this.active
|
|||
|
|
].join(' ');
|
|||
|
|
|
|||
|
|
this.out.write(erase.line + cursor.to(0) + this.outputText);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toggle = TogglePrompt;
|
|||
|
|
return toggle;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var datepart;
|
|||
|
|
var hasRequiredDatepart;
|
|||
|
|
|
|||
|
|
function requireDatepart () {
|
|||
|
|
if (hasRequiredDatepart) return datepart;
|
|||
|
|
hasRequiredDatepart = 1;
|
|||
|
|
|
|||
|
|
class DatePart {
|
|||
|
|
constructor({token, date, parts, locales}) {
|
|||
|
|
this.token = token;
|
|||
|
|
this.date = date || new Date();
|
|||
|
|
this.parts = parts || [this];
|
|||
|
|
this.locales = locales || {};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {}
|
|||
|
|
|
|||
|
|
down() {}
|
|||
|
|
|
|||
|
|
next() {
|
|||
|
|
const currentIdx = this.parts.indexOf(this);
|
|||
|
|
return this.parts.find((part, idx) => idx > currentIdx && part instanceof DatePart);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {}
|
|||
|
|
|
|||
|
|
prev() {
|
|||
|
|
let parts = [].concat(this.parts).reverse();
|
|||
|
|
const currentIdx = parts.indexOf(this);
|
|||
|
|
return parts.find((part, idx) => idx > currentIdx && part instanceof DatePart);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
return String(this.date);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
datepart = DatePart;
|
|||
|
|
return datepart;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var meridiem;
|
|||
|
|
var hasRequiredMeridiem;
|
|||
|
|
|
|||
|
|
function requireMeridiem () {
|
|||
|
|
if (hasRequiredMeridiem) return meridiem;
|
|||
|
|
hasRequiredMeridiem = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
class Meridiem extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setHours((this.date.getHours() + 12) % 24);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.up();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
let meridiem = this.date.getHours() > 12 ? 'pm' : 'am';
|
|||
|
|
return /\A/.test(this.token) ? meridiem.toUpperCase() : meridiem;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
meridiem = Meridiem;
|
|||
|
|
return meridiem;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var day;
|
|||
|
|
var hasRequiredDay;
|
|||
|
|
|
|||
|
|
function requireDay () {
|
|||
|
|
if (hasRequiredDay) return day;
|
|||
|
|
hasRequiredDay = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
const pos = n => {
|
|||
|
|
n = n % 10;
|
|||
|
|
return n === 1 ? 'st'
|
|||
|
|
: n === 2 ? 'nd'
|
|||
|
|
: n === 3 ? 'rd'
|
|||
|
|
: 'th';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class Day extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setDate(this.date.getDate() + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.date.setDate(this.date.getDate() - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {
|
|||
|
|
this.date.setDate(parseInt(val.substr(-2)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
let date = this.date.getDate();
|
|||
|
|
let day = this.date.getDay();
|
|||
|
|
return this.token === 'DD' ? String(date).padStart(2, '0')
|
|||
|
|
: this.token === 'Do' ? date + pos(date)
|
|||
|
|
: this.token === 'd' ? day + 1
|
|||
|
|
: this.token === 'ddd' ? this.locales.weekdaysShort[day]
|
|||
|
|
: this.token === 'dddd' ? this.locales.weekdays[day]
|
|||
|
|
: date;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
day = Day;
|
|||
|
|
return day;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var hours;
|
|||
|
|
var hasRequiredHours;
|
|||
|
|
|
|||
|
|
function requireHours () {
|
|||
|
|
if (hasRequiredHours) return hours;
|
|||
|
|
hasRequiredHours = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
class Hours extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setHours(this.date.getHours() + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.date.setHours(this.date.getHours() - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {
|
|||
|
|
this.date.setHours(parseInt(val.substr(-2)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
let hours = this.date.getHours();
|
|||
|
|
if (/h/.test(this.token))
|
|||
|
|
hours = (hours % 12) || 12;
|
|||
|
|
return this.token.length > 1 ? String(hours).padStart(2, '0') : hours;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
hours = Hours;
|
|||
|
|
return hours;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var milliseconds;
|
|||
|
|
var hasRequiredMilliseconds;
|
|||
|
|
|
|||
|
|
function requireMilliseconds () {
|
|||
|
|
if (hasRequiredMilliseconds) return milliseconds;
|
|||
|
|
hasRequiredMilliseconds = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
class Milliseconds extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setMilliseconds(this.date.getMilliseconds() + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.date.setMilliseconds(this.date.getMilliseconds() - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {
|
|||
|
|
this.date.setMilliseconds(parseInt(val.substr(-(this.token.length))));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
return String(this.date.getMilliseconds()).padStart(4, '0')
|
|||
|
|
.substr(0, this.token.length);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
milliseconds = Milliseconds;
|
|||
|
|
return milliseconds;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var minutes;
|
|||
|
|
var hasRequiredMinutes;
|
|||
|
|
|
|||
|
|
function requireMinutes () {
|
|||
|
|
if (hasRequiredMinutes) return minutes;
|
|||
|
|
hasRequiredMinutes = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
class Minutes extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setMinutes(this.date.getMinutes() + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.date.setMinutes(this.date.getMinutes() - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {
|
|||
|
|
this.date.setMinutes(parseInt(val.substr(-2)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
let m = this.date.getMinutes();
|
|||
|
|
return this.token.length > 1 ? String(m).padStart(2, '0') : m;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
minutes = Minutes;
|
|||
|
|
return minutes;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var month;
|
|||
|
|
var hasRequiredMonth;
|
|||
|
|
|
|||
|
|
function requireMonth () {
|
|||
|
|
if (hasRequiredMonth) return month;
|
|||
|
|
hasRequiredMonth = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
class Month extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setMonth(this.date.getMonth() + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.date.setMonth(this.date.getMonth() - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {
|
|||
|
|
val = parseInt(val.substr(-2)) - 1;
|
|||
|
|
this.date.setMonth(val < 0 ? 0 : val);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
let month = this.date.getMonth();
|
|||
|
|
let tl = this.token.length;
|
|||
|
|
return tl === 2 ? String(month + 1).padStart(2, '0')
|
|||
|
|
: tl === 3 ? this.locales.monthsShort[month]
|
|||
|
|
: tl === 4 ? this.locales.months[month]
|
|||
|
|
: String(month + 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
month = Month;
|
|||
|
|
return month;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var seconds;
|
|||
|
|
var hasRequiredSeconds;
|
|||
|
|
|
|||
|
|
function requireSeconds () {
|
|||
|
|
if (hasRequiredSeconds) return seconds;
|
|||
|
|
hasRequiredSeconds = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
class Seconds extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setSeconds(this.date.getSeconds() + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.date.setSeconds(this.date.getSeconds() - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {
|
|||
|
|
this.date.setSeconds(parseInt(val.substr(-2)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
let s = this.date.getSeconds();
|
|||
|
|
return this.token.length > 1 ? String(s).padStart(2, '0') : s;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
seconds = Seconds;
|
|||
|
|
return seconds;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var year;
|
|||
|
|
var hasRequiredYear;
|
|||
|
|
|
|||
|
|
function requireYear () {
|
|||
|
|
if (hasRequiredYear) return year;
|
|||
|
|
hasRequiredYear = 1;
|
|||
|
|
|
|||
|
|
const DatePart = requireDatepart();
|
|||
|
|
|
|||
|
|
class Year extends DatePart {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.date.setFullYear(this.date.getFullYear() + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.date.setFullYear(this.date.getFullYear() - 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setTo(val) {
|
|||
|
|
this.date.setFullYear(val.substr(-4));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toString() {
|
|||
|
|
let year = String(this.date.getFullYear()).padStart(4, '0');
|
|||
|
|
return this.token.length === 2 ? year.substr(-2) : year;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
year = Year;
|
|||
|
|
return year;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var dateparts;
|
|||
|
|
var hasRequiredDateparts;
|
|||
|
|
|
|||
|
|
function requireDateparts () {
|
|||
|
|
if (hasRequiredDateparts) return dateparts;
|
|||
|
|
hasRequiredDateparts = 1;
|
|||
|
|
|
|||
|
|
dateparts = {
|
|||
|
|
DatePart: requireDatepart(),
|
|||
|
|
Meridiem: requireMeridiem(),
|
|||
|
|
Day: requireDay(),
|
|||
|
|
Hours: requireHours(),
|
|||
|
|
Milliseconds: requireMilliseconds(),
|
|||
|
|
Minutes: requireMinutes(),
|
|||
|
|
Month: requireMonth(),
|
|||
|
|
Seconds: requireSeconds(),
|
|||
|
|
Year: requireYear(),
|
|||
|
|
};
|
|||
|
|
return dateparts;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var date;
|
|||
|
|
var hasRequiredDate;
|
|||
|
|
|
|||
|
|
function requireDate () {
|
|||
|
|
if (hasRequiredDate) return date;
|
|||
|
|
hasRequiredDate = 1;
|
|||
|
|
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { style, clear, figures } = requireUtil();
|
|||
|
|
const { erase, cursor } = requireSrc();
|
|||
|
|
const { DatePart, Meridiem, Day, Hours, Milliseconds, Minutes, Month, Seconds, Year } = requireDateparts();
|
|||
|
|
|
|||
|
|
const regex = /\\(.)|"((?:\\["\\]|[^"])+)"|(D[Do]?|d{3,4}|d)|(M{1,4})|(YY(?:YY)?)|([aA])|([Hh]{1,2})|(m{1,2})|(s{1,2})|(S{1,4})|./g;
|
|||
|
|
const regexGroups = {
|
|||
|
|
1: ({token}) => token.replace(/\\(.)/g, '$1'),
|
|||
|
|
2: (opts) => new Day(opts), // Day // TODO
|
|||
|
|
3: (opts) => new Month(opts), // Month
|
|||
|
|
4: (opts) => new Year(opts), // Year
|
|||
|
|
5: (opts) => new Meridiem(opts), // AM/PM // TODO (special)
|
|||
|
|
6: (opts) => new Hours(opts), // Hours
|
|||
|
|
7: (opts) => new Minutes(opts), // Minutes
|
|||
|
|
8: (opts) => new Seconds(opts), // Seconds
|
|||
|
|
9: (opts) => new Milliseconds(opts), // Fractional seconds
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const dfltLocales = {
|
|||
|
|
months: 'January,February,March,April,May,June,July,August,September,October,November,December'.split(','),
|
|||
|
|
monthsShort: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
|
|||
|
|
weekdays: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
|
|||
|
|
weekdaysShort: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(',')
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* DatePrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {Number} [opts.initial] Index of default value
|
|||
|
|
* @param {String} [opts.mask] The format mask
|
|||
|
|
* @param {object} [opts.locales] The date locales
|
|||
|
|
* @param {String} [opts.error] The error message shown on invalid value
|
|||
|
|
* @param {Function} [opts.validate] Function to validate the submitted value
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
*/
|
|||
|
|
class DatePrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.cursor = 0;
|
|||
|
|
this.typed = '';
|
|||
|
|
this.locales = Object.assign(dfltLocales, opts.locales);
|
|||
|
|
this._date = opts.initial || new Date();
|
|||
|
|
this.errorMsg = opts.error || 'Please Enter A Valid Value';
|
|||
|
|
this.validator = opts.validate || (() => true);
|
|||
|
|
this.mask = opts.mask || 'YYYY-MM-DD HH:mm:ss';
|
|||
|
|
this.clear = clear('', this.out.columns);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get value() {
|
|||
|
|
return this.date
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get date() {
|
|||
|
|
return this._date;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set date(date) {
|
|||
|
|
if (date) this._date.setTime(date.getTime());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set mask(mask) {
|
|||
|
|
let result;
|
|||
|
|
this.parts = [];
|
|||
|
|
while(result = regex.exec(mask)) {
|
|||
|
|
let match = result.shift();
|
|||
|
|
let idx = result.findIndex(gr => gr != null);
|
|||
|
|
this.parts.push(idx in regexGroups
|
|||
|
|
? regexGroups[idx]({ token: result[idx] || match, date: this.date, parts: this.parts, locales: this.locales })
|
|||
|
|
: result[idx] || match);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let parts = this.parts.reduce((arr, i) => {
|
|||
|
|
if (typeof i === 'string' && typeof arr[arr.length - 1] === 'string')
|
|||
|
|
arr[arr.length - 1] += i;
|
|||
|
|
else arr.push(i);
|
|||
|
|
return arr;
|
|||
|
|
}, []);
|
|||
|
|
|
|||
|
|
this.parts.splice(0);
|
|||
|
|
this.parts.push(...parts);
|
|||
|
|
this.reset();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
moveCursor(n) {
|
|||
|
|
this.typed = '';
|
|||
|
|
this.cursor = n;
|
|||
|
|
this.fire();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.moveCursor(this.parts.findIndex(p => p instanceof DatePart));
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
this.abort();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.error = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async validate() {
|
|||
|
|
let valid = await this.validator(this.value);
|
|||
|
|
if (typeof valid === 'string') {
|
|||
|
|
this.errorMsg = valid;
|
|||
|
|
valid = false;
|
|||
|
|
}
|
|||
|
|
this.error = !valid;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async submit() {
|
|||
|
|
await this.validate();
|
|||
|
|
if (this.error) {
|
|||
|
|
this.color = 'red';
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.typed = '';
|
|||
|
|
this.parts[this.cursor].up();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.typed = '';
|
|||
|
|
this.parts[this.cursor].down();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
left() {
|
|||
|
|
let prev = this.parts[this.cursor].prev();
|
|||
|
|
if (prev == null) return this.bell();
|
|||
|
|
this.moveCursor(this.parts.indexOf(prev));
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
right() {
|
|||
|
|
let next = this.parts[this.cursor].next();
|
|||
|
|
if (next == null) return this.bell();
|
|||
|
|
this.moveCursor(this.parts.indexOf(next));
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next() {
|
|||
|
|
let next = this.parts[this.cursor].next();
|
|||
|
|
this.moveCursor(next
|
|||
|
|
? this.parts.indexOf(next)
|
|||
|
|
: this.parts.findIndex((part) => part instanceof DatePart));
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c) {
|
|||
|
|
if (/\d/.test(c)) {
|
|||
|
|
this.typed += c;
|
|||
|
|
this.parts[this.cursor].setTo(this.typed);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|||
|
|
else this.out.write(clear(this.outputText, this.out.columns));
|
|||
|
|
super.render();
|
|||
|
|
|
|||
|
|
// Print prompt
|
|||
|
|
this.outputText = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(false),
|
|||
|
|
this.parts.reduce((arr, p, idx) => arr.concat(idx === this.cursor && !this.done ? color.cyan().underline(p.toString()) : p), [])
|
|||
|
|
.join('')
|
|||
|
|
].join(' ');
|
|||
|
|
|
|||
|
|
// Print error
|
|||
|
|
if (this.error) {
|
|||
|
|
this.outputText += this.errorMsg.split('\n').reduce(
|
|||
|
|
(a, l, i) => a + `\n${i ? ` ` : figures.pointerSmall} ${color.red().italic(l)}`, ``);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.out.write(erase.line + cursor.to(0) + this.outputText);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
date = DatePrompt;
|
|||
|
|
return date;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var number;
|
|||
|
|
var hasRequiredNumber;
|
|||
|
|
|
|||
|
|
function requireNumber () {
|
|||
|
|
if (hasRequiredNumber) return number;
|
|||
|
|
hasRequiredNumber = 1;
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { cursor, erase } = requireSrc();
|
|||
|
|
const { style, figures, clear, lines } = requireUtil();
|
|||
|
|
|
|||
|
|
const isNumber = /[0-9]/;
|
|||
|
|
const isDef = any => any !== undefined;
|
|||
|
|
const round = (number, precision) => {
|
|||
|
|
let factor = Math.pow(10, precision);
|
|||
|
|
return Math.round(number * factor) / factor;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* NumberPrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {String} [opts.style='default'] Render style
|
|||
|
|
* @param {Number} [opts.initial] Default value
|
|||
|
|
* @param {Number} [opts.max=+Infinity] Max value
|
|||
|
|
* @param {Number} [opts.min=-Infinity] Min value
|
|||
|
|
* @param {Boolean} [opts.float=false] Parse input as floats
|
|||
|
|
* @param {Number} [opts.round=2] Round floats to x decimals
|
|||
|
|
* @param {Number} [opts.increment=1] Number to increment by when using arrow-keys
|
|||
|
|
* @param {Function} [opts.validate] Validate function
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
* @param {String} [opts.error] The invalid error label
|
|||
|
|
*/
|
|||
|
|
class NumberPrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.transform = style.render(opts.style);
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.initial = isDef(opts.initial) ? opts.initial : '';
|
|||
|
|
this.float = !!opts.float;
|
|||
|
|
this.round = opts.round || 2;
|
|||
|
|
this.inc = opts.increment || 1;
|
|||
|
|
this.min = isDef(opts.min) ? opts.min : -Infinity;
|
|||
|
|
this.max = isDef(opts.max) ? opts.max : Infinity;
|
|||
|
|
this.errorMsg = opts.error || `Please Enter A Valid Value`;
|
|||
|
|
this.validator = opts.validate || (() => true);
|
|||
|
|
this.color = `cyan`;
|
|||
|
|
this.value = ``;
|
|||
|
|
this.typed = ``;
|
|||
|
|
this.lastHit = 0;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set value(v) {
|
|||
|
|
if (!v && v !== 0) {
|
|||
|
|
this.placeholder = true;
|
|||
|
|
this.rendered = color.gray(this.transform.render(`${this.initial}`));
|
|||
|
|
this._value = ``;
|
|||
|
|
} else {
|
|||
|
|
this.placeholder = false;
|
|||
|
|
this.rendered = this.transform.render(`${round(v, this.round)}`);
|
|||
|
|
this._value = round(v, this.round);
|
|||
|
|
}
|
|||
|
|
this.fire();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get value() {
|
|||
|
|
return this._value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
parse(x) {
|
|||
|
|
return this.float ? parseFloat(x) : parseInt(x);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
valid(c) {
|
|||
|
|
return c === `-` || c === `.` && this.float || isNumber.test(c)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.typed = ``;
|
|||
|
|
this.value = ``;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
this.abort();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
let x = this.value;
|
|||
|
|
this.value = x !== `` ? x : this.initial;
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.error = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write(`\n`);
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async validate() {
|
|||
|
|
let valid = await this.validator(this.value);
|
|||
|
|
if (typeof valid === `string`) {
|
|||
|
|
this.errorMsg = valid;
|
|||
|
|
valid = false;
|
|||
|
|
}
|
|||
|
|
this.error = !valid;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async submit() {
|
|||
|
|
await this.validate();
|
|||
|
|
if (this.error) {
|
|||
|
|
this.color = `red`;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
let x = this.value;
|
|||
|
|
this.value = x !== `` ? x : this.initial;
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.error = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write(`\n`);
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
this.typed = ``;
|
|||
|
|
if(this.value === '') {
|
|||
|
|
this.value = this.min - this.inc;
|
|||
|
|
}
|
|||
|
|
if (this.value >= this.max) return this.bell();
|
|||
|
|
this.value += this.inc;
|
|||
|
|
this.color = `cyan`;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
this.typed = ``;
|
|||
|
|
if(this.value === '') {
|
|||
|
|
this.value = this.min + this.inc;
|
|||
|
|
}
|
|||
|
|
if (this.value <= this.min) return this.bell();
|
|||
|
|
this.value -= this.inc;
|
|||
|
|
this.color = `cyan`;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
delete() {
|
|||
|
|
let val = this.value.toString();
|
|||
|
|
if (val.length === 0) return this.bell();
|
|||
|
|
this.value = this.parse((val = val.slice(0, -1))) || ``;
|
|||
|
|
if (this.value !== '' && this.value < this.min) {
|
|||
|
|
this.value = this.min;
|
|||
|
|
}
|
|||
|
|
this.color = `cyan`;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next() {
|
|||
|
|
this.value = this.initial;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
if (!this.valid(c)) return this.bell();
|
|||
|
|
|
|||
|
|
const now = Date.now();
|
|||
|
|
if (now - this.lastHit > 1000) this.typed = ``; // 1s elapsed
|
|||
|
|
this.typed += c;
|
|||
|
|
this.lastHit = now;
|
|||
|
|
this.color = `cyan`;
|
|||
|
|
|
|||
|
|
if (c === `.`) return this.fire();
|
|||
|
|
|
|||
|
|
this.value = Math.min(this.parse(this.typed), this.max);
|
|||
|
|
if (this.value > this.max) this.value = this.max;
|
|||
|
|
if (this.value < this.min) this.value = this.min;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (!this.firstRender) {
|
|||
|
|
if (this.outputError)
|
|||
|
|
this.out.write(cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns));
|
|||
|
|
this.out.write(clear(this.outputText, this.out.columns));
|
|||
|
|
}
|
|||
|
|
super.render();
|
|||
|
|
this.outputError = '';
|
|||
|
|
|
|||
|
|
// Print prompt
|
|||
|
|
this.outputText = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(this.done),
|
|||
|
|
!this.done || (!this.done && !this.placeholder)
|
|||
|
|
? color[this.color]().underline(this.rendered) : this.rendered
|
|||
|
|
].join(` `);
|
|||
|
|
|
|||
|
|
// Print error
|
|||
|
|
if (this.error) {
|
|||
|
|
this.outputError += this.errorMsg.split(`\n`)
|
|||
|
|
.reduce((a, l, i) => a + `\n${i ? ` ` : figures.pointerSmall} ${color.red().italic(l)}`, ``);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.out.write(erase.line + cursor.to(0) + this.outputText + cursor.save + this.outputError + cursor.restore);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
number = NumberPrompt;
|
|||
|
|
return number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var multiselect;
|
|||
|
|
var hasRequiredMultiselect;
|
|||
|
|
|
|||
|
|
function requireMultiselect () {
|
|||
|
|
if (hasRequiredMultiselect) return multiselect;
|
|||
|
|
hasRequiredMultiselect = 1;
|
|||
|
|
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const { cursor } = requireSrc();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { clear, figures, style, wrap, entriesToDisplay } = requireUtil();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* MultiselectPrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {Array} opts.choices Array of choice objects
|
|||
|
|
* @param {String} [opts.hint] Hint to display
|
|||
|
|
* @param {String} [opts.warn] Hint shown for disabled choices
|
|||
|
|
* @param {Number} [opts.max] Max choices
|
|||
|
|
* @param {Number} [opts.cursor=0] Cursor start position
|
|||
|
|
* @param {Number} [opts.optionsPerPage=10] Max options to display at once
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
*/
|
|||
|
|
class MultiselectPrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.cursor = opts.cursor || 0;
|
|||
|
|
this.scrollIndex = opts.cursor || 0;
|
|||
|
|
this.hint = opts.hint || '';
|
|||
|
|
this.warn = opts.warn || '- This option is disabled -';
|
|||
|
|
this.minSelected = opts.min;
|
|||
|
|
this.showMinError = false;
|
|||
|
|
this.maxChoices = opts.max;
|
|||
|
|
this.instructions = opts.instructions;
|
|||
|
|
this.optionsPerPage = opts.optionsPerPage || 10;
|
|||
|
|
this.value = opts.choices.map((ch, idx) => {
|
|||
|
|
if (typeof ch === 'string')
|
|||
|
|
ch = {title: ch, value: idx};
|
|||
|
|
return {
|
|||
|
|
title: ch && (ch.title || ch.value || ch),
|
|||
|
|
description: ch && ch.description,
|
|||
|
|
value: ch && (ch.value === undefined ? idx : ch.value),
|
|||
|
|
selected: ch && ch.selected,
|
|||
|
|
disabled: ch && ch.disabled
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
this.clear = clear('', this.out.columns);
|
|||
|
|
if (!opts.overrideRender) {
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.value.map(v => !v.selected);
|
|||
|
|
this.cursor = 0;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
selected() {
|
|||
|
|
return this.value.filter(v => v.selected);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
this.abort();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
submit() {
|
|||
|
|
const selected = this.value
|
|||
|
|
.filter(e => e.selected);
|
|||
|
|
if (this.minSelected && selected.length < this.minSelected) {
|
|||
|
|
this.showMinError = true;
|
|||
|
|
this.render();
|
|||
|
|
} else {
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
first() {
|
|||
|
|
this.cursor = 0;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
last() {
|
|||
|
|
this.cursor = this.value.length - 1;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
next() {
|
|||
|
|
this.cursor = (this.cursor + 1) % this.value.length;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
if (this.cursor === 0) {
|
|||
|
|
this.cursor = this.value.length - 1;
|
|||
|
|
} else {
|
|||
|
|
this.cursor--;
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
if (this.cursor === this.value.length - 1) {
|
|||
|
|
this.cursor = 0;
|
|||
|
|
} else {
|
|||
|
|
this.cursor++;
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
left() {
|
|||
|
|
this.value[this.cursor].selected = false;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
right() {
|
|||
|
|
if (this.value.filter(e => e.selected).length >= this.maxChoices) return this.bell();
|
|||
|
|
this.value[this.cursor].selected = true;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
handleSpaceToggle() {
|
|||
|
|
const v = this.value[this.cursor];
|
|||
|
|
|
|||
|
|
if (v.selected) {
|
|||
|
|
v.selected = false;
|
|||
|
|
this.render();
|
|||
|
|
} else if (v.disabled || this.value.filter(e => e.selected).length >= this.maxChoices) {
|
|||
|
|
return this.bell();
|
|||
|
|
} else {
|
|||
|
|
v.selected = true;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toggleAll() {
|
|||
|
|
if (this.maxChoices !== undefined || this.value[this.cursor].disabled) {
|
|||
|
|
return this.bell();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const newSelected = !this.value[this.cursor].selected;
|
|||
|
|
this.value.filter(v => !v.disabled).forEach(v => v.selected = newSelected);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
if (c === ' ') {
|
|||
|
|
this.handleSpaceToggle();
|
|||
|
|
} else if (c === 'a') {
|
|||
|
|
this.toggleAll();
|
|||
|
|
} else {
|
|||
|
|
return this.bell();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderInstructions() {
|
|||
|
|
if (this.instructions === undefined || this.instructions) {
|
|||
|
|
if (typeof this.instructions === 'string') {
|
|||
|
|
return this.instructions;
|
|||
|
|
}
|
|||
|
|
return '\nInstructions:\n'
|
|||
|
|
+ ` ${figures.arrowUp}/${figures.arrowDown}: Highlight option\n`
|
|||
|
|
+ ` ${figures.arrowLeft}/${figures.arrowRight}/[space]: Toggle selection\n`
|
|||
|
|
+ (this.maxChoices === undefined ? ` a: Toggle all\n` : '')
|
|||
|
|
+ ` enter/return: Complete answer`;
|
|||
|
|
}
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderOption(cursor, v, i, arrowIndicator) {
|
|||
|
|
const prefix = (v.selected ? color.green(figures.radioOn) : figures.radioOff) + ' ' + arrowIndicator + ' ';
|
|||
|
|
let title, desc;
|
|||
|
|
|
|||
|
|
if (v.disabled) {
|
|||
|
|
title = cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title);
|
|||
|
|
} else {
|
|||
|
|
title = cursor === i ? color.cyan().underline(v.title) : v.title;
|
|||
|
|
if (cursor === i && v.description) {
|
|||
|
|
desc = ` - ${v.description}`;
|
|||
|
|
if (prefix.length + title.length + desc.length >= this.out.columns
|
|||
|
|
|| v.description.split(/\r?\n/).length > 1) {
|
|||
|
|
desc = '\n' + wrap(v.description, { margin: prefix.length, width: this.out.columns });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return prefix + title + color.gray(desc || '');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// shared with autocompleteMultiselect
|
|||
|
|
paginateOptions(options) {
|
|||
|
|
if (options.length === 0) {
|
|||
|
|
return color.red('No matches for this query.');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let { startIndex, endIndex } = entriesToDisplay(this.cursor, options.length, this.optionsPerPage);
|
|||
|
|
let prefix, styledOptions = [];
|
|||
|
|
|
|||
|
|
for (let i = startIndex; i < endIndex; i++) {
|
|||
|
|
if (i === startIndex && startIndex > 0) {
|
|||
|
|
prefix = figures.arrowUp;
|
|||
|
|
} else if (i === endIndex - 1 && endIndex < options.length) {
|
|||
|
|
prefix = figures.arrowDown;
|
|||
|
|
} else {
|
|||
|
|
prefix = ' ';
|
|||
|
|
}
|
|||
|
|
styledOptions.push(this.renderOption(this.cursor, options[i], i, prefix));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return '\n' + styledOptions.join('\n');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// shared with autocomleteMultiselect
|
|||
|
|
renderOptions(options) {
|
|||
|
|
if (!this.done) {
|
|||
|
|
return this.paginateOptions(options);
|
|||
|
|
}
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderDoneOrInstructions() {
|
|||
|
|
if (this.done) {
|
|||
|
|
return this.value
|
|||
|
|
.filter(e => e.selected)
|
|||
|
|
.map(v => v.title)
|
|||
|
|
.join(', ');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const output = [color.gray(this.hint), this.renderInstructions()];
|
|||
|
|
|
|||
|
|
if (this.value[this.cursor].disabled) {
|
|||
|
|
output.push(color.yellow(this.warn));
|
|||
|
|
}
|
|||
|
|
return output.join(' ');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|||
|
|
super.render();
|
|||
|
|
|
|||
|
|
// print prompt
|
|||
|
|
let prompt = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(false),
|
|||
|
|
this.renderDoneOrInstructions()
|
|||
|
|
].join(' ');
|
|||
|
|
if (this.showMinError) {
|
|||
|
|
prompt += color.red(`You must select a minimum of ${this.minSelected} choices.`);
|
|||
|
|
this.showMinError = false;
|
|||
|
|
}
|
|||
|
|
prompt += this.renderOptions(this.value);
|
|||
|
|
|
|||
|
|
this.out.write(this.clear + prompt);
|
|||
|
|
this.clear = clear(prompt, this.out.columns);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
multiselect = MultiselectPrompt;
|
|||
|
|
return multiselect;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var autocomplete;
|
|||
|
|
var hasRequiredAutocomplete;
|
|||
|
|
|
|||
|
|
function requireAutocomplete () {
|
|||
|
|
if (hasRequiredAutocomplete) return autocomplete;
|
|||
|
|
hasRequiredAutocomplete = 1;
|
|||
|
|
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { erase, cursor } = requireSrc();
|
|||
|
|
const { style, clear, figures, wrap, entriesToDisplay } = requireUtil();
|
|||
|
|
|
|||
|
|
const getVal = (arr, i) => arr[i] && (arr[i].value || arr[i].title || arr[i]);
|
|||
|
|
const getTitle = (arr, i) => arr[i] && (arr[i].title || arr[i].value || arr[i]);
|
|||
|
|
const getIndex = (arr, valOrTitle) => {
|
|||
|
|
const index = arr.findIndex(el => el.value === valOrTitle || el.title === valOrTitle);
|
|||
|
|
return index > -1 ? index : undefined;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* TextPrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {Array} opts.choices Array of auto-complete choices objects
|
|||
|
|
* @param {Function} [opts.suggest] Filter function. Defaults to sort by title
|
|||
|
|
* @param {Number} [opts.limit=10] Max number of results to show
|
|||
|
|
* @param {Number} [opts.cursor=0] Cursor start position
|
|||
|
|
* @param {String} [opts.style='default'] Render style
|
|||
|
|
* @param {String} [opts.fallback] Fallback message - initial to default value
|
|||
|
|
* @param {String} [opts.initial] Index of the default value
|
|||
|
|
* @param {Boolean} [opts.clearFirst] The first ESCAPE keypress will clear the input
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
* @param {String} [opts.noMatches] The no matches found label
|
|||
|
|
*/
|
|||
|
|
class AutocompletePrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.suggest = opts.suggest;
|
|||
|
|
this.choices = opts.choices;
|
|||
|
|
this.initial = typeof opts.initial === 'number'
|
|||
|
|
? opts.initial
|
|||
|
|
: getIndex(opts.choices, opts.initial);
|
|||
|
|
this.select = this.initial || opts.cursor || 0;
|
|||
|
|
this.i18n = { noMatches: opts.noMatches || 'no matches found' };
|
|||
|
|
this.fallback = opts.fallback || this.initial;
|
|||
|
|
this.clearFirst = opts.clearFirst || false;
|
|||
|
|
this.suggestions = [];
|
|||
|
|
this.input = '';
|
|||
|
|
this.limit = opts.limit || 10;
|
|||
|
|
this.cursor = 0;
|
|||
|
|
this.transform = style.render(opts.style);
|
|||
|
|
this.scale = this.transform.scale;
|
|||
|
|
this.render = this.render.bind(this);
|
|||
|
|
this.complete = this.complete.bind(this);
|
|||
|
|
this.clear = clear('', this.out.columns);
|
|||
|
|
this.complete(this.render);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set fallback(fb) {
|
|||
|
|
this._fb = Number.isSafeInteger(parseInt(fb)) ? parseInt(fb) : fb;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get fallback() {
|
|||
|
|
let choice;
|
|||
|
|
if (typeof this._fb === 'number')
|
|||
|
|
choice = this.choices[this._fb];
|
|||
|
|
else if (typeof this._fb === 'string')
|
|||
|
|
choice = { title: this._fb };
|
|||
|
|
return choice || this._fb || { title: this.i18n.noMatches };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
moveSelect(i) {
|
|||
|
|
this.select = i;
|
|||
|
|
if (this.suggestions.length > 0)
|
|||
|
|
this.value = getVal(this.suggestions, i);
|
|||
|
|
else this.value = this.fallback.value;
|
|||
|
|
this.fire();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async complete(cb) {
|
|||
|
|
const p = (this.completing = this.suggest(this.input, this.choices));
|
|||
|
|
const suggestions = await p;
|
|||
|
|
|
|||
|
|
if (this.completing !== p) return;
|
|||
|
|
this.suggestions = suggestions
|
|||
|
|
.map((s, i, arr) => ({ title: getTitle(arr, i), value: getVal(arr, i), description: s.description }));
|
|||
|
|
this.completing = false;
|
|||
|
|
const l = Math.max(suggestions.length - 1, 0);
|
|||
|
|
this.moveSelect(Math.min(l, this.select));
|
|||
|
|
|
|||
|
|
cb && cb();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.input = '';
|
|||
|
|
this.complete(() => {
|
|||
|
|
this.moveSelect(this.initial !== void 0 ? this.initial : 0);
|
|||
|
|
this.render();
|
|||
|
|
});
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
if (this.clearFirst && this.input.length > 0) {
|
|||
|
|
this.reset();
|
|||
|
|
} else {
|
|||
|
|
this.done = this.exited = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.exited = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
submit() {
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = this.exited = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
let s1 = this.input.slice(0, this.cursor);
|
|||
|
|
let s2 = this.input.slice(this.cursor);
|
|||
|
|
this.input = `${s1}${c}${s2}`;
|
|||
|
|
this.cursor = s1.length+1;
|
|||
|
|
this.complete(this.render);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
delete() {
|
|||
|
|
if (this.cursor === 0) return this.bell();
|
|||
|
|
let s1 = this.input.slice(0, this.cursor-1);
|
|||
|
|
let s2 = this.input.slice(this.cursor);
|
|||
|
|
this.input = `${s1}${s2}`;
|
|||
|
|
this.complete(this.render);
|
|||
|
|
this.cursor = this.cursor-1;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
deleteForward() {
|
|||
|
|
if(this.cursor*this.scale >= this.rendered.length) return this.bell();
|
|||
|
|
let s1 = this.input.slice(0, this.cursor);
|
|||
|
|
let s2 = this.input.slice(this.cursor+1);
|
|||
|
|
this.input = `${s1}${s2}`;
|
|||
|
|
this.complete(this.render);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
first() {
|
|||
|
|
this.moveSelect(0);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
last() {
|
|||
|
|
this.moveSelect(this.suggestions.length - 1);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
if (this.select === 0) {
|
|||
|
|
this.moveSelect(this.suggestions.length - 1);
|
|||
|
|
} else {
|
|||
|
|
this.moveSelect(this.select - 1);
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
if (this.select === this.suggestions.length - 1) {
|
|||
|
|
this.moveSelect(0);
|
|||
|
|
} else {
|
|||
|
|
this.moveSelect(this.select + 1);
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
next() {
|
|||
|
|
if (this.select === this.suggestions.length - 1) {
|
|||
|
|
this.moveSelect(0);
|
|||
|
|
} else this.moveSelect(this.select + 1);
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
nextPage() {
|
|||
|
|
this.moveSelect(Math.min(this.select + this.limit, this.suggestions.length - 1));
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
prevPage() {
|
|||
|
|
this.moveSelect(Math.max(this.select - this.limit, 0));
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
left() {
|
|||
|
|
if (this.cursor <= 0) return this.bell();
|
|||
|
|
this.cursor = this.cursor-1;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
right() {
|
|||
|
|
if (this.cursor*this.scale >= this.rendered.length) return this.bell();
|
|||
|
|
this.cursor = this.cursor+1;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderOption(v, hovered, isStart, isEnd) {
|
|||
|
|
let desc;
|
|||
|
|
let prefix = isStart ? figures.arrowUp : isEnd ? figures.arrowDown : ' ';
|
|||
|
|
let title = hovered ? color.cyan().underline(v.title) : v.title;
|
|||
|
|
prefix = (hovered ? color.cyan(figures.pointer) + ' ' : ' ') + prefix;
|
|||
|
|
if (v.description) {
|
|||
|
|
desc = ` - ${v.description}`;
|
|||
|
|
if (prefix.length + title.length + desc.length >= this.out.columns
|
|||
|
|
|| v.description.split(/\r?\n/).length > 1) {
|
|||
|
|
desc = '\n' + wrap(v.description, { margin: 3, width: this.out.columns });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return prefix + ' ' + title + color.gray(desc || '');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|||
|
|
else this.out.write(clear(this.outputText, this.out.columns));
|
|||
|
|
super.render();
|
|||
|
|
|
|||
|
|
let { startIndex, endIndex } = entriesToDisplay(this.select, this.choices.length, this.limit);
|
|||
|
|
|
|||
|
|
this.outputText = [
|
|||
|
|
style.symbol(this.done, this.aborted, this.exited),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(this.completing),
|
|||
|
|
this.done && this.suggestions[this.select]
|
|||
|
|
? this.suggestions[this.select].title
|
|||
|
|
: this.rendered = this.transform.render(this.input)
|
|||
|
|
].join(' ');
|
|||
|
|
|
|||
|
|
if (!this.done) {
|
|||
|
|
const suggestions = this.suggestions
|
|||
|
|
.slice(startIndex, endIndex)
|
|||
|
|
.map((item, i) => this.renderOption(item,
|
|||
|
|
this.select === i + startIndex,
|
|||
|
|
i === 0 && startIndex > 0,
|
|||
|
|
i + startIndex === endIndex - 1 && endIndex < this.choices.length))
|
|||
|
|
.join('\n');
|
|||
|
|
this.outputText += `\n` + (suggestions || color.gray(this.fallback.title));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.out.write(erase.line + cursor.to(0) + this.outputText);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
autocomplete = AutocompletePrompt;
|
|||
|
|
return autocomplete;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var autocompleteMultiselect;
|
|||
|
|
var hasRequiredAutocompleteMultiselect;
|
|||
|
|
|
|||
|
|
function requireAutocompleteMultiselect () {
|
|||
|
|
if (hasRequiredAutocompleteMultiselect) return autocompleteMultiselect;
|
|||
|
|
hasRequiredAutocompleteMultiselect = 1;
|
|||
|
|
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const { cursor } = requireSrc();
|
|||
|
|
const MultiselectPrompt = requireMultiselect();
|
|||
|
|
const { clear, style, figures } = requireUtil();
|
|||
|
|
/**
|
|||
|
|
* MultiselectPrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {Array} opts.choices Array of choice objects
|
|||
|
|
* @param {String} [opts.hint] Hint to display
|
|||
|
|
* @param {String} [opts.warn] Hint shown for disabled choices
|
|||
|
|
* @param {Number} [opts.max] Max choices
|
|||
|
|
* @param {Number} [opts.cursor=0] Cursor start position
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
*/
|
|||
|
|
class AutocompleteMultiselectPrompt extends MultiselectPrompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
opts.overrideRender = true;
|
|||
|
|
super(opts);
|
|||
|
|
this.inputValue = '';
|
|||
|
|
this.clear = clear('', this.out.columns);
|
|||
|
|
this.filteredOptions = this.value;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
last() {
|
|||
|
|
this.cursor = this.filteredOptions.length - 1;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
next() {
|
|||
|
|
this.cursor = (this.cursor + 1) % this.filteredOptions.length;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
up() {
|
|||
|
|
if (this.cursor === 0) {
|
|||
|
|
this.cursor = this.filteredOptions.length - 1;
|
|||
|
|
} else {
|
|||
|
|
this.cursor--;
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
down() {
|
|||
|
|
if (this.cursor === this.filteredOptions.length - 1) {
|
|||
|
|
this.cursor = 0;
|
|||
|
|
} else {
|
|||
|
|
this.cursor++;
|
|||
|
|
}
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
left() {
|
|||
|
|
this.filteredOptions[this.cursor].selected = false;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
right() {
|
|||
|
|
if (this.value.filter(e => e.selected).length >= this.maxChoices) return this.bell();
|
|||
|
|
this.filteredOptions[this.cursor].selected = true;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
delete() {
|
|||
|
|
if (this.inputValue.length) {
|
|||
|
|
this.inputValue = this.inputValue.substr(0, this.inputValue.length - 1);
|
|||
|
|
this.updateFilteredOptions();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
updateFilteredOptions() {
|
|||
|
|
const currentHighlight = this.filteredOptions[this.cursor];
|
|||
|
|
this.filteredOptions = this.value
|
|||
|
|
.filter(v => {
|
|||
|
|
if (this.inputValue) {
|
|||
|
|
if (typeof v.title === 'string') {
|
|||
|
|
if (v.title.toLowerCase().includes(this.inputValue.toLowerCase())) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (typeof v.value === 'string') {
|
|||
|
|
if (v.value.toLowerCase().includes(this.inputValue.toLowerCase())) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
});
|
|||
|
|
const newHighlightIndex = this.filteredOptions.findIndex(v => v === currentHighlight);
|
|||
|
|
this.cursor = newHighlightIndex < 0 ? 0 : newHighlightIndex;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
handleSpaceToggle() {
|
|||
|
|
const v = this.filteredOptions[this.cursor];
|
|||
|
|
|
|||
|
|
if (v.selected) {
|
|||
|
|
v.selected = false;
|
|||
|
|
this.render();
|
|||
|
|
} else if (v.disabled || this.value.filter(e => e.selected).length >= this.maxChoices) {
|
|||
|
|
return this.bell();
|
|||
|
|
} else {
|
|||
|
|
v.selected = true;
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
handleInputChange(c) {
|
|||
|
|
this.inputValue = this.inputValue + c;
|
|||
|
|
this.updateFilteredOptions();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
if (c === ' ') {
|
|||
|
|
this.handleSpaceToggle();
|
|||
|
|
} else {
|
|||
|
|
this.handleInputChange(c);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderInstructions() {
|
|||
|
|
if (this.instructions === undefined || this.instructions) {
|
|||
|
|
if (typeof this.instructions === 'string') {
|
|||
|
|
return this.instructions;
|
|||
|
|
}
|
|||
|
|
return `
|
|||
|
|
Instructions:
|
|||
|
|
${figures.arrowUp}/${figures.arrowDown}: Highlight option
|
|||
|
|
${figures.arrowLeft}/${figures.arrowRight}/[space]: Toggle selection
|
|||
|
|
[a,b,c]/delete: Filter choices
|
|||
|
|
enter/return: Complete answer
|
|||
|
|
`;
|
|||
|
|
}
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderCurrentInput() {
|
|||
|
|
return `
|
|||
|
|
Filtered results for: ${this.inputValue ? this.inputValue : color.gray('Enter something to filter')}\n`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderOption(cursor, v, i, arrowIndicator) {
|
|||
|
|
const prefix = (v.selected ? color.green(figures.radioOn) : figures.radioOff) + ' ' + arrowIndicator + ' ';
|
|||
|
|
let title;
|
|||
|
|
if (v.disabled) title = cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title);
|
|||
|
|
else title = cursor === i ? color.cyan().underline(v.title) : v.title;
|
|||
|
|
return prefix + title;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
renderDoneOrInstructions() {
|
|||
|
|
if (this.done) {
|
|||
|
|
return this.value
|
|||
|
|
.filter(e => e.selected)
|
|||
|
|
.map(v => v.title)
|
|||
|
|
.join(', ');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const output = [color.gray(this.hint), this.renderInstructions(), this.renderCurrentInput()];
|
|||
|
|
|
|||
|
|
if (this.filteredOptions.length && this.filteredOptions[this.cursor].disabled) {
|
|||
|
|
output.push(color.yellow(this.warn));
|
|||
|
|
}
|
|||
|
|
return output.join(' ');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|||
|
|
super.render();
|
|||
|
|
|
|||
|
|
// print prompt
|
|||
|
|
|
|||
|
|
let prompt = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(false),
|
|||
|
|
this.renderDoneOrInstructions()
|
|||
|
|
].join(' ');
|
|||
|
|
|
|||
|
|
if (this.showMinError) {
|
|||
|
|
prompt += color.red(`You must select a minimum of ${this.minSelected} choices.`);
|
|||
|
|
this.showMinError = false;
|
|||
|
|
}
|
|||
|
|
prompt += this.renderOptions(this.filteredOptions);
|
|||
|
|
|
|||
|
|
this.out.write(this.clear + prompt);
|
|||
|
|
this.clear = clear(prompt, this.out.columns);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
autocompleteMultiselect = AutocompleteMultiselectPrompt;
|
|||
|
|
return autocompleteMultiselect;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var confirm;
|
|||
|
|
var hasRequiredConfirm;
|
|||
|
|
|
|||
|
|
function requireConfirm () {
|
|||
|
|
if (hasRequiredConfirm) return confirm;
|
|||
|
|
hasRequiredConfirm = 1;
|
|||
|
|
const color = requireKleur();
|
|||
|
|
const Prompt = requirePrompt();
|
|||
|
|
const { style, clear } = requireUtil();
|
|||
|
|
const { erase, cursor } = requireSrc();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* ConfirmPrompt Base Element
|
|||
|
|
* @param {Object} opts Options
|
|||
|
|
* @param {String} opts.message Message
|
|||
|
|
* @param {Boolean} [opts.initial] Default value (true/false)
|
|||
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|||
|
|
* @param {String} [opts.yes] The "Yes" label
|
|||
|
|
* @param {String} [opts.yesOption] The "Yes" option when choosing between yes/no
|
|||
|
|
* @param {String} [opts.no] The "No" label
|
|||
|
|
* @param {String} [opts.noOption] The "No" option when choosing between yes/no
|
|||
|
|
*/
|
|||
|
|
class ConfirmPrompt extends Prompt {
|
|||
|
|
constructor(opts={}) {
|
|||
|
|
super(opts);
|
|||
|
|
this.msg = opts.message;
|
|||
|
|
this.value = opts.initial;
|
|||
|
|
this.initialValue = !!opts.initial;
|
|||
|
|
this.yesMsg = opts.yes || 'yes';
|
|||
|
|
this.yesOption = opts.yesOption || '(Y/n)';
|
|||
|
|
this.noMsg = opts.no || 'no';
|
|||
|
|
this.noOption = opts.noOption || '(y/N)';
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
reset() {
|
|||
|
|
this.value = this.initialValue;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exit() {
|
|||
|
|
this.abort();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
abort() {
|
|||
|
|
this.done = this.aborted = true;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
submit() {
|
|||
|
|
this.value = this.value || false;
|
|||
|
|
this.done = true;
|
|||
|
|
this.aborted = false;
|
|||
|
|
this.fire();
|
|||
|
|
this.render();
|
|||
|
|
this.out.write('\n');
|
|||
|
|
this.close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_(c, key) {
|
|||
|
|
if (c.toLowerCase() === 'y') {
|
|||
|
|
this.value = true;
|
|||
|
|
return this.submit();
|
|||
|
|
}
|
|||
|
|
if (c.toLowerCase() === 'n') {
|
|||
|
|
this.value = false;
|
|||
|
|
return this.submit();
|
|||
|
|
}
|
|||
|
|
return this.bell();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
if (this.closed) return;
|
|||
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|||
|
|
else this.out.write(clear(this.outputText, this.out.columns));
|
|||
|
|
super.render();
|
|||
|
|
|
|||
|
|
this.outputText = [
|
|||
|
|
style.symbol(this.done, this.aborted),
|
|||
|
|
color.bold(this.msg),
|
|||
|
|
style.delimiter(this.done),
|
|||
|
|
this.done ? (this.value ? this.yesMsg : this.noMsg)
|
|||
|
|
: color.gray(this.initialValue ? this.yesOption : this.noOption)
|
|||
|
|
].join(' ');
|
|||
|
|
|
|||
|
|
this.out.write(erase.line + cursor.to(0) + this.outputText);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
confirm = ConfirmPrompt;
|
|||
|
|
return confirm;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var elements;
|
|||
|
|
var hasRequiredElements;
|
|||
|
|
|
|||
|
|
function requireElements () {
|
|||
|
|
if (hasRequiredElements) return elements;
|
|||
|
|
hasRequiredElements = 1;
|
|||
|
|
|
|||
|
|
elements = {
|
|||
|
|
TextPrompt: requireText(),
|
|||
|
|
SelectPrompt: requireSelect(),
|
|||
|
|
TogglePrompt: requireToggle(),
|
|||
|
|
DatePrompt: requireDate(),
|
|||
|
|
NumberPrompt: requireNumber(),
|
|||
|
|
MultiselectPrompt: requireMultiselect(),
|
|||
|
|
AutocompletePrompt: requireAutocomplete(),
|
|||
|
|
AutocompleteMultiselectPrompt: requireAutocompleteMultiselect(),
|
|||
|
|
ConfirmPrompt: requireConfirm()
|
|||
|
|
};
|
|||
|
|
return elements;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var hasRequiredPrompts$1;
|
|||
|
|
|
|||
|
|
function requirePrompts$1 () {
|
|||
|
|
if (hasRequiredPrompts$1) return prompts$2;
|
|||
|
|
hasRequiredPrompts$1 = 1;
|
|||
|
|
(function (exports) {
|
|||
|
|
const $ = exports;
|
|||
|
|
const el = requireElements();
|
|||
|
|
const noop = v => v;
|
|||
|
|
|
|||
|
|
function toPrompt(type, args, opts={}) {
|
|||
|
|
return new Promise((res, rej) => {
|
|||
|
|
const p = new el[type](args);
|
|||
|
|
const onAbort = opts.onAbort || noop;
|
|||
|
|
const onSubmit = opts.onSubmit || noop;
|
|||
|
|
const onExit = opts.onExit || noop;
|
|||
|
|
p.on('state', args.onState || noop);
|
|||
|
|
p.on('submit', x => res(onSubmit(x)));
|
|||
|
|
p.on('exit', x => res(onExit(x)));
|
|||
|
|
p.on('abort', x => rej(onAbort(x)));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Text prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {string} [args.initial] Default string value
|
|||
|
|
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {function} [args.validate] Function to validate user input
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.text = args => toPrompt('TextPrompt', args);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Password prompt with masked input
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {string} [args.initial] Default string value
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {function} [args.validate] Function to validate user input
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.password = args => {
|
|||
|
|
args.style = 'password';
|
|||
|
|
return $.text(args);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Prompt where input is invisible, like sudo
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {string} [args.initial] Default string value
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {function} [args.validate] Function to validate user input
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.invisible = args => {
|
|||
|
|
args.style = 'invisible';
|
|||
|
|
return $.text(args);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Number prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {number} args.initial Default number value
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {number} [args.max] Max value
|
|||
|
|
* @param {number} [args.min] Min value
|
|||
|
|
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
|||
|
|
* @param {Boolean} [opts.float=false] Parse input as floats
|
|||
|
|
* @param {Number} [opts.round=2] Round floats to x decimals
|
|||
|
|
* @param {Number} [opts.increment=1] Number to increment by when using arrow-keys
|
|||
|
|
* @param {function} [args.validate] Function to validate user input
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.number = args => toPrompt('NumberPrompt', args);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Date prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {number} args.initial Default number value
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {number} [args.max] Max value
|
|||
|
|
* @param {number} [args.min] Min value
|
|||
|
|
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
|||
|
|
* @param {Boolean} [opts.float=false] Parse input as floats
|
|||
|
|
* @param {Number} [opts.round=2] Round floats to x decimals
|
|||
|
|
* @param {Number} [opts.increment=1] Number to increment by when using arrow-keys
|
|||
|
|
* @param {function} [args.validate] Function to validate user input
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.date = args => toPrompt('DatePrompt', args);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Classic yes/no prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {boolean} [args.initial=false] Default value
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.confirm = args => toPrompt('ConfirmPrompt', args);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* List prompt, split intput string by `seperator`
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {string} [args.initial] Default string value
|
|||
|
|
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
|||
|
|
* @param {string} [args.separator] String separator
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input, in form of an `Array`
|
|||
|
|
*/
|
|||
|
|
$.list = args => {
|
|||
|
|
const sep = args.separator || ',';
|
|||
|
|
return toPrompt('TextPrompt', args, {
|
|||
|
|
onSubmit: str => str.split(sep).map(s => s.trim())
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Toggle/switch prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {boolean} [args.initial=false] Default value
|
|||
|
|
* @param {string} [args.active="on"] Text for `active` state
|
|||
|
|
* @param {string} [args.inactive="off"] Text for `inactive` state
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.toggle = args => toPrompt('TogglePrompt', args);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Interactive select prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {Array} args.choices Array of choices objects `[{ title, value }, ...]`
|
|||
|
|
* @param {number} [args.initial] Index of default value
|
|||
|
|
* @param {String} [args.hint] Hint to display
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.select = args => toPrompt('SelectPrompt', args);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Interactive multi-select / autocompleteMultiselect prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {Array} args.choices Array of choices objects `[{ title, value, [selected] }, ...]`
|
|||
|
|
* @param {number} [args.max] Max select
|
|||
|
|
* @param {string} [args.hint] Hint to display user
|
|||
|
|
* @param {Number} [args.cursor=0] Cursor start position
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.multiselect = args => {
|
|||
|
|
args.choices = [].concat(args.choices || []);
|
|||
|
|
const toSelected = items => items.filter(item => item.selected).map(item => item.value);
|
|||
|
|
return toPrompt('MultiselectPrompt', args, {
|
|||
|
|
onAbort: toSelected,
|
|||
|
|
onSubmit: toSelected
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
$.autocompleteMultiselect = args => {
|
|||
|
|
args.choices = [].concat(args.choices || []);
|
|||
|
|
const toSelected = items => items.filter(item => item.selected).map(item => item.value);
|
|||
|
|
return toPrompt('AutocompleteMultiselectPrompt', args, {
|
|||
|
|
onAbort: toSelected,
|
|||
|
|
onSubmit: toSelected
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const byTitle = (input, choices) => Promise.resolve(
|
|||
|
|
choices.filter(item => item.title.slice(0, input.length).toLowerCase() === input.toLowerCase())
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Interactive auto-complete prompt
|
|||
|
|
* @param {string} args.message Prompt message to display
|
|||
|
|
* @param {Array} args.choices Array of auto-complete choices objects `[{ title, value }, ...]`
|
|||
|
|
* @param {Function} [args.suggest] Function to filter results based on user input. Defaults to sort by `title`
|
|||
|
|
* @param {number} [args.limit=10] Max number of results to show
|
|||
|
|
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
|||
|
|
* @param {String} [args.initial] Index of the default value
|
|||
|
|
* @param {boolean} [opts.clearFirst] The first ESCAPE keypress will clear the input
|
|||
|
|
* @param {String} [args.fallback] Fallback message - defaults to initial value
|
|||
|
|
* @param {function} [args.onState] On state change callback
|
|||
|
|
* @param {Stream} [args.stdin] The Readable stream to listen to
|
|||
|
|
* @param {Stream} [args.stdout] The Writable stream to write readline data to
|
|||
|
|
* @returns {Promise} Promise with user input
|
|||
|
|
*/
|
|||
|
|
$.autocomplete = args => {
|
|||
|
|
args.suggest = args.suggest || byTitle;
|
|||
|
|
args.choices = [].concat(args.choices || []);
|
|||
|
|
return toPrompt('AutocompletePrompt', args);
|
|||
|
|
};
|
|||
|
|
} (prompts$2));
|
|||
|
|
return prompts$2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var lib$1;
|
|||
|
|
var hasRequiredLib$1;
|
|||
|
|
|
|||
|
|
function requireLib$1 () {
|
|||
|
|
if (hasRequiredLib$1) return lib$1;
|
|||
|
|
hasRequiredLib$1 = 1;
|
|||
|
|
|
|||
|
|
const prompts = requirePrompts$1();
|
|||
|
|
|
|||
|
|
const passOn = ['suggest', 'format', 'onState', 'validate', 'onRender', 'type'];
|
|||
|
|
const noop = () => {};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Prompt for a series of questions
|
|||
|
|
* @param {Array|Object} questions Single question object or Array of question objects
|
|||
|
|
* @param {Function} [onSubmit] Callback function called on prompt submit
|
|||
|
|
* @param {Function} [onCancel] Callback function called on cancel/abort
|
|||
|
|
* @returns {Object} Object with values from user input
|
|||
|
|
*/
|
|||
|
|
async function prompt(questions=[], { onSubmit=noop, onCancel=noop }={}) {
|
|||
|
|
const answers = {};
|
|||
|
|
const override = prompt._override || {};
|
|||
|
|
questions = [].concat(questions);
|
|||
|
|
let answer, question, quit, name, type, lastPrompt;
|
|||
|
|
|
|||
|
|
const getFormattedAnswer = async (question, answer, skipValidation = false) => {
|
|||
|
|
if (!skipValidation && question.validate && question.validate(answer) !== true) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
return question.format ? await question.format(answer, answers) : answer
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
for (question of questions) {
|
|||
|
|
({ name, type } = question);
|
|||
|
|
|
|||
|
|
// evaluate type first and skip if type is a falsy value
|
|||
|
|
if (typeof type === 'function') {
|
|||
|
|
type = await type(answer, { ...answers }, question);
|
|||
|
|
question['type'] = type;
|
|||
|
|
}
|
|||
|
|
if (!type) continue;
|
|||
|
|
|
|||
|
|
// if property is a function, invoke it unless it's a special function
|
|||
|
|
for (let key in question) {
|
|||
|
|
if (passOn.includes(key)) continue;
|
|||
|
|
let value = question[key];
|
|||
|
|
question[key] = typeof value === 'function' ? await value(answer, { ...answers }, lastPrompt) : value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
lastPrompt = question;
|
|||
|
|
|
|||
|
|
if (typeof question.message !== 'string') {
|
|||
|
|
throw new Error('prompt message is required');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// update vars in case they changed
|
|||
|
|
({ name, type } = question);
|
|||
|
|
|
|||
|
|
if (prompts[type] === void 0) {
|
|||
|
|
throw new Error(`prompt type (${type}) is not defined`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (override[question.name] !== undefined) {
|
|||
|
|
answer = await getFormattedAnswer(question, override[question.name]);
|
|||
|
|
if (answer !== undefined) {
|
|||
|
|
answers[name] = answer;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// Get the injected answer if there is one or prompt the user
|
|||
|
|
answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : await prompts[type](question);
|
|||
|
|
answers[name] = answer = await getFormattedAnswer(question, answer, true);
|
|||
|
|
quit = await onSubmit(question, answer, answers);
|
|||
|
|
} catch (err) {
|
|||
|
|
quit = !(await onCancel(question, answers));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (quit) return answers;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return answers;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getInjectedAnswer(injected, deafultValue) {
|
|||
|
|
const answer = injected.shift();
|
|||
|
|
if (answer instanceof Error) {
|
|||
|
|
throw answer;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (answer === undefined) ? deafultValue : answer;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function inject(answers) {
|
|||
|
|
prompt._injected = (prompt._injected || []).concat(answers);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function override(answers) {
|
|||
|
|
prompt._override = Object.assign({}, answers);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
lib$1 = Object.assign(prompt, { prompt, prompts, inject, override });
|
|||
|
|
return lib$1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var prompts$1;
|
|||
|
|
var hasRequiredPrompts;
|
|||
|
|
|
|||
|
|
function requirePrompts () {
|
|||
|
|
if (hasRequiredPrompts) return prompts$1;
|
|||
|
|
hasRequiredPrompts = 1;
|
|||
|
|
prompts$1 = requireLib$1();
|
|||
|
|
return prompts$1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var promptsExports = requirePrompts();
|
|||
|
|
const prompts = /*@__PURE__*/getDefaultExportFromCjs(promptsExports);
|
|||
|
|
|
|||
|
|
function npmRun(agent) {
|
|||
|
|
return (args) => {
|
|||
|
|
if (args.length > 1) {
|
|||
|
|
return [agent, "run", args[0], "--", ...args.slice(1)];
|
|||
|
|
} else {
|
|||
|
|
return [agent, "run", args[0]];
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
function denoExecute() {
|
|||
|
|
return (args) => {
|
|||
|
|
return ["deno", "run", `npm:${args[0]}`, ...args.slice(1)];
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
const npm = {
|
|||
|
|
"agent": ["npm", 0],
|
|||
|
|
"run": npmRun("npm"),
|
|||
|
|
"install": ["npm", "i", 0],
|
|||
|
|
"frozen": ["npm", "ci"],
|
|||
|
|
"global": ["npm", "i", "-g", 0],
|
|||
|
|
"add": ["npm", "i", 0],
|
|||
|
|
"upgrade": ["npm", "update", 0],
|
|||
|
|
"upgrade-interactive": null,
|
|||
|
|
"execute": ["npx", 0],
|
|||
|
|
"execute-local": ["npx", 0],
|
|||
|
|
"uninstall": ["npm", "uninstall", 0],
|
|||
|
|
"global_uninstall": ["npm", "uninstall", "-g", 0]
|
|||
|
|
};
|
|||
|
|
const yarn = {
|
|||
|
|
"agent": ["yarn", 0],
|
|||
|
|
"run": ["yarn", "run", 0],
|
|||
|
|
"install": ["yarn", "install", 0],
|
|||
|
|
"frozen": ["yarn", "install", "--frozen-lockfile"],
|
|||
|
|
"global": ["yarn", "global", "add", 0],
|
|||
|
|
"add": ["yarn", "add", 0],
|
|||
|
|
"upgrade": ["yarn", "upgrade", 0],
|
|||
|
|
"upgrade-interactive": ["yarn", "upgrade-interactive", 0],
|
|||
|
|
"execute": ["npx", 0],
|
|||
|
|
"execute-local": ["yarn", "exec", 0],
|
|||
|
|
"uninstall": ["yarn", "remove", 0],
|
|||
|
|
"global_uninstall": ["yarn", "global", "remove", 0]
|
|||
|
|
};
|
|||
|
|
const yarnBerry = {
|
|||
|
|
...yarn,
|
|||
|
|
"frozen": ["yarn", "install", "--immutable"],
|
|||
|
|
"upgrade": ["yarn", "up", 0],
|
|||
|
|
"upgrade-interactive": ["yarn", "up", "-i", 0],
|
|||
|
|
"execute": ["yarn", "dlx", 0],
|
|||
|
|
"execute-local": ["yarn", "exec", 0],
|
|||
|
|
// Yarn 2+ removed 'global', see https://github.com/yarnpkg/berry/issues/821
|
|||
|
|
"global": ["npm", "i", "-g", 0],
|
|||
|
|
"global_uninstall": ["npm", "uninstall", "-g", 0]
|
|||
|
|
};
|
|||
|
|
const pnpm = {
|
|||
|
|
"agent": ["pnpm", 0],
|
|||
|
|
"run": ["pnpm", "run", 0],
|
|||
|
|
"install": ["pnpm", "i", 0],
|
|||
|
|
"frozen": ["pnpm", "i", "--frozen-lockfile"],
|
|||
|
|
"global": ["pnpm", "add", "-g", 0],
|
|||
|
|
"add": ["pnpm", "add", 0],
|
|||
|
|
"upgrade": ["pnpm", "update", 0],
|
|||
|
|
"upgrade-interactive": ["pnpm", "update", "-i", 0],
|
|||
|
|
"execute": ["pnpm", "dlx", 0],
|
|||
|
|
"execute-local": ["pnpm", "exec", 0],
|
|||
|
|
"uninstall": ["pnpm", "remove", 0],
|
|||
|
|
"global_uninstall": ["pnpm", "remove", "--global", 0]
|
|||
|
|
};
|
|||
|
|
const bun = {
|
|||
|
|
"agent": ["bun", 0],
|
|||
|
|
"run": ["bun", "run", 0],
|
|||
|
|
"install": ["bun", "install", 0],
|
|||
|
|
"frozen": ["bun", "install", "--frozen-lockfile"],
|
|||
|
|
"global": ["bun", "add", "-g", 0],
|
|||
|
|
"add": ["bun", "add", 0],
|
|||
|
|
"upgrade": ["bun", "update", 0],
|
|||
|
|
"upgrade-interactive": ["bun", "update", 0],
|
|||
|
|
"execute": ["bun", "x", 0],
|
|||
|
|
"execute-local": ["bun", "x", 0],
|
|||
|
|
"uninstall": ["bun", "remove", 0],
|
|||
|
|
"global_uninstall": ["bun", "remove", "-g", 0]
|
|||
|
|
};
|
|||
|
|
const deno = {
|
|||
|
|
"agent": ["deno", 0],
|
|||
|
|
"run": ["deno", "task", 0],
|
|||
|
|
"install": ["deno", "install", 0],
|
|||
|
|
"frozen": ["deno", "install", "--frozen"],
|
|||
|
|
"global": ["deno", "install", "-g", 0],
|
|||
|
|
"add": ["deno", "add", 0],
|
|||
|
|
"upgrade": ["deno", "outdated", "--update", 0],
|
|||
|
|
"upgrade-interactive": ["deno", "outdated", "--update", 0],
|
|||
|
|
"execute": denoExecute(),
|
|||
|
|
"execute-local": ["deno", "task", "--eval", 0],
|
|||
|
|
"uninstall": ["deno", "remove", 0],
|
|||
|
|
"global_uninstall": ["deno", "uninstall", "-g", 0]
|
|||
|
|
};
|
|||
|
|
const COMMANDS = {
|
|||
|
|
"npm": npm,
|
|||
|
|
"yarn": yarn,
|
|||
|
|
"yarn@berry": yarnBerry,
|
|||
|
|
"pnpm": pnpm,
|
|||
|
|
// pnpm v6.x or below
|
|||
|
|
"pnpm@6": {
|
|||
|
|
...pnpm,
|
|||
|
|
run: npmRun("pnpm")
|
|||
|
|
},
|
|||
|
|
"bun": bun,
|
|||
|
|
"deno": deno
|
|||
|
|
};
|
|||
|
|
function resolveCommand(agent, command, args) {
|
|||
|
|
const value = COMMANDS[agent][command];
|
|||
|
|
return constructCommand(value, args);
|
|||
|
|
}
|
|||
|
|
function constructCommand(value, args) {
|
|||
|
|
if (value == null)
|
|||
|
|
return null;
|
|||
|
|
const list = typeof value === "function" ? value(args) : value.flatMap((v) => {
|
|||
|
|
if (typeof v === "number")
|
|||
|
|
return args;
|
|||
|
|
return [v];
|
|||
|
|
});
|
|||
|
|
return {
|
|||
|
|
command: list[0],
|
|||
|
|
args: list.slice(1)
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const AGENTS = [
|
|||
|
|
"npm",
|
|||
|
|
"yarn",
|
|||
|
|
"yarn@berry",
|
|||
|
|
"pnpm",
|
|||
|
|
"pnpm@6",
|
|||
|
|
"bun",
|
|||
|
|
"deno"
|
|||
|
|
];
|
|||
|
|
const LOCKS = {
|
|||
|
|
"bun.lock": "bun",
|
|||
|
|
"bun.lockb": "bun",
|
|||
|
|
"deno.lock": "deno",
|
|||
|
|
"pnpm-lock.yaml": "pnpm",
|
|||
|
|
"yarn.lock": "yarn",
|
|||
|
|
"package-lock.json": "npm",
|
|||
|
|
"npm-shrinkwrap.json": "npm"
|
|||
|
|
};
|
|||
|
|
const INSTALL_PAGE = {
|
|||
|
|
"bun": "https://bun.sh",
|
|||
|
|
"deno": "https://deno.com",
|
|||
|
|
"pnpm": "https://pnpm.io/installation",
|
|||
|
|
"pnpm@6": "https://pnpm.io/6.x/installation",
|
|||
|
|
"yarn": "https://classic.yarnpkg.com/en/docs/install",
|
|||
|
|
"yarn@berry": "https://yarnpkg.com/getting-started/install",
|
|||
|
|
"npm": "https://docs.npmjs.com/cli/v8/configuring-npm/install"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
async function detect$1(options = {}) {
|
|||
|
|
const { cwd, onUnknown } = options;
|
|||
|
|
for (const directory of lookup(cwd)) {
|
|||
|
|
for (const lock of Object.keys(LOCKS)) {
|
|||
|
|
if (await fileExists(path__default.join(directory, lock))) {
|
|||
|
|
const name = LOCKS[lock];
|
|||
|
|
const result2 = await parsePackageJson(path__default.join(directory, "package.json"), onUnknown);
|
|||
|
|
if (result2)
|
|||
|
|
return result2;
|
|||
|
|
else
|
|||
|
|
return { name, agent: name };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const result = await parsePackageJson(path__default.join(directory, "package.json"), onUnknown);
|
|||
|
|
if (result)
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
function* lookup(cwd = process__default.cwd()) {
|
|||
|
|
let directory = path__default.resolve(cwd);
|
|||
|
|
const { root } = path__default.parse(directory);
|
|||
|
|
while (directory && directory !== root) {
|
|||
|
|
yield directory;
|
|||
|
|
directory = path__default.dirname(directory);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
async function parsePackageJson(filepath, onUnknown) {
|
|||
|
|
return !filepath || !await fileExists(filepath) ? null : handlePackageManager(filepath, onUnknown);
|
|||
|
|
}
|
|||
|
|
function handlePackageManager(filepath, onUnknown) {
|
|||
|
|
try {
|
|||
|
|
const pkg = JSON.parse(fs__default.readFileSync(filepath, "utf8"));
|
|||
|
|
let agent;
|
|||
|
|
if (typeof pkg.packageManager === "string") {
|
|||
|
|
const [name, ver] = pkg.packageManager.replace(/^\^/, "").split("@");
|
|||
|
|
let version = ver;
|
|||
|
|
if (name === "yarn" && Number.parseInt(ver) > 1) {
|
|||
|
|
agent = "yarn@berry";
|
|||
|
|
version = "berry";
|
|||
|
|
return { name, agent, version };
|
|||
|
|
} else if (name === "pnpm" && Number.parseInt(ver) < 7) {
|
|||
|
|
agent = "pnpm@6";
|
|||
|
|
return { name, agent, version };
|
|||
|
|
} else if (AGENTS.includes(name)) {
|
|||
|
|
agent = name;
|
|||
|
|
return { name, agent, version };
|
|||
|
|
} else {
|
|||
|
|
return onUnknown?.(pkg.packageManager) ?? null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
async function fileExists(filePath) {
|
|||
|
|
try {
|
|||
|
|
const stats = await fsPromises__default.stat(filePath);
|
|||
|
|
if (stats.isFile()) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const ESC = '\u001B[';
|
|||
|
|
const OSC = '\u001B]';
|
|||
|
|
const BEL = '\u0007';
|
|||
|
|
const SEP = ';';
|
|||
|
|
const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
|
|||
|
|
|
|||
|
|
const ansiEscapes = {};
|
|||
|
|
|
|||
|
|
ansiEscapes.cursorTo = (x, y) => {
|
|||
|
|
if (typeof x !== 'number') {
|
|||
|
|
throw new TypeError('The `x` argument is required');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (typeof y !== 'number') {
|
|||
|
|
return ESC + (x + 1) + 'G';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ESC + (y + 1) + ';' + (x + 1) + 'H';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
ansiEscapes.cursorMove = (x, y) => {
|
|||
|
|
if (typeof x !== 'number') {
|
|||
|
|
throw new TypeError('The `x` argument is required');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let returnValue = '';
|
|||
|
|
|
|||
|
|
if (x < 0) {
|
|||
|
|
returnValue += ESC + (-x) + 'D';
|
|||
|
|
} else if (x > 0) {
|
|||
|
|
returnValue += ESC + x + 'C';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (y < 0) {
|
|||
|
|
returnValue += ESC + (-y) + 'A';
|
|||
|
|
} else if (y > 0) {
|
|||
|
|
returnValue += ESC + y + 'B';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return returnValue;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
ansiEscapes.cursorUp = (count = 1) => ESC + count + 'A';
|
|||
|
|
ansiEscapes.cursorDown = (count = 1) => ESC + count + 'B';
|
|||
|
|
ansiEscapes.cursorForward = (count = 1) => ESC + count + 'C';
|
|||
|
|
ansiEscapes.cursorBackward = (count = 1) => ESC + count + 'D';
|
|||
|
|
|
|||
|
|
ansiEscapes.cursorLeft = ESC + 'G';
|
|||
|
|
ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC + 's';
|
|||
|
|
ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC + 'u';
|
|||
|
|
ansiEscapes.cursorGetPosition = ESC + '6n';
|
|||
|
|
ansiEscapes.cursorNextLine = ESC + 'E';
|
|||
|
|
ansiEscapes.cursorPrevLine = ESC + 'F';
|
|||
|
|
ansiEscapes.cursorHide = ESC + '?25l';
|
|||
|
|
ansiEscapes.cursorShow = ESC + '?25h';
|
|||
|
|
|
|||
|
|
ansiEscapes.eraseLines = count => {
|
|||
|
|
let clear = '';
|
|||
|
|
|
|||
|
|
for (let i = 0; i < count; i++) {
|
|||
|
|
clear += ansiEscapes.eraseLine + (i < count - 1 ? ansiEscapes.cursorUp() : '');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (count) {
|
|||
|
|
clear += ansiEscapes.cursorLeft;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return clear;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
ansiEscapes.eraseEndLine = ESC + 'K';
|
|||
|
|
ansiEscapes.eraseStartLine = ESC + '1K';
|
|||
|
|
ansiEscapes.eraseLine = ESC + '2K';
|
|||
|
|
ansiEscapes.eraseDown = ESC + 'J';
|
|||
|
|
ansiEscapes.eraseUp = ESC + '1J';
|
|||
|
|
ansiEscapes.eraseScreen = ESC + '2J';
|
|||
|
|
ansiEscapes.scrollUp = ESC + 'S';
|
|||
|
|
ansiEscapes.scrollDown = ESC + 'T';
|
|||
|
|
|
|||
|
|
ansiEscapes.clearScreen = '\u001Bc';
|
|||
|
|
|
|||
|
|
ansiEscapes.clearTerminal = process.platform === 'win32' ?
|
|||
|
|
`${ansiEscapes.eraseScreen}${ESC}0f` :
|
|||
|
|
// 1. Erases the screen (Only done in case `2` is not supported)
|
|||
|
|
// 2. Erases the whole screen including scrollback buffer
|
|||
|
|
// 3. Moves cursor to the top-left position
|
|||
|
|
// More info: https://www.real-world-systems.com/docs/ANSIcode.html
|
|||
|
|
`${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`;
|
|||
|
|
|
|||
|
|
ansiEscapes.beep = BEL;
|
|||
|
|
|
|||
|
|
ansiEscapes.link = (text, url) => {
|
|||
|
|
return [
|
|||
|
|
OSC,
|
|||
|
|
'8',
|
|||
|
|
SEP,
|
|||
|
|
SEP,
|
|||
|
|
url,
|
|||
|
|
BEL,
|
|||
|
|
text,
|
|||
|
|
OSC,
|
|||
|
|
'8',
|
|||
|
|
SEP,
|
|||
|
|
SEP,
|
|||
|
|
BEL
|
|||
|
|
].join('');
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
ansiEscapes.image = (buffer, options = {}) => {
|
|||
|
|
let returnValue = `${OSC}1337;File=inline=1`;
|
|||
|
|
|
|||
|
|
if (options.width) {
|
|||
|
|
returnValue += `;width=${options.width}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (options.height) {
|
|||
|
|
returnValue += `;height=${options.height}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (options.preserveAspectRatio === false) {
|
|||
|
|
returnValue += ';preserveAspectRatio=0';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return returnValue + ':' + buffer.toString('base64') + BEL;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
ansiEscapes.iTerm = {
|
|||
|
|
setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`,
|
|||
|
|
|
|||
|
|
annotation: (message, options = {}) => {
|
|||
|
|
let returnValue = `${OSC}1337;`;
|
|||
|
|
|
|||
|
|
const hasX = typeof options.x !== 'undefined';
|
|||
|
|
const hasY = typeof options.y !== 'undefined';
|
|||
|
|
if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) {
|
|||
|
|
throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
message = message.replace(/\|/g, '');
|
|||
|
|
|
|||
|
|
returnValue += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation=';
|
|||
|
|
|
|||
|
|
if (options.length > 0) {
|
|||
|
|
returnValue +=
|
|||
|
|
(hasX ?
|
|||
|
|
[message, options.length, options.x, options.y] :
|
|||
|
|
[options.length, message]).join('|');
|
|||
|
|
} else {
|
|||
|
|
returnValue += message;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return returnValue + BEL;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
var hasFlag;
|
|||
|
|
var hasRequiredHasFlag;
|
|||
|
|
|
|||
|
|
function requireHasFlag () {
|
|||
|
|
if (hasRequiredHasFlag) return hasFlag;
|
|||
|
|
hasRequiredHasFlag = 1;
|
|||
|
|
|
|||
|
|
hasFlag = (flag, argv = process.argv) => {
|
|||
|
|
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
|
|||
|
|
const position = argv.indexOf(prefix + flag);
|
|||
|
|
const terminatorPosition = argv.indexOf('--');
|
|||
|
|
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|||
|
|
};
|
|||
|
|
return hasFlag;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var supportsColor_1;
|
|||
|
|
var hasRequiredSupportsColor;
|
|||
|
|
|
|||
|
|
function requireSupportsColor () {
|
|||
|
|
if (hasRequiredSupportsColor) return supportsColor_1;
|
|||
|
|
hasRequiredSupportsColor = 1;
|
|||
|
|
const os = require$$0__default$1;
|
|||
|
|
const tty = require$$1__default;
|
|||
|
|
const hasFlag = requireHasFlag();
|
|||
|
|
|
|||
|
|
const {env} = process;
|
|||
|
|
|
|||
|
|
let forceColor;
|
|||
|
|
if (hasFlag('no-color') ||
|
|||
|
|
hasFlag('no-colors') ||
|
|||
|
|
hasFlag('color=false') ||
|
|||
|
|
hasFlag('color=never')) {
|
|||
|
|
forceColor = 0;
|
|||
|
|
} else if (hasFlag('color') ||
|
|||
|
|
hasFlag('colors') ||
|
|||
|
|
hasFlag('color=true') ||
|
|||
|
|
hasFlag('color=always')) {
|
|||
|
|
forceColor = 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('FORCE_COLOR' in env) {
|
|||
|
|
if (env.FORCE_COLOR === 'true') {
|
|||
|
|
forceColor = 1;
|
|||
|
|
} else if (env.FORCE_COLOR === 'false') {
|
|||
|
|
forceColor = 0;
|
|||
|
|
} else {
|
|||
|
|
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function translateLevel(level) {
|
|||
|
|
if (level === 0) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
level,
|
|||
|
|
hasBasic: true,
|
|||
|
|
has256: level >= 2,
|
|||
|
|
has16m: level >= 3
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function supportsColor(haveStream, streamIsTTY) {
|
|||
|
|
if (forceColor === 0) {
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (hasFlag('color=16m') ||
|
|||
|
|
hasFlag('color=full') ||
|
|||
|
|
hasFlag('color=truecolor')) {
|
|||
|
|
return 3;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (hasFlag('color=256')) {
|
|||
|
|
return 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (haveStream && !streamIsTTY && forceColor === undefined) {
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const min = forceColor || 0;
|
|||
|
|
|
|||
|
|
if (env.TERM === 'dumb') {
|
|||
|
|
return min;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (process.platform === 'win32') {
|
|||
|
|
// Windows 10 build 10586 is the first Windows release that supports 256 colors.
|
|||
|
|
// Windows 10 build 14931 is the first release that supports 16m/TrueColor.
|
|||
|
|
const osRelease = os.release().split('.');
|
|||
|
|
if (
|
|||
|
|
Number(osRelease[0]) >= 10 &&
|
|||
|
|
Number(osRelease[2]) >= 10586
|
|||
|
|
) {
|
|||
|
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('CI' in env) {
|
|||
|
|
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return min;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('TEAMCITY_VERSION' in env) {
|
|||
|
|
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (env.COLORTERM === 'truecolor') {
|
|||
|
|
return 3;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('TERM_PROGRAM' in env) {
|
|||
|
|
const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
|
|||
|
|
|
|||
|
|
switch (env.TERM_PROGRAM) {
|
|||
|
|
case 'iTerm.app':
|
|||
|
|
return version >= 3 ? 3 : 2;
|
|||
|
|
case 'Apple_Terminal':
|
|||
|
|
return 2;
|
|||
|
|
// No default
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (/-256(color)?$/i.test(env.TERM)) {
|
|||
|
|
return 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('COLORTERM' in env) {
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return min;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getSupportLevel(stream) {
|
|||
|
|
const level = supportsColor(stream, stream && stream.isTTY);
|
|||
|
|
return translateLevel(level);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
supportsColor_1 = {
|
|||
|
|
supportsColor: getSupportLevel,
|
|||
|
|
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
|
|||
|
|
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
|
|||
|
|
};
|
|||
|
|
return supportsColor_1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var supportsHyperlinks$1;
|
|||
|
|
var hasRequiredSupportsHyperlinks;
|
|||
|
|
|
|||
|
|
function requireSupportsHyperlinks () {
|
|||
|
|
if (hasRequiredSupportsHyperlinks) return supportsHyperlinks$1;
|
|||
|
|
hasRequiredSupportsHyperlinks = 1;
|
|||
|
|
const supportsColor = requireSupportsColor();
|
|||
|
|
const hasFlag = requireHasFlag();
|
|||
|
|
|
|||
|
|
function parseVersion(versionString) {
|
|||
|
|
if (/^\d{3,4}$/.test(versionString)) {
|
|||
|
|
// Env var doesn't always use dots. example: 4601 => 46.1.0
|
|||
|
|
const m = /(\d{1,2})(\d{2})/.exec(versionString);
|
|||
|
|
return {
|
|||
|
|
major: 0,
|
|||
|
|
minor: parseInt(m[1], 10),
|
|||
|
|
patch: parseInt(m[2], 10)
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const versions = (versionString || '').split('.').map(n => parseInt(n, 10));
|
|||
|
|
return {
|
|||
|
|
major: versions[0],
|
|||
|
|
minor: versions[1],
|
|||
|
|
patch: versions[2]
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function supportsHyperlink(stream) {
|
|||
|
|
const {env} = process;
|
|||
|
|
|
|||
|
|
if ('FORCE_HYPERLINK' in env) {
|
|||
|
|
return !(env.FORCE_HYPERLINK.length > 0 && parseInt(env.FORCE_HYPERLINK, 10) === 0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (hasFlag('no-hyperlink') || hasFlag('no-hyperlinks') || hasFlag('hyperlink=false') || hasFlag('hyperlink=never')) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (hasFlag('hyperlink=true') || hasFlag('hyperlink=always')) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// If they specify no colors, they probably don't want hyperlinks.
|
|||
|
|
if (!supportsColor.supportsColor(stream)) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (stream && !stream.isTTY) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (process.platform === 'win32') {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('NETLIFY' in env) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('CI' in env) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('TEAMCITY_VERSION' in env) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('TERM_PROGRAM' in env) {
|
|||
|
|
const version = parseVersion(env.TERM_PROGRAM_VERSION);
|
|||
|
|
|
|||
|
|
switch (env.TERM_PROGRAM) {
|
|||
|
|
case 'iTerm.app':
|
|||
|
|
if (version.major === 3) {
|
|||
|
|
return version.minor >= 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return version.major > 3;
|
|||
|
|
// No default
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ('VTE_VERSION' in env) {
|
|||
|
|
// 0.50.0 was supposed to support hyperlinks, but throws a segfault
|
|||
|
|
if (env.VTE_VERSION === '0.50.0') {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const version = parseVersion(env.VTE_VERSION);
|
|||
|
|
return version.major > 0 || version.minor >= 50;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
supportsHyperlinks$1 = {
|
|||
|
|
supportsHyperlink,
|
|||
|
|
stdout: supportsHyperlink(process.stdout),
|
|||
|
|
stderr: supportsHyperlink(process.stderr)
|
|||
|
|
};
|
|||
|
|
return supportsHyperlinks$1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var supportsHyperlinksExports = requireSupportsHyperlinks();
|
|||
|
|
const supportsHyperlinks = /*@__PURE__*/getDefaultExportFromCjs(supportsHyperlinksExports);
|
|||
|
|
|
|||
|
|
function terminalLink(text, url, {target = 'stdout', ...options} = {}) {
|
|||
|
|
if (!supportsHyperlinks[target]) {
|
|||
|
|
// If the fallback has been explicitly disabled, don't modify the text itself.
|
|||
|
|
if (options.fallback === false) {
|
|||
|
|
return text;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return typeof options.fallback === 'function' ? options.fallback(text, url) : `${text} (\u200B${url}\u200B)`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ansiEscapes.link(text, url);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
terminalLink.isSupported = supportsHyperlinks.stdout;
|
|||
|
|
terminalLink.stderr = (text, url, options = {}) => terminalLink(text, url, {target: 'stderr', ...options});
|
|||
|
|
terminalLink.stderr.isSupported = supportsHyperlinks.stderr;
|
|||
|
|
|
|||
|
|
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/ni.C82eau-4.cjs', document.baseURI).href)));
|
|||
|
|
var St = Object.create;
|
|||
|
|
var $ = Object.defineProperty;
|
|||
|
|
var kt = Object.getOwnPropertyDescriptor;
|
|||
|
|
var Tt = Object.getOwnPropertyNames;
|
|||
|
|
var At = Object.getPrototypeOf, Rt = Object.prototype.hasOwnProperty;
|
|||
|
|
var h = /* @__PURE__ */ ((t) => typeof require$1 < "u" ? require$1 : typeof Proxy < "u" ? new Proxy(t, {
|
|||
|
|
get: (e, n) => (typeof require$1 < "u" ? require$1 : e)[n]
|
|||
|
|
}) : t)(function(t) {
|
|||
|
|
if (typeof require$1 < "u") return require$1.apply(this, arguments);
|
|||
|
|
throw Error('Dynamic require of "' + t + '" is not supported');
|
|||
|
|
});
|
|||
|
|
var l = (t, e) => () => (e || t((e = { exports: {} }).exports, e), e.exports);
|
|||
|
|
var $t = (t, e, n, r) => {
|
|||
|
|
if (e && typeof e == "object" || typeof e == "function")
|
|||
|
|
for (let s of Tt(e))
|
|||
|
|
!Rt.call(t, s) && s !== n && $(t, s, { get: () => e[s], enumerable: !(r = kt(e, s)) || r.enumerable });
|
|||
|
|
return t;
|
|||
|
|
};
|
|||
|
|
var Nt = (t, e, n) => (n = t != null ? St(At(t)) : {}, $t(
|
|||
|
|
// If the importer is in node compatibility mode or this is not an ESM
|
|||
|
|
// file that has been converted to a CommonJS file using a Babel-
|
|||
|
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|||
|
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|||
|
|
$(n, "default", { value: t, enumerable: !0 }) ,
|
|||
|
|
t
|
|||
|
|
));
|
|||
|
|
|
|||
|
|
// node_modules/isexe/windows.js
|
|||
|
|
var W = l((Se, H) => {
|
|||
|
|
H.exports = z;
|
|||
|
|
z.sync = Wt;
|
|||
|
|
var j = h("fs");
|
|||
|
|
function Ht(t, e) {
|
|||
|
|
var n = e.pathExt !== void 0 ? e.pathExt : process.env.PATHEXT;
|
|||
|
|
if (!n || (n = n.split(";"), n.indexOf("") !== -1))
|
|||
|
|
return !0;
|
|||
|
|
for (var r = 0; r < n.length; r++) {
|
|||
|
|
var s = n[r].toLowerCase();
|
|||
|
|
if (s && t.substr(-s.length).toLowerCase() === s)
|
|||
|
|
return !0;
|
|||
|
|
}
|
|||
|
|
return !1;
|
|||
|
|
}
|
|||
|
|
function F(t, e, n) {
|
|||
|
|
return !t.isSymbolicLink() && !t.isFile() ? !1 : Ht(e, n);
|
|||
|
|
}
|
|||
|
|
function z(t, e, n) {
|
|||
|
|
j.stat(t, function(r, s) {
|
|||
|
|
n(r, r ? !1 : F(s, t, e));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
function Wt(t, e) {
|
|||
|
|
return F(j.statSync(t), t, e);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/isexe/mode.js
|
|||
|
|
var X = l((ke, B) => {
|
|||
|
|
B.exports = K;
|
|||
|
|
K.sync = Dt;
|
|||
|
|
var D = h("fs");
|
|||
|
|
function K(t, e, n) {
|
|||
|
|
D.stat(t, function(r, s) {
|
|||
|
|
n(r, r ? !1 : M(s, e));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
function Dt(t, e) {
|
|||
|
|
return M(D.statSync(t), e);
|
|||
|
|
}
|
|||
|
|
function M(t, e) {
|
|||
|
|
return t.isFile() && Kt(t, e);
|
|||
|
|
}
|
|||
|
|
function Kt(t, e) {
|
|||
|
|
var n = t.mode, r = t.uid, s = t.gid, o = e.uid !== void 0 ? e.uid : process.getuid && process.getuid(), i = e.gid !== void 0 ? e.gid : process.getgid && process.getgid(), a = parseInt("100", 8), c = parseInt("010", 8), u = parseInt("001", 8), f = a | c, p = n & u || n & c && s === i || n & a && r === o || n & f && o === 0;
|
|||
|
|
return p;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/isexe/index.js
|
|||
|
|
var U = l((Ae, G) => {
|
|||
|
|
h("fs"); var v;
|
|||
|
|
process.platform === "win32" || global.TESTING_WINDOWS ? v = W() : v = X();
|
|||
|
|
G.exports = y;
|
|||
|
|
y.sync = Mt;
|
|||
|
|
function y(t, e, n) {
|
|||
|
|
if (typeof e == "function" && (n = e, e = {}), !n) {
|
|||
|
|
if (typeof Promise != "function")
|
|||
|
|
throw new TypeError("callback not provided");
|
|||
|
|
return new Promise(function(r, s) {
|
|||
|
|
y(t, e || {}, function(o, i) {
|
|||
|
|
o ? s(o) : r(i);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
v(t, e || {}, function(r, s) {
|
|||
|
|
r && (r.code === "EACCES" || e && e.ignoreErrors) && (r = null, s = !1), n(r, s);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
function Mt(t, e) {
|
|||
|
|
try {
|
|||
|
|
return v.sync(t, e || {});
|
|||
|
|
} catch (n) {
|
|||
|
|
if (e && e.ignoreErrors || n.code === "EACCES")
|
|||
|
|
return !1;
|
|||
|
|
throw n;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/which/which.js
|
|||
|
|
var et = l((Re, tt) => {
|
|||
|
|
var g = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys", Y = h("path"), Bt = g ? ";" : ":", V = U(), J = (t) => Object.assign(new Error(`not found: ${t}`), { code: "ENOENT" }), Q = (t, e) => {
|
|||
|
|
let n = e.colon || Bt, r = t.match(/\//) || g && t.match(/\\/) ? [""] : [
|
|||
|
|
// windows always checks the cwd first
|
|||
|
|
...g ? [process.cwd()] : [],
|
|||
|
|
...(e.path || process.env.PATH || /* istanbul ignore next: very unusual */
|
|||
|
|
"").split(n)
|
|||
|
|
], s = g ? e.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "", o = g ? s.split(n) : [""];
|
|||
|
|
return g && t.indexOf(".") !== -1 && o[0] !== "" && o.unshift(""), {
|
|||
|
|
pathEnv: r,
|
|||
|
|
pathExt: o,
|
|||
|
|
pathExtExe: s
|
|||
|
|
};
|
|||
|
|
}, Z = (t, e, n) => {
|
|||
|
|
typeof e == "function" && (n = e, e = {}), e || (e = {});
|
|||
|
|
let { pathEnv: r, pathExt: s, pathExtExe: o } = Q(t, e), i = [], a = (u) => new Promise((f, p) => {
|
|||
|
|
if (u === r.length)
|
|||
|
|
return e.all && i.length ? f(i) : p(J(t));
|
|||
|
|
let d = r[u], w = /^".*"$/.test(d) ? d.slice(1, -1) : d, m = Y.join(w, t), b = !w && /^\.[\\\/]/.test(t) ? t.slice(0, 2) + m : m;
|
|||
|
|
f(c(b, u, 0));
|
|||
|
|
}), c = (u, f, p) => new Promise((d, w) => {
|
|||
|
|
if (p === s.length)
|
|||
|
|
return d(a(f + 1));
|
|||
|
|
let m = s[p];
|
|||
|
|
V(u + m, { pathExt: o }, (b, Ot) => {
|
|||
|
|
if (!b && Ot)
|
|||
|
|
if (e.all)
|
|||
|
|
i.push(u + m);
|
|||
|
|
else
|
|||
|
|
return d(u + m);
|
|||
|
|
return d(c(u, f, p + 1));
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
return n ? a(0).then((u) => n(null, u), n) : a(0);
|
|||
|
|
}, Xt = (t, e) => {
|
|||
|
|
e = e || {};
|
|||
|
|
let { pathEnv: n, pathExt: r, pathExtExe: s } = Q(t, e), o = [];
|
|||
|
|
for (let i = 0; i < n.length; i++) {
|
|||
|
|
let a = n[i], c = /^".*"$/.test(a) ? a.slice(1, -1) : a, u = Y.join(c, t), f = !c && /^\.[\\\/]/.test(t) ? t.slice(0, 2) + u : u;
|
|||
|
|
for (let p = 0; p < r.length; p++) {
|
|||
|
|
let d = f + r[p];
|
|||
|
|
try {
|
|||
|
|
if (V.sync(d, { pathExt: s }))
|
|||
|
|
if (e.all)
|
|||
|
|
o.push(d);
|
|||
|
|
else
|
|||
|
|
return d;
|
|||
|
|
} catch {
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (e.all && o.length)
|
|||
|
|
return o;
|
|||
|
|
if (e.nothrow)
|
|||
|
|
return null;
|
|||
|
|
throw J(t);
|
|||
|
|
};
|
|||
|
|
tt.exports = Z;
|
|||
|
|
Z.sync = Xt;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/path-key/index.js
|
|||
|
|
var rt = l(($e, _) => {
|
|||
|
|
var nt = (t = {}) => {
|
|||
|
|
let e = t.env || process.env;
|
|||
|
|
return (t.platform || process.platform) !== "win32" ? "PATH" : Object.keys(e).reverse().find((r) => r.toUpperCase() === "PATH") || "Path";
|
|||
|
|
};
|
|||
|
|
_.exports = nt;
|
|||
|
|
_.exports.default = nt;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/cross-spawn/lib/util/resolveCommand.js
|
|||
|
|
var ct = l((Ne, it) => {
|
|||
|
|
var st = h("path"), Gt = et(), Ut = rt();
|
|||
|
|
function ot(t, e) {
|
|||
|
|
let n = t.options.env || process.env, r = process.cwd(), s = t.options.cwd != null, o = s && process.chdir !== void 0 && !process.chdir.disabled;
|
|||
|
|
if (o)
|
|||
|
|
try {
|
|||
|
|
process.chdir(t.options.cwd);
|
|||
|
|
} catch {
|
|||
|
|
}
|
|||
|
|
let i;
|
|||
|
|
try {
|
|||
|
|
i = Gt.sync(t.command, {
|
|||
|
|
path: n[Ut({ env: n })],
|
|||
|
|
pathExt: e ? st.delimiter : void 0
|
|||
|
|
});
|
|||
|
|
} catch {
|
|||
|
|
} finally {
|
|||
|
|
o && process.chdir(r);
|
|||
|
|
}
|
|||
|
|
return i && (i = st.resolve(s ? t.options.cwd : "", i)), i;
|
|||
|
|
}
|
|||
|
|
function Yt(t) {
|
|||
|
|
return ot(t) || ot(t, !0);
|
|||
|
|
}
|
|||
|
|
it.exports = Yt;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/cross-spawn/lib/util/escape.js
|
|||
|
|
var ut = l((qe, P) => {
|
|||
|
|
var C = /([()\][%!^"`<>&|;, *?])/g;
|
|||
|
|
function Vt(t) {
|
|||
|
|
return t = t.replace(C, "^$1"), t;
|
|||
|
|
}
|
|||
|
|
function Jt(t, e) {
|
|||
|
|
return t = `${t}`, t = t.replace(/(\\*)"/g, '$1$1\\"'), t = t.replace(/(\\*)$/, "$1$1"), t = `"${t}"`, t = t.replace(C, "^$1"), e && (t = t.replace(C, "^$1")), t;
|
|||
|
|
}
|
|||
|
|
P.exports.command = Vt;
|
|||
|
|
P.exports.argument = Jt;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/shebang-regex/index.js
|
|||
|
|
var lt = l((Ie, at) => {
|
|||
|
|
at.exports = /^#!(.*)/;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/shebang-command/index.js
|
|||
|
|
var dt = l((Le, pt) => {
|
|||
|
|
var Qt = lt();
|
|||
|
|
pt.exports = (t = "") => {
|
|||
|
|
let e = t.match(Qt);
|
|||
|
|
if (!e)
|
|||
|
|
return null;
|
|||
|
|
let [n, r] = e[0].replace(/#! ?/, "").split(" "), s = n.split("/").pop();
|
|||
|
|
return s === "env" ? r : r ? `${s} ${r}` : s;
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/cross-spawn/lib/util/readShebang.js
|
|||
|
|
var ht = l((je, ft) => {
|
|||
|
|
var O = h("fs"), Zt = dt();
|
|||
|
|
function te(t) {
|
|||
|
|
let n = Buffer.alloc(150), r;
|
|||
|
|
try {
|
|||
|
|
r = O.openSync(t, "r"), O.readSync(r, n, 0, 150, 0), O.closeSync(r);
|
|||
|
|
} catch {
|
|||
|
|
}
|
|||
|
|
return Zt(n.toString());
|
|||
|
|
}
|
|||
|
|
ft.exports = te;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/cross-spawn/lib/parse.js
|
|||
|
|
var wt = l((Fe, Et) => {
|
|||
|
|
var ee = h("path"), mt = ct(), gt = ut(), ne = ht(), re = process.platform === "win32", se = /\.(?:com|exe)$/i, oe = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
|||
|
|
function ie(t) {
|
|||
|
|
t.file = mt(t);
|
|||
|
|
let e = t.file && ne(t.file);
|
|||
|
|
return e ? (t.args.unshift(t.file), t.command = e, mt(t)) : t.file;
|
|||
|
|
}
|
|||
|
|
function ce(t) {
|
|||
|
|
if (!re)
|
|||
|
|
return t;
|
|||
|
|
let e = ie(t), n = !se.test(e);
|
|||
|
|
if (t.options.forceShell || n) {
|
|||
|
|
let r = oe.test(e);
|
|||
|
|
t.command = ee.normalize(t.command), t.command = gt.command(t.command), t.args = t.args.map((o) => gt.argument(o, r));
|
|||
|
|
let s = [t.command].concat(t.args).join(" ");
|
|||
|
|
t.args = ["/d", "/s", "/c", `"${s}"`], t.command = process.env.comspec || "cmd.exe", t.options.windowsVerbatimArguments = !0;
|
|||
|
|
}
|
|||
|
|
return t;
|
|||
|
|
}
|
|||
|
|
function ue(t, e, n) {
|
|||
|
|
e && !Array.isArray(e) && (n = e, e = null), e = e ? e.slice(0) : [], n = Object.assign({}, n);
|
|||
|
|
let r = {
|
|||
|
|
command: t,
|
|||
|
|
args: e,
|
|||
|
|
options: n,
|
|||
|
|
file: void 0,
|
|||
|
|
original: {
|
|||
|
|
command: t,
|
|||
|
|
args: e
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
return n.shell ? r : ce(r);
|
|||
|
|
}
|
|||
|
|
Et.exports = ue;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/cross-spawn/lib/enoent.js
|
|||
|
|
var bt = l((ze, vt) => {
|
|||
|
|
var S = process.platform === "win32";
|
|||
|
|
function k(t, e) {
|
|||
|
|
return Object.assign(new Error(`${e} ${t.command} ENOENT`), {
|
|||
|
|
code: "ENOENT",
|
|||
|
|
errno: "ENOENT",
|
|||
|
|
syscall: `${e} ${t.command}`,
|
|||
|
|
path: t.command,
|
|||
|
|
spawnargs: t.args
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
function ae(t, e) {
|
|||
|
|
if (!S)
|
|||
|
|
return;
|
|||
|
|
let n = t.emit;
|
|||
|
|
t.emit = function(r, s) {
|
|||
|
|
if (r === "exit") {
|
|||
|
|
let o = xt(s, e);
|
|||
|
|
if (o)
|
|||
|
|
return n.call(t, "error", o);
|
|||
|
|
}
|
|||
|
|
return n.apply(t, arguments);
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
function xt(t, e) {
|
|||
|
|
return S && t === 1 && !e.file ? k(e.original, "spawn") : null;
|
|||
|
|
}
|
|||
|
|
function le(t, e) {
|
|||
|
|
return S && t === 1 && !e.file ? k(e.original, "spawnSync") : null;
|
|||
|
|
}
|
|||
|
|
vt.exports = {
|
|||
|
|
hookChildProcess: ae,
|
|||
|
|
verifyENOENT: xt,
|
|||
|
|
verifyENOENTSync: le,
|
|||
|
|
notFoundError: k
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// node_modules/cross-spawn/index.js
|
|||
|
|
var Ct = l((He, E) => {
|
|||
|
|
var yt = h("child_process"), T = wt(), A = bt();
|
|||
|
|
function _t(t, e, n) {
|
|||
|
|
let r = T(t, e, n), s = yt.spawn(r.command, r.args, r.options);
|
|||
|
|
return A.hookChildProcess(s, r), s;
|
|||
|
|
}
|
|||
|
|
function pe(t, e, n) {
|
|||
|
|
let r = T(t, e, n), s = yt.spawnSync(r.command, r.args, r.options);
|
|||
|
|
return s.error = s.error || A.verifyENOENTSync(s.status, r), s;
|
|||
|
|
}
|
|||
|
|
E.exports = _t;
|
|||
|
|
E.exports.spawn = _t;
|
|||
|
|
E.exports.sync = pe;
|
|||
|
|
E.exports._parse = T;
|
|||
|
|
E.exports._enoent = A;
|
|||
|
|
});
|
|||
|
|
var Lt = /^path$/i, q = { key: "PATH", value: "" };
|
|||
|
|
function jt(t) {
|
|||
|
|
for (let e in t) {
|
|||
|
|
if (!Object.prototype.hasOwnProperty.call(t, e) || !Lt.test(e))
|
|||
|
|
continue;
|
|||
|
|
let n = t[e];
|
|||
|
|
return n ? { key: e, value: n } : q;
|
|||
|
|
}
|
|||
|
|
return q;
|
|||
|
|
}
|
|||
|
|
function Ft(t, e) {
|
|||
|
|
let n = e.value.split(require$$1$1.delimiter), r = t, s;
|
|||
|
|
do
|
|||
|
|
n.push(require$$1$1.resolve(r, "node_modules", ".bin")), s = r, r = require$$1$1.dirname(r);
|
|||
|
|
while (r !== s);
|
|||
|
|
return { key: e.key, value: n.join(require$$1$1.delimiter) };
|
|||
|
|
}
|
|||
|
|
function I(t, e) {
|
|||
|
|
let n = {
|
|||
|
|
...process.env,
|
|||
|
|
...e
|
|||
|
|
}, r = Ft(t, jt(n));
|
|||
|
|
return n[r.key] = r.value, n;
|
|||
|
|
}
|
|||
|
|
var L = (t) => {
|
|||
|
|
let e = t.length, n = new stream.PassThrough(), r = () => {
|
|||
|
|
--e === 0 && n.emit("end");
|
|||
|
|
};
|
|||
|
|
for (let s of t)
|
|||
|
|
s.pipe(n, { end: !1 }), s.on("end", r);
|
|||
|
|
return n;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// src/main.ts
|
|||
|
|
var Pt = Nt(Ct());
|
|||
|
|
|
|||
|
|
// src/non-zero-exit-error.ts
|
|||
|
|
var x = class extends Error {
|
|||
|
|
result;
|
|||
|
|
output;
|
|||
|
|
get exitCode() {
|
|||
|
|
if (this.result.exitCode !== null)
|
|||
|
|
return this.result.exitCode;
|
|||
|
|
}
|
|||
|
|
constructor(e, n) {
|
|||
|
|
super(`Process exited with non-zero status (${e.exitCode})`), this.result = e, this.output = n;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// src/main.ts
|
|||
|
|
var ge = {
|
|||
|
|
timeout: void 0,
|
|||
|
|
persist: !1
|
|||
|
|
}, Ee = {
|
|||
|
|
windowsHide: !0
|
|||
|
|
};
|
|||
|
|
function we(t, e) {
|
|||
|
|
return {
|
|||
|
|
command: require$$1$1.normalize(t),
|
|||
|
|
args: e ?? []
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
function xe(t) {
|
|||
|
|
let e = new AbortController();
|
|||
|
|
for (let n of t) {
|
|||
|
|
if (n.aborted)
|
|||
|
|
return e.abort(), n;
|
|||
|
|
let r = () => {
|
|||
|
|
e.abort(n.reason);
|
|||
|
|
};
|
|||
|
|
n.addEventListener("abort", r, {
|
|||
|
|
signal: e.signal
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return e.signal;
|
|||
|
|
}
|
|||
|
|
var R = class {
|
|||
|
|
_process;
|
|||
|
|
_aborted = !1;
|
|||
|
|
_options;
|
|||
|
|
_command;
|
|||
|
|
_args;
|
|||
|
|
_resolveClose;
|
|||
|
|
_processClosed;
|
|||
|
|
_thrownError;
|
|||
|
|
get process() {
|
|||
|
|
return this._process;
|
|||
|
|
}
|
|||
|
|
get pid() {
|
|||
|
|
return this._process?.pid;
|
|||
|
|
}
|
|||
|
|
get exitCode() {
|
|||
|
|
if (this._process && this._process.exitCode !== null)
|
|||
|
|
return this._process.exitCode;
|
|||
|
|
}
|
|||
|
|
constructor(e, n, r) {
|
|||
|
|
this._options = {
|
|||
|
|
...ge,
|
|||
|
|
...r
|
|||
|
|
}, this._command = e, this._args = n ?? [], this._processClosed = new Promise((s) => {
|
|||
|
|
this._resolveClose = s;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
kill(e) {
|
|||
|
|
return this._process?.kill(e) === !0;
|
|||
|
|
}
|
|||
|
|
get aborted() {
|
|||
|
|
return this._aborted;
|
|||
|
|
}
|
|||
|
|
get killed() {
|
|||
|
|
return this._process?.killed === !0;
|
|||
|
|
}
|
|||
|
|
pipe(e, n, r) {
|
|||
|
|
return be(e, n, {
|
|||
|
|
...r,
|
|||
|
|
stdin: this
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
async *[Symbol.asyncIterator]() {
|
|||
|
|
let e = this._process;
|
|||
|
|
if (!e)
|
|||
|
|
return;
|
|||
|
|
let n = [];
|
|||
|
|
this._streamErr && n.push(this._streamErr), this._streamOut && n.push(this._streamOut);
|
|||
|
|
let r = L(n), s = require$$0__default.createInterface({
|
|||
|
|
input: r
|
|||
|
|
});
|
|||
|
|
for await (let o of s)
|
|||
|
|
yield o.toString();
|
|||
|
|
if (await this._processClosed, e.removeAllListeners(), this._thrownError)
|
|||
|
|
throw this._thrownError;
|
|||
|
|
if (this._options?.throwOnError && this.exitCode !== 0 && this.exitCode !== void 0)
|
|||
|
|
throw new x(this);
|
|||
|
|
}
|
|||
|
|
async _waitForOutput() {
|
|||
|
|
let e = this._process;
|
|||
|
|
if (!e)
|
|||
|
|
throw new Error("No process was started");
|
|||
|
|
let n = "", r = "";
|
|||
|
|
if (this._streamErr)
|
|||
|
|
for await (let o of this._streamErr)
|
|||
|
|
n += o.toString();
|
|||
|
|
if (this._streamOut)
|
|||
|
|
for await (let o of this._streamOut)
|
|||
|
|
r += o.toString();
|
|||
|
|
if (await this._processClosed, this._options?.stdin && await this._options.stdin, e.removeAllListeners(), this._thrownError)
|
|||
|
|
throw this._thrownError;
|
|||
|
|
let s = {
|
|||
|
|
stderr: n,
|
|||
|
|
stdout: r,
|
|||
|
|
exitCode: this.exitCode
|
|||
|
|
};
|
|||
|
|
if (this._options.throwOnError && this.exitCode !== 0 && this.exitCode !== void 0)
|
|||
|
|
throw new x(this, s);
|
|||
|
|
return s;
|
|||
|
|
}
|
|||
|
|
then(e, n) {
|
|||
|
|
return this._waitForOutput().then(e, n);
|
|||
|
|
}
|
|||
|
|
_streamOut;
|
|||
|
|
_streamErr;
|
|||
|
|
spawn() {
|
|||
|
|
let e = process$2.cwd(), n = this._options, r = {
|
|||
|
|
...Ee,
|
|||
|
|
...n.nodeOptions
|
|||
|
|
}, s = [];
|
|||
|
|
this._resetState(), n.timeout !== void 0 && s.push(AbortSignal.timeout(n.timeout)), n.signal !== void 0 && s.push(n.signal), n.persist === !0 && (r.detached = !0), s.length > 0 && (r.signal = xe(s)), r.env = I(e, r.env);
|
|||
|
|
let { command: o, args: i } = we(this._command, this._args), a = (0, Pt._parse)(o, i, r), c = child_process.spawn(
|
|||
|
|
a.command,
|
|||
|
|
a.args,
|
|||
|
|
a.options
|
|||
|
|
);
|
|||
|
|
if (c.stderr && (this._streamErr = c.stderr), c.stdout && (this._streamOut = c.stdout), this._process = c, c.once("error", this._onError), c.once("close", this._onClose), n.stdin !== void 0 && c.stdin && n.stdin.process) {
|
|||
|
|
let { stdout: u } = n.stdin.process;
|
|||
|
|
u && u.pipe(c.stdin);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
_resetState() {
|
|||
|
|
this._aborted = !1, this._processClosed = new Promise((e) => {
|
|||
|
|
this._resolveClose = e;
|
|||
|
|
}), this._thrownError = void 0;
|
|||
|
|
}
|
|||
|
|
_onError = (e) => {
|
|||
|
|
if (e.name === "AbortError" && (!(e.cause instanceof Error) || e.cause.name !== "TimeoutError")) {
|
|||
|
|
this._aborted = !0;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
this._thrownError = e;
|
|||
|
|
};
|
|||
|
|
_onClose = () => {
|
|||
|
|
this._resolveClose && this._resolveClose();
|
|||
|
|
};
|
|||
|
|
}, ve = (t, e, n) => {
|
|||
|
|
let r = new R(t, e, n);
|
|||
|
|
return r.spawn(), r;
|
|||
|
|
}, be = ve;
|
|||
|
|
|
|||
|
|
var picocolors = {exports: {}};
|
|||
|
|
|
|||
|
|
var hasRequiredPicocolors;
|
|||
|
|
|
|||
|
|
function requirePicocolors () {
|
|||
|
|
if (hasRequiredPicocolors) return picocolors.exports;
|
|||
|
|
hasRequiredPicocolors = 1;
|
|||
|
|
let p = process || {}, argv = p.argv || [], env = p.env || {};
|
|||
|
|
let isColorSupported =
|
|||
|
|
!(!!env.NO_COLOR || argv.includes("--no-color")) &&
|
|||
|
|
(!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || ((p.stdout || {}).isTTY && env.TERM !== "dumb") || !!env.CI);
|
|||
|
|
|
|||
|
|
let formatter = (open, close, replace = open) =>
|
|||
|
|
input => {
|
|||
|
|
let string = "" + input, index = string.indexOf(close, open.length);
|
|||
|
|
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let replaceClose = (string, close, replace, index) => {
|
|||
|
|
let result = "", cursor = 0;
|
|||
|
|
do {
|
|||
|
|
result += string.substring(cursor, index) + replace;
|
|||
|
|
cursor = index + close.length;
|
|||
|
|
index = string.indexOf(close, cursor);
|
|||
|
|
} while (~index)
|
|||
|
|
return result + string.substring(cursor)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let createColors = (enabled = isColorSupported) => {
|
|||
|
|
let f = enabled ? formatter : () => String;
|
|||
|
|
return {
|
|||
|
|
isColorSupported: enabled,
|
|||
|
|
reset: f("\x1b[0m", "\x1b[0m"),
|
|||
|
|
bold: f("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m"),
|
|||
|
|
dim: f("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m"),
|
|||
|
|
italic: f("\x1b[3m", "\x1b[23m"),
|
|||
|
|
underline: f("\x1b[4m", "\x1b[24m"),
|
|||
|
|
inverse: f("\x1b[7m", "\x1b[27m"),
|
|||
|
|
hidden: f("\x1b[8m", "\x1b[28m"),
|
|||
|
|
strikethrough: f("\x1b[9m", "\x1b[29m"),
|
|||
|
|
|
|||
|
|
black: f("\x1b[30m", "\x1b[39m"),
|
|||
|
|
red: f("\x1b[31m", "\x1b[39m"),
|
|||
|
|
green: f("\x1b[32m", "\x1b[39m"),
|
|||
|
|
yellow: f("\x1b[33m", "\x1b[39m"),
|
|||
|
|
blue: f("\x1b[34m", "\x1b[39m"),
|
|||
|
|
magenta: f("\x1b[35m", "\x1b[39m"),
|
|||
|
|
cyan: f("\x1b[36m", "\x1b[39m"),
|
|||
|
|
white: f("\x1b[37m", "\x1b[39m"),
|
|||
|
|
gray: f("\x1b[90m", "\x1b[39m"),
|
|||
|
|
|
|||
|
|
bgBlack: f("\x1b[40m", "\x1b[49m"),
|
|||
|
|
bgRed: f("\x1b[41m", "\x1b[49m"),
|
|||
|
|
bgGreen: f("\x1b[42m", "\x1b[49m"),
|
|||
|
|
bgYellow: f("\x1b[43m", "\x1b[49m"),
|
|||
|
|
bgBlue: f("\x1b[44m", "\x1b[49m"),
|
|||
|
|
bgMagenta: f("\x1b[45m", "\x1b[49m"),
|
|||
|
|
bgCyan: f("\x1b[46m", "\x1b[49m"),
|
|||
|
|
bgWhite: f("\x1b[47m", "\x1b[49m"),
|
|||
|
|
|
|||
|
|
blackBright: f("\x1b[90m", "\x1b[39m"),
|
|||
|
|
redBright: f("\x1b[91m", "\x1b[39m"),
|
|||
|
|
greenBright: f("\x1b[92m", "\x1b[39m"),
|
|||
|
|
yellowBright: f("\x1b[93m", "\x1b[39m"),
|
|||
|
|
blueBright: f("\x1b[94m", "\x1b[39m"),
|
|||
|
|
magentaBright: f("\x1b[95m", "\x1b[39m"),
|
|||
|
|
cyanBright: f("\x1b[96m", "\x1b[39m"),
|
|||
|
|
whiteBright: f("\x1b[97m", "\x1b[39m"),
|
|||
|
|
|
|||
|
|
bgBlackBright: f("\x1b[100m", "\x1b[49m"),
|
|||
|
|
bgRedBright: f("\x1b[101m", "\x1b[49m"),
|
|||
|
|
bgGreenBright: f("\x1b[102m", "\x1b[49m"),
|
|||
|
|
bgYellowBright: f("\x1b[103m", "\x1b[49m"),
|
|||
|
|
bgBlueBright: f("\x1b[104m", "\x1b[49m"),
|
|||
|
|
bgMagentaBright: f("\x1b[105m", "\x1b[49m"),
|
|||
|
|
bgCyanBright: f("\x1b[106m", "\x1b[49m"),
|
|||
|
|
bgWhiteBright: f("\x1b[107m", "\x1b[49m"),
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
picocolors.exports = createColors();
|
|||
|
|
picocolors.exports.createColors = createColors;
|
|||
|
|
return picocolors.exports;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var picocolorsExports = /*@__PURE__*/ requirePicocolors();
|
|||
|
|
const c = /*@__PURE__*/getDefaultExportFromCjs(picocolorsExports);
|
|||
|
|
|
|||
|
|
var cjs = {};
|
|||
|
|
|
|||
|
|
var posix = {};
|
|||
|
|
|
|||
|
|
var hasRequiredPosix;
|
|||
|
|
|
|||
|
|
function requirePosix () {
|
|||
|
|
if (hasRequiredPosix) return posix;
|
|||
|
|
hasRequiredPosix = 1;
|
|||
|
|
/**
|
|||
|
|
* This is the Posix implementation of isexe, which uses the file
|
|||
|
|
* mode and uid/gid values.
|
|||
|
|
*
|
|||
|
|
* @module
|
|||
|
|
*/
|
|||
|
|
Object.defineProperty(posix, "__esModule", { value: true });
|
|||
|
|
posix.sync = posix.isexe = void 0;
|
|||
|
|
const fs_1 = require$$0__default$2;
|
|||
|
|
const promises_1 = require$$1__default$1;
|
|||
|
|
/**
|
|||
|
|
* Determine whether a path is executable according to the mode and
|
|||
|
|
* current (or specified) user and group IDs.
|
|||
|
|
*/
|
|||
|
|
const isexe = async (path, options = {}) => {
|
|||
|
|
const { ignoreErrors = false } = options;
|
|||
|
|
try {
|
|||
|
|
return checkStat(await (0, promises_1.stat)(path), options);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
const er = e;
|
|||
|
|
if (ignoreErrors || er.code === 'EACCES')
|
|||
|
|
return false;
|
|||
|
|
throw er;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
posix.isexe = isexe;
|
|||
|
|
/**
|
|||
|
|
* Synchronously determine whether a path is executable according to
|
|||
|
|
* the mode and current (or specified) user and group IDs.
|
|||
|
|
*/
|
|||
|
|
const sync = (path, options = {}) => {
|
|||
|
|
const { ignoreErrors = false } = options;
|
|||
|
|
try {
|
|||
|
|
return checkStat((0, fs_1.statSync)(path), options);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
const er = e;
|
|||
|
|
if (ignoreErrors || er.code === 'EACCES')
|
|||
|
|
return false;
|
|||
|
|
throw er;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
posix.sync = sync;
|
|||
|
|
const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options);
|
|||
|
|
const checkMode = (stat, options) => {
|
|||
|
|
const myUid = options.uid ?? process.getuid?.();
|
|||
|
|
const myGroups = options.groups ?? process.getgroups?.() ?? [];
|
|||
|
|
const myGid = options.gid ?? process.getgid?.() ?? myGroups[0];
|
|||
|
|
if (myUid === undefined || myGid === undefined) {
|
|||
|
|
throw new Error('cannot get uid or gid');
|
|||
|
|
}
|
|||
|
|
const groups = new Set([myGid, ...myGroups]);
|
|||
|
|
const mod = stat.mode;
|
|||
|
|
const uid = stat.uid;
|
|||
|
|
const gid = stat.gid;
|
|||
|
|
const u = parseInt('100', 8);
|
|||
|
|
const g = parseInt('010', 8);
|
|||
|
|
const o = parseInt('001', 8);
|
|||
|
|
const ug = u | g;
|
|||
|
|
return !!(mod & o ||
|
|||
|
|
(mod & g && groups.has(gid)) ||
|
|||
|
|
(mod & u && uid === myUid) ||
|
|||
|
|
(mod & ug && myUid === 0));
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return posix;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var win32 = {};
|
|||
|
|
|
|||
|
|
var hasRequiredWin32;
|
|||
|
|
|
|||
|
|
function requireWin32 () {
|
|||
|
|
if (hasRequiredWin32) return win32;
|
|||
|
|
hasRequiredWin32 = 1;
|
|||
|
|
/**
|
|||
|
|
* This is the Windows implementation of isexe, which uses the file
|
|||
|
|
* extension and PATHEXT setting.
|
|||
|
|
*
|
|||
|
|
* @module
|
|||
|
|
*/
|
|||
|
|
Object.defineProperty(win32, "__esModule", { value: true });
|
|||
|
|
win32.sync = win32.isexe = void 0;
|
|||
|
|
const fs_1 = require$$0__default$2;
|
|||
|
|
const promises_1 = require$$1__default$1;
|
|||
|
|
/**
|
|||
|
|
* Determine whether a path is executable based on the file extension
|
|||
|
|
* and PATHEXT environment variable (or specified pathExt option)
|
|||
|
|
*/
|
|||
|
|
const isexe = async (path, options = {}) => {
|
|||
|
|
const { ignoreErrors = false } = options;
|
|||
|
|
try {
|
|||
|
|
return checkStat(await (0, promises_1.stat)(path), path, options);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
const er = e;
|
|||
|
|
if (ignoreErrors || er.code === 'EACCES')
|
|||
|
|
return false;
|
|||
|
|
throw er;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
win32.isexe = isexe;
|
|||
|
|
/**
|
|||
|
|
* Synchronously determine whether a path is executable based on the file
|
|||
|
|
* extension and PATHEXT environment variable (or specified pathExt option)
|
|||
|
|
*/
|
|||
|
|
const sync = (path, options = {}) => {
|
|||
|
|
const { ignoreErrors = false } = options;
|
|||
|
|
try {
|
|||
|
|
return checkStat((0, fs_1.statSync)(path), path, options);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
const er = e;
|
|||
|
|
if (ignoreErrors || er.code === 'EACCES')
|
|||
|
|
return false;
|
|||
|
|
throw er;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
win32.sync = sync;
|
|||
|
|
const checkPathExt = (path, options) => {
|
|||
|
|
const { pathExt = process.env.PATHEXT || '' } = options;
|
|||
|
|
const peSplit = pathExt.split(';');
|
|||
|
|
if (peSplit.indexOf('') !== -1) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
for (let i = 0; i < peSplit.length; i++) {
|
|||
|
|
const p = peSplit[i].toLowerCase();
|
|||
|
|
const ext = path.substring(path.length - p.length).toLowerCase();
|
|||
|
|
if (p && ext === p) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
};
|
|||
|
|
const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options);
|
|||
|
|
|
|||
|
|
return win32;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var options = {};
|
|||
|
|
|
|||
|
|
var hasRequiredOptions;
|
|||
|
|
|
|||
|
|
function requireOptions () {
|
|||
|
|
if (hasRequiredOptions) return options;
|
|||
|
|
hasRequiredOptions = 1;
|
|||
|
|
Object.defineProperty(options, "__esModule", { value: true });
|
|||
|
|
|
|||
|
|
return options;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var hasRequiredCjs;
|
|||
|
|
|
|||
|
|
function requireCjs () {
|
|||
|
|
if (hasRequiredCjs) return cjs;
|
|||
|
|
hasRequiredCjs = 1;
|
|||
|
|
(function (exports) {
|
|||
|
|
var __createBinding = (cjs && cjs.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|||
|
|
if (k2 === undefined) k2 = k;
|
|||
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|||
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|||
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|||
|
|
}
|
|||
|
|
Object.defineProperty(o, k2, desc);
|
|||
|
|
}) : (function(o, m, k, k2) {
|
|||
|
|
if (k2 === undefined) k2 = k;
|
|||
|
|
o[k2] = m[k];
|
|||
|
|
}));
|
|||
|
|
var __setModuleDefault = (cjs && cjs.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|||
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|||
|
|
}) : function(o, v) {
|
|||
|
|
o["default"] = v;
|
|||
|
|
});
|
|||
|
|
var __importStar = (cjs && cjs.__importStar) || function (mod) {
|
|||
|
|
if (mod && mod.__esModule) return mod;
|
|||
|
|
var result = {};
|
|||
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|||
|
|
__setModuleDefault(result, mod);
|
|||
|
|
return result;
|
|||
|
|
};
|
|||
|
|
var __exportStar = (cjs && cjs.__exportStar) || function(m, exports) {
|
|||
|
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|||
|
|
};
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
exports.sync = exports.isexe = exports.posix = exports.win32 = void 0;
|
|||
|
|
const posix = __importStar(requirePosix());
|
|||
|
|
exports.posix = posix;
|
|||
|
|
const win32 = __importStar(requireWin32());
|
|||
|
|
exports.win32 = win32;
|
|||
|
|
__exportStar(requireOptions(), exports);
|
|||
|
|
const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform;
|
|||
|
|
const impl = platform === 'win32' ? win32 : posix;
|
|||
|
|
/**
|
|||
|
|
* Determine whether a path is executable on the current platform.
|
|||
|
|
*/
|
|||
|
|
exports.isexe = impl.isexe;
|
|||
|
|
/**
|
|||
|
|
* Synchronously determine whether a path is executable on the
|
|||
|
|
* current platform.
|
|||
|
|
*/
|
|||
|
|
exports.sync = impl.sync;
|
|||
|
|
|
|||
|
|
} (cjs));
|
|||
|
|
return cjs;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var lib;
|
|||
|
|
var hasRequiredLib;
|
|||
|
|
|
|||
|
|
function requireLib () {
|
|||
|
|
if (hasRequiredLib) return lib;
|
|||
|
|
hasRequiredLib = 1;
|
|||
|
|
const { isexe, sync: isexeSync } = requireCjs();
|
|||
|
|
const { join, delimiter, sep, posix } = require$$1__default$2;
|
|||
|
|
|
|||
|
|
const isWindows = process.platform === 'win32';
|
|||
|
|
|
|||
|
|
// used to check for slashed in commands passed in. always checks for the posix
|
|||
|
|
// seperator on all platforms, and checks for the current separator when not on
|
|||
|
|
// a posix platform. don't use the isWindows check for this since that is mocked
|
|||
|
|
// in tests but we still need the code to actually work when called. that is also
|
|||
|
|
// why it is ignored from coverage.
|
|||
|
|
/* istanbul ignore next */
|
|||
|
|
const rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? '' : sep}]`.replace(/(\\)/g, '\\$1'));
|
|||
|
|
const rRel = new RegExp(`^\\.${rSlash.source}`);
|
|||
|
|
|
|||
|
|
const getNotFoundError = (cmd) =>
|
|||
|
|
Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' });
|
|||
|
|
|
|||
|
|
const getPathInfo = (cmd, {
|
|||
|
|
path: optPath = process.env.PATH,
|
|||
|
|
pathExt: optPathExt = process.env.PATHEXT,
|
|||
|
|
delimiter: optDelimiter = delimiter,
|
|||
|
|
}) => {
|
|||
|
|
// If it has a slash, then we don't bother searching the pathenv.
|
|||
|
|
// just check the file itself, and that's it.
|
|||
|
|
const pathEnv = cmd.match(rSlash) ? [''] : [
|
|||
|
|
// windows always checks the cwd first
|
|||
|
|
...(isWindows ? [process.cwd()] : []),
|
|||
|
|
...(optPath || /* istanbul ignore next: very unusual */ '').split(optDelimiter),
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
if (isWindows) {
|
|||
|
|
const pathExtExe = optPathExt ||
|
|||
|
|
['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter);
|
|||
|
|
const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()]);
|
|||
|
|
if (cmd.includes('.') && pathExt[0] !== '') {
|
|||
|
|
pathExt.unshift('');
|
|||
|
|
}
|
|||
|
|
return { pathEnv, pathExt, pathExtExe }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return { pathEnv, pathExt: [''] }
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const getPathPart = (raw, cmd) => {
|
|||
|
|
const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
|
|||
|
|
const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : '';
|
|||
|
|
return prefix + join(pathPart, cmd)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const which = async (cmd, opt = {}) => {
|
|||
|
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|||
|
|
const found = [];
|
|||
|
|
|
|||
|
|
for (const envPart of pathEnv) {
|
|||
|
|
const p = getPathPart(envPart, cmd);
|
|||
|
|
|
|||
|
|
for (const ext of pathExt) {
|
|||
|
|
const withExt = p + ext;
|
|||
|
|
const is = await isexe(withExt, { pathExt: pathExtExe, ignoreErrors: true });
|
|||
|
|
if (is) {
|
|||
|
|
if (!opt.all) {
|
|||
|
|
return withExt
|
|||
|
|
}
|
|||
|
|
found.push(withExt);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (opt.all && found.length) {
|
|||
|
|
return found
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (opt.nothrow) {
|
|||
|
|
return null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
throw getNotFoundError(cmd)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const whichSync = (cmd, opt = {}) => {
|
|||
|
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|||
|
|
const found = [];
|
|||
|
|
|
|||
|
|
for (const pathEnvPart of pathEnv) {
|
|||
|
|
const p = getPathPart(pathEnvPart, cmd);
|
|||
|
|
|
|||
|
|
for (const ext of pathExt) {
|
|||
|
|
const withExt = p + ext;
|
|||
|
|
const is = isexeSync(withExt, { pathExt: pathExtExe, ignoreErrors: true });
|
|||
|
|
if (is) {
|
|||
|
|
if (!opt.all) {
|
|||
|
|
return withExt
|
|||
|
|
}
|
|||
|
|
found.push(withExt);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (opt.all && found.length) {
|
|||
|
|
return found
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (opt.nothrow) {
|
|||
|
|
return null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
throw getNotFoundError(cmd)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
lib = which;
|
|||
|
|
which.sync = whichSync;
|
|||
|
|
return lib;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var libExports = requireLib();
|
|||
|
|
const which = /*@__PURE__*/getDefaultExportFromCjs(libExports);
|
|||
|
|
|
|||
|
|
const CLI_TEMP_DIR = path.join(os__default.tmpdir(), "antfu-ni");
|
|||
|
|
function remove(arr, v) {
|
|||
|
|
const index = arr.indexOf(v);
|
|||
|
|
if (index >= 0)
|
|||
|
|
arr.splice(index, 1);
|
|||
|
|
return arr;
|
|||
|
|
}
|
|||
|
|
function exclude(arr, ...v) {
|
|||
|
|
return arr.slice().filter((item) => !v.includes(item));
|
|||
|
|
}
|
|||
|
|
function cmdExists(cmd) {
|
|||
|
|
return which.sync(cmd, { nothrow: true }) !== null;
|
|||
|
|
}
|
|||
|
|
let counter = 0;
|
|||
|
|
async function openTemp() {
|
|||
|
|
if (!fs.existsSync(CLI_TEMP_DIR))
|
|||
|
|
await fs.promises.mkdir(CLI_TEMP_DIR, { recursive: true });
|
|||
|
|
const competitivePath = path.join(CLI_TEMP_DIR, `.${process__default.pid}.${counter}`);
|
|||
|
|
counter += 1;
|
|||
|
|
return fs.promises.open(competitivePath, "wx").then((fd) => ({
|
|||
|
|
fd,
|
|||
|
|
path: competitivePath,
|
|||
|
|
cleanup() {
|
|||
|
|
fd.close().then(() => {
|
|||
|
|
if (fs.existsSync(competitivePath))
|
|||
|
|
fs.promises.unlink(competitivePath);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
})).catch((error) => {
|
|||
|
|
if (error && error.code === "EEXIST")
|
|||
|
|
return openTemp();
|
|||
|
|
else
|
|||
|
|
return void 0;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
async function writeFileSafe(path$1, data = "") {
|
|||
|
|
const temp = await openTemp();
|
|||
|
|
if (temp) {
|
|||
|
|
fs.promises.writeFile(temp.path, data).then(() => {
|
|||
|
|
const directory = path.dirname(path$1);
|
|||
|
|
if (!fs.existsSync(directory))
|
|||
|
|
fs.promises.mkdir(directory, { recursive: true });
|
|||
|
|
return fs.promises.rename(temp.path, path$1).then(() => true).catch(() => false);
|
|||
|
|
}).catch(() => false).finally(temp.cleanup);
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
function limitText(text, maxWidth) {
|
|||
|
|
if (text.length <= maxWidth)
|
|||
|
|
return text;
|
|||
|
|
return `${text.slice(0, maxWidth)}${c.dim("\u2026")}`;
|
|||
|
|
}
|
|||
|
|
function formatPackageWithUrl(pkg, url, limits = 80) {
|
|||
|
|
return url ? terminalLink(
|
|||
|
|
pkg,
|
|||
|
|
url,
|
|||
|
|
{
|
|||
|
|
fallback: (_, url2) => pkg.length + url2.length > limits ? pkg : pkg + c.dim(` - ${url2}`)
|
|||
|
|
}
|
|||
|
|
) : pkg;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function detect({ autoInstall, programmatic, cwd } = {}) {
|
|||
|
|
const {
|
|||
|
|
name,
|
|||
|
|
agent,
|
|||
|
|
version
|
|||
|
|
} = await detect$1({
|
|||
|
|
cwd,
|
|||
|
|
onUnknown: (packageManager) => {
|
|||
|
|
if (!programmatic) {
|
|||
|
|
console.warn("[ni] Unknown packageManager:", packageManager);
|
|||
|
|
}
|
|||
|
|
return void 0;
|
|||
|
|
}
|
|||
|
|
}) || {};
|
|||
|
|
if (name && !cmdExists(name) && !programmatic) {
|
|||
|
|
if (!autoInstall) {
|
|||
|
|
console.warn(`[ni] Detected ${name} but it doesn't seem to be installed.
|
|||
|
|
`);
|
|||
|
|
if (process__default.env.CI)
|
|||
|
|
process__default.exit(1);
|
|||
|
|
const link = terminalLink(name, INSTALL_PAGE[name]);
|
|||
|
|
const { tryInstall } = await prompts({
|
|||
|
|
name: "tryInstall",
|
|||
|
|
type: "confirm",
|
|||
|
|
message: `Would you like to globally install ${link}?`
|
|||
|
|
});
|
|||
|
|
if (!tryInstall)
|
|||
|
|
process__default.exit(1);
|
|||
|
|
}
|
|||
|
|
await ve(
|
|||
|
|
"npm",
|
|||
|
|
["i", "-g", `${name}${version ? `@${version}` : ""}`],
|
|||
|
|
{
|
|||
|
|
nodeOptions: {
|
|||
|
|
stdio: "inherit",
|
|||
|
|
cwd
|
|||
|
|
},
|
|||
|
|
throwOnError: true
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
return agent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const customRcPath = process__default.env.NI_CONFIG_FILE;
|
|||
|
|
const home = process__default.platform === "win32" ? process__default.env.USERPROFILE : process__default.env.HOME;
|
|||
|
|
const defaultRcPath = path__default.join(home || "~/", ".nirc");
|
|||
|
|
const rcPath = customRcPath || defaultRcPath;
|
|||
|
|
const defaultConfig = {
|
|||
|
|
defaultAgent: "prompt",
|
|||
|
|
globalAgent: "npm"
|
|||
|
|
};
|
|||
|
|
let config;
|
|||
|
|
async function getConfig() {
|
|||
|
|
if (!config) {
|
|||
|
|
config = Object.assign(
|
|||
|
|
{},
|
|||
|
|
defaultConfig,
|
|||
|
|
fs__default.existsSync(rcPath) ? ini.parse(fs__default.readFileSync(rcPath, "utf-8")) : null
|
|||
|
|
);
|
|||
|
|
if (process__default.env.NI_DEFAULT_AGENT)
|
|||
|
|
config.defaultAgent = process__default.env.NI_DEFAULT_AGENT;
|
|||
|
|
if (process__default.env.NI_GLOBAL_AGENT)
|
|||
|
|
config.globalAgent = process__default.env.NI_GLOBAL_AGENT;
|
|||
|
|
const agent = await detect({ programmatic: true });
|
|||
|
|
if (agent)
|
|||
|
|
config.defaultAgent = agent;
|
|||
|
|
}
|
|||
|
|
return config;
|
|||
|
|
}
|
|||
|
|
async function getDefaultAgent(programmatic) {
|
|||
|
|
const { defaultAgent } = await getConfig();
|
|||
|
|
if (defaultAgent === "prompt" && (programmatic || process__default.env.CI))
|
|||
|
|
return "npm";
|
|||
|
|
return defaultAgent;
|
|||
|
|
}
|
|||
|
|
async function getGlobalAgent() {
|
|||
|
|
const { globalAgent } = await getConfig();
|
|||
|
|
return globalAgent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class UnsupportedCommand extends Error {
|
|||
|
|
constructor({ agent, command }) {
|
|||
|
|
super(`Command "${command}" is not support by agent "${agent}"`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function getCommand(agent, command, args = []) {
|
|||
|
|
if (!COMMANDS[agent])
|
|||
|
|
throw new Error(`Unsupported agent "${agent}"`);
|
|||
|
|
if (!COMMANDS[agent][command])
|
|||
|
|
throw new UnsupportedCommand({ agent, command });
|
|||
|
|
return constructCommand(COMMANDS[agent][command], args);
|
|||
|
|
}
|
|||
|
|
const parseNi = (agent, args, ctx) => {
|
|||
|
|
if (agent === "bun")
|
|||
|
|
args = args.map((i) => i === "-D" ? "-d" : i);
|
|||
|
|
if (args.includes("-g"))
|
|||
|
|
return getCommand(agent, "global", exclude(args, "-g"));
|
|||
|
|
if (args.includes("--frozen-if-present")) {
|
|||
|
|
args = exclude(args, "--frozen-if-present");
|
|||
|
|
return getCommand(agent, ctx?.hasLock ? "frozen" : "install", args);
|
|||
|
|
}
|
|||
|
|
if (args.includes("--frozen"))
|
|||
|
|
return getCommand(agent, "frozen", exclude(args, "--frozen"));
|
|||
|
|
if (args.length === 0 || args.every((i) => i.startsWith("-")))
|
|||
|
|
return getCommand(agent, "install", args);
|
|||
|
|
return getCommand(agent, "add", args);
|
|||
|
|
};
|
|||
|
|
const parseNr = (agent, args) => {
|
|||
|
|
if (args.length === 0)
|
|||
|
|
args.push("start");
|
|||
|
|
let hasIfPresent = false;
|
|||
|
|
if (args.includes("--if-present")) {
|
|||
|
|
args = exclude(args, "--if-present");
|
|||
|
|
hasIfPresent = true;
|
|||
|
|
}
|
|||
|
|
const cmd = getCommand(agent, "run", args);
|
|||
|
|
if (!cmd)
|
|||
|
|
return cmd;
|
|||
|
|
if (hasIfPresent)
|
|||
|
|
cmd.args.splice(1, 0, "--if-present");
|
|||
|
|
return cmd;
|
|||
|
|
};
|
|||
|
|
const parseNu = (agent, args) => {
|
|||
|
|
if (args.includes("-i"))
|
|||
|
|
return getCommand(agent, "upgrade-interactive", exclude(args, "-i"));
|
|||
|
|
return getCommand(agent, "upgrade", args);
|
|||
|
|
};
|
|||
|
|
const parseNun = (agent, args) => {
|
|||
|
|
if (args.includes("-g"))
|
|||
|
|
return getCommand(agent, "global_uninstall", exclude(args, "-g"));
|
|||
|
|
return getCommand(agent, "uninstall", args);
|
|||
|
|
};
|
|||
|
|
const parseNlx = (agent, args) => {
|
|||
|
|
return getCommand(agent, "execute", args);
|
|||
|
|
};
|
|||
|
|
const parseNa = (agent, args) => {
|
|||
|
|
return getCommand(agent, "agent", args);
|
|||
|
|
};
|
|||
|
|
function serializeCommand(command) {
|
|||
|
|
if (!command)
|
|||
|
|
return void 0;
|
|||
|
|
if (command.args.length === 0)
|
|||
|
|
return command.command;
|
|||
|
|
return `${command.command} ${command.args.map((i) => i.includes(" ") ? `"${i}"` : i).join(" ")}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const version = "0.23.2";
|
|||
|
|
|
|||
|
|
const DEBUG_SIGN = "?";
|
|||
|
|
async function runCli(fn, options = {}) {
|
|||
|
|
const {
|
|||
|
|
args = process__default.argv.slice(2).filter(Boolean)
|
|||
|
|
} = options;
|
|||
|
|
try {
|
|||
|
|
await run(fn, args, options);
|
|||
|
|
} catch (error) {
|
|||
|
|
if (error instanceof UnsupportedCommand && !options.programmatic)
|
|||
|
|
console.log(c.red(`\u2717 ${error.message}`));
|
|||
|
|
if (!options.programmatic)
|
|||
|
|
process__default.exit(1);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
async function getCliCommand(fn, args, options = {}, cwd = options.cwd ?? process__default.cwd()) {
|
|||
|
|
const isGlobal = args.includes("-g");
|
|||
|
|
if (isGlobal)
|
|||
|
|
return await fn(await getGlobalAgent(), args);
|
|||
|
|
let agent = await detect({ ...options, cwd }) || await getDefaultAgent(options.programmatic);
|
|||
|
|
if (agent === "prompt") {
|
|||
|
|
agent = (await prompts({
|
|||
|
|
name: "agent",
|
|||
|
|
type: "select",
|
|||
|
|
message: "Choose the agent",
|
|||
|
|
choices: AGENTS.filter((i) => !i.includes("@")).map((value) => ({ title: value, value }))
|
|||
|
|
})).agent;
|
|||
|
|
if (!agent)
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
return await fn(agent, args, {
|
|||
|
|
programmatic: options.programmatic,
|
|||
|
|
hasLock: Boolean(agent),
|
|||
|
|
cwd
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
async function run(fn, args, options = {}) {
|
|||
|
|
const {
|
|||
|
|
detectVolta = true
|
|||
|
|
} = options;
|
|||
|
|
const debug = args.includes(DEBUG_SIGN);
|
|||
|
|
if (debug)
|
|||
|
|
remove(args, DEBUG_SIGN);
|
|||
|
|
let cwd = options.cwd ?? process__default.cwd();
|
|||
|
|
if (args[0] === "-C") {
|
|||
|
|
cwd = path.resolve(cwd, args[1]);
|
|||
|
|
args.splice(0, 2);
|
|||
|
|
}
|
|||
|
|
if (args.length === 1 && (args[0]?.toLowerCase() === "-v" || args[0] === "--version")) {
|
|||
|
|
const getCmd = (a) => AGENTS.includes(a) ? getCommand(a, "agent", ["-v"]) : { command: a, args: ["-v"] };
|
|||
|
|
const xVersionOptions = {
|
|||
|
|
nodeOptions: {
|
|||
|
|
cwd
|
|||
|
|
},
|
|||
|
|
throwOnError: true
|
|||
|
|
};
|
|||
|
|
const getV = (a) => {
|
|||
|
|
const { command: command2, args: args2 } = getCmd(a);
|
|||
|
|
return ve(command2, args2, xVersionOptions).then((e) => e.stdout).then((e) => e.startsWith("v") ? e : `v${e}`);
|
|||
|
|
};
|
|||
|
|
const globalAgentPromise = getGlobalAgent();
|
|||
|
|
const globalAgentVersionPromise = globalAgentPromise.then(getV);
|
|||
|
|
const agentPromise = detect({ ...options, cwd }).then((a) => a || "");
|
|||
|
|
const agentVersionPromise = agentPromise.then((a) => a && getV(a));
|
|||
|
|
const nodeVersionPromise = getV("node");
|
|||
|
|
console.log(`@antfu/ni ${c.cyan(`v${version}`)}`);
|
|||
|
|
console.log(`node ${c.green(await nodeVersionPromise)}`);
|
|||
|
|
const [agent, agentVersion] = await Promise.all([agentPromise, agentVersionPromise]);
|
|||
|
|
if (agent)
|
|||
|
|
console.log(`${agent.padEnd(10)} ${c.blue(agentVersion)}`);
|
|||
|
|
else
|
|||
|
|
console.log("agent no lock file");
|
|||
|
|
const [globalAgent, globalAgentVersion] = await Promise.all([globalAgentPromise, globalAgentVersionPromise]);
|
|||
|
|
console.log(`${`${globalAgent} -g`.padEnd(10)} ${c.blue(globalAgentVersion)}`);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (args.length === 1 && ["-h", "--help"].includes(args[0])) {
|
|||
|
|
const dash = c.dim("-");
|
|||
|
|
console.log(c.green(c.bold("@antfu/ni")) + c.dim(` use the right package manager v${version}
|
|||
|
|
`));
|
|||
|
|
console.log(`ni ${dash} install`);
|
|||
|
|
console.log(`nr ${dash} run`);
|
|||
|
|
console.log(`nlx ${dash} execute`);
|
|||
|
|
console.log(`nu ${dash} upgrade`);
|
|||
|
|
console.log(`nun ${dash} uninstall`);
|
|||
|
|
console.log(`nci ${dash} clean install`);
|
|||
|
|
console.log(`na ${dash} agent alias`);
|
|||
|
|
console.log(`ni -v ${dash} show used agent`);
|
|||
|
|
console.log(`ni -i ${dash} interactive package management`);
|
|||
|
|
console.log(c.yellow("\ncheck https://github.com/antfu/ni for more documentation."));
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const command = await getCliCommand(fn, args, options, cwd);
|
|||
|
|
if (!command)
|
|||
|
|
return;
|
|||
|
|
if (detectVolta && cmdExists("volta")) {
|
|||
|
|
command.args = ["run", command.command, ...command.args];
|
|||
|
|
command.command = "volta";
|
|||
|
|
}
|
|||
|
|
if (debug) {
|
|||
|
|
console.log(command);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
await ve(
|
|||
|
|
command.command,
|
|||
|
|
command.args,
|
|||
|
|
{
|
|||
|
|
nodeOptions: {
|
|||
|
|
stdio: "inherit",
|
|||
|
|
cwd
|
|||
|
|
},
|
|||
|
|
throwOnError: true
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exports.AGENTS = AGENTS;
|
|||
|
|
exports.CLI_TEMP_DIR = CLI_TEMP_DIR;
|
|||
|
|
exports.COMMANDS = COMMANDS;
|
|||
|
|
exports.INSTALL_PAGE = INSTALL_PAGE;
|
|||
|
|
exports.LOCKS = LOCKS;
|
|||
|
|
exports.UnsupportedCommand = UnsupportedCommand;
|
|||
|
|
exports.c = c;
|
|||
|
|
exports.cmdExists = cmdExists;
|
|||
|
|
exports.constructCommand = constructCommand;
|
|||
|
|
exports.detect = detect;
|
|||
|
|
exports.exclude = exclude;
|
|||
|
|
exports.formatPackageWithUrl = formatPackageWithUrl;
|
|||
|
|
exports.getCliCommand = getCliCommand;
|
|||
|
|
exports.getCommand = getCommand;
|
|||
|
|
exports.getConfig = getConfig;
|
|||
|
|
exports.getDefaultAgent = getDefaultAgent;
|
|||
|
|
exports.getGlobalAgent = getGlobalAgent;
|
|||
|
|
exports.limitText = limitText;
|
|||
|
|
exports.parseNa = parseNa;
|
|||
|
|
exports.parseNi = parseNi;
|
|||
|
|
exports.parseNlx = parseNlx;
|
|||
|
|
exports.parseNr = parseNr;
|
|||
|
|
exports.parseNu = parseNu;
|
|||
|
|
exports.parseNun = parseNun;
|
|||
|
|
exports.prompts = prompts;
|
|||
|
|
exports.remove = remove;
|
|||
|
|
exports.resolveCommand = resolveCommand;
|
|||
|
|
exports.run = run;
|
|||
|
|
exports.runCli = runCli;
|
|||
|
|
exports.serializeCommand = serializeCommand;
|
|||
|
|
exports.writeFileSafe = writeFileSafe;
|