@gunshi/bone 0.37.1 → 0.37.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/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/parser-DT7Ztcch.d.ts
1
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/parser-DT7Ztcch.d.ts
2
2
  //#region src/parser.d.ts
3
3
  /**
4
4
  * Entry point of argument parser.
@@ -55,7 +55,7 @@ interface ArgToken {
55
55
  * Parser Options.
56
56
  */
57
57
  //#endregion
58
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/resolver.d.ts
58
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/resolver.d.ts
59
59
  //#region src/resolver.d.ts
60
60
  /**
61
61
  * An argument schema definition for command-line argument parsing.
@@ -508,13 +508,6 @@ interface ArgSchema {
508
508
  */
509
509
  parse?: (value: string) => any;
510
510
  }
511
- /**
512
- * Machine-readable error codes for {@link ArgsValidationError}.
513
- *
514
- * Each code identifies a validation failure category and is also suitable as an
515
- * i18n resource key for localized rendering.
516
- */
517
-
518
511
  /**
519
512
  * An object that contains {@link ArgSchema | argument schema}.
520
513
  *
@@ -548,7 +541,7 @@ type ResolveOptionValue<A extends ArgSchema, T> = A['multiple'] extends true ? T
548
541
  *
549
542
  * @internal
550
543
  */
551
- type ResolveArgValues<A extends Args, V extends Record<keyof A, unknown>> = { -readonly [Arg in keyof A]?: V[Arg] } & FilterArgs<A, V, 'default'> & FilterArgs<A, V, 'required'> & FilterPositionalArgs<A, V> extends infer P ? { [K in keyof P]: P[K] } : never;
544
+ type ResolveArgValues<A extends Args, V extends Record<keyof A, unknown>> = { -readonly [Arg in keyof A]?: V[Arg] } & FilterArgs<A, V, 'default'> & FilterArgs<A, V, 'required'> & FilterPositionalArgs<A, V> extends (infer P) ? { [K in keyof P]: P[K] } : never;
552
545
  /**
553
546
  * Filters the arguments based on their default values.
554
547
  *
@@ -582,38 +575,6 @@ type IsRequiredPositionalArg<A extends ArgSchema> = A['type'] extends 'positiona
582
575
  * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
583
576
  */
584
577
  type ArgExplicitlyProvided<A extends Args> = { [K in keyof A]: boolean };
585
- /**
586
- * Resolve command line arguments.
587
- *
588
- * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
589
- *
590
- * @param args - An arguments that contains {@link ArgSchema | arguments schema}.
591
- * @param tokens - An array of {@link ArgToken | tokens}.
592
- * @param resolveArgs - An arguments that contains {@link ResolveArgs | resolve arguments}.
593
- * @returns An object that contains the values of the arguments, positional arguments, rest arguments, {@link AggregateError | validation errors}, and explicit provision status.
594
- *
595
- * @example
596
- * ```typescript
597
- * // passed tokens: --port 3000
598
- *
599
- * const { values, explicit } = resolveArgs({
600
- * port: {
601
- * type: 'number',
602
- * default: 8080
603
- * },
604
- * host: {
605
- * type: 'string',
606
- * default: 'localhost'
607
- * }
608
- * }, parsedTokens)
609
- *
610
- * values.port // 3000
611
- * values.host // 'localhost'
612
- *
613
- * explicit.port // true (explicitly provided)
614
- * explicit.host // false (not provided, fallback to default)
615
- * ```
616
- */
617
578
  //#endregion
618
579
  //#region ../gunshi/src/plugin/context.d.ts
619
580
  /**
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/parser.js
1
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/parser.js
2
2
  /**
3
3
  * forked from `nodejs/node` (`pkgjs/parseargs`)
4
4
  * repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
@@ -203,7 +203,7 @@ function hasOptionValue(value) {
203
203
  return !(value == null) && value.codePointAt(0) !== HYPHEN_CODE;
204
204
  }
205
205
  //#endregion
206
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/utils.js
206
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/utils.js
207
207
  /**
208
208
  * Entry point of utils.
209
209
  *
@@ -234,7 +234,7 @@ function formatChoices(choices) {
234
234
  return choices.map((value) => JSON.stringify(value)).join(", ");
235
235
  }
236
236
  //#endregion
237
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/resolver.js
237
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/resolver.js
238
238
  /**
239
239
  * Entry point of argument options resolver.
240
240
  *
@@ -259,11 +259,24 @@ const ArgsValidationErrorKeys = {
259
259
  unknownOption: "err:arg:unknown-option"
260
260
  };
261
261
  /**
262
+ * Brand that marks {@link ArgsValidationError} instances.
263
+ *
264
+ * The brand is looked up in the global symbol registry with `Symbol.for`, so it stays
265
+ * identical across bundled copies of this module and across realms. It lets
266
+ * {@link isArgsValidationError} recognize errors created by another copy of `args-tokens`,
267
+ * where `instanceof` cannot match.
268
+ */
269
+ const ARGS_VALIDATION_ERROR_BRAND = Symbol.for("args-tokens.ArgsValidationError");
270
+ /**
262
271
  * An error that contains structured metadata for argument validation failures.
263
272
  *
264
273
  * The `message` remains the English fallback message. Renderers can use `code`
265
274
  * and `values` to localize the error, falling back to `message` when localization
266
275
  * is unavailable.
276
+ *
277
+ * Each instance carries a non-enumerable brand keyed by
278
+ * `Symbol.for('args-tokens.ArgsValidationError')`, which {@link isArgsValidationError}
279
+ * uses to recognize instances created by another bundled copy of `args-tokens`.
267
280
  */
268
281
  var ArgsValidationError = class extends Error {
269
282
  /**
@@ -287,16 +300,35 @@ var ArgsValidationError = class extends Error {
287
300
  this.name = "ArgsValidationError";
288
301
  this.code = options.code;
289
302
  this.values = options.values ?? {};
303
+ Object.defineProperty(this, ARGS_VALIDATION_ERROR_BRAND, {
304
+ value: true,
305
+ enumerable: false,
306
+ writable: false,
307
+ configurable: false
308
+ });
290
309
  }
291
310
  };
292
311
  /**
293
312
  * Check whether the given value is an {@link ArgsValidationError}.
294
313
  *
314
+ * This guard also recognizes errors created by another bundled copy of `args-tokens`
315
+ * (0.29.0 or later), where `instanceof` does not match. Such an error must have an own brand
316
+ * keyed by `Symbol.for('args-tokens.ArgsValidationError')` set to `true`, and a `values` object.
317
+ * The guard does not rely on `error.name`, so subclasses such as {@link ArgResolveError} that
318
+ * override `name` are still recognized.
319
+ *
320
+ * The guard narrows to `ArgsValidationError` only. Across bundled copies,
321
+ * `instanceof ArgResolveError` still does not match.
322
+ *
295
323
  * @param error - value to check
296
324
  * @returns `true` when the value is an `ArgsValidationError`
297
325
  */
298
- function isArgsValidationError(error) {
299
- return error instanceof ArgsValidationError;
326
+ function isArgsValidationError$1(error) {
327
+ if (error instanceof ArgsValidationError) return true;
328
+ if (typeof error !== "object" || error === null) return false;
329
+ if (!Object.hasOwn(error, ARGS_VALIDATION_ERROR_BRAND) || error[ARGS_VALIDATION_ERROR_BRAND] !== true) return false;
330
+ const values = error.values;
331
+ return typeof values === "object" && values !== null;
300
332
  }
301
333
  const SKIP_POSITIONAL_DEFAULT = -1;
302
334
  /**
@@ -389,46 +421,52 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
389
421
  rest.push(token.value);
390
422
  continue;
391
423
  }
392
- if (currentShortOption) if (schemas.find((schema) => schema.short === currentShortOption.name && schema.type === "boolean")) {
393
- positionalTokens.push({ ...token });
394
- applyShortOptionValue();
395
- } else applyShortOptionValue(token.value);
396
- else if (currentLongOption) if (booleanLongOptionNames.has(currentLongOption.name)) {
397
- positionalTokens.push({ ...token });
398
- applyLongOptionValue();
399
- } else applyLongOptionValue(token.value);
400
- else positionalTokens.push({ ...token });
401
- } else if (token.kind === "option") if (token.rawName) {
402
- if (hasLongOptionPrefix(token.rawName)) {
403
- applyLongOptionValue();
404
- if (token.inlineValue) optionTokens.push({ ...token });
405
- else currentLongOption = { ...token };
406
- applyShortOptionValue();
407
- } else if (isShortOption(token.rawName)) if (currentShortOption) {
408
- if (currentShortOption.index === token.index) if (shortGrouping) {
424
+ if (currentShortOption) {
425
+ if (schemas.find((schema) => schema.short === currentShortOption.name && schema.type === "boolean")) {
426
+ positionalTokens.push({ ...token });
427
+ applyShortOptionValue();
428
+ } else applyShortOptionValue(token.value);
429
+ } else if (currentLongOption) {
430
+ if (booleanLongOptionNames.has(currentLongOption.name)) {
431
+ positionalTokens.push({ ...token });
432
+ applyLongOptionValue();
433
+ } else applyLongOptionValue(token.value);
434
+ } else positionalTokens.push({ ...token });
435
+ } else if (token.kind === "option") {
436
+ if (token.rawName) {
437
+ if (hasLongOptionPrefix(token.rawName)) {
438
+ applyLongOptionValue();
439
+ if (token.inlineValue) optionTokens.push({ ...token });
440
+ else currentLongOption = { ...token };
441
+ applyShortOptionValue();
442
+ } else if (isShortOption(token.rawName)) {
443
+ if (currentShortOption) {
444
+ if (currentShortOption.index === token.index) {
445
+ if (shortGrouping) {
446
+ currentShortOption.value = token.value;
447
+ optionTokens.push({ ...currentShortOption });
448
+ currentShortOption = { ...token };
449
+ } else expandableShortOptions.push({ ...token });
450
+ } else {
451
+ currentShortOption.value = toShortValue();
452
+ optionTokens.push({ ...currentShortOption });
453
+ currentShortOption = { ...token };
454
+ }
455
+ applyLongOptionValue();
456
+ } else {
457
+ currentShortOption = { ...token };
458
+ applyLongOptionValue();
459
+ }
460
+ }
461
+ } else {
462
+ if (currentShortOption && currentShortOption.index == token.index && token.inlineValue) {
409
463
  currentShortOption.value = token.value;
410
464
  optionTokens.push({ ...currentShortOption });
411
- currentShortOption = { ...token };
412
- } else expandableShortOptions.push({ ...token });
413
- else {
414
- currentShortOption.value = toShortValue();
415
- optionTokens.push({ ...currentShortOption });
416
- currentShortOption = { ...token };
465
+ currentShortOption = void 0;
417
466
  }
418
467
  applyLongOptionValue();
419
- } else {
420
- currentShortOption = { ...token };
421
- applyLongOptionValue();
422
468
  }
423
469
  } else {
424
- if (currentShortOption && currentShortOption.index == token.index && token.inlineValue) {
425
- currentShortOption.value = token.value;
426
- optionTokens.push({ ...currentShortOption });
427
- currentShortOption = void 0;
428
- }
429
- applyLongOptionValue();
430
- }
431
- else {
432
470
  if (token.kind === "option-terminator") terminated = true;
433
471
  applyLongOptionValue();
434
472
  applyShortOptionValue();
@@ -673,10 +711,8 @@ function createChoiceError(rawArg, option, schema, actual) {
673
711
  });
674
712
  }
675
713
  function createCustomParseError(error, rawArg, option, schema, value) {
676
- if (isArgsValidationError(error)) {
677
- augmentValidationError(error, rawArg, option, schema, value);
678
- return error;
679
- }
714
+ const reused = reuseValidationError(error, rawArg, option, schema, value);
715
+ if (reused) return reused;
680
716
  const reason = getErrorReason(error);
681
717
  return new ArgsValidationError(reason, {
682
718
  code: ArgsValidationErrorKeys.customParse,
@@ -688,6 +724,26 @@ function createCustomParseError(error, rawArg, option, schema, value) {
688
724
  cause: error
689
725
  });
690
726
  }
727
+ /**
728
+ * Reuse an {@link ArgsValidationError} thrown from a custom `parse` function, filling in missing values.
729
+ *
730
+ * @param error - The value thrown from `parse`
731
+ * @param rawArg - The argument key in the schema
732
+ * @param option - The option name used on the command line
733
+ * @param schema - The argument schema
734
+ * @param value - The raw input value
735
+ * @returns The same error when it can be reused, otherwise `undefined` so the caller wraps it.
736
+ * Inspecting or updating the thrown value can throw, for example when its `values` object is frozen
737
+ * or an accessor throws; such values are not reused, so a custom `parse` cannot make `resolveArgs` throw this way.
738
+ */
739
+ function reuseValidationError(error, rawArg, option, schema, value) {
740
+ try {
741
+ if (isArgsValidationError$1(error)) {
742
+ augmentValidationError(error, rawArg, option, schema, value);
743
+ return error;
744
+ }
745
+ } catch {}
746
+ }
691
747
  function augmentValidationError(error, rawArg, option, schema, value) {
692
748
  const values = error.values;
693
749
  values.name ??= rawArg;
@@ -720,7 +776,7 @@ function checkConflicts(args, explicit, toKebab, actualInputNames) {
720
776
  return [];
721
777
  }
722
778
  //#endregion
723
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/index.js
779
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/index.js
724
780
  /**
725
781
  * @author kazuya kawaguchi (a.k.a. kazupon)
726
782
  * @license MIT
@@ -1033,7 +1089,20 @@ function createDecorators() {
1033
1089
  */
1034
1090
  const CommandNotFoundErrorKeys = { notFound: "err:cmd:not-found" };
1035
1091
  /**
1092
+ * Brand that marks {@link CommandNotFoundError} instances.
1093
+ *
1094
+ * The brand is looked up in the global symbol registry with `Symbol.for`, so it stays
1095
+ * identical across bundled copies of gunshi (`gunshi`, `@gunshi/plugin`, `@gunshi/bone`)
1096
+ * and across realms. It lets {@link isCommandNotFoundError} recognize errors created by
1097
+ * another copy, where `instanceof` cannot match.
1098
+ */
1099
+ const COMMAND_NOT_FOUND_ERROR_BRAND = Symbol.for("gunshi.CommandNotFoundError");
1100
+ /**
1036
1101
  * Error raised when a command cannot be resolved.
1102
+ *
1103
+ * Each instance carries a non-enumerable brand keyed by
1104
+ * `Symbol.for('gunshi.CommandNotFoundError')`, so that {@link isCommandNotFoundError}
1105
+ * recognizes it even when it was created by another bundled copy of gunshi.
1037
1106
  */
1038
1107
  var CommandNotFoundError = class extends Error {
1039
1108
  code;
@@ -1055,16 +1124,77 @@ var CommandNotFoundError = class extends Error {
1055
1124
  this.commandName = options.commandName;
1056
1125
  this.candidates = options.candidates || [];
1057
1126
  this.commandPath = options.commandPath || [];
1127
+ Object.defineProperty(this, COMMAND_NOT_FOUND_ERROR_BRAND, {
1128
+ value: true,
1129
+ enumerable: false,
1130
+ writable: false,
1131
+ configurable: false
1132
+ });
1058
1133
  }
1059
1134
  };
1060
1135
  /**
1061
1136
  * Check whether an error is a {@link CommandNotFoundError}.
1062
1137
  *
1138
+ * `instanceof` alone is not enough: `@gunshi/plugin` is bundled with its own copy of this
1139
+ * class (`noExternal: ['gunshi/plugin']`), so an error thrown by `gunshi` is never an instance
1140
+ * of the class a plugin imports. Errors from another copy are recognized through the
1141
+ * `Symbol.for('gunshi.CommandNotFoundError')` brand, which does not depend on `error.name`.
1142
+ *
1063
1143
  * @param error - An unknown error
1064
1144
  * @returns `true` if the error is a {@link CommandNotFoundError}
1065
1145
  */
1066
1146
  function isCommandNotFoundError(error) {
1067
- return error instanceof CommandNotFoundError;
1147
+ if (error instanceof CommandNotFoundError) return true;
1148
+ if (!isRecord(error) || !hasCommandNotFoundErrorShape(error)) return false;
1149
+ if (Object.hasOwn(error, COMMAND_NOT_FOUND_ERROR_BRAND) && error[COMMAND_NOT_FOUND_ERROR_BRAND] === true) return true;
1150
+ return error instanceof Error && error.name === "CommandNotFoundError";
1151
+ }
1152
+ /**
1153
+ * Check whether an error is an {@link ArgsValidationError}.
1154
+ *
1155
+ * Prefer this over the `args-tokens` guard of the same name. Both recognize errors from another
1156
+ * bundled copy through the `Symbol.for('args-tokens.ArgsValidationError')` brand that
1157
+ * `args-tokens` 0.29.0 or later sets, including subclasses such as `ArgResolveError` that
1158
+ * override `name` with the argument name. This guard additionally:
1159
+ *
1160
+ * - recognizes direct `ArgsValidationError` instances from copies bundling `args-tokens`
1161
+ * older than 0.29.0, which do not set the brand
1162
+ * - checks that `code` and `values` of an error from another copy have the expected types
1163
+ *
1164
+ * The guard narrows only to {@link ArgsValidationError}: across copies,
1165
+ * `instanceof ArgResolveError` still fails, so do not rely on `type` or `schema` for such errors.
1166
+ *
1167
+ * @param error - An unknown error
1168
+ * @returns `true` if the error is an {@link ArgsValidationError}
1169
+ */
1170
+ function isArgsValidationError(error) {
1171
+ if (error instanceof ArgsValidationError) return true;
1172
+ if (!isRecord(error) || !hasArgsValidationErrorShape(error)) return false;
1173
+ if (isArgsValidationError$1(error)) return true;
1174
+ return error instanceof Error && error.name === "ArgsValidationError";
1175
+ }
1176
+ function isRecord(value) {
1177
+ return typeof value === "object" && value !== null;
1178
+ }
1179
+ function isStringArray(value) {
1180
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
1181
+ }
1182
+ /**
1183
+ * Check whether `code` is an own or inherited property that is a string or `undefined`.
1184
+ *
1185
+ * Constructors always assign `code`, even when the option is omitted.
1186
+ *
1187
+ * @param error - An error from another copy
1188
+ * @returns `true` if `code` has the expected type
1189
+ */
1190
+ function hasOptionalStringCode(error) {
1191
+ return "code" in error && (error.code === void 0 || typeof error.code === "string");
1192
+ }
1193
+ function hasCommandNotFoundErrorShape(error) {
1194
+ return hasOptionalStringCode(error) && isRecord(error.values) && typeof error.commandName === "string" && isStringArray(error.candidates) && isStringArray(error.commandPath);
1195
+ }
1196
+ function hasArgsValidationErrorShape(error) {
1197
+ return hasOptionalStringCode(error) && isRecord(error.values);
1068
1198
  }
1069
1199
  /**
1070
1200
  * Check whether validation errors should be handled before version, help, or command execution.
@@ -1366,27 +1496,28 @@ function getPositionalTokens(tokens) {
1366
1496
  function resolveCommandTree(tokens, entry, options) {
1367
1497
  const positionals = getPositionalTokens(tokens);
1368
1498
  function resolveAsEntry() {
1369
- if (typeof entry === "function") if ("commandName" in entry && entry.commandName) return {
1370
- commandName: entry.commandName,
1371
- command: entry,
1372
- callMode: "entry",
1373
- commandPath: [],
1374
- depth: 0,
1375
- omitted: options.subCommands.size > 0 && !positionals[0],
1376
- levelSubCommands: options.subCommands.size > 0 ? options.subCommands : void 0
1377
- };
1378
- else return {
1379
- command: {
1380
- run: entry,
1381
- entry: true
1382
- },
1383
- callMode: "entry",
1384
- commandPath: [],
1385
- depth: 0,
1386
- omitted: options.subCommands.size > 0 && !positionals[0],
1387
- levelSubCommands: options.subCommands.size > 0 ? options.subCommands : void 0
1388
- };
1389
- else if (typeof entry === "object") return {
1499
+ if (typeof entry === "function") {
1500
+ if ("commandName" in entry && entry.commandName) return {
1501
+ commandName: entry.commandName,
1502
+ command: entry,
1503
+ callMode: "entry",
1504
+ commandPath: [],
1505
+ depth: 0,
1506
+ omitted: options.subCommands.size > 0 && !positionals[0],
1507
+ levelSubCommands: options.subCommands.size > 0 ? options.subCommands : void 0
1508
+ };
1509
+ else return {
1510
+ command: {
1511
+ run: entry,
1512
+ entry: true
1513
+ },
1514
+ callMode: "entry",
1515
+ commandPath: [],
1516
+ depth: 0,
1517
+ omitted: options.subCommands.size > 0 && !positionals[0],
1518
+ levelSubCommands: options.subCommands.size > 0 ? options.subCommands : void 0
1519
+ };
1520
+ } else if (typeof entry === "object") return {
1390
1521
  commandName: resolveEntryName(entry),
1391
1522
  command: entry,
1392
1523
  callMode: "entry",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gunshi/bone",
3
3
  "description": "gunshi minimum",
4
- "version": "0.37.1",
4
+ "version": "0.37.3",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -56,10 +56,10 @@
56
56
  "jsr-exports-lint": "^0.4.2",
57
57
  "publint": "^0.3.20",
58
58
  "tsdown": "0.21.0",
59
- "@gunshi/plugin-global": "0.37.1",
60
- "@gunshi/definition": "0.37.1",
61
- "@gunshi/plugin-renderer": "0.37.1",
62
- "gunshi": "0.37.1"
59
+ "@gunshi/definition": "0.37.3",
60
+ "@gunshi/plugin-global": "0.37.3",
61
+ "@gunshi/plugin-renderer": "0.37.3",
62
+ "gunshi": "0.37.3"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "tsdown",