@retailcrm/embed-ui 0.9.22-alpha.1 → 0.9.22-alpha.3

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