@retailcrm/embed-ui 0.9.22-alpha.2 → 0.9.22-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +4 -3
- package/bin/embed-ui.mjs +2338 -147
- package/package.json +7 -6
package/bin/embed-ui.mjs
CHANGED
|
@@ -4,9 +4,14 @@ import { execFileSync } from "node:child_process";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
|
-
import process$
|
|
7
|
+
import process$2 from "node:process";
|
|
8
8
|
import yargs from "yargs";
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
10
|
+
import * as readline$1 from "node:readline";
|
|
11
|
+
import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
|
|
12
|
+
import require$$0$1 from "stream";
|
|
13
|
+
import { styleText, stripVTControlCharacters } from "node:util";
|
|
14
|
+
import require$$0 from "tty";
|
|
10
15
|
const PACKAGE_MANAGERS = ["yarn", "npm", "pnpm", "bun"];
|
|
11
16
|
const HELP_TEXT = `Usage:
|
|
12
17
|
npx @retailcrm/embed-ui [target] [version] [options]
|
|
@@ -14,14 +19,15 @@ const HELP_TEXT = `Usage:
|
|
|
14
19
|
|
|
15
20
|
Options:
|
|
16
21
|
-t, --target <path> Target path (default: current directory)
|
|
17
|
-
-v, --version <ver> Target version.
|
|
22
|
+
-v, --version <ver> Target version. In init mode, defaults to the current CLI version
|
|
18
23
|
--exact Use exact version instead of range
|
|
19
24
|
--dry-run Show changes without writing package.json
|
|
20
25
|
--add Add selected embed-ui packages into one package.json
|
|
21
26
|
--packages <list> Comma-separated package ids or names for --add/init
|
|
22
27
|
--cwd <path> Project working directory for init
|
|
23
28
|
--package-manager Package manager for init installs
|
|
24
|
-
--interactive Ask init questions
|
|
29
|
+
--interactive Ask init questions with TTY selection prompts
|
|
30
|
+
--verbose Print detailed init change lists
|
|
25
31
|
--no-install Do not run package manager install in init mode
|
|
26
32
|
--no-configs Do not create root TypeScript, Vite, ESLint and env config files
|
|
27
33
|
--force-deps Replace incompatible existing init dependencies
|
|
@@ -59,7 +65,7 @@ const parseInitArgs = (argv) => {
|
|
|
59
65
|
"boolean-negation": true
|
|
60
66
|
}).option("cwd", {
|
|
61
67
|
type: "string",
|
|
62
|
-
default: process$
|
|
68
|
+
default: process$2.cwd(),
|
|
63
69
|
describe: "Project working directory"
|
|
64
70
|
}).option("help", {
|
|
65
71
|
alias: "h",
|
|
@@ -104,14 +110,14 @@ const parseInitArgs = (argv) => {
|
|
|
104
110
|
type: "string",
|
|
105
111
|
default: "order/card:common.after",
|
|
106
112
|
describe: "Starter widget target"
|
|
107
|
-
}).option("dry-run", { type: "boolean", default: false }).option("exact", { type: "boolean", default: false }).option("interactive", { type: "boolean", default: false }).option("install", { type: "boolean", default: true }).option("force", { type: "boolean", default: false }).option("force-deps", { type: "boolean", default: false }).option("fix-sections", { type: "boolean", default: false }).option("force-files", { type: "boolean", default: false }).option("configs", { type: "boolean", default: true }).option("dirs-enabled", { type: "boolean", default: true }).option("template-enabled", { type: "boolean", default: true }).option("agents", { type: "boolean", default: true }).option("force-agents", { type: "boolean", default: false }).option("agents-only", { type: "boolean", default: false }).option("mcp", { type: "boolean", default: true }).option("force-mcp", { type: "boolean", default: false }).option("mcp-client-configs", {
|
|
113
|
+
}).option("dry-run", { type: "boolean", default: false }).option("exact", { type: "boolean", default: false }).option("interactive", { type: "boolean", default: false }).option("verbose", { type: "boolean", default: false }).option("install", { type: "boolean", default: true }).option("force", { type: "boolean", default: false }).option("force-deps", { type: "boolean", default: false }).option("fix-sections", { type: "boolean", default: false }).option("force-files", { type: "boolean", default: false }).option("configs", { type: "boolean", default: true }).option("dirs-enabled", { type: "boolean", default: true }).option("template-enabled", { type: "boolean", default: true }).option("agents", { type: "boolean", default: true }).option("force-agents", { type: "boolean", default: false }).option("agents-only", { type: "boolean", default: false }).option("mcp", { type: "boolean", default: true }).option("force-mcp", { type: "boolean", default: false }).option("mcp-client-configs", {
|
|
108
114
|
type: "string",
|
|
109
115
|
coerce: parsePackageList,
|
|
110
116
|
describe: "Comma-separated MCP client config ids"
|
|
111
117
|
}).parseSync();
|
|
112
118
|
if (parsed.help || parsed.h) {
|
|
113
119
|
console.log(HELP_TEXT);
|
|
114
|
-
process$
|
|
120
|
+
process$2.exit(0);
|
|
115
121
|
}
|
|
116
122
|
const positionals = parsed._.map(String);
|
|
117
123
|
if (positionals.length > 1) {
|
|
@@ -122,7 +128,7 @@ const parseInitArgs = (argv) => {
|
|
|
122
128
|
}
|
|
123
129
|
return {
|
|
124
130
|
command: "init",
|
|
125
|
-
cwd: path.resolve(process$
|
|
131
|
+
cwd: path.resolve(process$2.cwd(), parsed.cwd),
|
|
126
132
|
target: parsed.target ?? positionals[0] ?? null,
|
|
127
133
|
version: parsed.version ?? null,
|
|
128
134
|
dryRun: parsed.dryRun,
|
|
@@ -131,6 +137,7 @@ const parseInitArgs = (argv) => {
|
|
|
131
137
|
with: parsed.with ?? null,
|
|
132
138
|
packageManager: parsed.packageManager ?? null,
|
|
133
139
|
interactive: parsed.interactive,
|
|
140
|
+
verbose: parsed.verbose,
|
|
134
141
|
noInstall: !parsed.install,
|
|
135
142
|
force: parsed.force,
|
|
136
143
|
forceDeps: parsed.forceDeps,
|
|
@@ -159,7 +166,7 @@ const parseArgs = (argv) => {
|
|
|
159
166
|
const parsed = yargs(argv).scriptName("embed-ui").usage("Usage: $0 [target] [version] [options]").help(false).version(false).exitProcess(false).strictOptions().option("target", {
|
|
160
167
|
alias: "t",
|
|
161
168
|
type: "string",
|
|
162
|
-
default: process$
|
|
169
|
+
default: process$2.cwd()
|
|
163
170
|
}).option("help", {
|
|
164
171
|
alias: "h",
|
|
165
172
|
type: "boolean"
|
|
@@ -173,7 +180,7 @@ const parseArgs = (argv) => {
|
|
|
173
180
|
}).parseSync();
|
|
174
181
|
if (parsed.help || parsed.h) {
|
|
175
182
|
console.log(HELP_TEXT);
|
|
176
|
-
process$
|
|
183
|
+
process$2.exit(0);
|
|
177
184
|
}
|
|
178
185
|
const positionals = parsed._.map(String);
|
|
179
186
|
if (positionals.length > 2) {
|
|
@@ -181,7 +188,7 @@ const parseArgs = (argv) => {
|
|
|
181
188
|
}
|
|
182
189
|
const options = {
|
|
183
190
|
command: "update",
|
|
184
|
-
target: path.resolve(process$
|
|
191
|
+
target: path.resolve(process$2.cwd(), parsed.target),
|
|
185
192
|
version: parsed.version ?? null,
|
|
186
193
|
dryRun: parsed.dryRun,
|
|
187
194
|
exact: parsed.exact,
|
|
@@ -193,7 +200,7 @@ const parseArgs = (argv) => {
|
|
|
193
200
|
if (!options.version && isSemverLike(first)) {
|
|
194
201
|
options.version = stripLeadingV(first);
|
|
195
202
|
} else {
|
|
196
|
-
options.target = path.resolve(process$
|
|
203
|
+
options.target = path.resolve(process$2.cwd(), first);
|
|
197
204
|
}
|
|
198
205
|
}
|
|
199
206
|
if (positionals.length === 2) {
|
|
@@ -291,6 +298,24 @@ const resolveLatestVersion = () => {
|
|
|
291
298
|
}
|
|
292
299
|
return output;
|
|
293
300
|
};
|
|
301
|
+
const resolveCurrentPackageVersion = (startPath = fileURLToPath(import.meta.url)) => {
|
|
302
|
+
let currentDir = fs.existsSync(startPath) && fs.statSync(startPath).isDirectory() ? startPath : path.dirname(startPath);
|
|
303
|
+
while (true) {
|
|
304
|
+
const packageJsonPath = path.join(currentDir, "package.json");
|
|
305
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
306
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
307
|
+
if (packageJson.name === ROOT_PACKAGE && typeof packageJson.version === "string") {
|
|
308
|
+
return packageJson.version;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const parentDir = path.dirname(currentDir);
|
|
312
|
+
if (parentDir === currentDir) {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
currentDir = parentDir;
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
const resolveDefaultInitVersion = () => resolveCurrentPackageVersion() ?? resolveLatestVersion();
|
|
294
319
|
const isTargetPackage = (name) => name === ROOT_PACKAGE || name.startsWith(`${ROOT_PACKAGE}-`);
|
|
295
320
|
const createRange = (version, exact) => exact ? version : `^${version}`;
|
|
296
321
|
const formatRange = (currentRange, nextVersion, exact) => {
|
|
@@ -391,7 +416,7 @@ const installPackages = (packageJson, packages, version, exact) => {
|
|
|
391
416
|
return updates;
|
|
392
417
|
};
|
|
393
418
|
const promptForInstallSelection = async (packageJson) => {
|
|
394
|
-
if (!process$
|
|
419
|
+
if (!process$2.stdin.isTTY || !process$2.stdout.isTTY) {
|
|
395
420
|
throw new Error("Interactive add mode requires a TTY. Use --packages to select packages explicitly.");
|
|
396
421
|
}
|
|
397
422
|
console.log("Выберите пакеты для установки в текущий package.json:");
|
|
@@ -401,13 +426,13 @@ const promptForInstallSelection = async (packageJson) => {
|
|
|
401
426
|
console.log(` ${index + 1}. ${selectedPackage.name} (${selectedPackage.id})`);
|
|
402
427
|
console.log(` ${selectedPackage.description} Раздел по умолчанию: ${selectedPackage.section}.${installedHint}`);
|
|
403
428
|
}
|
|
404
|
-
const
|
|
405
|
-
input: process$
|
|
406
|
-
output: process$
|
|
429
|
+
const readline2 = createInterface({
|
|
430
|
+
input: process$2.stdin,
|
|
431
|
+
output: process$2.stdout
|
|
407
432
|
});
|
|
408
433
|
try {
|
|
409
434
|
while (true) {
|
|
410
|
-
const answer = await
|
|
435
|
+
const answer = await readline2.question(
|
|
411
436
|
"Введите номера, ids или имена пакетов через запятую (например: 1,3 или components,types): "
|
|
412
437
|
);
|
|
413
438
|
const tokens = parsePackageList(answer);
|
|
@@ -422,21 +447,23 @@ const promptForInstallSelection = async (packageJson) => {
|
|
|
422
447
|
}
|
|
423
448
|
}
|
|
424
449
|
} finally {
|
|
425
|
-
|
|
450
|
+
readline2.close();
|
|
426
451
|
}
|
|
427
452
|
};
|
|
428
453
|
const DEFAULT_INDENT = " ";
|
|
429
454
|
const DEFAULT_NEWLINE = "\n";
|
|
430
455
|
const INIT_RUNTIME_DEPENDENCIES = [
|
|
431
456
|
{ name: "@omnicajs/vue-remote", range: "^0.2.23" },
|
|
457
|
+
{ name: "@remote-ui/rpc", range: "^1.4.7" },
|
|
432
458
|
{ name: "pinia", range: "^2.2" },
|
|
433
459
|
{ name: "vue", range: "^3.5" },
|
|
434
|
-
{ name: "vue-i18n", range: "^11" }
|
|
460
|
+
{ name: "vue-i18n", range: "^11" },
|
|
461
|
+
{ name: "zod", range: "^4.4" }
|
|
435
462
|
];
|
|
436
463
|
const INIT_DEV_DEPENDENCIES = [
|
|
437
464
|
{ name: "@eslint/js", range: "^9.39" },
|
|
438
|
-
{ name: "@intlify/eslint-plugin-vue-i18n", range: "
|
|
439
|
-
{ name: "@intlify/unplugin-vue-i18n", range: "^11.
|
|
465
|
+
{ name: "@intlify/eslint-plugin-vue-i18n", range: "^4.4" },
|
|
466
|
+
{ name: "@intlify/unplugin-vue-i18n", range: "^11.2" },
|
|
440
467
|
{ name: "@omnicajs/eslint-plugin-dependencies", range: "^0.0.2" },
|
|
441
468
|
{ name: "@types/node", range: "^22.19" },
|
|
442
469
|
{ name: "@vitejs/plugin-vue", range: "^6.0" },
|
|
@@ -444,12 +471,14 @@ const INIT_DEV_DEPENDENCIES = [
|
|
|
444
471
|
{ name: "eslint", range: "^9.39" },
|
|
445
472
|
{ name: "eslint-plugin-vue", range: "^10.9" },
|
|
446
473
|
{ name: "globals", range: "^16.5" },
|
|
474
|
+
{ name: "jsonc-eslint-parser", range: "^3.1" },
|
|
447
475
|
{ name: "less", range: "^4.6" },
|
|
448
476
|
{ name: "typescript", range: "^5.9" },
|
|
449
477
|
{ name: "typescript-eslint", range: "^8.59" },
|
|
450
478
|
{ name: "vite", range: "^7.3" },
|
|
451
479
|
{ name: "vite-svg-loader", range: "^5.1" },
|
|
452
|
-
{ name: "vue-eslint-parser", range: "^10.4" }
|
|
480
|
+
{ name: "vue-eslint-parser", range: "^10.4" },
|
|
481
|
+
{ name: "yaml-eslint-parser", range: "^2.0" }
|
|
453
482
|
];
|
|
454
483
|
const I18N_RUNTIME_DEPENDENCY = "vue-i18n";
|
|
455
484
|
const hasExistingDependency = (packageJson, name) => findDependencySection(packageJson, name) !== null;
|
|
@@ -586,18 +615,44 @@ const resolveLocalBinPath = (cwd, binName) => {
|
|
|
586
615
|
return fs.existsSync(binPath) ? binPath : null;
|
|
587
616
|
};
|
|
588
617
|
const hasLocalPackage = (cwd, packageName) => fs.existsSync(path.join(cwd, "node_modules", packageName, "package.json"));
|
|
589
|
-
const
|
|
618
|
+
const createPackageSpec = (packageName, version) => version && version !== "not used" ? `${packageName}@${version}` : packageName;
|
|
619
|
+
const resolvePackageManagerVersion$1 = (packageManager) => {
|
|
620
|
+
try {
|
|
621
|
+
return execFileSync(packageManager, ["--version"], {
|
|
622
|
+
encoding: "utf8",
|
|
623
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
624
|
+
}).trim();
|
|
625
|
+
} catch {
|
|
626
|
+
return null;
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
const resolveMajorVersion = (version) => {
|
|
630
|
+
const major = version?.match(/^\d+/u)?.[0];
|
|
631
|
+
return major ? Number(major) : null;
|
|
632
|
+
};
|
|
633
|
+
const resolveDownloadCommand = (packageName, binName, packageManager, args, packageVersion, versionResolver) => {
|
|
634
|
+
const packageSpec = createPackageSpec(packageName, packageVersion);
|
|
590
635
|
if (packageManager === "yarn") {
|
|
591
|
-
const
|
|
636
|
+
const yarnMajor = resolveMajorVersion(versionResolver("yarn"));
|
|
637
|
+
if (yarnMajor !== null && yarnMajor >= 2) {
|
|
638
|
+
const commandArgs3 = ["dlx", "-p", packageSpec, binName, ...args];
|
|
639
|
+
return {
|
|
640
|
+
command: "yarn",
|
|
641
|
+
args: commandArgs3,
|
|
642
|
+
display: `yarn ${commandArgs3.join(" ")}`,
|
|
643
|
+
source: "transient"
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
const commandArgs2 = ["-y", "--loglevel=error", "-p", packageSpec, binName, ...args];
|
|
592
647
|
return {
|
|
593
|
-
command: "
|
|
648
|
+
command: "npx",
|
|
594
649
|
args: commandArgs2,
|
|
595
|
-
display: `
|
|
650
|
+
display: `npx ${commandArgs2.join(" ")}`,
|
|
596
651
|
source: "transient"
|
|
597
652
|
};
|
|
598
653
|
}
|
|
599
654
|
if (packageManager === "pnpm") {
|
|
600
|
-
const commandArgs2 = ["dlx", "--package",
|
|
655
|
+
const commandArgs2 = ["dlx", "--package", packageSpec, binName, ...args];
|
|
601
656
|
return {
|
|
602
657
|
command: "pnpm",
|
|
603
658
|
args: commandArgs2,
|
|
@@ -606,7 +661,7 @@ const resolveDownloadCommand = (packageName, binName, packageManager, args) => {
|
|
|
606
661
|
};
|
|
607
662
|
}
|
|
608
663
|
if (packageManager === "bun") {
|
|
609
|
-
const commandArgs2 = ["x", "--package",
|
|
664
|
+
const commandArgs2 = ["x", "--package", packageSpec, binName, ...args];
|
|
610
665
|
return {
|
|
611
666
|
command: "bun",
|
|
612
667
|
args: commandArgs2,
|
|
@@ -614,7 +669,7 @@ const resolveDownloadCommand = (packageName, binName, packageManager, args) => {
|
|
|
614
669
|
source: "transient"
|
|
615
670
|
};
|
|
616
671
|
}
|
|
617
|
-
const commandArgs = ["exec", "--yes", "--package",
|
|
672
|
+
const commandArgs = ["exec", "--yes", "--loglevel=error", "--package", packageSpec, "--", binName, ...args];
|
|
618
673
|
return {
|
|
619
674
|
command: "npm",
|
|
620
675
|
args: commandArgs,
|
|
@@ -622,7 +677,7 @@ const resolveDownloadCommand = (packageName, binName, packageManager, args) => {
|
|
|
622
677
|
source: "transient"
|
|
623
678
|
};
|
|
624
679
|
};
|
|
625
|
-
const resolvePackageHookCommand = (cwd, packageName, binName, packageManager, args) => {
|
|
680
|
+
const resolvePackageHookCommand = (cwd, packageName, binName, packageManager, args, packageVersion = null, versionResolver = resolvePackageManagerVersion$1) => {
|
|
626
681
|
const localBinPath = resolveLocalBinPath(cwd, binName);
|
|
627
682
|
if (localBinPath) {
|
|
628
683
|
return {
|
|
@@ -637,16 +692,32 @@ const resolvePackageHookCommand = (cwd, packageName, binName, packageManager, ar
|
|
|
637
692
|
`${packageName} is installed, but ${binName} was not found in node_modules/.bin. Reinstall dependencies or check the package bin metadata.`
|
|
638
693
|
);
|
|
639
694
|
}
|
|
640
|
-
return resolveDownloadCommand(packageName, binName, packageManager, args);
|
|
695
|
+
return resolveDownloadCommand(packageName, binName, packageManager, args, packageVersion, versionResolver);
|
|
641
696
|
};
|
|
642
697
|
const getExecErrorMessage = (error) => {
|
|
698
|
+
if (error && typeof error === "object") {
|
|
699
|
+
const output = [
|
|
700
|
+
"stderr" in error ? error.stderr : null,
|
|
701
|
+
"stdout" in error ? error.stdout : null
|
|
702
|
+
].map((value) => value instanceof Buffer ? value.toString("utf8") : value).filter((value) => typeof value === "string" && value.trim().length > 0).map((value) => value.trim()).join("\n");
|
|
703
|
+
if (output) {
|
|
704
|
+
return output;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
643
707
|
if (error instanceof Error && error.message) {
|
|
644
708
|
return error.message;
|
|
645
709
|
}
|
|
646
710
|
return String(error);
|
|
647
711
|
};
|
|
648
712
|
const runPackageHookCommand = (cwd, packageName, binName, packageManager, args, failureMode, options, changes) => {
|
|
649
|
-
const command = resolvePackageHookCommand(
|
|
713
|
+
const command = resolvePackageHookCommand(
|
|
714
|
+
cwd,
|
|
715
|
+
packageName,
|
|
716
|
+
binName,
|
|
717
|
+
packageManager,
|
|
718
|
+
args,
|
|
719
|
+
options.version
|
|
720
|
+
);
|
|
650
721
|
changes.hooks.push(command.display);
|
|
651
722
|
if (options.dryRun) {
|
|
652
723
|
return;
|
|
@@ -654,7 +725,7 @@ const runPackageHookCommand = (cwd, packageName, binName, packageManager, args,
|
|
|
654
725
|
try {
|
|
655
726
|
execFileSync(command.command, command.args, {
|
|
656
727
|
cwd,
|
|
657
|
-
stdio: "
|
|
728
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
658
729
|
});
|
|
659
730
|
} catch (error) {
|
|
660
731
|
if (command.source === "transient" && failureMode === "advisory") {
|
|
@@ -2150,6 +2221,10 @@ const printChanges = (changes) => {
|
|
|
2150
2221
|
}
|
|
2151
2222
|
};
|
|
2152
2223
|
const printInitReport = (cwd, sourceRoot, version, packageManager, changes, options) => {
|
|
2224
|
+
if (!options.verbose && !options.dryRun) {
|
|
2225
|
+
printInitSummary(cwd, sourceRoot, version, packageManager, changes);
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2153
2228
|
console.log(`CWD: ${cwd}`);
|
|
2154
2229
|
console.log(`Target: ${sourceRoot}`);
|
|
2155
2230
|
console.log(`Resolved version: ${version}`);
|
|
@@ -2225,124 +2300,2202 @@ const printInitReport = (cwd, sourceRoot, version, packageManager, changes, opti
|
|
|
2225
2300
|
console.log("Dry run enabled, no files were modified.");
|
|
2226
2301
|
}
|
|
2227
2302
|
};
|
|
2228
|
-
const
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2303
|
+
const printInitSummary = (cwd, sourceRoot, version, packageManager, changes) => {
|
|
2304
|
+
console.log(`Initialized ${cwd}`);
|
|
2305
|
+
console.log(` source root: ${sourceRoot}`);
|
|
2306
|
+
console.log(` version: ${version}`);
|
|
2307
|
+
console.log(` package manager: ${packageManager}`);
|
|
2308
|
+
const summary = [
|
|
2309
|
+
changes.packageJson.length ? `package.json updated (${changes.packageJson.length} change(s))` : null,
|
|
2310
|
+
changes.directories.length ? `directories created: ${changes.directories.length}` : null,
|
|
2311
|
+
changes.files.length ? `files created: ${changes.files.length}` : null,
|
|
2312
|
+
changes.agents.length ? "AGENTS.md updated" : null,
|
|
2313
|
+
changes.mcp.length ? "MCP config updated" : null,
|
|
2314
|
+
changes.hooks.length ? `package hooks ran: ${changes.hooks.length}` : null,
|
|
2315
|
+
changes.install ? `install: ${changes.install}` : null
|
|
2316
|
+
].filter((item) => typeof item === "string");
|
|
2317
|
+
if (summary.length > 0) {
|
|
2318
|
+
console.log("");
|
|
2319
|
+
console.log("changes");
|
|
2320
|
+
for (const item of summary) {
|
|
2321
|
+
console.log(` ${item}`);
|
|
2322
|
+
}
|
|
2232
2323
|
}
|
|
2233
|
-
if (
|
|
2234
|
-
|
|
2324
|
+
if (changes.skipped.length > 0) {
|
|
2325
|
+
console.log("");
|
|
2326
|
+
console.log("skipped");
|
|
2327
|
+
for (const skipped of changes.skipped) {
|
|
2328
|
+
console.log(` ${skipped}`);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
if (changes.warnings.length > 0) {
|
|
2332
|
+
console.log("");
|
|
2333
|
+
console.log("warnings");
|
|
2334
|
+
for (const warning of new Set(changes.warnings)) {
|
|
2335
|
+
console.log(` ${warning}`);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
};
|
|
2339
|
+
const isUpKey = (key, keybindings = []) => (
|
|
2340
|
+
// The up key
|
|
2341
|
+
key.name === "up" || // Vim keybinding: hjkl keys map to left/down/up/right
|
|
2342
|
+
keybindings.includes("vim") && key.name === "k" || // Emacs keybinding: Ctrl+P means "previous" in Emacs navigation conventions
|
|
2343
|
+
keybindings.includes("emacs") && key.ctrl && key.name === "p"
|
|
2344
|
+
);
|
|
2345
|
+
const isDownKey = (key, keybindings = []) => (
|
|
2346
|
+
// The down key
|
|
2347
|
+
key.name === "down" || // Vim keybinding: hjkl keys map to left/down/up/right
|
|
2348
|
+
keybindings.includes("vim") && key.name === "j" || // Emacs keybinding: Ctrl+N means "next" in Emacs navigation conventions
|
|
2349
|
+
keybindings.includes("emacs") && key.ctrl && key.name === "n"
|
|
2350
|
+
);
|
|
2351
|
+
const isSpaceKey = (key) => key.name === "space";
|
|
2352
|
+
const isBackspaceKey = (key) => key.name === "backspace";
|
|
2353
|
+
const isTabKey = (key) => key.name === "tab";
|
|
2354
|
+
const isNumberKey = (key) => "1234567890".includes(key.name);
|
|
2355
|
+
const isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
2356
|
+
class AbortPromptError extends Error {
|
|
2357
|
+
name = "AbortPromptError";
|
|
2358
|
+
message = "Prompt was aborted";
|
|
2359
|
+
constructor(options) {
|
|
2360
|
+
super();
|
|
2361
|
+
this.cause = options?.cause;
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
class CancelPromptError extends Error {
|
|
2365
|
+
name = "CancelPromptError";
|
|
2366
|
+
message = "Prompt was canceled";
|
|
2367
|
+
}
|
|
2368
|
+
class ExitPromptError extends Error {
|
|
2369
|
+
name = "ExitPromptError";
|
|
2370
|
+
}
|
|
2371
|
+
class HookError extends Error {
|
|
2372
|
+
name = "HookError";
|
|
2373
|
+
}
|
|
2374
|
+
class ValidationError extends Error {
|
|
2375
|
+
name = "ValidationError";
|
|
2376
|
+
}
|
|
2377
|
+
const hookStorage = new AsyncLocalStorage();
|
|
2378
|
+
function createStore(rl) {
|
|
2379
|
+
const store = {
|
|
2380
|
+
rl,
|
|
2381
|
+
hooks: [],
|
|
2382
|
+
hooksCleanup: [],
|
|
2383
|
+
hooksEffect: [],
|
|
2384
|
+
index: 0,
|
|
2385
|
+
handleChange() {
|
|
2386
|
+
}
|
|
2387
|
+
};
|
|
2388
|
+
return store;
|
|
2389
|
+
}
|
|
2390
|
+
function withHooks(rl, cb) {
|
|
2391
|
+
const store = createStore(rl);
|
|
2392
|
+
return hookStorage.run(store, () => {
|
|
2393
|
+
function cycle(render) {
|
|
2394
|
+
store.handleChange = () => {
|
|
2395
|
+
store.index = 0;
|
|
2396
|
+
render();
|
|
2397
|
+
};
|
|
2398
|
+
store.handleChange();
|
|
2399
|
+
}
|
|
2400
|
+
return cb(cycle);
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
function getStore() {
|
|
2404
|
+
const store = hookStorage.getStore();
|
|
2405
|
+
if (!store) {
|
|
2406
|
+
throw new HookError("[Inquirer] Hook functions can only be called from within a prompt");
|
|
2407
|
+
}
|
|
2408
|
+
return store;
|
|
2409
|
+
}
|
|
2410
|
+
function readline() {
|
|
2411
|
+
return getStore().rl;
|
|
2412
|
+
}
|
|
2413
|
+
function withUpdates(fn) {
|
|
2414
|
+
const wrapped = (...args) => {
|
|
2415
|
+
const store = getStore();
|
|
2416
|
+
let shouldUpdate = false;
|
|
2417
|
+
const oldHandleChange = store.handleChange;
|
|
2418
|
+
store.handleChange = () => {
|
|
2419
|
+
shouldUpdate = true;
|
|
2420
|
+
};
|
|
2421
|
+
const returnValue = fn(...args);
|
|
2422
|
+
if (shouldUpdate) {
|
|
2423
|
+
oldHandleChange();
|
|
2424
|
+
}
|
|
2425
|
+
store.handleChange = oldHandleChange;
|
|
2426
|
+
return returnValue;
|
|
2427
|
+
};
|
|
2428
|
+
return AsyncResource.bind(wrapped);
|
|
2429
|
+
}
|
|
2430
|
+
function withPointer(cb) {
|
|
2431
|
+
const store = getStore();
|
|
2432
|
+
const { index } = store;
|
|
2433
|
+
const pointer = {
|
|
2434
|
+
get() {
|
|
2435
|
+
return store.hooks[index];
|
|
2436
|
+
},
|
|
2437
|
+
set(value) {
|
|
2438
|
+
store.hooks[index] = value;
|
|
2439
|
+
},
|
|
2440
|
+
initialized: index in store.hooks
|
|
2441
|
+
};
|
|
2442
|
+
const returnValue = cb(pointer);
|
|
2443
|
+
store.index++;
|
|
2444
|
+
return returnValue;
|
|
2445
|
+
}
|
|
2446
|
+
function handleChange() {
|
|
2447
|
+
getStore().handleChange();
|
|
2448
|
+
}
|
|
2449
|
+
const effectScheduler = {
|
|
2450
|
+
queue(cb) {
|
|
2451
|
+
const store = getStore();
|
|
2452
|
+
const { index } = store;
|
|
2453
|
+
store.hooksEffect.push(() => {
|
|
2454
|
+
store.hooksCleanup[index]?.();
|
|
2455
|
+
const cleanFn = cb(readline());
|
|
2456
|
+
if (cleanFn != null && typeof cleanFn !== "function") {
|
|
2457
|
+
throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
|
|
2458
|
+
}
|
|
2459
|
+
store.hooksCleanup[index] = cleanFn;
|
|
2460
|
+
});
|
|
2461
|
+
},
|
|
2462
|
+
run() {
|
|
2463
|
+
const store = getStore();
|
|
2464
|
+
withUpdates(() => {
|
|
2465
|
+
store.hooksEffect.forEach((effect) => {
|
|
2466
|
+
effect();
|
|
2467
|
+
});
|
|
2468
|
+
store.hooksEffect.length = 0;
|
|
2469
|
+
})();
|
|
2470
|
+
},
|
|
2471
|
+
clearAll() {
|
|
2472
|
+
const store = getStore();
|
|
2473
|
+
store.hooksCleanup.forEach((cleanFn) => {
|
|
2474
|
+
cleanFn?.();
|
|
2475
|
+
});
|
|
2476
|
+
store.hooksEffect.length = 0;
|
|
2477
|
+
store.hooksCleanup.length = 0;
|
|
2235
2478
|
}
|
|
2236
|
-
return fs.existsSync(path.join(cwd, "src")) ? "./web" : "./src";
|
|
2237
2479
|
};
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2480
|
+
function isFactory(value) {
|
|
2481
|
+
return typeof value === "function";
|
|
2482
|
+
}
|
|
2483
|
+
function useState(defaultValue) {
|
|
2484
|
+
return withPointer((pointer) => {
|
|
2485
|
+
const setState = AsyncResource.bind(function setState2(newValue) {
|
|
2486
|
+
if (pointer.get() !== newValue) {
|
|
2487
|
+
pointer.set(newValue);
|
|
2488
|
+
handleChange();
|
|
2489
|
+
}
|
|
2490
|
+
});
|
|
2491
|
+
if (pointer.initialized) {
|
|
2492
|
+
return [pointer.get(), setState];
|
|
2493
|
+
}
|
|
2494
|
+
const value = isFactory(defaultValue) ? defaultValue() : defaultValue;
|
|
2495
|
+
pointer.set(value);
|
|
2496
|
+
return [value, setState];
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2499
|
+
function useEffect(cb, depArray) {
|
|
2500
|
+
withPointer((pointer) => {
|
|
2501
|
+
const oldDeps = pointer.get();
|
|
2502
|
+
const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
|
|
2503
|
+
if (hasChanged) {
|
|
2504
|
+
effectScheduler.queue(cb);
|
|
2505
|
+
}
|
|
2506
|
+
pointer.set(depArray);
|
|
2507
|
+
});
|
|
2508
|
+
}
|
|
2509
|
+
function isUnicodeSupported() {
|
|
2510
|
+
if (!process$2.platform.startsWith("win")) {
|
|
2511
|
+
return process$2.env["TERM"] !== "linux";
|
|
2512
|
+
}
|
|
2513
|
+
return Boolean(process$2.env["CI"]) || // CI environments generally support unicode
|
|
2514
|
+
Boolean(process$2.env["WT_SESSION"]) || // Windows Terminal
|
|
2515
|
+
Boolean(process$2.env["TERMINUS_SUBLIME"]) || // Terminus (<0.2.27)
|
|
2516
|
+
process$2.env["ConEmuTask"] === "{cmd::Cmder}" || // ConEmu and cmder
|
|
2517
|
+
process$2.env["TERM_PROGRAM"] === "Terminus-Sublime" || process$2.env["TERM_PROGRAM"] === "vscode" || process$2.env["TERM"] === "xterm-256color" || process$2.env["TERM"] === "alacritty" || process$2.env["TERMINAL_EMULATOR"] === "JetBrains-JediTerm";
|
|
2518
|
+
}
|
|
2519
|
+
const common = {
|
|
2520
|
+
circleQuestionMark: "(?)",
|
|
2521
|
+
questionMarkPrefix: "(?)",
|
|
2522
|
+
square: "█",
|
|
2523
|
+
squareDarkShade: "▓",
|
|
2524
|
+
squareMediumShade: "▒",
|
|
2525
|
+
squareLightShade: "░",
|
|
2526
|
+
squareTop: "▀",
|
|
2527
|
+
squareBottom: "▄",
|
|
2528
|
+
squareLeft: "▌",
|
|
2529
|
+
squareRight: "▐",
|
|
2530
|
+
squareCenter: "■",
|
|
2531
|
+
bullet: "●",
|
|
2532
|
+
dot: "․",
|
|
2533
|
+
ellipsis: "…",
|
|
2534
|
+
pointerSmall: "›",
|
|
2535
|
+
triangleUp: "▲",
|
|
2536
|
+
triangleUpSmall: "▴",
|
|
2537
|
+
triangleDown: "▼",
|
|
2538
|
+
triangleDownSmall: "▾",
|
|
2539
|
+
triangleLeftSmall: "◂",
|
|
2540
|
+
triangleRightSmall: "▸",
|
|
2541
|
+
home: "⌂",
|
|
2542
|
+
heart: "♥",
|
|
2543
|
+
musicNote: "♪",
|
|
2544
|
+
musicNoteBeamed: "♫",
|
|
2545
|
+
arrowUp: "↑",
|
|
2546
|
+
arrowDown: "↓",
|
|
2547
|
+
arrowLeft: "←",
|
|
2548
|
+
arrowRight: "→",
|
|
2549
|
+
arrowLeftRight: "↔",
|
|
2550
|
+
arrowUpDown: "↕",
|
|
2551
|
+
almostEqual: "≈",
|
|
2552
|
+
notEqual: "≠",
|
|
2553
|
+
lessOrEqual: "≤",
|
|
2554
|
+
greaterOrEqual: "≥",
|
|
2555
|
+
identical: "≡",
|
|
2556
|
+
infinity: "∞",
|
|
2557
|
+
subscriptZero: "₀",
|
|
2558
|
+
subscriptOne: "₁",
|
|
2559
|
+
subscriptTwo: "₂",
|
|
2560
|
+
subscriptThree: "₃",
|
|
2561
|
+
subscriptFour: "₄",
|
|
2562
|
+
subscriptFive: "₅",
|
|
2563
|
+
subscriptSix: "₆",
|
|
2564
|
+
subscriptSeven: "₇",
|
|
2565
|
+
subscriptEight: "₈",
|
|
2566
|
+
subscriptNine: "₉",
|
|
2567
|
+
oneHalf: "½",
|
|
2568
|
+
oneThird: "⅓",
|
|
2569
|
+
oneQuarter: "¼",
|
|
2570
|
+
oneFifth: "⅕",
|
|
2571
|
+
oneSixth: "⅙",
|
|
2572
|
+
oneEighth: "⅛",
|
|
2573
|
+
twoThirds: "⅔",
|
|
2574
|
+
twoFifths: "⅖",
|
|
2575
|
+
threeQuarters: "¾",
|
|
2576
|
+
threeFifths: "⅗",
|
|
2577
|
+
threeEighths: "⅜",
|
|
2578
|
+
fourFifths: "⅘",
|
|
2579
|
+
fiveSixths: "⅚",
|
|
2580
|
+
fiveEighths: "⅝",
|
|
2581
|
+
sevenEighths: "⅞",
|
|
2582
|
+
line: "─",
|
|
2583
|
+
lineBold: "━",
|
|
2584
|
+
lineDouble: "═",
|
|
2585
|
+
lineDashed0: "┄",
|
|
2586
|
+
lineDashed1: "┅",
|
|
2587
|
+
lineDashed2: "┈",
|
|
2588
|
+
lineDashed3: "┉",
|
|
2589
|
+
lineDashed4: "╌",
|
|
2590
|
+
lineDashed5: "╍",
|
|
2591
|
+
lineDashed6: "╴",
|
|
2592
|
+
lineDashed7: "╶",
|
|
2593
|
+
lineDashed8: "╸",
|
|
2594
|
+
lineDashed9: "╺",
|
|
2595
|
+
lineDashed10: "╼",
|
|
2596
|
+
lineDashed11: "╾",
|
|
2597
|
+
lineDashed12: "−",
|
|
2598
|
+
lineDashed13: "–",
|
|
2599
|
+
lineDashed14: "‐",
|
|
2600
|
+
lineDashed15: "⁃",
|
|
2601
|
+
lineVertical: "│",
|
|
2602
|
+
lineVerticalBold: "┃",
|
|
2603
|
+
lineVerticalDouble: "║",
|
|
2604
|
+
lineVerticalDashed0: "┆",
|
|
2605
|
+
lineVerticalDashed1: "┇",
|
|
2606
|
+
lineVerticalDashed2: "┊",
|
|
2607
|
+
lineVerticalDashed3: "┋",
|
|
2608
|
+
lineVerticalDashed4: "╎",
|
|
2609
|
+
lineVerticalDashed5: "╏",
|
|
2610
|
+
lineVerticalDashed6: "╵",
|
|
2611
|
+
lineVerticalDashed7: "╷",
|
|
2612
|
+
lineVerticalDashed8: "╹",
|
|
2613
|
+
lineVerticalDashed9: "╻",
|
|
2614
|
+
lineVerticalDashed10: "╽",
|
|
2615
|
+
lineVerticalDashed11: "╿",
|
|
2616
|
+
lineDownLeft: "┐",
|
|
2617
|
+
lineDownLeftArc: "╮",
|
|
2618
|
+
lineDownBoldLeftBold: "┓",
|
|
2619
|
+
lineDownBoldLeft: "┒",
|
|
2620
|
+
lineDownLeftBold: "┑",
|
|
2621
|
+
lineDownDoubleLeftDouble: "╗",
|
|
2622
|
+
lineDownDoubleLeft: "╖",
|
|
2623
|
+
lineDownLeftDouble: "╕",
|
|
2624
|
+
lineDownRight: "┌",
|
|
2625
|
+
lineDownRightArc: "╭",
|
|
2626
|
+
lineDownBoldRightBold: "┏",
|
|
2627
|
+
lineDownBoldRight: "┎",
|
|
2628
|
+
lineDownRightBold: "┍",
|
|
2629
|
+
lineDownDoubleRightDouble: "╔",
|
|
2630
|
+
lineDownDoubleRight: "╓",
|
|
2631
|
+
lineDownRightDouble: "╒",
|
|
2632
|
+
lineUpLeft: "┘",
|
|
2633
|
+
lineUpLeftArc: "╯",
|
|
2634
|
+
lineUpBoldLeftBold: "┛",
|
|
2635
|
+
lineUpBoldLeft: "┚",
|
|
2636
|
+
lineUpLeftBold: "┙",
|
|
2637
|
+
lineUpDoubleLeftDouble: "╝",
|
|
2638
|
+
lineUpDoubleLeft: "╜",
|
|
2639
|
+
lineUpLeftDouble: "╛",
|
|
2640
|
+
lineUpRight: "└",
|
|
2641
|
+
lineUpRightArc: "╰",
|
|
2642
|
+
lineUpBoldRightBold: "┗",
|
|
2643
|
+
lineUpBoldRight: "┖",
|
|
2644
|
+
lineUpRightBold: "┕",
|
|
2645
|
+
lineUpDoubleRightDouble: "╚",
|
|
2646
|
+
lineUpDoubleRight: "╙",
|
|
2647
|
+
lineUpRightDouble: "╘",
|
|
2648
|
+
lineUpDownLeft: "┤",
|
|
2649
|
+
lineUpBoldDownBoldLeftBold: "┫",
|
|
2650
|
+
lineUpBoldDownBoldLeft: "┨",
|
|
2651
|
+
lineUpDownLeftBold: "┥",
|
|
2652
|
+
lineUpBoldDownLeftBold: "┩",
|
|
2653
|
+
lineUpDownBoldLeftBold: "┪",
|
|
2654
|
+
lineUpDownBoldLeft: "┧",
|
|
2655
|
+
lineUpBoldDownLeft: "┦",
|
|
2656
|
+
lineUpDoubleDownDoubleLeftDouble: "╣",
|
|
2657
|
+
lineUpDoubleDownDoubleLeft: "╢",
|
|
2658
|
+
lineUpDownLeftDouble: "╡",
|
|
2659
|
+
lineUpDownRight: "├",
|
|
2660
|
+
lineUpBoldDownBoldRightBold: "┣",
|
|
2661
|
+
lineUpBoldDownBoldRight: "┠",
|
|
2662
|
+
lineUpDownRightBold: "┝",
|
|
2663
|
+
lineUpBoldDownRightBold: "┡",
|
|
2664
|
+
lineUpDownBoldRightBold: "┢",
|
|
2665
|
+
lineUpDownBoldRight: "┟",
|
|
2666
|
+
lineUpBoldDownRight: "┞",
|
|
2667
|
+
lineUpDoubleDownDoubleRightDouble: "╠",
|
|
2668
|
+
lineUpDoubleDownDoubleRight: "╟",
|
|
2669
|
+
lineUpDownRightDouble: "╞",
|
|
2670
|
+
lineDownLeftRight: "┬",
|
|
2671
|
+
lineDownBoldLeftBoldRightBold: "┳",
|
|
2672
|
+
lineDownLeftBoldRightBold: "┯",
|
|
2673
|
+
lineDownBoldLeftRight: "┰",
|
|
2674
|
+
lineDownBoldLeftBoldRight: "┱",
|
|
2675
|
+
lineDownBoldLeftRightBold: "┲",
|
|
2676
|
+
lineDownLeftRightBold: "┮",
|
|
2677
|
+
lineDownLeftBoldRight: "┭",
|
|
2678
|
+
lineDownDoubleLeftDoubleRightDouble: "╦",
|
|
2679
|
+
lineDownDoubleLeftRight: "╥",
|
|
2680
|
+
lineDownLeftDoubleRightDouble: "╤",
|
|
2681
|
+
lineUpLeftRight: "┴",
|
|
2682
|
+
lineUpBoldLeftBoldRightBold: "┻",
|
|
2683
|
+
lineUpLeftBoldRightBold: "┷",
|
|
2684
|
+
lineUpBoldLeftRight: "┸",
|
|
2685
|
+
lineUpBoldLeftBoldRight: "┹",
|
|
2686
|
+
lineUpBoldLeftRightBold: "┺",
|
|
2687
|
+
lineUpLeftRightBold: "┶",
|
|
2688
|
+
lineUpLeftBoldRight: "┵",
|
|
2689
|
+
lineUpDoubleLeftDoubleRightDouble: "╩",
|
|
2690
|
+
lineUpDoubleLeftRight: "╨",
|
|
2691
|
+
lineUpLeftDoubleRightDouble: "╧",
|
|
2692
|
+
lineUpDownLeftRight: "┼",
|
|
2693
|
+
lineUpBoldDownBoldLeftBoldRightBold: "╋",
|
|
2694
|
+
lineUpDownBoldLeftBoldRightBold: "╈",
|
|
2695
|
+
lineUpBoldDownLeftBoldRightBold: "╇",
|
|
2696
|
+
lineUpBoldDownBoldLeftRightBold: "╊",
|
|
2697
|
+
lineUpBoldDownBoldLeftBoldRight: "╉",
|
|
2698
|
+
lineUpBoldDownLeftRight: "╀",
|
|
2699
|
+
lineUpDownBoldLeftRight: "╁",
|
|
2700
|
+
lineUpDownLeftBoldRight: "┽",
|
|
2701
|
+
lineUpDownLeftRightBold: "┾",
|
|
2702
|
+
lineUpBoldDownBoldLeftRight: "╂",
|
|
2703
|
+
lineUpDownLeftBoldRightBold: "┿",
|
|
2704
|
+
lineUpBoldDownLeftBoldRight: "╃",
|
|
2705
|
+
lineUpBoldDownLeftRightBold: "╄",
|
|
2706
|
+
lineUpDownBoldLeftBoldRight: "╅",
|
|
2707
|
+
lineUpDownBoldLeftRightBold: "╆",
|
|
2708
|
+
lineUpDoubleDownDoubleLeftDoubleRightDouble: "╬",
|
|
2709
|
+
lineUpDoubleDownDoubleLeftRight: "╫",
|
|
2710
|
+
lineUpDownLeftDoubleRightDouble: "╪",
|
|
2711
|
+
lineCross: "╳",
|
|
2712
|
+
lineBackslash: "╲",
|
|
2713
|
+
lineSlash: "╱"
|
|
2241
2714
|
};
|
|
2242
|
-
const
|
|
2243
|
-
|
|
2244
|
-
|
|
2715
|
+
const specialMainSymbols = {
|
|
2716
|
+
tick: "✔",
|
|
2717
|
+
info: "ℹ",
|
|
2718
|
+
warning: "⚠",
|
|
2719
|
+
cross: "✘",
|
|
2720
|
+
squareSmall: "◻",
|
|
2721
|
+
squareSmallFilled: "◼",
|
|
2722
|
+
circle: "◯",
|
|
2723
|
+
circleFilled: "◉",
|
|
2724
|
+
circleDotted: "◌",
|
|
2725
|
+
circleDouble: "◎",
|
|
2726
|
+
circleCircle: "ⓞ",
|
|
2727
|
+
circleCross: "ⓧ",
|
|
2728
|
+
circlePipe: "Ⓘ",
|
|
2729
|
+
radioOn: "◉",
|
|
2730
|
+
radioOff: "◯",
|
|
2731
|
+
checkboxOn: "☒",
|
|
2732
|
+
checkboxOff: "☐",
|
|
2733
|
+
checkboxCircleOn: "ⓧ",
|
|
2734
|
+
checkboxCircleOff: "Ⓘ",
|
|
2735
|
+
pointer: "❯",
|
|
2736
|
+
triangleUpOutline: "△",
|
|
2737
|
+
triangleLeft: "◀",
|
|
2738
|
+
triangleRight: "▶",
|
|
2739
|
+
lozenge: "◆",
|
|
2740
|
+
lozengeOutline: "◇",
|
|
2741
|
+
hamburger: "☰",
|
|
2742
|
+
smiley: "㋡",
|
|
2743
|
+
mustache: "෴",
|
|
2744
|
+
star: "★",
|
|
2745
|
+
play: "▶",
|
|
2746
|
+
nodejs: "⬢",
|
|
2747
|
+
oneSeventh: "⅐",
|
|
2748
|
+
oneNinth: "⅑",
|
|
2749
|
+
oneTenth: "⅒"
|
|
2245
2750
|
};
|
|
2246
|
-
const
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2751
|
+
const specialFallbackSymbols = {
|
|
2752
|
+
tick: "√",
|
|
2753
|
+
info: "i",
|
|
2754
|
+
warning: "‼",
|
|
2755
|
+
cross: "×",
|
|
2756
|
+
squareSmall: "□",
|
|
2757
|
+
squareSmallFilled: "■",
|
|
2758
|
+
circle: "( )",
|
|
2759
|
+
circleFilled: "(*)",
|
|
2760
|
+
circleDotted: "( )",
|
|
2761
|
+
circleDouble: "( )",
|
|
2762
|
+
circleCircle: "(○)",
|
|
2763
|
+
circleCross: "(×)",
|
|
2764
|
+
circlePipe: "(│)",
|
|
2765
|
+
radioOn: "(*)",
|
|
2766
|
+
radioOff: "( )",
|
|
2767
|
+
checkboxOn: "[×]",
|
|
2768
|
+
checkboxOff: "[ ]",
|
|
2769
|
+
checkboxCircleOn: "(×)",
|
|
2770
|
+
checkboxCircleOff: "( )",
|
|
2771
|
+
pointer: ">",
|
|
2772
|
+
triangleUpOutline: "∆",
|
|
2773
|
+
triangleLeft: "◄",
|
|
2774
|
+
triangleRight: "►",
|
|
2775
|
+
lozenge: "♦",
|
|
2776
|
+
lozengeOutline: "◊",
|
|
2777
|
+
hamburger: "≡",
|
|
2778
|
+
smiley: "☺",
|
|
2779
|
+
mustache: "┌─┐",
|
|
2780
|
+
star: "✶",
|
|
2781
|
+
play: "►",
|
|
2782
|
+
nodejs: "♦",
|
|
2783
|
+
oneSeventh: "1/7",
|
|
2784
|
+
oneNinth: "1/9",
|
|
2785
|
+
oneTenth: "1/10"
|
|
2786
|
+
};
|
|
2787
|
+
const mainSymbols = {
|
|
2788
|
+
...common,
|
|
2789
|
+
...specialMainSymbols
|
|
2790
|
+
};
|
|
2791
|
+
const fallbackSymbols = {
|
|
2792
|
+
...common,
|
|
2793
|
+
...specialFallbackSymbols
|
|
2794
|
+
};
|
|
2795
|
+
const shouldUseMain = isUnicodeSupported();
|
|
2796
|
+
const figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
2797
|
+
const defaultTheme = {
|
|
2798
|
+
prefix: {
|
|
2799
|
+
idle: styleText("blue", "?"),
|
|
2800
|
+
done: styleText("green", figures.tick)
|
|
2801
|
+
},
|
|
2802
|
+
spinner: {
|
|
2803
|
+
interval: 80,
|
|
2804
|
+
frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"].map((frame) => styleText("yellow", frame))
|
|
2805
|
+
},
|
|
2806
|
+
style: {
|
|
2807
|
+
answer: (text) => styleText("cyan", text),
|
|
2808
|
+
message: (text) => styleText("bold", text),
|
|
2809
|
+
error: (text) => styleText("red", `> ${text}`),
|
|
2810
|
+
defaultAnswer: (text) => styleText("dim", `(${text})`),
|
|
2811
|
+
help: (text) => styleText("dim", text),
|
|
2812
|
+
highlight: (text) => styleText("cyan", text),
|
|
2813
|
+
key: (text) => styleText("cyan", styleText("bold", `<${text}>`))
|
|
2814
|
+
}
|
|
2815
|
+
};
|
|
2816
|
+
function isPlainObject(value) {
|
|
2817
|
+
if (typeof value !== "object" || value === null)
|
|
2818
|
+
return false;
|
|
2819
|
+
let proto = value;
|
|
2820
|
+
while (Object.getPrototypeOf(proto) !== null) {
|
|
2821
|
+
proto = Object.getPrototypeOf(proto);
|
|
2822
|
+
}
|
|
2823
|
+
return Object.getPrototypeOf(value) === proto;
|
|
2824
|
+
}
|
|
2825
|
+
function deepMerge(...objects) {
|
|
2826
|
+
const output = {};
|
|
2827
|
+
for (const obj of objects) {
|
|
2828
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
2829
|
+
const prevValue = output[key];
|
|
2830
|
+
output[key] = isPlainObject(prevValue) && isPlainObject(value) ? deepMerge(prevValue, value) : value;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
return output;
|
|
2834
|
+
}
|
|
2835
|
+
function makeTheme(...themes) {
|
|
2836
|
+
const themesToMerge = [
|
|
2837
|
+
defaultTheme,
|
|
2838
|
+
...themes.filter((theme) => theme != null)
|
|
2839
|
+
];
|
|
2840
|
+
return deepMerge(...themesToMerge);
|
|
2841
|
+
}
|
|
2842
|
+
function usePrefix({ status = "idle", theme }) {
|
|
2843
|
+
const [showLoader, setShowLoader] = useState(false);
|
|
2844
|
+
const [tick, setTick] = useState(0);
|
|
2845
|
+
const { prefix, spinner } = makeTheme(theme);
|
|
2846
|
+
useEffect(() => {
|
|
2847
|
+
if (status === "loading") {
|
|
2848
|
+
let tickInterval;
|
|
2849
|
+
let inc = -1;
|
|
2850
|
+
const delayTimeout = setTimeout(() => {
|
|
2851
|
+
setShowLoader(true);
|
|
2852
|
+
tickInterval = setInterval(() => {
|
|
2853
|
+
inc = inc + 1;
|
|
2854
|
+
setTick(inc % spinner.frames.length);
|
|
2855
|
+
}, spinner.interval);
|
|
2856
|
+
}, 300);
|
|
2857
|
+
return () => {
|
|
2858
|
+
clearTimeout(delayTimeout);
|
|
2859
|
+
clearInterval(tickInterval);
|
|
2860
|
+
};
|
|
2861
|
+
} else {
|
|
2862
|
+
setShowLoader(false);
|
|
2863
|
+
}
|
|
2864
|
+
}, [status]);
|
|
2865
|
+
if (showLoader) {
|
|
2866
|
+
return spinner.frames[tick];
|
|
2867
|
+
}
|
|
2868
|
+
const iconName = status === "loading" ? "idle" : status;
|
|
2869
|
+
return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
|
|
2870
|
+
}
|
|
2871
|
+
function useMemo(fn, dependencies) {
|
|
2872
|
+
return withPointer((pointer) => {
|
|
2873
|
+
const prev = pointer.get();
|
|
2874
|
+
if (!prev || prev.dependencies.length !== dependencies.length || prev.dependencies.some((dep, i) => dep !== dependencies[i])) {
|
|
2875
|
+
const value = fn();
|
|
2876
|
+
pointer.set({ value, dependencies });
|
|
2877
|
+
return value;
|
|
2878
|
+
}
|
|
2879
|
+
return prev.value;
|
|
2880
|
+
});
|
|
2881
|
+
}
|
|
2882
|
+
function useRef(val) {
|
|
2883
|
+
return useState({ current: val })[0];
|
|
2884
|
+
}
|
|
2885
|
+
function useKeypress(userHandler) {
|
|
2886
|
+
const signal = useRef(userHandler);
|
|
2887
|
+
signal.current = userHandler;
|
|
2888
|
+
useEffect((rl) => {
|
|
2889
|
+
let ignore = false;
|
|
2890
|
+
const handler = withUpdates((_input, event) => {
|
|
2891
|
+
if (ignore)
|
|
2892
|
+
return;
|
|
2893
|
+
void signal.current(event, rl);
|
|
2894
|
+
});
|
|
2895
|
+
rl.input.on("keypress", handler);
|
|
2896
|
+
return () => {
|
|
2897
|
+
ignore = true;
|
|
2898
|
+
rl.input.removeListener("keypress", handler);
|
|
2899
|
+
};
|
|
2900
|
+
}, []);
|
|
2901
|
+
}
|
|
2902
|
+
function getDefaultExportFromCjs(x) {
|
|
2903
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
2904
|
+
}
|
|
2905
|
+
var cliWidth_1;
|
|
2906
|
+
var hasRequiredCliWidth;
|
|
2907
|
+
function requireCliWidth() {
|
|
2908
|
+
if (hasRequiredCliWidth) return cliWidth_1;
|
|
2909
|
+
hasRequiredCliWidth = 1;
|
|
2910
|
+
cliWidth_1 = cliWidth2;
|
|
2911
|
+
function normalizeOpts(options) {
|
|
2912
|
+
const defaultOpts = {
|
|
2913
|
+
defaultWidth: 0,
|
|
2914
|
+
output: process.stdout,
|
|
2915
|
+
tty: require$$0
|
|
2916
|
+
};
|
|
2917
|
+
if (!options) {
|
|
2918
|
+
return defaultOpts;
|
|
2919
|
+
}
|
|
2920
|
+
Object.keys(defaultOpts).forEach(function(key) {
|
|
2921
|
+
if (!options[key]) {
|
|
2922
|
+
options[key] = defaultOpts[key];
|
|
2923
|
+
}
|
|
2924
|
+
});
|
|
2925
|
+
return options;
|
|
2926
|
+
}
|
|
2927
|
+
function cliWidth2(options) {
|
|
2928
|
+
const opts = normalizeOpts(options);
|
|
2929
|
+
if (opts.output.getWindowSize) {
|
|
2930
|
+
return opts.output.getWindowSize()[0] || opts.defaultWidth;
|
|
2931
|
+
}
|
|
2932
|
+
if (opts.tty.getWindowSize) {
|
|
2933
|
+
return opts.tty.getWindowSize()[1] || opts.defaultWidth;
|
|
2934
|
+
}
|
|
2935
|
+
if (opts.output.columns) {
|
|
2936
|
+
return opts.output.columns;
|
|
2937
|
+
}
|
|
2938
|
+
if (process.env.CLI_WIDTH) {
|
|
2939
|
+
const width = parseInt(process.env.CLI_WIDTH, 10);
|
|
2940
|
+
if (!isNaN(width) && width !== 0) {
|
|
2941
|
+
return width;
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
return opts.defaultWidth;
|
|
2945
|
+
}
|
|
2946
|
+
return cliWidth_1;
|
|
2947
|
+
}
|
|
2948
|
+
var cliWidthExports = requireCliWidth();
|
|
2949
|
+
const cliWidth = /* @__PURE__ */ getDefaultExportFromCjs(cliWidthExports);
|
|
2950
|
+
const getCodePointsLength = /* @__PURE__ */ (() => {
|
|
2951
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
2952
|
+
return (input2) => {
|
|
2953
|
+
let surrogatePairsNr = 0;
|
|
2954
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
2955
|
+
while (SURROGATE_PAIR_RE.test(input2)) {
|
|
2956
|
+
surrogatePairsNr += 1;
|
|
2957
|
+
}
|
|
2958
|
+
return input2.length - surrogatePairsNr;
|
|
2959
|
+
};
|
|
2960
|
+
})();
|
|
2961
|
+
const isFullWidth = (x) => {
|
|
2962
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
2963
|
+
};
|
|
2964
|
+
const isWideNotCJKTNotEmoji = (x) => {
|
|
2965
|
+
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
2966
|
+
};
|
|
2967
|
+
const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
2968
|
+
const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
2969
|
+
const CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
|
|
2970
|
+
const TAB_RE = /\t{1,1000}/y;
|
|
2971
|
+
const EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
|
|
2972
|
+
const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
2973
|
+
const MODIFIER_RE = new RegExp("\\p{M}+", "gu");
|
|
2974
|
+
const NO_TRUNCATION$1 = { limit: Infinity, ellipsis: "" };
|
|
2975
|
+
const getStringTruncatedWidth = (input2, truncationOptions = {}, widthOptions = {}) => {
|
|
2976
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
2977
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
2978
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION$1, widthOptions).width : 0);
|
|
2979
|
+
const ANSI_WIDTH = 0;
|
|
2980
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
2981
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
2982
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
2983
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
2984
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
2985
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
2986
|
+
const PARSE_BLOCKS = [
|
|
2987
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
2988
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
2989
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
2990
|
+
[TAB_RE, TAB_WIDTH],
|
|
2991
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
2992
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
2993
|
+
];
|
|
2994
|
+
let indexPrev = 0;
|
|
2995
|
+
let index = 0;
|
|
2996
|
+
let length = input2.length;
|
|
2997
|
+
let lengthExtra = 0;
|
|
2998
|
+
let truncationEnabled = false;
|
|
2999
|
+
let truncationIndex = length;
|
|
3000
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
3001
|
+
let unmatchedStart = 0;
|
|
3002
|
+
let unmatchedEnd = 0;
|
|
3003
|
+
let width = 0;
|
|
3004
|
+
let widthExtra = 0;
|
|
3005
|
+
outer: while (true) {
|
|
3006
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
3007
|
+
const unmatched = input2.slice(unmatchedStart, unmatchedEnd) || input2.slice(indexPrev, index);
|
|
3008
|
+
lengthExtra = 0;
|
|
3009
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
3010
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
3011
|
+
if (isFullWidth(codePoint)) {
|
|
3012
|
+
widthExtra = FULL_WIDTH_WIDTH;
|
|
3013
|
+
} else if (isWideNotCJKTNotEmoji(codePoint)) {
|
|
3014
|
+
widthExtra = WIDE_WIDTH;
|
|
3015
|
+
} else {
|
|
3016
|
+
widthExtra = REGULAR_WIDTH;
|
|
3017
|
+
}
|
|
3018
|
+
if (width + widthExtra > truncationLimit) {
|
|
3019
|
+
truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
3020
|
+
}
|
|
3021
|
+
if (width + widthExtra > LIMIT) {
|
|
3022
|
+
truncationEnabled = true;
|
|
3023
|
+
break outer;
|
|
3024
|
+
}
|
|
3025
|
+
lengthExtra += char.length;
|
|
3026
|
+
width += widthExtra;
|
|
3027
|
+
}
|
|
3028
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
3029
|
+
}
|
|
3030
|
+
if (index >= length) {
|
|
3031
|
+
break outer;
|
|
3032
|
+
}
|
|
3033
|
+
for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
|
|
3034
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
3035
|
+
BLOCK_RE.lastIndex = index;
|
|
3036
|
+
if (BLOCK_RE.test(input2)) {
|
|
3037
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input2.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
3038
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
3039
|
+
if (width + widthExtra > truncationLimit) {
|
|
3040
|
+
truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
3041
|
+
}
|
|
3042
|
+
if (width + widthExtra > LIMIT) {
|
|
3043
|
+
truncationEnabled = true;
|
|
3044
|
+
break outer;
|
|
3045
|
+
}
|
|
3046
|
+
width += widthExtra;
|
|
3047
|
+
unmatchedStart = indexPrev;
|
|
3048
|
+
unmatchedEnd = index;
|
|
3049
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
3050
|
+
continue outer;
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
index += 1;
|
|
3054
|
+
}
|
|
3055
|
+
return {
|
|
3056
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
3057
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
3058
|
+
truncated: truncationEnabled,
|
|
3059
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
3060
|
+
};
|
|
3061
|
+
};
|
|
3062
|
+
const NO_TRUNCATION = {
|
|
3063
|
+
limit: Infinity,
|
|
3064
|
+
ellipsis: "",
|
|
3065
|
+
ellipsisWidth: 0
|
|
3066
|
+
};
|
|
3067
|
+
const fastStringWidth = (input2, options = {}) => {
|
|
3068
|
+
return getStringTruncatedWidth(input2, NO_TRUNCATION, options).width;
|
|
3069
|
+
};
|
|
3070
|
+
const ESC$1 = "\x1B";
|
|
3071
|
+
const CSI = "";
|
|
3072
|
+
const END_CODE = 39;
|
|
3073
|
+
const ANSI_ESCAPE_BELL = "\x07";
|
|
3074
|
+
const ANSI_CSI = "[";
|
|
3075
|
+
const ANSI_OSC = "]";
|
|
3076
|
+
const ANSI_SGR_TERMINATOR = "m";
|
|
3077
|
+
const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
3078
|
+
const GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
3079
|
+
const getClosingCode = (openingCode) => {
|
|
3080
|
+
if (openingCode >= 30 && openingCode <= 37)
|
|
3081
|
+
return 39;
|
|
3082
|
+
if (openingCode >= 90 && openingCode <= 97)
|
|
3083
|
+
return 39;
|
|
3084
|
+
if (openingCode >= 40 && openingCode <= 47)
|
|
3085
|
+
return 49;
|
|
3086
|
+
if (openingCode >= 100 && openingCode <= 107)
|
|
3087
|
+
return 49;
|
|
3088
|
+
if (openingCode === 1 || openingCode === 2)
|
|
3089
|
+
return 22;
|
|
3090
|
+
if (openingCode === 3)
|
|
3091
|
+
return 23;
|
|
3092
|
+
if (openingCode === 4)
|
|
3093
|
+
return 24;
|
|
3094
|
+
if (openingCode === 7)
|
|
3095
|
+
return 27;
|
|
3096
|
+
if (openingCode === 8)
|
|
3097
|
+
return 28;
|
|
3098
|
+
if (openingCode === 9)
|
|
3099
|
+
return 29;
|
|
3100
|
+
if (openingCode === 0)
|
|
3101
|
+
return 0;
|
|
3102
|
+
return void 0;
|
|
3103
|
+
};
|
|
3104
|
+
const wrapAnsiCode = (code) => `${ESC$1}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
3105
|
+
const wrapAnsiHyperlink = (url) => `${ESC$1}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
3106
|
+
const wrapWord = (rows, word, columns) => {
|
|
3107
|
+
const characters = word[Symbol.iterator]();
|
|
3108
|
+
let isInsideEscape = false;
|
|
3109
|
+
let isInsideLinkEscape = false;
|
|
3110
|
+
let lastRow = rows.at(-1);
|
|
3111
|
+
let visible = lastRow === void 0 ? 0 : fastStringWidth(lastRow);
|
|
3112
|
+
let currentCharacter = characters.next();
|
|
3113
|
+
let nextCharacter = characters.next();
|
|
3114
|
+
let rawCharacterIndex = 0;
|
|
3115
|
+
while (!currentCharacter.done) {
|
|
3116
|
+
const character = currentCharacter.value;
|
|
3117
|
+
const characterLength = fastStringWidth(character);
|
|
3118
|
+
if (visible + characterLength <= columns) {
|
|
3119
|
+
rows[rows.length - 1] += character;
|
|
3120
|
+
} else {
|
|
3121
|
+
rows.push(character);
|
|
3122
|
+
visible = 0;
|
|
3123
|
+
}
|
|
3124
|
+
if (character === ESC$1 || character === CSI) {
|
|
3125
|
+
isInsideEscape = true;
|
|
3126
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
3127
|
+
}
|
|
3128
|
+
if (isInsideEscape) {
|
|
3129
|
+
if (isInsideLinkEscape) {
|
|
3130
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
3131
|
+
isInsideEscape = false;
|
|
3132
|
+
isInsideLinkEscape = false;
|
|
3133
|
+
}
|
|
3134
|
+
} else if (character === ANSI_SGR_TERMINATOR) {
|
|
3135
|
+
isInsideEscape = false;
|
|
3136
|
+
}
|
|
3137
|
+
} else {
|
|
3138
|
+
visible += characterLength;
|
|
3139
|
+
if (visible === columns && !nextCharacter.done) {
|
|
3140
|
+
rows.push("");
|
|
3141
|
+
visible = 0;
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
currentCharacter = nextCharacter;
|
|
3145
|
+
nextCharacter = characters.next();
|
|
3146
|
+
rawCharacterIndex += character.length;
|
|
3147
|
+
}
|
|
3148
|
+
lastRow = rows.at(-1);
|
|
3149
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
|
|
3150
|
+
rows[rows.length - 2] += rows.pop();
|
|
3151
|
+
}
|
|
3152
|
+
};
|
|
3153
|
+
const stringVisibleTrimSpacesRight = (string) => {
|
|
3154
|
+
const words = string.split(" ");
|
|
3155
|
+
let last = words.length;
|
|
3156
|
+
while (last) {
|
|
3157
|
+
if (fastStringWidth(words[last - 1])) {
|
|
3158
|
+
break;
|
|
3159
|
+
}
|
|
3160
|
+
last--;
|
|
3161
|
+
}
|
|
3162
|
+
if (last === words.length) {
|
|
3163
|
+
return string;
|
|
3164
|
+
}
|
|
3165
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
3166
|
+
};
|
|
3167
|
+
const exec = (string, columns, options = {}) => {
|
|
3168
|
+
if (options.trim !== false && string.trim() === "") {
|
|
3169
|
+
return "";
|
|
3170
|
+
}
|
|
3171
|
+
let returnValue = "";
|
|
3172
|
+
let escapeCode;
|
|
3173
|
+
let escapeUrl;
|
|
3174
|
+
const words = string.split(" ");
|
|
3175
|
+
let rows = [""];
|
|
3176
|
+
let rowLength = 0;
|
|
3177
|
+
for (let index = 0; index < words.length; index++) {
|
|
3178
|
+
const word = words[index];
|
|
3179
|
+
if (options.trim !== false) {
|
|
3180
|
+
const row = rows.at(-1) ?? "";
|
|
3181
|
+
const trimmed = row.trimStart();
|
|
3182
|
+
if (row.length !== trimmed.length) {
|
|
3183
|
+
rows[rows.length - 1] = trimmed;
|
|
3184
|
+
rowLength = fastStringWidth(trimmed);
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
if (index !== 0) {
|
|
3188
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
3189
|
+
rows.push("");
|
|
3190
|
+
rowLength = 0;
|
|
3191
|
+
}
|
|
3192
|
+
if (rowLength || options.trim === false) {
|
|
3193
|
+
rows[rows.length - 1] += " ";
|
|
3194
|
+
rowLength++;
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
const wordLength = fastStringWidth(word);
|
|
3198
|
+
if (options.hard && wordLength > columns) {
|
|
3199
|
+
const remainingColumns = columns - rowLength;
|
|
3200
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
3201
|
+
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
|
|
3202
|
+
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
3203
|
+
rows.push("");
|
|
3204
|
+
}
|
|
3205
|
+
wrapWord(rows, word, columns);
|
|
3206
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3207
|
+
continue;
|
|
3208
|
+
}
|
|
3209
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
3210
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
3211
|
+
wrapWord(rows, word, columns);
|
|
3212
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3213
|
+
continue;
|
|
3214
|
+
}
|
|
3215
|
+
rows.push("");
|
|
3216
|
+
rowLength = 0;
|
|
3217
|
+
}
|
|
3218
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
3219
|
+
wrapWord(rows, word, columns);
|
|
3220
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
3221
|
+
continue;
|
|
3222
|
+
}
|
|
3223
|
+
rows[rows.length - 1] += word;
|
|
3224
|
+
rowLength += wordLength;
|
|
3225
|
+
}
|
|
3226
|
+
if (options.trim !== false) {
|
|
3227
|
+
rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
3228
|
+
}
|
|
3229
|
+
const preString = rows.join("\n");
|
|
3230
|
+
let inSurrogate = false;
|
|
3231
|
+
for (let i = 0; i < preString.length; i++) {
|
|
3232
|
+
const character = preString[i];
|
|
3233
|
+
returnValue += character;
|
|
3234
|
+
if (!inSurrogate) {
|
|
3235
|
+
inSurrogate = character >= "\uD800" && character <= "\uDBFF";
|
|
3236
|
+
if (inSurrogate) {
|
|
3237
|
+
continue;
|
|
3238
|
+
}
|
|
3239
|
+
} else {
|
|
3240
|
+
inSurrogate = false;
|
|
3241
|
+
}
|
|
3242
|
+
if (character === ESC$1 || character === CSI) {
|
|
3243
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
3244
|
+
const groupsResult = GROUP_REGEX.exec(preString);
|
|
3245
|
+
const groups = groupsResult?.groups;
|
|
3246
|
+
if (groups?.code !== void 0) {
|
|
3247
|
+
const code = Number.parseFloat(groups.code);
|
|
3248
|
+
escapeCode = code === END_CODE ? void 0 : code;
|
|
3249
|
+
} else if (groups?.uri !== void 0) {
|
|
3250
|
+
escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
if (preString[i + 1] === "\n") {
|
|
3254
|
+
if (escapeUrl) {
|
|
3255
|
+
returnValue += wrapAnsiHyperlink("");
|
|
3256
|
+
}
|
|
3257
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
|
|
3258
|
+
if (escapeCode && closingCode) {
|
|
3259
|
+
returnValue += wrapAnsiCode(closingCode);
|
|
3260
|
+
}
|
|
3261
|
+
} else if (character === "\n") {
|
|
3262
|
+
if (escapeCode && getClosingCode(escapeCode)) {
|
|
3263
|
+
returnValue += wrapAnsiCode(escapeCode);
|
|
3264
|
+
}
|
|
3265
|
+
if (escapeUrl) {
|
|
3266
|
+
returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
return returnValue;
|
|
3271
|
+
};
|
|
3272
|
+
const CRLF_OR_LF = /\r?\n/;
|
|
3273
|
+
function wrapAnsi(string, columns, options) {
|
|
3274
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
3275
|
+
}
|
|
3276
|
+
function breakLines(content, width) {
|
|
3277
|
+
return content.split("\n").flatMap((line) => wrapAnsi(line, width, { trim: false, hard: true }).split("\n").map((str) => str.trimEnd())).join("\n");
|
|
3278
|
+
}
|
|
3279
|
+
function readlineWidth() {
|
|
3280
|
+
return cliWidth({ defaultWidth: 80, output: readline().output });
|
|
3281
|
+
}
|
|
3282
|
+
function usePointerPosition({ active, renderedItems, pageSize, loop }) {
|
|
3283
|
+
const state = useRef({
|
|
3284
|
+
lastPointer: active,
|
|
3285
|
+
lastActive: void 0
|
|
3286
|
+
});
|
|
3287
|
+
const { lastPointer, lastActive } = state.current;
|
|
3288
|
+
const middle = Math.floor(pageSize / 2);
|
|
3289
|
+
const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
|
|
3290
|
+
const defaultPointerPosition = renderedItems.slice(0, active).reduce((acc, item) => acc + item.length, 0);
|
|
3291
|
+
let pointer = defaultPointerPosition;
|
|
3292
|
+
if (renderedLength > pageSize) {
|
|
3293
|
+
if (loop) {
|
|
3294
|
+
pointer = lastPointer;
|
|
3295
|
+
if (
|
|
3296
|
+
// First render, skip this logic.
|
|
3297
|
+
lastActive != null && // Only move the pointer down when the user moves down.
|
|
3298
|
+
lastActive < active && // Check user didn't move up across page boundary.
|
|
3299
|
+
active - lastActive < pageSize
|
|
3300
|
+
) {
|
|
3301
|
+
pointer = Math.min(
|
|
3302
|
+
// Furthest allowed position for the pointer is the middle of the list
|
|
3303
|
+
middle,
|
|
3304
|
+
Math.abs(active - lastActive) === 1 ? Math.min(
|
|
3305
|
+
// Move the pointer at most the height of the last active item.
|
|
3306
|
+
lastPointer + (renderedItems[lastActive]?.length ?? 0),
|
|
3307
|
+
// If the user moved by one item, move the pointer to the natural position of the active item as
|
|
3308
|
+
// long as it doesn't move the cursor up.
|
|
3309
|
+
Math.max(defaultPointerPosition, lastPointer)
|
|
3310
|
+
) : (
|
|
3311
|
+
// Otherwise, move the pointer down by the difference between the active and last active item.
|
|
3312
|
+
lastPointer + active - lastActive
|
|
3313
|
+
)
|
|
3314
|
+
);
|
|
3315
|
+
}
|
|
3316
|
+
} else {
|
|
3317
|
+
const spaceUnderActive = renderedItems.slice(active).reduce((acc, item) => acc + item.length, 0);
|
|
3318
|
+
pointer = spaceUnderActive < pageSize - middle ? (
|
|
3319
|
+
// If the active item is near the end of the list, progressively move the cursor towards the end.
|
|
3320
|
+
pageSize - spaceUnderActive
|
|
3321
|
+
) : (
|
|
3322
|
+
// Otherwise, progressively move the pointer to the middle of the list.
|
|
3323
|
+
Math.min(defaultPointerPosition, middle)
|
|
3324
|
+
);
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
state.current.lastPointer = pointer;
|
|
3328
|
+
state.current.lastActive = active;
|
|
3329
|
+
return pointer;
|
|
3330
|
+
}
|
|
3331
|
+
function usePagination({ items, active, renderItem, pageSize, loop = true }) {
|
|
3332
|
+
const width = readlineWidth();
|
|
3333
|
+
const bound = (num) => (num % items.length + items.length) % items.length;
|
|
3334
|
+
const renderedItems = items.map((item, index) => {
|
|
3335
|
+
if (item == null)
|
|
3336
|
+
return [];
|
|
3337
|
+
return breakLines(renderItem({ item, index, isActive: index === active }), width).split("\n");
|
|
3338
|
+
});
|
|
3339
|
+
const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
|
|
3340
|
+
const renderItemAtIndex = (index) => renderedItems[index] ?? [];
|
|
3341
|
+
const pointer = usePointerPosition({ active, renderedItems, pageSize, loop });
|
|
3342
|
+
const activeItem = renderItemAtIndex(active).slice(0, pageSize);
|
|
3343
|
+
const activeItemPosition = pointer + activeItem.length <= pageSize ? pointer : pageSize - activeItem.length;
|
|
3344
|
+
const pageBuffer = Array.from({ length: pageSize });
|
|
3345
|
+
pageBuffer.splice(activeItemPosition, activeItem.length, ...activeItem);
|
|
3346
|
+
const itemVisited = /* @__PURE__ */ new Set([active]);
|
|
3347
|
+
let bufferPointer = activeItemPosition + activeItem.length;
|
|
3348
|
+
let itemPointer = bound(active + 1);
|
|
3349
|
+
while (bufferPointer < pageSize && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer > active)) {
|
|
3350
|
+
const lines = renderItemAtIndex(itemPointer);
|
|
3351
|
+
const linesToAdd = lines.slice(0, pageSize - bufferPointer);
|
|
3352
|
+
pageBuffer.splice(bufferPointer, linesToAdd.length, ...linesToAdd);
|
|
3353
|
+
itemVisited.add(itemPointer);
|
|
3354
|
+
bufferPointer += linesToAdd.length;
|
|
3355
|
+
itemPointer = bound(itemPointer + 1);
|
|
3356
|
+
}
|
|
3357
|
+
bufferPointer = activeItemPosition - 1;
|
|
3358
|
+
itemPointer = bound(active - 1);
|
|
3359
|
+
while (bufferPointer >= 0 && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer < active)) {
|
|
3360
|
+
const lines = renderItemAtIndex(itemPointer);
|
|
3361
|
+
const linesToAdd = lines.slice(Math.max(0, lines.length - bufferPointer - 1));
|
|
3362
|
+
pageBuffer.splice(bufferPointer - linesToAdd.length + 1, linesToAdd.length, ...linesToAdd);
|
|
3363
|
+
itemVisited.add(itemPointer);
|
|
3364
|
+
bufferPointer -= linesToAdd.length;
|
|
3365
|
+
itemPointer = bound(itemPointer - 1);
|
|
3366
|
+
}
|
|
3367
|
+
return pageBuffer.filter((line) => typeof line === "string").join("\n");
|
|
3368
|
+
}
|
|
3369
|
+
var lib;
|
|
3370
|
+
var hasRequiredLib;
|
|
3371
|
+
function requireLib() {
|
|
3372
|
+
if (hasRequiredLib) return lib;
|
|
3373
|
+
hasRequiredLib = 1;
|
|
3374
|
+
const Stream = require$$0$1;
|
|
3375
|
+
class MuteStream2 extends Stream {
|
|
3376
|
+
#isTTY = null;
|
|
3377
|
+
constructor(opts = {}) {
|
|
3378
|
+
super(opts);
|
|
3379
|
+
this.writable = this.readable = true;
|
|
3380
|
+
this.muted = false;
|
|
3381
|
+
this.on("pipe", this._onpipe);
|
|
3382
|
+
this.replace = opts.replace;
|
|
3383
|
+
this._prompt = opts.prompt || null;
|
|
3384
|
+
this._hadControl = false;
|
|
3385
|
+
}
|
|
3386
|
+
#destSrc(key, def) {
|
|
3387
|
+
if (this._dest) {
|
|
3388
|
+
return this._dest[key];
|
|
3389
|
+
}
|
|
3390
|
+
if (this._src) {
|
|
3391
|
+
return this._src[key];
|
|
3392
|
+
}
|
|
3393
|
+
return def;
|
|
3394
|
+
}
|
|
3395
|
+
#proxy(method, ...args) {
|
|
3396
|
+
if (typeof this._dest?.[method] === "function") {
|
|
3397
|
+
this._dest[method](...args);
|
|
3398
|
+
}
|
|
3399
|
+
if (typeof this._src?.[method] === "function") {
|
|
3400
|
+
this._src[method](...args);
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
get isTTY() {
|
|
3404
|
+
if (this.#isTTY !== null) {
|
|
3405
|
+
return this.#isTTY;
|
|
3406
|
+
}
|
|
3407
|
+
return this.#destSrc("isTTY", false);
|
|
3408
|
+
}
|
|
3409
|
+
// basically just get replace the getter/setter with a regular value
|
|
3410
|
+
set isTTY(val) {
|
|
3411
|
+
this.#isTTY = val;
|
|
3412
|
+
}
|
|
3413
|
+
get rows() {
|
|
3414
|
+
return this.#destSrc("rows");
|
|
3415
|
+
}
|
|
3416
|
+
get columns() {
|
|
3417
|
+
return this.#destSrc("columns");
|
|
3418
|
+
}
|
|
3419
|
+
mute() {
|
|
3420
|
+
this.muted = true;
|
|
3421
|
+
}
|
|
3422
|
+
unmute() {
|
|
3423
|
+
this.muted = false;
|
|
3424
|
+
}
|
|
3425
|
+
_onpipe(src) {
|
|
3426
|
+
this._src = src;
|
|
3427
|
+
}
|
|
3428
|
+
pipe(dest, options) {
|
|
3429
|
+
this._dest = dest;
|
|
3430
|
+
return super.pipe(dest, options);
|
|
3431
|
+
}
|
|
3432
|
+
pause() {
|
|
3433
|
+
if (this._src) {
|
|
3434
|
+
return this._src.pause();
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
resume() {
|
|
3438
|
+
if (this._src) {
|
|
3439
|
+
return this._src.resume();
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
write(c) {
|
|
3443
|
+
if (this.muted) {
|
|
3444
|
+
if (!this.replace) {
|
|
3445
|
+
return true;
|
|
3446
|
+
}
|
|
3447
|
+
if (c.match(/^\u001b/)) {
|
|
3448
|
+
if (c.indexOf(this._prompt) === 0) {
|
|
3449
|
+
c = c.slice(this._prompt.length);
|
|
3450
|
+
c = c.replace(/./g, this.replace);
|
|
3451
|
+
c = this._prompt + c;
|
|
3452
|
+
}
|
|
3453
|
+
this._hadControl = true;
|
|
3454
|
+
return this.emit("data", c);
|
|
3455
|
+
} else {
|
|
3456
|
+
if (this._prompt && this._hadControl && c.indexOf(this._prompt) === 0) {
|
|
3457
|
+
this._hadControl = false;
|
|
3458
|
+
this.emit("data", this._prompt);
|
|
3459
|
+
c = c.slice(this._prompt.length);
|
|
3460
|
+
}
|
|
3461
|
+
c = c.toString().replace(/./g, this.replace);
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
this.emit("data", c);
|
|
2252
3465
|
}
|
|
2253
|
-
|
|
2254
|
-
|
|
3466
|
+
end(c) {
|
|
3467
|
+
if (this.muted) {
|
|
3468
|
+
if (c && this.replace) {
|
|
3469
|
+
c = c.toString().replace(/./g, this.replace);
|
|
3470
|
+
} else {
|
|
3471
|
+
c = null;
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
if (c) {
|
|
3475
|
+
this.emit("data", c);
|
|
3476
|
+
}
|
|
3477
|
+
this.emit("end");
|
|
3478
|
+
}
|
|
3479
|
+
destroy(...args) {
|
|
3480
|
+
return this.#proxy("destroy", ...args);
|
|
3481
|
+
}
|
|
3482
|
+
destroySoon(...args) {
|
|
3483
|
+
return this.#proxy("destroySoon", ...args);
|
|
2255
3484
|
}
|
|
2256
|
-
|
|
3485
|
+
close(...args) {
|
|
3486
|
+
return this.#proxy("close", ...args);
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
lib = MuteStream2;
|
|
3490
|
+
return lib;
|
|
3491
|
+
}
|
|
3492
|
+
var libExports = requireLib();
|
|
3493
|
+
const MuteStream = /* @__PURE__ */ getDefaultExportFromCjs(libExports);
|
|
3494
|
+
const signals = [];
|
|
3495
|
+
signals.push("SIGHUP", "SIGINT", "SIGTERM");
|
|
3496
|
+
if (process.platform !== "win32") {
|
|
3497
|
+
signals.push(
|
|
3498
|
+
"SIGALRM",
|
|
3499
|
+
"SIGABRT",
|
|
3500
|
+
"SIGVTALRM",
|
|
3501
|
+
"SIGXCPU",
|
|
3502
|
+
"SIGXFSZ",
|
|
3503
|
+
"SIGUSR2",
|
|
3504
|
+
"SIGTRAP",
|
|
3505
|
+
"SIGSYS",
|
|
3506
|
+
"SIGQUIT",
|
|
3507
|
+
"SIGIOT"
|
|
3508
|
+
// should detect profiler and enable/disable accordingly.
|
|
3509
|
+
// see #21
|
|
3510
|
+
// 'SIGPROF'
|
|
3511
|
+
);
|
|
3512
|
+
}
|
|
3513
|
+
if (process.platform === "linux") {
|
|
3514
|
+
signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
|
|
3515
|
+
}
|
|
3516
|
+
const processOk = (process2) => !!process2 && typeof process2 === "object" && typeof process2.removeListener === "function" && typeof process2.emit === "function" && typeof process2.reallyExit === "function" && typeof process2.listeners === "function" && typeof process2.kill === "function" && typeof process2.pid === "number" && typeof process2.on === "function";
|
|
3517
|
+
const kExitEmitter = /* @__PURE__ */ Symbol.for("signal-exit emitter");
|
|
3518
|
+
const global = globalThis;
|
|
3519
|
+
const ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
3520
|
+
class Emitter {
|
|
3521
|
+
emitted = {
|
|
3522
|
+
afterExit: false,
|
|
3523
|
+
exit: false
|
|
3524
|
+
};
|
|
3525
|
+
listeners = {
|
|
3526
|
+
afterExit: [],
|
|
3527
|
+
exit: []
|
|
3528
|
+
};
|
|
3529
|
+
count = 0;
|
|
3530
|
+
id = Math.random();
|
|
3531
|
+
constructor() {
|
|
3532
|
+
if (global[kExitEmitter]) {
|
|
3533
|
+
return global[kExitEmitter];
|
|
3534
|
+
}
|
|
3535
|
+
ObjectDefineProperty(global, kExitEmitter, {
|
|
3536
|
+
value: this,
|
|
3537
|
+
writable: false,
|
|
3538
|
+
enumerable: false,
|
|
3539
|
+
configurable: false
|
|
3540
|
+
});
|
|
3541
|
+
}
|
|
3542
|
+
on(ev, fn) {
|
|
3543
|
+
this.listeners[ev].push(fn);
|
|
3544
|
+
}
|
|
3545
|
+
removeListener(ev, fn) {
|
|
3546
|
+
const list = this.listeners[ev];
|
|
3547
|
+
const i = list.indexOf(fn);
|
|
3548
|
+
if (i === -1) {
|
|
3549
|
+
return;
|
|
3550
|
+
}
|
|
3551
|
+
if (i === 0 && list.length === 1) {
|
|
3552
|
+
list.length = 0;
|
|
3553
|
+
} else {
|
|
3554
|
+
list.splice(i, 1);
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3557
|
+
emit(ev, code, signal) {
|
|
3558
|
+
if (this.emitted[ev]) {
|
|
2257
3559
|
return false;
|
|
2258
3560
|
}
|
|
2259
|
-
|
|
3561
|
+
this.emitted[ev] = true;
|
|
3562
|
+
let ret = false;
|
|
3563
|
+
for (const fn of this.listeners[ev]) {
|
|
3564
|
+
ret = fn(code, signal) === true || ret;
|
|
3565
|
+
}
|
|
3566
|
+
if (ev === "exit") {
|
|
3567
|
+
ret = this.emit("afterExit", code, signal) || ret;
|
|
3568
|
+
}
|
|
3569
|
+
return ret;
|
|
2260
3570
|
}
|
|
3571
|
+
}
|
|
3572
|
+
class SignalExitBase {
|
|
3573
|
+
}
|
|
3574
|
+
const signalExitWrap = (handler) => {
|
|
3575
|
+
return {
|
|
3576
|
+
onExit(cb, opts) {
|
|
3577
|
+
return handler.onExit(cb, opts);
|
|
3578
|
+
},
|
|
3579
|
+
load() {
|
|
3580
|
+
return handler.load();
|
|
3581
|
+
},
|
|
3582
|
+
unload() {
|
|
3583
|
+
return handler.unload();
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
2261
3586
|
};
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
return
|
|
3587
|
+
class SignalExitFallback extends SignalExitBase {
|
|
3588
|
+
onExit() {
|
|
3589
|
+
return () => {
|
|
3590
|
+
};
|
|
2265
3591
|
}
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
3592
|
+
load() {
|
|
3593
|
+
}
|
|
3594
|
+
unload() {
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
class SignalExit extends SignalExitBase {
|
|
3598
|
+
// "SIGHUP" throws an `ENOSYS` error on Windows,
|
|
3599
|
+
// so use a supported signal instead
|
|
3600
|
+
/* c8 ignore start */
|
|
3601
|
+
#hupSig = process$1.platform === "win32" ? "SIGINT" : "SIGHUP";
|
|
3602
|
+
/* c8 ignore stop */
|
|
3603
|
+
#emitter = new Emitter();
|
|
3604
|
+
#process;
|
|
3605
|
+
#originalProcessEmit;
|
|
3606
|
+
#originalProcessReallyExit;
|
|
3607
|
+
#sigListeners = {};
|
|
3608
|
+
#loaded = false;
|
|
3609
|
+
constructor(process2) {
|
|
3610
|
+
super();
|
|
3611
|
+
this.#process = process2;
|
|
3612
|
+
this.#sigListeners = {};
|
|
3613
|
+
for (const sig of signals) {
|
|
3614
|
+
this.#sigListeners[sig] = () => {
|
|
3615
|
+
const listeners = this.#process.listeners(sig);
|
|
3616
|
+
let { count } = this.#emitter;
|
|
3617
|
+
const p = process2;
|
|
3618
|
+
if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") {
|
|
3619
|
+
count += p.__signal_exit_emitter__.count;
|
|
3620
|
+
}
|
|
3621
|
+
if (listeners.length === count) {
|
|
3622
|
+
this.unload();
|
|
3623
|
+
const ret = this.#emitter.emit("exit", null, sig);
|
|
3624
|
+
const s = sig === "SIGHUP" ? this.#hupSig : sig;
|
|
3625
|
+
if (!ret)
|
|
3626
|
+
process2.kill(process2.pid, s);
|
|
3627
|
+
}
|
|
3628
|
+
};
|
|
3629
|
+
}
|
|
3630
|
+
this.#originalProcessReallyExit = process2.reallyExit;
|
|
3631
|
+
this.#originalProcessEmit = process2.emit;
|
|
3632
|
+
}
|
|
3633
|
+
onExit(cb, opts) {
|
|
3634
|
+
if (!processOk(this.#process)) {
|
|
3635
|
+
return () => {
|
|
3636
|
+
};
|
|
3637
|
+
}
|
|
3638
|
+
if (this.#loaded === false) {
|
|
3639
|
+
this.load();
|
|
3640
|
+
}
|
|
3641
|
+
const ev = opts?.alwaysLast ? "afterExit" : "exit";
|
|
3642
|
+
this.#emitter.on(ev, cb);
|
|
3643
|
+
return () => {
|
|
3644
|
+
this.#emitter.removeListener(ev, cb);
|
|
3645
|
+
if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) {
|
|
3646
|
+
this.unload();
|
|
3647
|
+
}
|
|
3648
|
+
};
|
|
3649
|
+
}
|
|
3650
|
+
load() {
|
|
3651
|
+
if (this.#loaded) {
|
|
3652
|
+
return;
|
|
3653
|
+
}
|
|
3654
|
+
this.#loaded = true;
|
|
3655
|
+
this.#emitter.count += 1;
|
|
3656
|
+
for (const sig of signals) {
|
|
3657
|
+
try {
|
|
3658
|
+
const fn = this.#sigListeners[sig];
|
|
3659
|
+
if (fn)
|
|
3660
|
+
this.#process.on(sig, fn);
|
|
3661
|
+
} catch (_) {
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
this.#process.emit = (ev, ...a) => {
|
|
3665
|
+
return this.#processEmit(ev, ...a);
|
|
3666
|
+
};
|
|
3667
|
+
this.#process.reallyExit = (code) => {
|
|
3668
|
+
return this.#processReallyExit(code);
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
unload() {
|
|
3672
|
+
if (!this.#loaded) {
|
|
3673
|
+
return;
|
|
3674
|
+
}
|
|
3675
|
+
this.#loaded = false;
|
|
3676
|
+
signals.forEach((sig) => {
|
|
3677
|
+
const listener = this.#sigListeners[sig];
|
|
3678
|
+
if (!listener) {
|
|
3679
|
+
throw new Error("Listener not defined for signal: " + sig);
|
|
3680
|
+
}
|
|
3681
|
+
try {
|
|
3682
|
+
this.#process.removeListener(sig, listener);
|
|
3683
|
+
} catch (_) {
|
|
3684
|
+
}
|
|
3685
|
+
});
|
|
3686
|
+
this.#process.emit = this.#originalProcessEmit;
|
|
3687
|
+
this.#process.reallyExit = this.#originalProcessReallyExit;
|
|
3688
|
+
this.#emitter.count -= 1;
|
|
3689
|
+
}
|
|
3690
|
+
#processReallyExit(code) {
|
|
3691
|
+
if (!processOk(this.#process)) {
|
|
3692
|
+
return 0;
|
|
3693
|
+
}
|
|
3694
|
+
this.#process.exitCode = code || 0;
|
|
3695
|
+
this.#emitter.emit("exit", this.#process.exitCode, null);
|
|
3696
|
+
return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
|
|
3697
|
+
}
|
|
3698
|
+
#processEmit(ev, ...args) {
|
|
3699
|
+
const og = this.#originalProcessEmit;
|
|
3700
|
+
if (ev === "exit" && processOk(this.#process)) {
|
|
3701
|
+
if (typeof args[0] === "number") {
|
|
3702
|
+
this.#process.exitCode = args[0];
|
|
3703
|
+
}
|
|
3704
|
+
const ret = og.call(this.#process, ev, ...args);
|
|
3705
|
+
this.#emitter.emit("exit", this.#process.exitCode, null);
|
|
3706
|
+
return ret;
|
|
3707
|
+
} else {
|
|
3708
|
+
return og.call(this.#process, ev, ...args);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
const process$1 = globalThis.process;
|
|
3713
|
+
const {
|
|
3714
|
+
/**
|
|
3715
|
+
* Called when the process is exiting, whether via signal, explicit
|
|
3716
|
+
* exit, or running out of stuff to do.
|
|
3717
|
+
*
|
|
3718
|
+
* If the global process object is not suitable for instrumentation,
|
|
3719
|
+
* then this will be a no-op.
|
|
3720
|
+
*
|
|
3721
|
+
* Returns a function that may be used to unload signal-exit.
|
|
3722
|
+
*/
|
|
3723
|
+
onExit
|
|
3724
|
+
} = signalExitWrap(processOk(process$1) ? new SignalExit(process$1) : new SignalExitFallback());
|
|
3725
|
+
const ESC = "\x1B[";
|
|
3726
|
+
const cursorLeft = ESC + "G";
|
|
3727
|
+
const cursorHide = ESC + "?25l";
|
|
3728
|
+
const cursorShow = ESC + "?25h";
|
|
3729
|
+
const cursorUp = (rows = 1) => rows > 0 ? `${ESC}${rows}A` : "";
|
|
3730
|
+
const cursorDown = (rows = 1) => rows > 0 ? `${ESC}${rows}B` : "";
|
|
3731
|
+
const cursorTo = (x, y) => {
|
|
3732
|
+
return `${ESC}${x + 1}G`;
|
|
3733
|
+
};
|
|
3734
|
+
const eraseLine = ESC + "2K";
|
|
3735
|
+
const eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
|
|
3736
|
+
const height = (content) => content.split("\n").length;
|
|
3737
|
+
const lastLine = (content) => content.split("\n").pop() ?? "";
|
|
3738
|
+
class ScreenManager {
|
|
3739
|
+
// These variables are keeping information to allow correct prompt re-rendering
|
|
3740
|
+
height = 0;
|
|
3741
|
+
extraLinesUnderPrompt = 0;
|
|
3742
|
+
cursorPos;
|
|
3743
|
+
rl;
|
|
3744
|
+
constructor(rl) {
|
|
3745
|
+
this.rl = rl;
|
|
3746
|
+
this.cursorPos = rl.getCursorPos();
|
|
3747
|
+
}
|
|
3748
|
+
write(content) {
|
|
3749
|
+
this.rl.output.unmute();
|
|
3750
|
+
this.rl.output.write(content);
|
|
3751
|
+
this.rl.output.mute();
|
|
3752
|
+
}
|
|
3753
|
+
render(content, bottomContent = "") {
|
|
3754
|
+
const promptLine = lastLine(content);
|
|
3755
|
+
const rawPromptLine = stripVTControlCharacters(promptLine);
|
|
3756
|
+
let prompt = rawPromptLine;
|
|
3757
|
+
if (this.rl.line.length > 0) {
|
|
3758
|
+
prompt = prompt.slice(0, -this.rl.line.length);
|
|
3759
|
+
}
|
|
3760
|
+
this.rl.setPrompt(prompt);
|
|
3761
|
+
this.cursorPos = this.rl.getCursorPos();
|
|
3762
|
+
const width = readlineWidth();
|
|
3763
|
+
content = breakLines(content, width);
|
|
3764
|
+
bottomContent = breakLines(bottomContent, width);
|
|
3765
|
+
if (rawPromptLine.length % width === 0) {
|
|
3766
|
+
content += "\n";
|
|
3767
|
+
}
|
|
3768
|
+
let output = content + (bottomContent ? "\n" + bottomContent : "");
|
|
3769
|
+
const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
|
|
3770
|
+
const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
|
|
3771
|
+
if (bottomContentHeight > 0)
|
|
3772
|
+
output += cursorUp(bottomContentHeight);
|
|
3773
|
+
output += cursorTo(this.cursorPos.cols);
|
|
3774
|
+
this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
|
|
3775
|
+
this.extraLinesUnderPrompt = bottomContentHeight;
|
|
3776
|
+
this.height = height(output);
|
|
3777
|
+
}
|
|
3778
|
+
checkCursorPos() {
|
|
3779
|
+
const cursorPos = this.rl.getCursorPos();
|
|
3780
|
+
if (cursorPos.cols !== this.cursorPos.cols) {
|
|
3781
|
+
this.write(cursorTo(cursorPos.cols));
|
|
3782
|
+
this.cursorPos = cursorPos;
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3785
|
+
done({ clearContent }) {
|
|
3786
|
+
this.rl.setPrompt("");
|
|
3787
|
+
let output = cursorDown(this.extraLinesUnderPrompt);
|
|
3788
|
+
output += clearContent ? eraseLines(this.height) : "\n";
|
|
3789
|
+
output += cursorLeft;
|
|
3790
|
+
output += cursorShow;
|
|
3791
|
+
this.write(output);
|
|
3792
|
+
this.rl.close();
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3795
|
+
class PromisePolyfill extends Promise {
|
|
3796
|
+
// Available starting from Node 22
|
|
3797
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
3798
|
+
static withResolver() {
|
|
3799
|
+
let resolve;
|
|
3800
|
+
let reject;
|
|
3801
|
+
const promise = new Promise((res, rej) => {
|
|
3802
|
+
resolve = res;
|
|
3803
|
+
reject = rej;
|
|
3804
|
+
});
|
|
3805
|
+
return { promise, resolve, reject };
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
const nativeSetImmediate = globalThis.setImmediate;
|
|
3809
|
+
function getCallSites() {
|
|
3810
|
+
const savedPrepareStackTrace = Error.prepareStackTrace;
|
|
3811
|
+
let result = [];
|
|
3812
|
+
try {
|
|
3813
|
+
Error.prepareStackTrace = (_, callSites) => {
|
|
3814
|
+
const callSitesWithoutCurrent = callSites.slice(1);
|
|
3815
|
+
result = callSitesWithoutCurrent;
|
|
3816
|
+
return callSitesWithoutCurrent;
|
|
3817
|
+
};
|
|
3818
|
+
new Error().stack;
|
|
3819
|
+
} catch {
|
|
3820
|
+
return result;
|
|
3821
|
+
}
|
|
3822
|
+
Error.prepareStackTrace = savedPrepareStackTrace;
|
|
3823
|
+
return result;
|
|
3824
|
+
}
|
|
3825
|
+
function createPrompt(view) {
|
|
3826
|
+
const callSites = getCallSites();
|
|
3827
|
+
const prompt = (config, context = {}) => {
|
|
3828
|
+
const { input: input2 = process.stdin, signal } = context;
|
|
3829
|
+
const cleanups = /* @__PURE__ */ new Set();
|
|
3830
|
+
const output = new MuteStream();
|
|
3831
|
+
output.pipe(context.output ?? process.stdout);
|
|
3832
|
+
const rl = readline$1.createInterface({
|
|
3833
|
+
terminal: true,
|
|
3834
|
+
input: input2,
|
|
3835
|
+
output
|
|
3836
|
+
});
|
|
3837
|
+
output.mute();
|
|
3838
|
+
const screen = new ScreenManager(rl);
|
|
3839
|
+
const { promise, resolve, reject } = PromisePolyfill.withResolver();
|
|
3840
|
+
const cancel = () => reject(new CancelPromptError());
|
|
3841
|
+
if (signal) {
|
|
3842
|
+
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
3843
|
+
if (signal.aborted) {
|
|
3844
|
+
abort();
|
|
3845
|
+
return Object.assign(promise, { cancel });
|
|
3846
|
+
}
|
|
3847
|
+
signal.addEventListener("abort", abort);
|
|
3848
|
+
cleanups.add(() => signal.removeEventListener("abort", abort));
|
|
3849
|
+
}
|
|
3850
|
+
cleanups.add(onExit((code, signal2) => {
|
|
3851
|
+
reject(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
|
|
3852
|
+
}));
|
|
3853
|
+
const sigint = () => reject(new ExitPromptError(`User force closed the prompt with SIGINT`));
|
|
3854
|
+
rl.on("SIGINT", sigint);
|
|
3855
|
+
cleanups.add(() => rl.removeListener("SIGINT", sigint));
|
|
3856
|
+
return withHooks(rl, (cycle) => {
|
|
3857
|
+
const hooksCleanup = AsyncResource.bind(() => effectScheduler.clearAll());
|
|
3858
|
+
rl.on("close", hooksCleanup);
|
|
3859
|
+
cleanups.add(() => rl.removeListener("close", hooksCleanup));
|
|
3860
|
+
const startCycle = () => {
|
|
3861
|
+
const checkCursorPos = () => screen.checkCursorPos();
|
|
3862
|
+
rl.input.on("keypress", checkCursorPos);
|
|
3863
|
+
cleanups.add(() => rl.input.removeListener("keypress", checkCursorPos));
|
|
3864
|
+
let pendingDone = null;
|
|
3865
|
+
cycle(() => {
|
|
3866
|
+
let effectsSettled = false;
|
|
3867
|
+
try {
|
|
3868
|
+
const nextView = view(config, (value) => {
|
|
3869
|
+
if (effectsSettled) {
|
|
3870
|
+
resolve(value);
|
|
3871
|
+
} else {
|
|
3872
|
+
pendingDone = { value };
|
|
3873
|
+
}
|
|
3874
|
+
});
|
|
3875
|
+
if (nextView === void 0) {
|
|
3876
|
+
let callerFilename = callSites[1]?.getFileName();
|
|
3877
|
+
if (callerFilename && !callerFilename.startsWith("file://")) {
|
|
3878
|
+
callerFilename = path.resolve(callerFilename);
|
|
3879
|
+
}
|
|
3880
|
+
throw new Error(`Prompt functions must return a string.
|
|
3881
|
+
at ${callerFilename}`);
|
|
3882
|
+
}
|
|
3883
|
+
const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
|
|
3884
|
+
screen.render(content, bottomContent);
|
|
3885
|
+
effectScheduler.run();
|
|
3886
|
+
} catch (error) {
|
|
3887
|
+
reject(error);
|
|
3888
|
+
}
|
|
3889
|
+
effectsSettled = true;
|
|
3890
|
+
if (pendingDone !== null) {
|
|
3891
|
+
const { value } = pendingDone;
|
|
3892
|
+
pendingDone = null;
|
|
3893
|
+
resolve(value);
|
|
3894
|
+
}
|
|
3895
|
+
});
|
|
3896
|
+
};
|
|
3897
|
+
if ("readableFlowing" in input2) {
|
|
3898
|
+
nativeSetImmediate(startCycle);
|
|
3899
|
+
} else {
|
|
3900
|
+
startCycle();
|
|
3901
|
+
}
|
|
3902
|
+
return Object.assign(promise.then((answer) => {
|
|
3903
|
+
effectScheduler.clearAll();
|
|
3904
|
+
return answer;
|
|
3905
|
+
}, (error) => {
|
|
3906
|
+
effectScheduler.clearAll();
|
|
3907
|
+
throw error;
|
|
3908
|
+
}).finally(() => {
|
|
3909
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
3910
|
+
screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
|
|
3911
|
+
output.end();
|
|
3912
|
+
}).then(() => promise), { cancel });
|
|
3913
|
+
});
|
|
3914
|
+
};
|
|
3915
|
+
return prompt;
|
|
3916
|
+
}
|
|
3917
|
+
class Separator {
|
|
3918
|
+
separator = styleText("dim", Array.from({ length: 15 }).join(figures.line));
|
|
3919
|
+
type = "separator";
|
|
3920
|
+
constructor(separator) {
|
|
3921
|
+
if (separator) {
|
|
3922
|
+
this.separator = separator;
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
static isSeparator(choice) {
|
|
3926
|
+
return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
const checkboxTheme = {
|
|
3930
|
+
icon: {
|
|
3931
|
+
checked: styleText("green", figures.circleFilled),
|
|
3932
|
+
unchecked: figures.circle,
|
|
3933
|
+
cursor: figures.pointer,
|
|
3934
|
+
disabledChecked: styleText("green", figures.circleDouble),
|
|
3935
|
+
disabledUnchecked: "-"
|
|
3936
|
+
},
|
|
3937
|
+
style: {
|
|
3938
|
+
disabled: (text) => styleText("dim", text),
|
|
3939
|
+
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
3940
|
+
description: (text) => styleText("cyan", text),
|
|
3941
|
+
keysHelpTip: (keys) => keys.map(([key, action]) => `${styleText("bold", key)} ${styleText("dim", action)}`).join(styleText("dim", " • "))
|
|
3942
|
+
},
|
|
3943
|
+
i18n: { disabledError: "This option is disabled and cannot be toggled." },
|
|
3944
|
+
keybindings: []
|
|
3945
|
+
};
|
|
3946
|
+
function isSelectable$1(item) {
|
|
3947
|
+
return !Separator.isSeparator(item) && !item.disabled;
|
|
3948
|
+
}
|
|
3949
|
+
function isNavigable$1(item) {
|
|
3950
|
+
return !Separator.isSeparator(item);
|
|
3951
|
+
}
|
|
3952
|
+
function isChecked(item) {
|
|
3953
|
+
return !Separator.isSeparator(item) && item.checked;
|
|
3954
|
+
}
|
|
3955
|
+
function toggle(item) {
|
|
3956
|
+
return isSelectable$1(item) ? { ...item, checked: !item.checked } : item;
|
|
3957
|
+
}
|
|
3958
|
+
function check(checked) {
|
|
3959
|
+
return function(item) {
|
|
3960
|
+
return isSelectable$1(item) ? { ...item, checked } : item;
|
|
3961
|
+
};
|
|
3962
|
+
}
|
|
3963
|
+
function normalizeChoices$1(choices) {
|
|
3964
|
+
return choices.map((choice) => {
|
|
3965
|
+
if (Separator.isSeparator(choice))
|
|
3966
|
+
return choice;
|
|
3967
|
+
if (typeof choice !== "object" || choice === null || !("value" in choice)) {
|
|
3968
|
+
const name2 = String(choice);
|
|
3969
|
+
return {
|
|
3970
|
+
value: choice,
|
|
3971
|
+
name: name2,
|
|
3972
|
+
short: name2,
|
|
3973
|
+
checkedName: name2,
|
|
3974
|
+
disabled: false,
|
|
3975
|
+
checked: false
|
|
3976
|
+
};
|
|
3977
|
+
}
|
|
3978
|
+
const name = choice.name ?? String(choice.value);
|
|
3979
|
+
const normalizedChoice = {
|
|
3980
|
+
value: choice.value,
|
|
3981
|
+
name,
|
|
3982
|
+
short: choice.short ?? name,
|
|
3983
|
+
checkedName: choice.checkedName ?? name,
|
|
3984
|
+
disabled: choice.disabled ?? false,
|
|
3985
|
+
checked: choice.checked ?? false
|
|
3986
|
+
};
|
|
3987
|
+
if (choice.description) {
|
|
3988
|
+
normalizedChoice.description = choice.description;
|
|
3989
|
+
}
|
|
3990
|
+
return normalizedChoice;
|
|
3991
|
+
});
|
|
3992
|
+
}
|
|
3993
|
+
const checkbox = createPrompt((config, done) => {
|
|
3994
|
+
const { pageSize = 7, loop = true, required, validate = () => true } = config;
|
|
3995
|
+
const shortcuts = { all: "a", invert: "i", ...config.shortcuts };
|
|
3996
|
+
const theme = makeTheme(checkboxTheme, config.theme);
|
|
3997
|
+
const { keybindings } = theme;
|
|
3998
|
+
const [status, setStatus] = useState("idle");
|
|
3999
|
+
const prefix = usePrefix({ status, theme });
|
|
4000
|
+
const [items, setItems] = useState(normalizeChoices$1(config.choices));
|
|
4001
|
+
const bounds = useMemo(() => {
|
|
4002
|
+
const first = items.findIndex(isNavigable$1);
|
|
4003
|
+
const last = items.findLastIndex(isNavigable$1);
|
|
4004
|
+
if (first === -1) {
|
|
4005
|
+
throw new ValidationError("[checkbox prompt] No selectable choices. All choices are disabled.");
|
|
4006
|
+
}
|
|
4007
|
+
return { first, last };
|
|
4008
|
+
}, [items]);
|
|
4009
|
+
const [active, setActive] = useState(bounds.first);
|
|
4010
|
+
const [errorMsg, setError] = useState();
|
|
4011
|
+
useKeypress(async (key) => {
|
|
4012
|
+
if (isEnterKey(key)) {
|
|
4013
|
+
const selection = items.filter(isChecked);
|
|
4014
|
+
const isValid = await validate([...selection]);
|
|
4015
|
+
if (required && !selection.length) {
|
|
4016
|
+
setError("At least one choice must be selected");
|
|
4017
|
+
} else if (isValid === true) {
|
|
4018
|
+
setStatus("done");
|
|
4019
|
+
done(selection.map((choice) => choice.value));
|
|
4020
|
+
} else {
|
|
4021
|
+
setError(isValid || "You must select a valid value");
|
|
4022
|
+
}
|
|
4023
|
+
} else if (isUpKey(key, keybindings) || isDownKey(key, keybindings)) {
|
|
4024
|
+
if (errorMsg) {
|
|
4025
|
+
setError(void 0);
|
|
4026
|
+
}
|
|
4027
|
+
if (loop || isUpKey(key, keybindings) && active !== bounds.first || isDownKey(key, keybindings) && active !== bounds.last) {
|
|
4028
|
+
const offset = isUpKey(key, keybindings) ? -1 : 1;
|
|
4029
|
+
let next = active;
|
|
4030
|
+
do {
|
|
4031
|
+
next = (next + offset + items.length) % items.length;
|
|
4032
|
+
} while (!isNavigable$1(items[next]));
|
|
4033
|
+
setActive(next);
|
|
4034
|
+
}
|
|
4035
|
+
} else if (isSpaceKey(key)) {
|
|
4036
|
+
const activeItem = items[active];
|
|
4037
|
+
if (activeItem && !Separator.isSeparator(activeItem)) {
|
|
4038
|
+
if (activeItem.disabled) {
|
|
4039
|
+
setError(theme.i18n.disabledError);
|
|
4040
|
+
} else {
|
|
4041
|
+
setError(void 0);
|
|
4042
|
+
setItems(items.map((choice, i) => i === active ? toggle(choice) : choice));
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
} else if (key.name === shortcuts.all) {
|
|
4046
|
+
const selectAll = items.some((choice) => isSelectable$1(choice) && !choice.checked);
|
|
4047
|
+
setItems(items.map(check(selectAll)));
|
|
4048
|
+
} else if (key.name === shortcuts.invert) {
|
|
4049
|
+
setItems(items.map(toggle));
|
|
4050
|
+
} else if (isNumberKey(key)) {
|
|
4051
|
+
const selectedIndex = Number(key.name) - 1;
|
|
4052
|
+
let selectableIndex = -1;
|
|
4053
|
+
const position = items.findIndex((item) => {
|
|
4054
|
+
if (Separator.isSeparator(item))
|
|
4055
|
+
return false;
|
|
4056
|
+
selectableIndex++;
|
|
4057
|
+
return selectableIndex === selectedIndex;
|
|
4058
|
+
});
|
|
4059
|
+
const selectedItem = items[position];
|
|
4060
|
+
if (selectedItem && isSelectable$1(selectedItem)) {
|
|
4061
|
+
setActive(position);
|
|
4062
|
+
setItems(items.map((choice, i) => i === position ? toggle(choice) : choice));
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
});
|
|
4066
|
+
const message = theme.style.message(config.message, status);
|
|
4067
|
+
let description;
|
|
4068
|
+
const page = usePagination({
|
|
4069
|
+
items,
|
|
4070
|
+
active,
|
|
4071
|
+
renderItem({ item, isActive }) {
|
|
4072
|
+
if (Separator.isSeparator(item)) {
|
|
4073
|
+
return ` ${item.separator}`;
|
|
4074
|
+
}
|
|
4075
|
+
const cursor = isActive ? theme.icon.cursor : " ";
|
|
4076
|
+
if (item.disabled) {
|
|
4077
|
+
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
4078
|
+
const checkbox3 = item.checked ? theme.icon.disabledChecked : theme.icon.disabledUnchecked;
|
|
4079
|
+
return theme.style.disabled(`${cursor}${checkbox3} ${item.name} ${disabledLabel}`);
|
|
4080
|
+
}
|
|
4081
|
+
if (isActive) {
|
|
4082
|
+
description = item.description;
|
|
4083
|
+
}
|
|
4084
|
+
const checkbox2 = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
4085
|
+
const name = item.checked ? item.checkedName : item.name;
|
|
4086
|
+
const color = isActive ? theme.style.highlight : (x) => x;
|
|
4087
|
+
return color(`${cursor}${checkbox2} ${name}`);
|
|
4088
|
+
},
|
|
4089
|
+
pageSize,
|
|
4090
|
+
loop
|
|
4091
|
+
});
|
|
4092
|
+
if (status === "done") {
|
|
4093
|
+
const selection = items.filter(isChecked);
|
|
4094
|
+
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
4095
|
+
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
4096
|
+
}
|
|
4097
|
+
const keys = [
|
|
4098
|
+
["↑↓", "navigate"],
|
|
4099
|
+
["space", "select"]
|
|
4100
|
+
];
|
|
4101
|
+
if (shortcuts.all)
|
|
4102
|
+
keys.push([shortcuts.all, "all"]);
|
|
4103
|
+
if (shortcuts.invert)
|
|
4104
|
+
keys.push([shortcuts.invert, "invert"]);
|
|
4105
|
+
keys.push(["⏎", "submit"]);
|
|
4106
|
+
const helpLine = theme.style.keysHelpTip(keys);
|
|
4107
|
+
const lines = [
|
|
4108
|
+
[prefix, message].filter(Boolean).join(" "),
|
|
4109
|
+
page,
|
|
4110
|
+
" ",
|
|
4111
|
+
description ? theme.style.description(description) : "",
|
|
4112
|
+
errorMsg ? theme.style.error(errorMsg) : "",
|
|
4113
|
+
helpLine
|
|
4114
|
+
].filter(Boolean).join("\n").trimEnd();
|
|
4115
|
+
return `${lines}${cursorHide}`;
|
|
4116
|
+
});
|
|
4117
|
+
const inputTheme = {
|
|
4118
|
+
validationFailureMode: "keep"
|
|
4119
|
+
};
|
|
4120
|
+
const input = createPrompt((config, done) => {
|
|
4121
|
+
const { prefill = "tab" } = config;
|
|
4122
|
+
const theme = makeTheme(inputTheme, config.theme);
|
|
4123
|
+
const [status, setStatus] = useState("idle");
|
|
4124
|
+
const [defaultValue, setDefaultValue] = useState(String(config.default ?? ""));
|
|
4125
|
+
const [errorMsg, setError] = useState();
|
|
4126
|
+
const [value, setValue] = useState("");
|
|
4127
|
+
const prefix = usePrefix({ status, theme });
|
|
4128
|
+
async function validate(value2) {
|
|
4129
|
+
const { required, pattern, patternError = "Invalid input" } = config;
|
|
4130
|
+
if (required && !value2) {
|
|
4131
|
+
return "You must provide a value";
|
|
4132
|
+
}
|
|
4133
|
+
if (pattern && !pattern.test(value2)) {
|
|
4134
|
+
return patternError;
|
|
2275
4135
|
}
|
|
2276
|
-
|
|
4136
|
+
if (typeof config.validate === "function") {
|
|
4137
|
+
return await config.validate(value2) || "You must provide a valid value";
|
|
4138
|
+
}
|
|
4139
|
+
return true;
|
|
4140
|
+
}
|
|
4141
|
+
useKeypress(async (key, rl) => {
|
|
4142
|
+
if (status !== "idle") {
|
|
4143
|
+
return;
|
|
4144
|
+
}
|
|
4145
|
+
if (isEnterKey(key)) {
|
|
4146
|
+
const answer = value || defaultValue;
|
|
4147
|
+
setStatus("loading");
|
|
4148
|
+
const isValid = await validate(answer);
|
|
4149
|
+
if (isValid === true) {
|
|
4150
|
+
setValue(answer);
|
|
4151
|
+
setStatus("done");
|
|
4152
|
+
done(answer);
|
|
4153
|
+
} else {
|
|
4154
|
+
if (theme.validationFailureMode === "clear") {
|
|
4155
|
+
setValue("");
|
|
4156
|
+
} else {
|
|
4157
|
+
rl.write(value);
|
|
4158
|
+
}
|
|
4159
|
+
setError(isValid);
|
|
4160
|
+
setStatus("idle");
|
|
4161
|
+
}
|
|
4162
|
+
} else if (isBackspaceKey(key) && !value) {
|
|
4163
|
+
setDefaultValue("");
|
|
4164
|
+
} else if (isTabKey(key) && !value) {
|
|
4165
|
+
setDefaultValue("");
|
|
4166
|
+
rl.clearLine(0);
|
|
4167
|
+
rl.write(defaultValue);
|
|
4168
|
+
setValue(defaultValue);
|
|
4169
|
+
} else {
|
|
4170
|
+
setValue(rl.line);
|
|
4171
|
+
setError(void 0);
|
|
4172
|
+
}
|
|
4173
|
+
});
|
|
4174
|
+
useEffect((rl) => {
|
|
4175
|
+
if (prefill === "editable" && defaultValue) {
|
|
4176
|
+
rl.write(defaultValue);
|
|
4177
|
+
setValue(defaultValue);
|
|
4178
|
+
}
|
|
4179
|
+
}, []);
|
|
4180
|
+
const message = theme.style.message(config.message, status);
|
|
4181
|
+
let formattedValue = value;
|
|
4182
|
+
if (typeof config.transformer === "function") {
|
|
4183
|
+
formattedValue = config.transformer(value, { isFinal: status === "done" });
|
|
4184
|
+
} else if (status === "done") {
|
|
4185
|
+
formattedValue = theme.style.answer(value);
|
|
4186
|
+
}
|
|
4187
|
+
let defaultStr;
|
|
4188
|
+
if (defaultValue && status !== "done" && !value) {
|
|
4189
|
+
defaultStr = theme.style.defaultAnswer(defaultValue);
|
|
4190
|
+
}
|
|
4191
|
+
let error = "";
|
|
4192
|
+
if (errorMsg) {
|
|
4193
|
+
error = theme.style.error(errorMsg);
|
|
4194
|
+
}
|
|
4195
|
+
return [
|
|
4196
|
+
[prefix, message, defaultStr, formattedValue].filter((v) => v !== void 0).join(" "),
|
|
4197
|
+
error
|
|
4198
|
+
];
|
|
4199
|
+
});
|
|
4200
|
+
const selectTheme = {
|
|
4201
|
+
icon: { cursor: figures.pointer },
|
|
4202
|
+
style: {
|
|
4203
|
+
disabled: (text) => styleText("dim", text),
|
|
4204
|
+
description: (text) => styleText("cyan", text),
|
|
4205
|
+
keysHelpTip: (keys) => keys.map(([key, action]) => `${styleText("bold", key)} ${styleText("dim", action)}`).join(styleText("dim", " • "))
|
|
4206
|
+
},
|
|
4207
|
+
i18n: { disabledError: "This option is disabled and cannot be selected." },
|
|
4208
|
+
indexMode: "hidden",
|
|
4209
|
+
keybindings: []
|
|
4210
|
+
};
|
|
4211
|
+
function isSelectable(item) {
|
|
4212
|
+
return !Separator.isSeparator(item) && !item.disabled;
|
|
4213
|
+
}
|
|
4214
|
+
function isNavigable(item) {
|
|
4215
|
+
return !Separator.isSeparator(item);
|
|
4216
|
+
}
|
|
4217
|
+
function normalizeChoices(choices) {
|
|
4218
|
+
return choices.map((choice) => {
|
|
4219
|
+
if (Separator.isSeparator(choice))
|
|
4220
|
+
return choice;
|
|
4221
|
+
if (typeof choice !== "object" || choice === null || !("value" in choice)) {
|
|
4222
|
+
const name2 = String(choice);
|
|
4223
|
+
return {
|
|
4224
|
+
value: choice,
|
|
4225
|
+
name: name2,
|
|
4226
|
+
short: name2,
|
|
4227
|
+
disabled: false
|
|
4228
|
+
};
|
|
4229
|
+
}
|
|
4230
|
+
const name = choice.name ?? String(choice.value);
|
|
4231
|
+
const normalizedChoice = {
|
|
4232
|
+
value: choice.value,
|
|
4233
|
+
name,
|
|
4234
|
+
short: choice.short ?? name,
|
|
4235
|
+
disabled: choice.disabled ?? false
|
|
4236
|
+
};
|
|
4237
|
+
if (choice.description) {
|
|
4238
|
+
normalizedChoice.description = choice.description;
|
|
4239
|
+
}
|
|
4240
|
+
return normalizedChoice;
|
|
4241
|
+
});
|
|
4242
|
+
}
|
|
4243
|
+
const select = createPrompt((config, done) => {
|
|
4244
|
+
const { loop = true, pageSize = 7 } = config;
|
|
4245
|
+
const theme = makeTheme(selectTheme, config.theme);
|
|
4246
|
+
const { keybindings } = theme;
|
|
4247
|
+
const [status, setStatus] = useState("idle");
|
|
4248
|
+
const prefix = usePrefix({ status, theme });
|
|
4249
|
+
const searchTimeoutRef = useRef();
|
|
4250
|
+
const searchEnabled = !keybindings.includes("vim");
|
|
4251
|
+
const items = useMemo(() => normalizeChoices(config.choices), [config.choices]);
|
|
4252
|
+
const bounds = useMemo(() => {
|
|
4253
|
+
const first = items.findIndex(isNavigable);
|
|
4254
|
+
const last = items.findLastIndex(isNavigable);
|
|
4255
|
+
if (first === -1) {
|
|
4256
|
+
throw new ValidationError("[select prompt] No selectable choices. All choices are disabled.");
|
|
4257
|
+
}
|
|
4258
|
+
return { first, last };
|
|
4259
|
+
}, [items]);
|
|
4260
|
+
const defaultItemIndex = useMemo(() => {
|
|
4261
|
+
if (!("default" in config))
|
|
4262
|
+
return -1;
|
|
4263
|
+
return items.findIndex((item) => isSelectable(item) && item.value === config.default);
|
|
4264
|
+
}, [config.default, items]);
|
|
4265
|
+
const [active, setActive] = useState(defaultItemIndex === -1 ? bounds.first : defaultItemIndex);
|
|
4266
|
+
const selectedChoice = items[active];
|
|
4267
|
+
if (selectedChoice == null || Separator.isSeparator(selectedChoice)) {
|
|
4268
|
+
throw new Error("Active index does not point to a choice");
|
|
4269
|
+
}
|
|
4270
|
+
const [errorMsg, setError] = useState();
|
|
4271
|
+
useKeypress((key, rl) => {
|
|
4272
|
+
clearTimeout(searchTimeoutRef.current);
|
|
4273
|
+
if (errorMsg) {
|
|
4274
|
+
setError(void 0);
|
|
4275
|
+
}
|
|
4276
|
+
if (isEnterKey(key)) {
|
|
4277
|
+
if (selectedChoice.disabled) {
|
|
4278
|
+
setError(theme.i18n.disabledError);
|
|
4279
|
+
} else {
|
|
4280
|
+
setStatus("done");
|
|
4281
|
+
done(selectedChoice.value);
|
|
4282
|
+
}
|
|
4283
|
+
} else if (isUpKey(key, keybindings) || isDownKey(key, keybindings)) {
|
|
4284
|
+
rl.clearLine(0);
|
|
4285
|
+
if (loop || isUpKey(key, keybindings) && active !== bounds.first || isDownKey(key, keybindings) && active !== bounds.last) {
|
|
4286
|
+
const offset = isUpKey(key, keybindings) ? -1 : 1;
|
|
4287
|
+
let next = active;
|
|
4288
|
+
do {
|
|
4289
|
+
next = (next + offset + items.length) % items.length;
|
|
4290
|
+
} while (!isNavigable(items[next]));
|
|
4291
|
+
setActive(next);
|
|
4292
|
+
}
|
|
4293
|
+
} else if (isNumberKey(key) && !Number.isNaN(Number(rl.line))) {
|
|
4294
|
+
const selectedIndex = Number(rl.line) - 1;
|
|
4295
|
+
let selectableIndex = -1;
|
|
4296
|
+
const position = items.findIndex((item2) => {
|
|
4297
|
+
if (Separator.isSeparator(item2))
|
|
4298
|
+
return false;
|
|
4299
|
+
selectableIndex++;
|
|
4300
|
+
return selectableIndex === selectedIndex;
|
|
4301
|
+
});
|
|
4302
|
+
const item = items[position];
|
|
4303
|
+
if (item != null && isSelectable(item)) {
|
|
4304
|
+
setActive(position);
|
|
4305
|
+
}
|
|
4306
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
4307
|
+
rl.clearLine(0);
|
|
4308
|
+
}, 700);
|
|
4309
|
+
} else if (isBackspaceKey(key)) {
|
|
4310
|
+
rl.clearLine(0);
|
|
4311
|
+
} else if (searchEnabled) {
|
|
4312
|
+
const searchTerm = rl.line.toLowerCase();
|
|
4313
|
+
const matchIndex = items.findIndex((item) => {
|
|
4314
|
+
if (Separator.isSeparator(item) || !isSelectable(item))
|
|
4315
|
+
return false;
|
|
4316
|
+
return item.name.toLowerCase().startsWith(searchTerm);
|
|
4317
|
+
});
|
|
4318
|
+
if (matchIndex !== -1) {
|
|
4319
|
+
setActive(matchIndex);
|
|
4320
|
+
}
|
|
4321
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
4322
|
+
rl.clearLine(0);
|
|
4323
|
+
}, 700);
|
|
4324
|
+
}
|
|
4325
|
+
});
|
|
4326
|
+
useEffect(() => () => {
|
|
4327
|
+
clearTimeout(searchTimeoutRef.current);
|
|
4328
|
+
}, []);
|
|
4329
|
+
const message = theme.style.message(config.message, status);
|
|
4330
|
+
const helpLine = theme.style.keysHelpTip([
|
|
4331
|
+
["↑↓", "navigate"],
|
|
4332
|
+
["⏎", "select"]
|
|
4333
|
+
]);
|
|
4334
|
+
let separatorCount = 0;
|
|
4335
|
+
const page = usePagination({
|
|
4336
|
+
items,
|
|
4337
|
+
active,
|
|
4338
|
+
renderItem({ item, isActive, index }) {
|
|
4339
|
+
if (Separator.isSeparator(item)) {
|
|
4340
|
+
separatorCount++;
|
|
4341
|
+
return ` ${item.separator}`;
|
|
4342
|
+
}
|
|
4343
|
+
const cursor = isActive ? theme.icon.cursor : " ";
|
|
4344
|
+
const indexLabel = theme.indexMode === "number" ? `${index + 1 - separatorCount}. ` : "";
|
|
4345
|
+
if (item.disabled) {
|
|
4346
|
+
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
4347
|
+
const disabledCursor = isActive ? theme.icon.cursor : "-";
|
|
4348
|
+
return theme.style.disabled(`${disabledCursor} ${indexLabel}${item.name} ${disabledLabel}`);
|
|
4349
|
+
}
|
|
4350
|
+
const color = isActive ? theme.style.highlight : (x) => x;
|
|
4351
|
+
return color(`${cursor} ${indexLabel}${item.name}`);
|
|
4352
|
+
},
|
|
4353
|
+
pageSize,
|
|
4354
|
+
loop
|
|
4355
|
+
});
|
|
4356
|
+
if (status === "done") {
|
|
4357
|
+
return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ");
|
|
4358
|
+
}
|
|
4359
|
+
const { description } = selectedChoice;
|
|
4360
|
+
const lines = [
|
|
4361
|
+
[prefix, message].filter(Boolean).join(" "),
|
|
4362
|
+
page,
|
|
4363
|
+
" ",
|
|
4364
|
+
description ? theme.style.description(description) : "",
|
|
4365
|
+
errorMsg ? theme.style.error(errorMsg) : "",
|
|
4366
|
+
helpLine
|
|
4367
|
+
].filter(Boolean).join("\n").trimEnd();
|
|
4368
|
+
return `${lines}${cursorHide}`;
|
|
4369
|
+
});
|
|
4370
|
+
const INIT_ACTION_LABELS = {
|
|
4371
|
+
configs: "Создать базовые конфиги",
|
|
4372
|
+
template: "Создать стартовый шаблон",
|
|
4373
|
+
agents: "Обновить AGENTS.md",
|
|
4374
|
+
mcp: "Добавить MCP-настройки",
|
|
4375
|
+
install: "Запустить установку зависимостей"
|
|
4376
|
+
};
|
|
4377
|
+
const INIT_ACTION_DESCRIPTIONS = {
|
|
4378
|
+
configs: "tsconfig.json, vite.config.ts, eslint.config.js и env.d.ts",
|
|
4379
|
+
template: "Vue-точка входа, страница настроек, виджет заказа, i18n и publish script",
|
|
4380
|
+
agents: "Общие и пакетные инструкции для AI-агентов",
|
|
4381
|
+
mcp: ".mcp.json и MCP-инструкции пакетов",
|
|
4382
|
+
install: "Запуск выбранного package manager после изменения package.json"
|
|
4383
|
+
};
|
|
4384
|
+
const resolveDefaultSourceRoot = (cwd, options) => {
|
|
4385
|
+
if (options.srcDir) {
|
|
4386
|
+
return options.srcDir;
|
|
4387
|
+
}
|
|
4388
|
+
if (options.target) {
|
|
4389
|
+
return options.target;
|
|
2277
4390
|
}
|
|
4391
|
+
return fs.existsSync(path.join(cwd, "src")) ? "./web" : "./src";
|
|
2278
4392
|
};
|
|
2279
|
-
const
|
|
4393
|
+
const resolvePromptedPackages = async (options) => {
|
|
2280
4394
|
if (options.packages) {
|
|
2281
4395
|
return options.packages;
|
|
2282
4396
|
}
|
|
2283
4397
|
const defaultPackageIds = [...DEFAULT_INIT_PACKAGE_IDS, ...options.with ?? []];
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
4398
|
+
if (defaultPackageIds.includes("testing")) {
|
|
4399
|
+
throw new Error("@retailcrm/embed-ui-v1-testing is not published for public init yet");
|
|
4400
|
+
}
|
|
4401
|
+
const selectedPackageIds = await checkbox({
|
|
4402
|
+
message: "Пакеты для init",
|
|
4403
|
+
choices: INSTALLABLE_PACKAGES.filter((selectedPackage) => selectedPackage.id !== "testing").map((selectedPackage) => ({
|
|
4404
|
+
name: `${selectedPackage.id}: ${selectedPackage.name}`,
|
|
4405
|
+
value: selectedPackage.id,
|
|
4406
|
+
checked: defaultPackageIds.includes(selectedPackage.id),
|
|
4407
|
+
description: selectedPackage.description
|
|
4408
|
+
})),
|
|
4409
|
+
required: true
|
|
4410
|
+
});
|
|
4411
|
+
resolveInstallPackages(selectedPackageIds);
|
|
4412
|
+
return selectedPackageIds;
|
|
4413
|
+
};
|
|
4414
|
+
const resolveAvailableActions = (options) => {
|
|
4415
|
+
const actions = [];
|
|
4416
|
+
if (!options.agentsOnly && !options.noConfigs) {
|
|
4417
|
+
actions.push("configs");
|
|
2288
4418
|
}
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
);
|
|
2295
|
-
const tokens = parsePackageList(answer);
|
|
2296
|
-
try {
|
|
2297
|
-
const selectedPackages = resolveInstallPackages(tokens);
|
|
2298
|
-
if (selectedPackages.some((selectedPackage) => selectedPackage.id === "testing")) {
|
|
2299
|
-
throw new Error("@retailcrm/embed-ui-v1-testing is not published for public init yet");
|
|
2300
|
-
}
|
|
2301
|
-
return tokens;
|
|
2302
|
-
} catch (error) {
|
|
2303
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
2304
|
-
}
|
|
4419
|
+
if (!options.agentsOnly && !options.noTemplate) {
|
|
4420
|
+
actions.push("template");
|
|
4421
|
+
}
|
|
4422
|
+
if (!options.noAgents) {
|
|
4423
|
+
actions.push("agents");
|
|
2305
4424
|
}
|
|
4425
|
+
if (!options.noMcp) {
|
|
4426
|
+
actions.push("mcp");
|
|
4427
|
+
}
|
|
4428
|
+
if (!options.agentsOnly && !options.noInstall) {
|
|
4429
|
+
actions.push("install");
|
|
4430
|
+
}
|
|
4431
|
+
return actions;
|
|
4432
|
+
};
|
|
4433
|
+
const applyPromptedActions = (options, selectedActions) => {
|
|
4434
|
+
const selectedActionSet = new Set(selectedActions);
|
|
4435
|
+
options.noConfigs = options.noConfigs || !selectedActionSet.has("configs");
|
|
4436
|
+
options.noTemplate = options.noTemplate || !selectedActionSet.has("template");
|
|
4437
|
+
options.noAgents = options.noAgents || !selectedActionSet.has("agents");
|
|
4438
|
+
options.noMcp = options.noMcp || !selectedActionSet.has("mcp");
|
|
4439
|
+
options.noInstall = options.noInstall || !selectedActionSet.has("install");
|
|
4440
|
+
};
|
|
4441
|
+
const resolvePromptedActions = async (options) => {
|
|
4442
|
+
const availableActions = resolveAvailableActions(options);
|
|
4443
|
+
if (availableActions.length === 0) {
|
|
4444
|
+
return [];
|
|
4445
|
+
}
|
|
4446
|
+
return checkbox({
|
|
4447
|
+
message: "Действия init",
|
|
4448
|
+
choices: availableActions.map((action) => ({
|
|
4449
|
+
name: INIT_ACTION_LABELS[action],
|
|
4450
|
+
value: action,
|
|
4451
|
+
checked: true,
|
|
4452
|
+
description: INIT_ACTION_DESCRIPTIONS[action]
|
|
4453
|
+
}))
|
|
4454
|
+
});
|
|
4455
|
+
};
|
|
4456
|
+
const resolvePromptedPackageManager = async (detectedPackageManager, explicitPackageManager) => {
|
|
4457
|
+
if (explicitPackageManager) {
|
|
4458
|
+
return explicitPackageManager;
|
|
4459
|
+
}
|
|
4460
|
+
const defaultPackageManager = detectedPackageManager ?? "npm";
|
|
4461
|
+
return select({
|
|
4462
|
+
message: "Package manager",
|
|
4463
|
+
default: defaultPackageManager,
|
|
4464
|
+
choices: PACKAGE_MANAGERS.map((packageManager) => ({
|
|
4465
|
+
name: packageManager,
|
|
4466
|
+
value: packageManager
|
|
4467
|
+
}))
|
|
4468
|
+
});
|
|
2306
4469
|
};
|
|
2307
4470
|
const resolveInteractiveInitOptions = async (cwd, options, detectedPackageManager) => {
|
|
2308
4471
|
if (!options.interactive) {
|
|
2309
4472
|
return options;
|
|
2310
4473
|
}
|
|
2311
|
-
if (!process$
|
|
4474
|
+
if (!process$2.stdin.isTTY || !process$2.stdout.isTTY) {
|
|
2312
4475
|
throw new Error("Interactive init mode requires a TTY. Use explicit flags or omit --interactive.");
|
|
2313
4476
|
}
|
|
2314
|
-
const
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
nextOptions.target = sourceRoot;
|
|
2327
|
-
}
|
|
2328
|
-
nextOptions.packages = await askPackages(readline, nextOptions);
|
|
2329
|
-
nextOptions.noConfigs = nextOptions.noConfigs || !await askBoolean(readline, "Создать базовые конфиги", true);
|
|
2330
|
-
nextOptions.noTemplate = nextOptions.noTemplate || !await askBoolean(readline, "Создать стартовый шаблон", true);
|
|
2331
|
-
}
|
|
2332
|
-
nextOptions.packageManager = await askPackageManager(
|
|
2333
|
-
readline,
|
|
2334
|
-
detectedPackageManager,
|
|
2335
|
-
nextOptions.packageManager
|
|
2336
|
-
);
|
|
2337
|
-
nextOptions.noAgents = nextOptions.noAgents || !await askBoolean(readline, "Обновить AGENTS.md", true);
|
|
2338
|
-
nextOptions.noMcp = nextOptions.noMcp || !await askBoolean(readline, "Добавить MCP-настройки", true);
|
|
2339
|
-
if (!nextOptions.agentsOnly) {
|
|
2340
|
-
nextOptions.noInstall = nextOptions.noInstall || !await askBoolean(readline, "Запустить установку зависимостей", true);
|
|
4477
|
+
const nextOptions = { ...options };
|
|
4478
|
+
if (!nextOptions.agentsOnly) {
|
|
4479
|
+
const defaultSourceRoot = resolveDefaultSourceRoot(cwd, nextOptions);
|
|
4480
|
+
const sourceRoot = await input({
|
|
4481
|
+
message: "Frontend source root",
|
|
4482
|
+
default: defaultSourceRoot,
|
|
4483
|
+
validate: (value) => value.trim().length > 0 || "Укажите каталог фронтенда."
|
|
4484
|
+
});
|
|
4485
|
+
if (nextOptions.srcDir) {
|
|
4486
|
+
nextOptions.srcDir = sourceRoot;
|
|
4487
|
+
} else {
|
|
4488
|
+
nextOptions.target = sourceRoot;
|
|
2341
4489
|
}
|
|
2342
|
-
|
|
2343
|
-
} finally {
|
|
2344
|
-
readline.close();
|
|
4490
|
+
nextOptions.packages = await resolvePromptedPackages(nextOptions);
|
|
2345
4491
|
}
|
|
4492
|
+
const selectedActions = await resolvePromptedActions(nextOptions);
|
|
4493
|
+
applyPromptedActions(nextOptions, selectedActions);
|
|
4494
|
+
nextOptions.packageManager = await resolvePromptedPackageManager(
|
|
4495
|
+
detectedPackageManager,
|
|
4496
|
+
nextOptions.packageManager
|
|
4497
|
+
);
|
|
4498
|
+
return nextOptions;
|
|
2346
4499
|
};
|
|
2347
4500
|
const DEFAULT_INIT_DIRS = ["endpoint", "pages", "widgets", "shared", "i18n"];
|
|
2348
4501
|
const detectPackageManagerByLockfile = (cwd) => {
|
|
@@ -2365,21 +4518,25 @@ const resolvePackageManagerVersion = (packageManager) => {
|
|
|
2365
4518
|
return null;
|
|
2366
4519
|
}
|
|
2367
4520
|
};
|
|
4521
|
+
const resolvePackageManagerMajorVersion = (packageManager) => {
|
|
4522
|
+
const major = resolvePackageManagerVersion(packageManager)?.match(/^\d+/u)?.[0];
|
|
4523
|
+
return major ? Number(major) : null;
|
|
4524
|
+
};
|
|
2368
4525
|
const promptForPackageManager = async () => {
|
|
2369
|
-
const
|
|
2370
|
-
input: process$
|
|
2371
|
-
output: process$
|
|
4526
|
+
const readline2 = createInterface({
|
|
4527
|
+
input: process$2.stdin,
|
|
4528
|
+
output: process$2.stdout
|
|
2372
4529
|
});
|
|
2373
4530
|
try {
|
|
2374
4531
|
while (true) {
|
|
2375
|
-
const answer = await
|
|
4532
|
+
const answer = await readline2.question("Choose package manager (yarn/npm/pnpm/bun): ");
|
|
2376
4533
|
if (PACKAGE_MANAGERS.includes(answer)) {
|
|
2377
4534
|
return answer;
|
|
2378
4535
|
}
|
|
2379
4536
|
console.error(`Unknown package manager: ${answer}`);
|
|
2380
4537
|
}
|
|
2381
4538
|
} finally {
|
|
2382
|
-
|
|
4539
|
+
readline2.close();
|
|
2383
4540
|
}
|
|
2384
4541
|
};
|
|
2385
4542
|
const resolvePackageManager = async (cwd, explicitPackageManager) => {
|
|
@@ -2393,7 +4550,7 @@ const resolvePackageManager = async (cwd, explicitPackageManager) => {
|
|
|
2393
4550
|
if (packageManager) {
|
|
2394
4551
|
return packageManager;
|
|
2395
4552
|
}
|
|
2396
|
-
if (process$
|
|
4553
|
+
if (process$2.stdin.isTTY && process$2.stdout.isTTY) {
|
|
2397
4554
|
return promptForPackageManager();
|
|
2398
4555
|
}
|
|
2399
4556
|
return "npm";
|
|
@@ -2605,15 +4762,48 @@ const runInstall = (cwd, packageManager, options, changes, packageJsonChanged) =
|
|
|
2605
4762
|
changes.skipped.push("install skipped because package.json was not changed");
|
|
2606
4763
|
return;
|
|
2607
4764
|
}
|
|
2608
|
-
const args =
|
|
4765
|
+
const args = resolveInstallArgs(packageManager);
|
|
2609
4766
|
changes.install = `${packageManager} ${args.join(" ")}`;
|
|
2610
4767
|
if (options.dryRun) {
|
|
2611
4768
|
return;
|
|
2612
4769
|
}
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
4770
|
+
try {
|
|
4771
|
+
execFileSync(packageManager, args, {
|
|
4772
|
+
cwd,
|
|
4773
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4774
|
+
});
|
|
4775
|
+
} catch (error) {
|
|
4776
|
+
printExecErrorOutput(error);
|
|
4777
|
+
throw error;
|
|
4778
|
+
}
|
|
4779
|
+
};
|
|
4780
|
+
const resolveInstallArgs = (packageManager) => {
|
|
4781
|
+
if (packageManager === "yarn" && resolvePackageManagerMajorVersion(packageManager) === 1) {
|
|
4782
|
+
return ["install", "--silent"];
|
|
4783
|
+
}
|
|
4784
|
+
if (packageManager === "npm") {
|
|
4785
|
+
return ["install", "--loglevel=error"];
|
|
4786
|
+
}
|
|
4787
|
+
if (packageManager === "pnpm") {
|
|
4788
|
+
return ["install", "--loglevel=error"];
|
|
4789
|
+
}
|
|
4790
|
+
if (packageManager === "bun") {
|
|
4791
|
+
return ["install", "--silent"];
|
|
4792
|
+
}
|
|
4793
|
+
return ["install"];
|
|
4794
|
+
};
|
|
4795
|
+
const printExecErrorOutput = (error) => {
|
|
4796
|
+
if (!error || typeof error !== "object") {
|
|
4797
|
+
return;
|
|
4798
|
+
}
|
|
4799
|
+
const execError = error;
|
|
4800
|
+
for (const field of ["stdout", "stderr"]) {
|
|
4801
|
+
const value = execError[field];
|
|
4802
|
+
const output = value instanceof Buffer ? value.toString("utf8") : value;
|
|
4803
|
+
if (typeof output === "string" && output.trim().length > 0) {
|
|
4804
|
+
console.error(output.trim());
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
2617
4807
|
};
|
|
2618
4808
|
const runInit = async (options) => {
|
|
2619
4809
|
const cwd = resolveInitCwd(options);
|
|
@@ -2627,23 +4817,24 @@ const runInit = async (options) => {
|
|
|
2627
4817
|
throw new Error(`Target path is not a directory: ${sourceRoot}`);
|
|
2628
4818
|
}
|
|
2629
4819
|
const selectedPackages = resolveInitPackages(interactiveOptions.packages, interactiveOptions.with);
|
|
2630
|
-
const version = interactiveOptions.agentsOnly ? interactiveOptions.version ?? "not used" : interactiveOptions.version ??
|
|
4820
|
+
const version = interactiveOptions.agentsOnly ? interactiveOptions.version ?? "not used" : interactiveOptions.version ?? resolveDefaultInitVersion();
|
|
4821
|
+
const resolvedOptions = version === "not used" ? interactiveOptions : { ...interactiveOptions, version };
|
|
2631
4822
|
const packageManager = interactiveOptions.agentsOnly ? interactiveOptions.packageManager ?? detectPackageManagerByLockfile(cwd) ?? "npm" : await resolvePackageManager(cwd, interactiveOptions.packageManager);
|
|
2632
4823
|
const changes = createInitChanges();
|
|
2633
|
-
applyInitPreflight(cwd, sourceRoot, packageManager, selectedPackages, version,
|
|
4824
|
+
applyInitPreflight(cwd, sourceRoot, packageManager, selectedPackages, version, resolvedOptions, changes);
|
|
2634
4825
|
let packageJsonPath = null;
|
|
2635
|
-
if (!
|
|
2636
|
-
packageJsonPath = applyInitPackageJson(cwd, selectedPackages, version, packageManager,
|
|
2637
|
-
applyInitDirectories(sourceRoot,
|
|
2638
|
-
applyInitConfigs(cwd, sourceRoot,
|
|
2639
|
-
applyInitTemplate(cwd, sourceRoot, packageManager,
|
|
2640
|
-
applyInitPackageConfigHooks(cwd, selectedPackages, packageManager,
|
|
2641
|
-
}
|
|
2642
|
-
applyInitAgents(cwd, selectedPackages, packageManager,
|
|
2643
|
-
runInstall(cwd, packageManager,
|
|
2644
|
-
printInitReport(cwd, sourceRoot, version, packageManager, changes,
|
|
2645
|
-
};
|
|
2646
|
-
const main = async (argv = process$
|
|
4826
|
+
if (!resolvedOptions.agentsOnly) {
|
|
4827
|
+
packageJsonPath = applyInitPackageJson(cwd, selectedPackages, version, packageManager, resolvedOptions, changes);
|
|
4828
|
+
applyInitDirectories(sourceRoot, resolvedOptions, changes);
|
|
4829
|
+
applyInitConfigs(cwd, sourceRoot, resolvedOptions, changes);
|
|
4830
|
+
applyInitTemplate(cwd, sourceRoot, packageManager, resolvedOptions, changes);
|
|
4831
|
+
applyInitPackageConfigHooks(cwd, selectedPackages, packageManager, resolvedOptions, changes);
|
|
4832
|
+
}
|
|
4833
|
+
applyInitAgents(cwd, selectedPackages, packageManager, resolvedOptions, changes);
|
|
4834
|
+
runInstall(cwd, packageManager, resolvedOptions, changes, Boolean(packageJsonPath && changes.packageJson.length > 0));
|
|
4835
|
+
printInitReport(cwd, sourceRoot, version, packageManager, changes, resolvedOptions);
|
|
4836
|
+
};
|
|
4837
|
+
const main = async (argv = process$2.argv.slice(2)) => {
|
|
2647
4838
|
const options = parseArgs(argv);
|
|
2648
4839
|
if (options.command === "init") {
|
|
2649
4840
|
await runInit(options);
|
|
@@ -2663,7 +4854,7 @@ const isSameExecutablePath = (entryPath, moduleUrl) => {
|
|
|
2663
4854
|
}
|
|
2664
4855
|
};
|
|
2665
4856
|
const isExecutedDirectly = () => {
|
|
2666
|
-
const entryPath = process$
|
|
4857
|
+
const entryPath = process$2.argv[1];
|
|
2667
4858
|
if (!entryPath) {
|
|
2668
4859
|
return false;
|
|
2669
4860
|
}
|
|
@@ -2675,7 +4866,7 @@ if (isExecutedDirectly()) {
|
|
|
2675
4866
|
} catch (error) {
|
|
2676
4867
|
const message = error instanceof Error ? error.message : String(error);
|
|
2677
4868
|
console.error(message);
|
|
2678
|
-
process$
|
|
4869
|
+
process$2.exit(1);
|
|
2679
4870
|
}
|
|
2680
4871
|
}
|
|
2681
4872
|
export {
|