@gunshi/plugin 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.
@@ -515,12 +515,12 @@ interface ArgSchema {
515
515
  * i18n resource key for localized rendering.
516
516
  */
517
517
  declare const ArgsValidationErrorKeys: {
518
- readonly requiredOption: "err:arg:required-option";
519
- readonly requiredPositional: "err:arg:required-positional";
520
- readonly invalidType: "err:arg:invalid-type";
521
- readonly invalidChoice: "err:arg:invalid-choice";
522
- readonly customParse: "err:arg:custom-parse";
523
- readonly unknownOption: "err:arg:unknown-option";
518
+ readonly requiredOption: 'err:arg:required-option';
519
+ readonly requiredPositional: 'err:arg:required-positional';
520
+ readonly invalidType: 'err:arg:invalid-type';
521
+ readonly invalidChoice: 'err:arg:invalid-choice';
522
+ readonly customParse: 'err:arg:custom-parse';
523
+ readonly unknownOption: 'err:arg:unknown-option';
524
524
  };
525
525
  /**
526
526
  * A machine-readable argument validation error code.
@@ -535,6 +535,10 @@ type ArgsValidationErrorCode = (typeof ArgsValidationErrorKeys)[keyof typeof Arg
535
535
  * The `message` remains the English fallback message. Renderers can use `code`
536
536
  * and `values` to localize the error, falling back to `message` when localization
537
537
  * is unavailable.
538
+ *
539
+ * Each instance carries a non-enumerable brand keyed by
540
+ * `Symbol.for('args-tokens.ArgsValidationError')`, which {@link isArgsValidationError}
541
+ * uses to recognize instances created by another bundled copy of `args-tokens`.
538
542
  */
539
543
  declare class ArgsValidationError extends Error {
540
544
  /**
@@ -559,13 +563,6 @@ declare class ArgsValidationError extends Error {
559
563
  cause?: unknown;
560
564
  });
561
565
  }
562
- /**
563
- * Check whether the given value is an {@link ArgsValidationError}.
564
- *
565
- * @param error - value to check
566
- * @returns `true` when the value is an `ArgsValidationError`
567
- */
568
- declare function isArgsValidationError(error: unknown): error is ArgsValidationError;
569
566
  /**
570
567
  * An object that contains {@link ArgSchema | argument schema}.
571
568
  *
@@ -599,7 +596,7 @@ type ResolveOptionValue<A extends ArgSchema, T> = A['multiple'] extends true ? T
599
596
  *
600
597
  * @internal
601
598
  */
602
- 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;
599
+ 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;
603
600
  /**
604
601
  * Filters the arguments based on their default values.
605
602
  *
@@ -633,38 +630,6 @@ type IsRequiredPositionalArg<A extends ArgSchema> = A['type'] extends 'positiona
633
630
  * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
634
631
  */
635
632
  type ArgExplicitlyProvided<A extends Args> = { [K in keyof A]: boolean };
636
- /**
637
- * Resolve command line arguments.
638
- *
639
- * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
640
- *
641
- * @param args - An arguments that contains {@link ArgSchema | arguments schema}.
642
- * @param tokens - An array of {@link ArgToken | tokens}.
643
- * @param resolveArgs - An arguments that contains {@link ResolveArgs | resolve arguments}.
644
- * @returns An object that contains the values of the arguments, positional arguments, rest arguments, {@link AggregateError | validation errors}, and explicit provision status.
645
- *
646
- * @example
647
- * ```typescript
648
- * // passed tokens: --port 3000
649
- *
650
- * const { values, explicit } = resolveArgs({
651
- * port: {
652
- * type: 'number',
653
- * default: 8080
654
- * },
655
- * host: {
656
- * type: 'string',
657
- * default: 'localhost'
658
- * }
659
- * }, parsedTokens)
660
- *
661
- * values.port // 3000
662
- * values.host // 'localhost'
663
- *
664
- * explicit.port // true (explicitly provided)
665
- * explicit.host // false (not provided, fallback to default)
666
- * ```
667
- */
668
633
  //#endregion
669
634
  //#region ../gunshi/src/plugin/context.d.ts
670
635
  /**
@@ -1830,10 +1795,6 @@ declare function createCommandContext<G extends GunshiParamsConstraint = Default
1830
1795
  }: CommandContextParams<G, V, C, E>): Promise<CommandContextResult<G, E>>;
1831
1796
  //#endregion
1832
1797
  //#region ../gunshi/src/error.d.ts
1833
- /**
1834
- * @author kazuya kawaguchi (a.k.a. kazupon)
1835
- * @license MIT
1836
- */
1837
1798
  /**
1838
1799
  * Command not found error resource keys.
1839
1800
  */
@@ -1875,6 +1836,10 @@ type CommandNotFoundErrorOptions = {
1875
1836
  };
1876
1837
  /**
1877
1838
  * Error raised when a command cannot be resolved.
1839
+ *
1840
+ * Each instance carries a non-enumerable brand keyed by
1841
+ * `Symbol.for('gunshi.CommandNotFoundError')`, so that {@link isCommandNotFoundError}
1842
+ * recognizes it even when it was created by another bundled copy of gunshi.
1878
1843
  */
1879
1844
  declare class CommandNotFoundError extends Error {
1880
1845
  readonly code?: CommandNotFoundErrorCode;
@@ -1893,10 +1858,34 @@ declare class CommandNotFoundError extends Error {
1893
1858
  /**
1894
1859
  * Check whether an error is a {@link CommandNotFoundError}.
1895
1860
  *
1861
+ * `instanceof` alone is not enough: `@gunshi/plugin` is bundled with its own copy of this
1862
+ * class (`noExternal: ['gunshi/plugin']`), so an error thrown by `gunshi` is never an instance
1863
+ * of the class a plugin imports. Errors from another copy are recognized through the
1864
+ * `Symbol.for('gunshi.CommandNotFoundError')` brand, which does not depend on `error.name`.
1865
+ *
1896
1866
  * @param error - An unknown error
1897
1867
  * @returns `true` if the error is a {@link CommandNotFoundError}
1898
1868
  */
1899
1869
  declare function isCommandNotFoundError(error: unknown): error is CommandNotFoundError;
1870
+ /**
1871
+ * Check whether an error is an {@link ArgsValidationError}.
1872
+ *
1873
+ * Prefer this over the `args-tokens` guard of the same name. Both recognize errors from another
1874
+ * bundled copy through the `Symbol.for('args-tokens.ArgsValidationError')` brand that
1875
+ * `args-tokens` 0.29.0 or later sets, including subclasses such as `ArgResolveError` that
1876
+ * override `name` with the argument name. This guard additionally:
1877
+ *
1878
+ * - recognizes direct `ArgsValidationError` instances from copies bundling `args-tokens`
1879
+ * older than 0.29.0, which do not set the brand
1880
+ * - checks that `code` and `values` of an error from another copy have the expected types
1881
+ *
1882
+ * The guard narrows only to {@link ArgsValidationError}: across copies,
1883
+ * `instanceof ArgResolveError` still fails, so do not rely on `type` or `schema` for such errors.
1884
+ *
1885
+ * @param error - An unknown error
1886
+ * @returns `true` if the error is an {@link ArgsValidationError}
1887
+ */
1888
+ declare function isArgsValidationError(error: unknown): error is ArgsValidationError;
1900
1889
  /**
1901
1890
  * Check whether validation errors should be handled before version, help, or command execution.
1902
1891
  *
package/lib/index.js CHANGED
@@ -173,7 +173,7 @@ function getCommandName(cmd) {
173
173
  "-".codePointAt(0);
174
174
  "=".codePointAt(0);
175
175
  //#endregion
176
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/resolver.js
176
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/resolver.js
177
177
  /**
178
178
  * Entry point of argument options resolver.
179
179
  *
@@ -198,11 +198,24 @@ const ArgsValidationErrorKeys = {
198
198
  unknownOption: "err:arg:unknown-option"
199
199
  };
200
200
  /**
201
+ * Brand that marks {@link ArgsValidationError} instances.
202
+ *
203
+ * The brand is looked up in the global symbol registry with `Symbol.for`, so it stays
204
+ * identical across bundled copies of this module and across realms. It lets
205
+ * {@link isArgsValidationError} recognize errors created by another copy of `args-tokens`,
206
+ * where `instanceof` cannot match.
207
+ */
208
+ const ARGS_VALIDATION_ERROR_BRAND = Symbol.for("args-tokens.ArgsValidationError");
209
+ /**
201
210
  * An error that contains structured metadata for argument validation failures.
202
211
  *
203
212
  * The `message` remains the English fallback message. Renderers can use `code`
204
213
  * and `values` to localize the error, falling back to `message` when localization
205
214
  * is unavailable.
215
+ *
216
+ * Each instance carries a non-enumerable brand keyed by
217
+ * `Symbol.for('args-tokens.ArgsValidationError')`, which {@link isArgsValidationError}
218
+ * uses to recognize instances created by another bundled copy of `args-tokens`.
206
219
  */
207
220
  var ArgsValidationError = class extends Error {
208
221
  /**
@@ -226,19 +239,38 @@ var ArgsValidationError = class extends Error {
226
239
  this.name = "ArgsValidationError";
227
240
  this.code = options.code;
228
241
  this.values = options.values ?? {};
242
+ Object.defineProperty(this, ARGS_VALIDATION_ERROR_BRAND, {
243
+ value: true,
244
+ enumerable: false,
245
+ writable: false,
246
+ configurable: false
247
+ });
229
248
  }
230
249
  };
231
250
  /**
232
251
  * Check whether the given value is an {@link ArgsValidationError}.
233
252
  *
253
+ * This guard also recognizes errors created by another bundled copy of `args-tokens`
254
+ * (0.29.0 or later), where `instanceof` does not match. Such an error must have an own brand
255
+ * keyed by `Symbol.for('args-tokens.ArgsValidationError')` set to `true`, and a `values` object.
256
+ * The guard does not rely on `error.name`, so subclasses such as {@link ArgResolveError} that
257
+ * override `name` are still recognized.
258
+ *
259
+ * The guard narrows to `ArgsValidationError` only. Across bundled copies,
260
+ * `instanceof ArgResolveError` still does not match.
261
+ *
234
262
  * @param error - value to check
235
263
  * @returns `true` when the value is an `ArgsValidationError`
236
264
  */
237
- function isArgsValidationError(error) {
238
- return error instanceof ArgsValidationError;
265
+ function isArgsValidationError$1(error) {
266
+ if (error instanceof ArgsValidationError) return true;
267
+ if (typeof error !== "object" || error === null) return false;
268
+ if (!Object.hasOwn(error, ARGS_VALIDATION_ERROR_BRAND) || error[ARGS_VALIDATION_ERROR_BRAND] !== true) return false;
269
+ const values = error.values;
270
+ return typeof values === "object" && values !== null;
239
271
  }
240
272
  //#endregion
241
- //#region ../../node_modules/.pnpm/args-tokens@0.28.1/node_modules/args-tokens/lib/index.js
273
+ //#region ../../node_modules/.pnpm/args-tokens@0.29.0/node_modules/args-tokens/lib/index.js
242
274
  /**
243
275
  * @author kazuya kawaguchi (a.k.a. kazupon)
244
276
  * @license MIT
@@ -258,7 +290,20 @@ function isArgsValidationError(error) {
258
290
  */
259
291
  const CommandNotFoundErrorKeys = { notFound: "err:cmd:not-found" };
260
292
  /**
293
+ * Brand that marks {@link CommandNotFoundError} instances.
294
+ *
295
+ * The brand is looked up in the global symbol registry with `Symbol.for`, so it stays
296
+ * identical across bundled copies of gunshi (`gunshi`, `@gunshi/plugin`, `@gunshi/bone`)
297
+ * and across realms. It lets {@link isCommandNotFoundError} recognize errors created by
298
+ * another copy, where `instanceof` cannot match.
299
+ */
300
+ const COMMAND_NOT_FOUND_ERROR_BRAND = Symbol.for("gunshi.CommandNotFoundError");
301
+ /**
261
302
  * Error raised when a command cannot be resolved.
303
+ *
304
+ * Each instance carries a non-enumerable brand keyed by
305
+ * `Symbol.for('gunshi.CommandNotFoundError')`, so that {@link isCommandNotFoundError}
306
+ * recognizes it even when it was created by another bundled copy of gunshi.
262
307
  */
263
308
  var CommandNotFoundError = class extends Error {
264
309
  code;
@@ -280,16 +325,77 @@ var CommandNotFoundError = class extends Error {
280
325
  this.commandName = options.commandName;
281
326
  this.candidates = options.candidates || [];
282
327
  this.commandPath = options.commandPath || [];
328
+ Object.defineProperty(this, COMMAND_NOT_FOUND_ERROR_BRAND, {
329
+ value: true,
330
+ enumerable: false,
331
+ writable: false,
332
+ configurable: false
333
+ });
283
334
  }
284
335
  };
285
336
  /**
286
337
  * Check whether an error is a {@link CommandNotFoundError}.
287
338
  *
339
+ * `instanceof` alone is not enough: `@gunshi/plugin` is bundled with its own copy of this
340
+ * class (`noExternal: ['gunshi/plugin']`), so an error thrown by `gunshi` is never an instance
341
+ * of the class a plugin imports. Errors from another copy are recognized through the
342
+ * `Symbol.for('gunshi.CommandNotFoundError')` brand, which does not depend on `error.name`.
343
+ *
288
344
  * @param error - An unknown error
289
345
  * @returns `true` if the error is a {@link CommandNotFoundError}
290
346
  */
291
347
  function isCommandNotFoundError(error) {
292
- return error instanceof CommandNotFoundError;
348
+ if (error instanceof CommandNotFoundError) return true;
349
+ if (!isRecord(error) || !hasCommandNotFoundErrorShape(error)) return false;
350
+ if (Object.hasOwn(error, COMMAND_NOT_FOUND_ERROR_BRAND) && error[COMMAND_NOT_FOUND_ERROR_BRAND] === true) return true;
351
+ return error instanceof Error && error.name === "CommandNotFoundError";
352
+ }
353
+ /**
354
+ * Check whether an error is an {@link ArgsValidationError}.
355
+ *
356
+ * Prefer this over the `args-tokens` guard of the same name. Both recognize errors from another
357
+ * bundled copy through the `Symbol.for('args-tokens.ArgsValidationError')` brand that
358
+ * `args-tokens` 0.29.0 or later sets, including subclasses such as `ArgResolveError` that
359
+ * override `name` with the argument name. This guard additionally:
360
+ *
361
+ * - recognizes direct `ArgsValidationError` instances from copies bundling `args-tokens`
362
+ * older than 0.29.0, which do not set the brand
363
+ * - checks that `code` and `values` of an error from another copy have the expected types
364
+ *
365
+ * The guard narrows only to {@link ArgsValidationError}: across copies,
366
+ * `instanceof ArgResolveError` still fails, so do not rely on `type` or `schema` for such errors.
367
+ *
368
+ * @param error - An unknown error
369
+ * @returns `true` if the error is an {@link ArgsValidationError}
370
+ */
371
+ function isArgsValidationError(error) {
372
+ if (error instanceof ArgsValidationError) return true;
373
+ if (!isRecord(error) || !hasArgsValidationErrorShape(error)) return false;
374
+ if (isArgsValidationError$1(error)) return true;
375
+ return error instanceof Error && error.name === "ArgsValidationError";
376
+ }
377
+ function isRecord(value) {
378
+ return typeof value === "object" && value !== null;
379
+ }
380
+ function isStringArray(value) {
381
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
382
+ }
383
+ /**
384
+ * Check whether `code` is an own or inherited property that is a string or `undefined`.
385
+ *
386
+ * Constructors always assign `code`, even when the option is omitted.
387
+ *
388
+ * @param error - An error from another copy
389
+ * @returns `true` if `code` has the expected type
390
+ */
391
+ function hasOptionalStringCode(error) {
392
+ return "code" in error && (error.code === void 0 || typeof error.code === "string");
393
+ }
394
+ function hasCommandNotFoundErrorShape(error) {
395
+ return hasOptionalStringCode(error) && isRecord(error.values) && typeof error.commandName === "string" && isStringArray(error.candidates) && isStringArray(error.commandPath);
396
+ }
397
+ function hasArgsValidationErrorShape(error) {
398
+ return hasOptionalStringCode(error) && isRecord(error.values);
293
399
  }
294
400
  /**
295
401
  * 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/plugin",
3
3
  "description": "plugin development kit for gunshi",
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,7 +56,7 @@
56
56
  "jsr-exports-lint": "^0.4.2",
57
57
  "publint": "^0.3.20",
58
58
  "tsdown": "0.21.0",
59
- "gunshi": "0.37.1"
59
+ "gunshi": "0.37.3"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "tsdown",