@gunshi/bone 0.37.2 → 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.2/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.2/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
  *
@@ -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.2/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.2/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.2/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
  /**
@@ -679,10 +711,8 @@ function createChoiceError(rawArg, option, schema, actual) {
679
711
  });
680
712
  }
681
713
  function createCustomParseError(error, rawArg, option, schema, value) {
682
- if (isArgsValidationError(error)) {
683
- augmentValidationError(error, rawArg, option, schema, value);
684
- return error;
685
- }
714
+ const reused = reuseValidationError(error, rawArg, option, schema, value);
715
+ if (reused) return reused;
686
716
  const reason = getErrorReason(error);
687
717
  return new ArgsValidationError(reason, {
688
718
  code: ArgsValidationErrorKeys.customParse,
@@ -694,6 +724,26 @@ function createCustomParseError(error, rawArg, option, schema, value) {
694
724
  cause: error
695
725
  });
696
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
+ }
697
747
  function augmentValidationError(error, rawArg, option, schema, value) {
698
748
  const values = error.values;
699
749
  values.name ??= rawArg;
@@ -726,7 +776,7 @@ function checkConflicts(args, explicit, toKebab, actualInputNames) {
726
776
  return [];
727
777
  }
728
778
  //#endregion
729
- //#region ../../node_modules/.pnpm/args-tokens@0.28.2/node_modules/args-tokens/lib/index.js
779
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/index.js
730
780
  /**
731
781
  * @author kazuya kawaguchi (a.k.a. kazupon)
732
782
  * @license MIT
@@ -1039,7 +1089,20 @@ function createDecorators() {
1039
1089
  */
1040
1090
  const CommandNotFoundErrorKeys = { notFound: "err:cmd:not-found" };
1041
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
+ /**
1042
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.
1043
1106
  */
1044
1107
  var CommandNotFoundError = class extends Error {
1045
1108
  code;
@@ -1061,16 +1124,77 @@ var CommandNotFoundError = class extends Error {
1061
1124
  this.commandName = options.commandName;
1062
1125
  this.candidates = options.candidates || [];
1063
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
+ });
1064
1133
  }
1065
1134
  };
1066
1135
  /**
1067
1136
  * Check whether an error is a {@link CommandNotFoundError}.
1068
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
+ *
1069
1143
  * @param error - An unknown error
1070
1144
  * @returns `true` if the error is a {@link CommandNotFoundError}
1071
1145
  */
1072
1146
  function isCommandNotFoundError(error) {
1073
- 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);
1074
1198
  }
1075
1199
  /**
1076
1200
  * Check whether validation errors should be handled before version, help, or command execution.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gunshi/bone",
3
3
  "description": "gunshi minimum",
4
- "version": "0.37.2",
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.2",
60
- "@gunshi/definition": "0.37.2",
61
- "@gunshi/plugin-renderer": "0.37.2",
62
- "gunshi": "0.37.2"
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",