gunshi 0.35.0 → 0.35.2

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.
@@ -1,7 +1,5 @@
1
- import { n as CLI_OPTIONS_DEFAULT, r as NOOP } from "./constants-CQq1R_68.js";
2
- import { i as isLazyCommand, o as resolveLazyCommand, r as getCommandSubCommands, s as kebabnize, t as create } from "./utils-DNVHO9MQ.js";
3
- import { createCommandContext } from "./context.js";
4
- //#region ../../node_modules/.pnpm/args-tokens@0.27.0/node_modules/args-tokens/lib/parser.js
1
+ import { n as kebabnize, t as formatChoices } from "./utils-BKhsrjPW.js";
2
+ //#region ../../node_modules/.pnpm/args-tokens@0.28.0/node_modules/args-tokens/lib/parser.js
5
3
  /**
6
4
  * forked from `nodejs/node` (`pkgjs/parseargs`)
7
5
  * repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
@@ -206,7 +204,7 @@ function hasOptionValue(value) {
206
204
  return !(value == null) && value.codePointAt(0) !== HYPHEN_CODE;
207
205
  }
208
206
  //#endregion
209
- //#region ../../node_modules/.pnpm/args-tokens@0.27.0/node_modules/args-tokens/lib/resolver.js
207
+ //#region ../../node_modules/.pnpm/args-tokens@0.28.0/node_modules/args-tokens/lib/resolver.js
210
208
  /**
211
209
  * Entry point of argument options resolver.
212
210
  *
@@ -216,6 +214,60 @@ function hasOptionValue(value) {
216
214
  * @author kazuya kawaguchi (a.k.a. kazupon)
217
215
  * @license MIT
218
216
  */
217
+ /**
218
+ * Machine-readable error codes for {@link ArgsValidationError}.
219
+ *
220
+ * Each code identifies a validation failure category and is also suitable as an
221
+ * i18n resource key for localized rendering.
222
+ */
223
+ const ArgsValidationErrorKeys = {
224
+ requiredOption: "err:arg:required-option",
225
+ requiredPositional: "err:arg:required-positional",
226
+ invalidType: "err:arg:invalid-type",
227
+ invalidChoice: "err:arg:invalid-choice",
228
+ customParse: "err:arg:custom-parse",
229
+ unknownOption: "err:arg:unknown-option"
230
+ };
231
+ /**
232
+ * An error that contains structured metadata for argument validation failures.
233
+ *
234
+ * The `message` remains the English fallback message. Renderers can use `code`
235
+ * and `values` to localize the error, falling back to `message` when localization
236
+ * is unavailable.
237
+ */
238
+ var ArgsValidationError = class extends Error {
239
+ /**
240
+ * Machine-readable error code for this validation failure.
241
+ *
242
+ * This code can also be used as an i18n resource key.
243
+ */
244
+ code;
245
+ /**
246
+ * Interpolation values for `code`.
247
+ */
248
+ values;
249
+ /**
250
+ * Create an `ArgsValidationError` instance.
251
+ *
252
+ * @param message - fallback error message
253
+ * @param options - structured validation metadata
254
+ */
255
+ constructor(message, options = {}) {
256
+ super(message, { cause: options.cause });
257
+ this.name = "ArgsValidationError";
258
+ this.code = options.code;
259
+ this.values = options.values ?? {};
260
+ }
261
+ };
262
+ /**
263
+ * Check whether the given value is an {@link ArgsValidationError}.
264
+ *
265
+ * @param error - value to check
266
+ * @returns `true` when the value is an `ArgsValidationError`
267
+ */
268
+ function isArgsValidationError(error) {
269
+ return error instanceof ArgsValidationError;
270
+ }
219
271
  const SKIP_POSITIONAL_DEFAULT = -1;
220
272
  /**
221
273
  * Resolve command line arguments.
@@ -379,11 +431,9 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
379
431
  const parsed = [];
380
432
  for (let i = positionalsCount; i < endPositionals; i++) {
381
433
  const p = positionalTokens[i];
382
- try {
383
- parsed.push(schema.parse(p.value));
384
- } catch (error) {
385
- errors.push(error);
386
- }
434
+ const [parsedValue, error] = parseSchemaValue(p.value, rawArg, arg, schema);
435
+ if (error) errors.push(error);
436
+ else parsed.push(parsedValue);
387
437
  }
388
438
  values[rawArg] = parsed;
389
439
  } else {
@@ -393,22 +443,22 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
393
443
  }
394
444
  positionalsCount = endPositionals;
395
445
  explicit[rawArg] = true;
396
- } else if (schema.required) errors.push(createRequireError(arg, schema));
397
- } else if (schema.required) errors.push(createRequireError(arg, schema));
446
+ } else if (schema.required) errors.push(createRequireError(rawArg, arg, schema));
447
+ } else if (schema.required) errors.push(createRequireError(rawArg, arg, schema));
398
448
  } else {
399
449
  const positional = positionalTokens[positionalsCount];
400
450
  if (shouldRequireMissingSinglePositional(schema)) {
401
451
  if (positional != null) {
402
- resolveSinglePositionalValue(values, errors, rawArg, schema, positional);
452
+ resolveSinglePositionalValue(values, errors, rawArg, arg, schema, positional);
403
453
  explicit[rawArg] = true;
404
454
  positionalsCount++;
405
- } else errors.push(createRequireError(arg, schema));
455
+ } else errors.push(createRequireError(rawArg, arg, schema));
406
456
  continue;
407
457
  }
408
458
  if (positional != null) {
409
459
  const requiredPositionals = getRequiredPositionalsAfter(rawArg);
410
460
  if (Math.max(positionalTokens.length - positionalsCount, 0) > requiredPositionals) {
411
- resolveSinglePositionalValue(values, errors, rawArg, schema, positional);
461
+ resolveSinglePositionalValue(values, errors, rawArg, arg, schema, positional);
412
462
  explicit[rawArg] = true;
413
463
  positionalsCount++;
414
464
  continue;
@@ -422,14 +472,14 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
422
472
  if (!optionTokens.find((token) => {
423
473
  return schema.short && token.name === schema.short || token.rawName && hasLongOptionPrefix(token.rawName) && token.name === arg;
424
474
  })) {
425
- errors.push(createRequireError(arg, schema));
475
+ errors.push(createRequireError(rawArg, arg, schema));
426
476
  continue;
427
477
  }
428
478
  }
429
479
  for (let i = 0; i < optionTokens.length; i++) {
430
480
  const token = optionTokens[i];
431
481
  if (checkTokenName(arg, schema, token) && token.rawName != void 0 && hasLongOptionPrefix(token.rawName) || schema.short === token.name && token.rawName != void 0 && isShortOption(token.rawName)) {
432
- const invalid = validateRequire(token, arg, schema);
482
+ const invalid = validateRequire(token, rawArg, arg, schema);
433
483
  if (invalid) {
434
484
  errors.push(invalid);
435
485
  continue;
@@ -437,7 +487,7 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
437
487
  explicit[rawArg] = true;
438
488
  const actualInputName = isShortOption(token.rawName) ? `-${token.name}` : `--${arg}`;
439
489
  actualInputNames.set(rawArg, actualInputName);
440
- const [parsedValue, error] = parse(token, arg, schema);
490
+ const [parsedValue, error] = parse(token, rawArg, arg, schema);
441
491
  if (error) errors.push(error);
442
492
  else if (schema.multiple) {
443
493
  values[rawArg] ||= [];
@@ -457,39 +507,49 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
457
507
  explicit
458
508
  };
459
509
  }
460
- function parse(token, option, schema) {
461
- if (typeof schema.parse === "function") try {
510
+ function parse(token, rawArg, option, schema) {
511
+ if (typeof schema.parse === "function") {
462
512
  if (schema.type === "boolean") {
463
513
  const boolValue = !(schema.negatable && token.name.startsWith("no-"));
464
- return [schema.parse(String(boolValue)), void 0];
514
+ return parseSchemaValue(String(boolValue), rawArg, option, schema);
465
515
  }
466
- return [schema.parse(token.value ?? String(schema.default ?? "")), void 0];
467
- } catch (error) {
468
- return [void 0, error];
516
+ return parseSchemaValue(token.value ?? String(schema.default ?? ""), rawArg, option, schema);
469
517
  }
470
518
  switch (schema.type) {
471
- case "string": return typeof token.value === "string" ? [token.value || schema.default, void 0] : [void 0, createTypeError(option, schema)];
519
+ case "string": return typeof token.value === "string" ? [token.value || schema.default, void 0] : [void 0, createTypeError(rawArg, option, schema, token.value)];
472
520
  case "boolean": return [!(schema.negatable && token.name.startsWith("no-")), void 0];
473
521
  case "number":
474
- if (!isNumeric(token.value)) return [void 0, createTypeError(option, schema)];
522
+ if (!isNumeric(token.value)) return [void 0, createTypeError(rawArg, option, schema, token.value)];
475
523
  return token.value ? [+token.value, void 0] : [+(schema.default || ""), void 0];
476
524
  case "enum":
477
- if (schema.choices && !schema.choices.includes(token.value)) return [void 0, new ArgResolveError(`Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}should be chosen from '${schema.type}' [${schema.choices.map((c) => JSON.stringify(c)).join(", ")}] values`, option, "type", schema)];
525
+ if (schema.choices && !schema.choices.includes(token.value)) return [void 0, createChoiceError(rawArg, option, schema, token.value)];
478
526
  return [token.value || schema.default, void 0];
479
527
  case "custom": throw new TypeError(`argument '${option}' should have a 'parse' function`);
480
528
  default: throw new Error(`Unsupported argument type '${schema.type}' for option '${option}'`);
481
529
  }
482
530
  }
483
- function createRequireError(option, schema) {
484
- return new ArgResolveError(schema.type === "positional" ? `Positional argument '${option}' is required` : `Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}is required`, option, "required", schema);
485
- }
486
- function resolveSinglePositionalValue(values, errors, rawArg, schema, positional) {
487
- if (typeof schema.parse === "function") try {
488
- values[rawArg] = schema.parse(positional.value);
531
+ function parseSchemaValue(value, rawArg, option, schema) {
532
+ try {
533
+ return [schema.parse(value), void 0];
489
534
  } catch (error) {
490
- errors.push(error);
535
+ return [void 0, createCustomParseError(error, rawArg, option, schema, value)];
491
536
  }
492
- else values[rawArg] = positional.value;
537
+ }
538
+ function createRequireError(rawArg, option, schema) {
539
+ return new ArgResolveError(schema.type === "positional" ? `Positional argument '${option}' is required` : `Optional argument ${createOptionDisplayName(option, schema)} is required`, option, "required", schema, {
540
+ code: schema.type === "positional" ? ArgsValidationErrorKeys.requiredPositional : ArgsValidationErrorKeys.requiredOption,
541
+ values: schema.type === "positional" ? { name: rawArg } : {
542
+ displayName: createOptionDisplayName(option, schema),
543
+ name: rawArg
544
+ }
545
+ });
546
+ }
547
+ function resolveSinglePositionalValue(values, errors, rawArg, option, schema, positional) {
548
+ if (typeof schema.parse === "function") {
549
+ const [parsedValue, error] = parseSchemaValue(positional.value, rawArg, option, schema);
550
+ if (error) errors.push(error);
551
+ else values[rawArg] = parsedValue;
552
+ } else values[rawArg] = positional.value;
493
553
  }
494
554
  function hasDefault(schema) {
495
555
  return schema.default != null;
@@ -519,7 +579,7 @@ function createRequiredPositionalsAfter(argEntries) {
519
579
  * An error that occurs when resolving arguments.
520
580
  * This error is thrown when the argument is not valid.
521
581
  */
522
- var ArgResolveError = class extends Error {
582
+ var ArgResolveError = class extends ArgsValidationError {
523
583
  name;
524
584
  schema;
525
585
  type;
@@ -528,24 +588,78 @@ var ArgResolveError = class extends Error {
528
588
  *
529
589
  * @param message - the error message
530
590
  * @param name - the name of the argument
531
- * @param type - the type of the error, either 'type' or 'required'
591
+ * @param type - the type of the error: 'type', 'required', or 'conflict'
532
592
  * @param schema - the argument schema that caused the error
593
+ * @param options - structured validation metadata
533
594
  */
534
- constructor(message, name, type, schema) {
535
- super(message);
595
+ constructor(message, name, type, schema, options = {}) {
596
+ super(message, options);
536
597
  this.name = name;
537
598
  this.type = type;
538
599
  this.schema = schema;
539
600
  }
540
601
  };
541
- function validateRequire(token, option, schema) {
542
- if (schema.required && schema.type !== "boolean" && !token.value) return createRequireError(option, schema);
602
+ function validateRequire(token, rawArg, option, schema) {
603
+ if (schema.required && schema.type !== "boolean" && !token.value) return createRequireError(rawArg, option, schema);
543
604
  }
544
605
  function isNumeric(str) {
545
606
  return str.trim() !== "" && !isNaN(str);
546
607
  }
547
- function createTypeError(option, schema) {
548
- return new ArgResolveError(`Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}should be '${schema.type}'`, option, "type", schema);
608
+ function createTypeError(rawArg, option, schema, actual) {
609
+ return new ArgResolveError(`Optional argument ${createOptionDisplayName(option, schema)} should be '${schema.type}'`, option, "type", schema, {
610
+ code: ArgsValidationErrorKeys.invalidType,
611
+ values: {
612
+ displayName: createOptionDisplayName(option, schema),
613
+ name: rawArg,
614
+ expected: schema.type,
615
+ ...actual != null ? { actual } : {}
616
+ }
617
+ });
618
+ }
619
+ function createChoiceError(rawArg, option, schema, actual) {
620
+ const choices = schema.choices ?? [];
621
+ return new ArgResolveError(`Optional argument ${createOptionDisplayName(option, schema)} should be chosen from '${schema.type}' [${formatChoices(choices)}] values`, option, "type", schema, {
622
+ code: ArgsValidationErrorKeys.invalidChoice,
623
+ values: {
624
+ displayName: createOptionDisplayName(option, schema),
625
+ name: rawArg,
626
+ expected: schema.type,
627
+ choices: formatChoices(choices),
628
+ choiceValues: [...choices],
629
+ ...actual != null ? { actual } : {}
630
+ }
631
+ });
632
+ }
633
+ function createCustomParseError(error, rawArg, option, schema, value) {
634
+ if (isArgsValidationError(error)) {
635
+ augmentValidationError(error, rawArg, option, schema, value);
636
+ return error;
637
+ }
638
+ const reason = getErrorReason(error);
639
+ return new ArgsValidationError(reason, {
640
+ code: ArgsValidationErrorKeys.customParse,
641
+ values: {
642
+ displayName: createArgumentDisplayName(option, schema),
643
+ name: rawArg,
644
+ reason
645
+ },
646
+ cause: error
647
+ });
648
+ }
649
+ function augmentValidationError(error, rawArg, option, schema, value) {
650
+ const values = error.values;
651
+ values.name ??= rawArg;
652
+ values.displayName ??= createArgumentDisplayName(option, schema);
653
+ if ((error.code === ArgsValidationErrorKeys.invalidType || error.code === ArgsValidationErrorKeys.invalidChoice) && values.actual == null) values.actual = value;
654
+ }
655
+ function getErrorReason(error) {
656
+ return error instanceof Error ? error.message : String(error);
657
+ }
658
+ function createArgumentDisplayName(option, schema) {
659
+ return schema.type === "positional" ? `'${option}'` : createOptionDisplayName(option, schema);
660
+ }
661
+ function createOptionDisplayName(option, schema) {
662
+ return `'--${option}'${schema.short ? ` or '-${schema.short}'` : ""}`;
549
663
  }
550
664
  function checkConflicts(args, explicit, toKebab, actualInputNames) {
551
665
  for (const rawArg in args) {
@@ -564,416 +678,4 @@ function checkConflicts(args, explicit, toKebab, actualInputNames) {
564
678
  return [];
565
679
  }
566
680
  //#endregion
567
- //#region ../../node_modules/.pnpm/args-tokens@0.27.0/node_modules/args-tokens/lib/index.js
568
- /**
569
- * @author kazuya kawaguchi (a.k.a. kazupon)
570
- * @license MIT
571
- */
572
- /**
573
- * @author kazuya kawaguchi (a.k.a. kazupon)
574
- * @license MIT
575
- */
576
- //#endregion
577
- //#region src/decorators.ts
578
- /**
579
- * @author kazuya kawaguchi (a.k.a. kazupon)
580
- * @license MIT
581
- */
582
- const EMPTY_RENDERER = () => Promise.resolve("");
583
- /**
584
- * Factory function for creating a decorators manager.
585
- *
586
- * @returns A new decorators manager instance
587
- */
588
- function createDecorators() {
589
- /**
590
- * private states
591
- */
592
- const headerDecorators = [];
593
- const usageDecorators = [];
594
- const validationDecorators = [];
595
- const commandDecorators = [];
596
- /**
597
- * helper function for building renderers
598
- */
599
- function buildRenderer(decorators, defaultRenderer) {
600
- if (decorators.length === 0) return defaultRenderer;
601
- let renderer = defaultRenderer;
602
- for (const decorator of decorators) {
603
- const previousRenderer = renderer;
604
- renderer = (ctx) => decorator(previousRenderer, ctx);
605
- }
606
- return renderer;
607
- }
608
- /**
609
- * public interfaces
610
- */
611
- return Object.freeze({
612
- addHeaderDecorator(decorator) {
613
- headerDecorators.push(decorator);
614
- },
615
- addUsageDecorator(decorator) {
616
- usageDecorators.push(decorator);
617
- },
618
- addValidationErrorsDecorator(decorator) {
619
- validationDecorators.push(decorator);
620
- },
621
- addCommandDecorator(decorator) {
622
- commandDecorators.push(decorator);
623
- },
624
- get commandDecorators() {
625
- return [...commandDecorators];
626
- },
627
- getHeaderRenderer() {
628
- return buildRenderer(headerDecorators, EMPTY_RENDERER);
629
- },
630
- getUsageRenderer() {
631
- return buildRenderer(usageDecorators, EMPTY_RENDERER);
632
- },
633
- getValidationErrorsRenderer() {
634
- if (validationDecorators.length === 0) return EMPTY_RENDERER;
635
- let renderer = EMPTY_RENDERER;
636
- for (const decorator of validationDecorators) {
637
- const previousRenderer = renderer;
638
- renderer = (ctx, error) => decorator(previousRenderer, ctx, error);
639
- }
640
- return renderer;
641
- }
642
- });
643
- }
644
- //#endregion
645
- //#region src/plugin/context.ts
646
- /**
647
- * @author kazuya kawaguchi (a.k.a. kazupon)
648
- * @license MIT
649
- */
650
- /**
651
- * Factory function for creating a plugin context.
652
- *
653
- * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command parameters.
654
- *
655
- * @param decorators - A {@linkcode Decorators} instance.
656
- * @param initialSubCommands - Initial sub commands map.
657
- * @returns A new {@linkcode PluginContext} instance.
658
- */
659
- function createPluginContext(decorators, initialSubCommands) {
660
- /**
661
- * private states
662
- */
663
- const globalOptions = /* @__PURE__ */ new Map();
664
- const subCommands = new Map(initialSubCommands || []);
665
- /**
666
- * public interfaces
667
- */
668
- return Object.freeze({
669
- get globalOptions() {
670
- return new Map(globalOptions);
671
- },
672
- addGlobalOption(name, schema) {
673
- if (!name) throw new Error("Option name must be a non-empty string");
674
- if (globalOptions.has(name)) throw new Error(`Global option '${name}' is already registered`);
675
- globalOptions.set(name, schema);
676
- },
677
- get subCommands() {
678
- return new Map(subCommands);
679
- },
680
- addCommand(name, command) {
681
- if (!name) throw new Error("Command name must be a non-empty string");
682
- if (subCommands.has(name)) throw new Error(`Command '${name}' is already registered`);
683
- subCommands.set(name, command);
684
- },
685
- hasCommand(name) {
686
- return subCommands.has(name);
687
- },
688
- decorateHeaderRenderer(decorator) {
689
- decorators.addHeaderDecorator(decorator);
690
- },
691
- decorateUsageRenderer(decorator) {
692
- decorators.addUsageDecorator(decorator);
693
- },
694
- decorateValidationErrorsRenderer(decorator) {
695
- decorators.addValidationErrorsDecorator(decorator);
696
- },
697
- decorateCommand(decorator) {
698
- decorators.addCommandDecorator(decorator);
699
- }
700
- });
701
- }
702
- //#endregion
703
- //#region src/plugin/dependency.ts
704
- /**
705
- * @author kazuya kawaguchi (a.k.a. kazupon)
706
- * @license MIT
707
- */
708
- /**
709
- * Resolve plugin dependencies using topological sort
710
- *
711
- * @param plugins - Array of plugins to resolve
712
- * @returns Array of plugins sorted by dependencies
713
- */
714
- function resolveDependencies(plugins) {
715
- const sorted = [];
716
- const visited = /* @__PURE__ */ new Set();
717
- const visiting = /* @__PURE__ */ new Set();
718
- const pluginMap = /* @__PURE__ */ new Map();
719
- for (const plugin of plugins) if (plugin.id) {
720
- if (pluginMap.has(plugin.id)) console.warn(`Duplicate plugin id detected: \`${plugin.id}\``);
721
- pluginMap.set(plugin.id, plugin);
722
- }
723
- function visit(plugin) {
724
- if (!plugin.id) return;
725
- if (visited.has(plugin.id)) return;
726
- if (visiting.has(plugin.id)) throw new Error(`Circular dependency detected: \`${[...visiting].join(` -> `) + " -> " + plugin.id}\``);
727
- visiting.add(plugin.id);
728
- const deps = plugin.dependencies || [];
729
- for (const dep of deps) {
730
- const depId = typeof dep === "string" ? dep : dep.id;
731
- const isOptional = typeof dep === "string" ? false : dep.optional || false;
732
- const depPlugin = pluginMap.get(depId);
733
- if (!depPlugin && !isOptional) throw new Error(`Missing required dependency: \`${depId}\` on \`${plugin.id}\``);
734
- if (depPlugin) visit(depPlugin);
735
- }
736
- visiting.delete(plugin.id);
737
- visited.add(plugin.id);
738
- sorted.push(plugin);
739
- }
740
- for (const plugin of plugins) visit(plugin);
741
- return sorted;
742
- }
743
- //#endregion
744
- //#region src/cli/core.ts
745
- /**
746
- * @author kazuya kawaguchi (a.k.a. kazupon)
747
- * @license MIT
748
- */
749
- /**
750
- * Run the command.
751
- *
752
- * @typeParam G - A type extending {@linkcode GunshiParams} to specify the shape of command and cli options.
753
- *
754
- * @param argv - Command line arguments
755
- * @param entry - A {@link Command | entry command}, an {@link CommandRunner | inline command runner}, or a {@link LazyCommand | lazily-loaded command}
756
- * @param options - A {@link CliOptions | CLI options}
757
- * @param plugins - An array of {@link Plugin | plugins} to be applied
758
- * @returns A rendered usage or undefined. if you will use {@link CliOptions.usageSilent} option, it will return rendered usage string.
759
- */
760
- async function cliCore(argv, entry, options, plugins) {
761
- const decorators = createDecorators();
762
- const pluginContext = createPluginContext(decorators, createInitialSubCommands(options, entry));
763
- const resolvedPlugins = await applyPlugins(pluginContext, [...plugins, ...options.plugins || []]);
764
- const cliOptions = normalizeCliOptions(options, decorators, pluginContext);
765
- const tokens = parseArgs(argv);
766
- const resolved = resolveCommandTree(tokens, entry, cliOptions);
767
- const { commandName: name, command, callMode, commandPath, depth, levelSubCommands } = resolved;
768
- if (!command) throw new Error(`Command not found: ${name || ""}`);
769
- if (levelSubCommands) cliOptions.subCommands = levelSubCommands;
770
- const resolvedCommand = isLazyCommand(command) ? await resolveLazyCommand(command, name, true) : command;
771
- const args = resolveArguments(pluginContext, getCommandArgs(resolvedCommand));
772
- const skipPositional = depth > 0 ? depth - 1 : -1;
773
- const { explicit, values, positionals, rest, error } = resolveArgs(args, tokens, {
774
- shortGrouping: true,
775
- toKebab: resolvedCommand.toKebab,
776
- skipPositional
777
- });
778
- const omitted = resolved.omitted;
779
- return await executeCommand(resolvedCommand, await createCommandContext({
780
- args,
781
- explicit,
782
- values,
783
- positionals,
784
- rest,
785
- argv,
786
- tokens,
787
- omitted,
788
- callMode,
789
- commandPath,
790
- command: resolvedCommand,
791
- extensions: getPluginExtensions(resolvedPlugins),
792
- validationError: error,
793
- cliOptions
794
- }), decorators.commandDecorators);
795
- }
796
- async function applyPlugins(pluginContext, plugins) {
797
- const sortedPlugins = resolveDependencies(plugins);
798
- try {
799
- for (const plugin of sortedPlugins)
800
- /**
801
- * NOTE(kazupon):
802
- * strictly `Args` are not required for plugin installation.
803
- * because the strictly `Args` required by each plugin are unknown,
804
- * and the plugin side can not know what the user will specify.
805
- */
806
- await plugin(pluginContext);
807
- } catch (error) {
808
- console.error("Error loading plugin:", error.message);
809
- }
810
- return sortedPlugins;
811
- }
812
- function getCommandArgs(cmd) {
813
- if (isLazyCommand(cmd)) return cmd.args || create();
814
- else if (typeof cmd === "object") return cmd.args || create();
815
- else return create();
816
- }
817
- function resolveArguments(pluginContext, args) {
818
- return Object.assign(create(), Object.fromEntries(pluginContext.globalOptions), args);
819
- }
820
- const isObject = (val) => val !== null && typeof val === "object";
821
- function createInitialSubCommands(options, entryCmd) {
822
- const hasSubCommands = options.subCommands ? options.subCommands instanceof Map ? options.subCommands.size > 0 : isObject(options.subCommands) && Object.keys(options.subCommands).length > 0 : false;
823
- const subCommands = new Map(options.subCommands instanceof Map ? options.subCommands : []);
824
- if (!(options.subCommands instanceof Map) && isObject(options.subCommands)) for (const [name, cmd] of Object.entries(options.subCommands)) subCommands.set(name, cmd);
825
- if (hasSubCommands) {
826
- if (isLazyCommand(entryCmd)) {
827
- const entryCopy = Object.assign((...args) => entryCmd(...args), entryCmd, { entry: true });
828
- subCommands.set(resolveEntryName(entryCopy), entryCopy);
829
- } else if (typeof entryCmd === "object") {
830
- const entryCopy = Object.assign(create(), entryCmd, { entry: true });
831
- subCommands.set(resolveEntryName(entryCopy), entryCopy);
832
- } else if (typeof entryCmd === "function") {
833
- const name = entryCmd.name || "(anonymous)";
834
- subCommands.set(name, {
835
- run: entryCmd,
836
- name,
837
- entry: true
838
- });
839
- }
840
- }
841
- return subCommands;
842
- }
843
- function normalizeCliOptions(options, decorators, pluginContext) {
844
- const subCommands = new Map(pluginContext.subCommands);
845
- const resolvedOptions = Object.assign(create(), CLI_OPTIONS_DEFAULT, options, { subCommands });
846
- if (resolvedOptions.renderHeader === void 0) resolvedOptions.renderHeader = decorators.getHeaderRenderer();
847
- if (resolvedOptions.renderUsage === void 0) resolvedOptions.renderUsage = decorators.getUsageRenderer();
848
- if (resolvedOptions.renderValidationErrors === void 0) resolvedOptions.renderValidationErrors = decorators.getValidationErrorsRenderer();
849
- return resolvedOptions;
850
- }
851
- function getPositionalTokens(tokens) {
852
- return tokens.filter((t) => t.kind === "positional").map((t) => t.value).filter((v) => !!v);
853
- }
854
- function resolveCommandTree(tokens, entry, options) {
855
- const positionals = getPositionalTokens(tokens);
856
- function resolveAsEntry() {
857
- if (typeof entry === "function") if ("commandName" in entry && entry.commandName) return {
858
- commandName: entry.commandName,
859
- command: entry,
860
- callMode: "entry",
861
- commandPath: [],
862
- depth: 0,
863
- omitted: options.subCommands.size > 0 && !positionals[0],
864
- levelSubCommands: options.subCommands.size > 0 ? options.subCommands : void 0
865
- };
866
- else return {
867
- command: {
868
- run: entry,
869
- entry: true
870
- },
871
- callMode: "entry",
872
- commandPath: [],
873
- depth: 0,
874
- omitted: options.subCommands.size > 0 && !positionals[0],
875
- levelSubCommands: options.subCommands.size > 0 ? options.subCommands : void 0
876
- };
877
- else if (typeof entry === "object") return {
878
- commandName: resolveEntryName(entry),
879
- command: entry,
880
- callMode: "entry",
881
- commandPath: [],
882
- depth: 0,
883
- omitted: options.subCommands.size > 0 && !positionals[0],
884
- levelSubCommands: options.subCommands.size > 0 ? options.subCommands : void 0
885
- };
886
- else return {
887
- callMode: "unexpected",
888
- commandPath: [],
889
- depth: 0,
890
- omitted: false,
891
- levelSubCommands: void 0
892
- };
893
- }
894
- if (positionals.length === 0 || options.subCommands.size === 0) return resolveAsEntry();
895
- let currentSubCommands = options.subCommands;
896
- let resolvedCommand;
897
- let resolvedName;
898
- const commandPath = [];
899
- let depth = 0;
900
- for (let i = 0; i < positionals.length; i++) {
901
- const token = positionals[i];
902
- const cmd = currentSubCommands.get(token);
903
- if (cmd == null) {
904
- if (depth === 0) {
905
- if (options.fallbackToEntry) return resolveAsEntry();
906
- return {
907
- commandName: token,
908
- callMode: "unexpected",
909
- commandPath: [],
910
- depth: 0,
911
- omitted: false,
912
- levelSubCommands: void 0
913
- };
914
- }
915
- break;
916
- }
917
- let resolved = cmd;
918
- if (typeof cmd === "function" && cmd.commandName == null) resolved = Object.assign((...args) => cmd(...args), cmd, { commandName: token });
919
- else if (typeof cmd === "object" && cmd.name == null) resolved = Object.assign(create(), cmd, { name: token });
920
- resolvedCommand = resolved;
921
- resolvedName = token;
922
- commandPath.push(token);
923
- depth++;
924
- const nestedSubCommands = getCommandSubCommands(cmd);
925
- if (nestedSubCommands && nestedSubCommands.size > 0) currentSubCommands = nestedSubCommands;
926
- else break;
927
- }
928
- if (!resolvedCommand) return resolveAsEntry();
929
- const resolvedSubCommands = getCommandSubCommands(resolvedCommand);
930
- const omitted = resolvedSubCommands != null && resolvedSubCommands.size > 0;
931
- let levelSubCommands;
932
- if (omitted && resolvedSubCommands) {
933
- levelSubCommands = new Map(resolvedSubCommands);
934
- let entryCopy;
935
- if (typeof resolvedCommand === "function") entryCopy = Object.assign((...args) => resolvedCommand(...args), resolvedCommand, { entry: true });
936
- else entryCopy = Object.assign(create(), resolvedCommand, { entry: true });
937
- levelSubCommands.set(resolvedName || resolveEntryName(entryCopy), entryCopy);
938
- }
939
- return {
940
- commandName: resolvedName,
941
- command: resolvedCommand,
942
- callMode: depth > 0 ? "subCommand" : "entry",
943
- commandPath,
944
- depth,
945
- omitted,
946
- levelSubCommands
947
- };
948
- }
949
- function resolveEntryName(entry) {
950
- return isLazyCommand(entry) ? entry.commandName || "(anonymous)" : entry.name || "(anonymous)";
951
- }
952
- function getPluginExtensions(plugins) {
953
- const extensions = create();
954
- for (const plugin of plugins) if (plugin.extension) {
955
- const key = plugin.id;
956
- if (extensions[key]) console.warn(`Plugin "${key}" is already installed. Ignore it for command context extending.`);
957
- else extensions[key] = plugin.extension;
958
- }
959
- return extensions;
960
- }
961
- async function executeCommand(cmd, ctx, decorators) {
962
- const baseRunner = cmd.run || NOOP;
963
- const decoratedRunner = decorators.reduceRight((runner, decorator) => decorator(runner), baseRunner);
964
- try {
965
- if (ctx.env.onBeforeCommand) await ctx.env.onBeforeCommand(ctx);
966
- const result = await decoratedRunner(ctx);
967
- if (ctx.env.onAfterCommand) await ctx.env.onAfterCommand(ctx, result);
968
- return typeof result === "string" ? result : void 0;
969
- } catch (error) {
970
- if (ctx.env.onErrorCommand) try {
971
- await ctx.env.onErrorCommand(ctx, error);
972
- } catch (hookError) {
973
- console.error("Error in onErrorCommand hook:", hookError);
974
- }
975
- throw error;
976
- }
977
- }
978
- //#endregion
979
- export { resolveArgs as n, parseArgs as r, cliCore as t };
681
+ export { parseArgs as a, resolveArgs as i, ArgsValidationErrorKeys as n, isArgsValidationError as r, ArgsValidationError as t };