@gunshi/bone 0.33.0 → 0.35.0

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.25.0/node_modules/args-tokens/lib/parser-D95CJBHr.d.ts
1
+ //#region ../../node_modules/.pnpm/args-tokens@0.27.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,13 +55,13 @@ interface ArgToken {
55
55
  * Parser Options.
56
56
  */
57
57
  //#endregion
58
- //#region ../../node_modules/.pnpm/args-tokens@0.25.0/node_modules/args-tokens/lib/resolver.d.ts
58
+ //#region ../../node_modules/.pnpm/args-tokens@0.27.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.
62
62
  *
63
63
  * This schema is similar to the schema of Node.js `util.parseArgs` but with extended features:
64
- * - Additional `required` and `description` properties
64
+ * - Additional `required`, `description`, and `hidden` properties
65
65
  * - Extended `type` support: 'string', 'boolean', 'number', 'enum', 'positional', 'custom'
66
66
  * - Simplified `default` property (single type, not union types)
67
67
  *
@@ -166,13 +166,35 @@ interface ArgSchema {
166
166
  * ```
167
167
  */
168
168
  description?: string;
169
+ /**
170
+ * Hide the argument from generated help or usage output.
171
+ *
172
+ * This is metadata for renderers. It does not affect parsing, validation,
173
+ * required checks, defaults, conflicts, or resolved values.
174
+ *
175
+ * @example
176
+ * Hidden compatibility option:
177
+ * ```ts
178
+ * {
179
+ * legacy: {
180
+ * type: 'string',
181
+ * hidden: true,
182
+ * description: 'Deprecated compatibility option'
183
+ * }
184
+ * }
185
+ * ```
186
+ */
187
+ hidden?: boolean;
169
188
  /**
170
189
  * Marks the argument as required.
171
190
  *
172
191
  * When `true`, the argument must be provided by the user.
173
192
  * If missing, an `ArgResolveError` with type 'required' will be thrown.
174
193
  *
175
- * Note: Only `true` is allowed (not `false`) to make intent explicit.
194
+ * For single-value positional arguments, omitting `required` keeps the argument
195
+ * required for compatibility. Set `required: false` to make a positional argument
196
+ * optional. Optional positional arguments leave enough input values for later
197
+ * required positional arguments before consuming a value.
176
198
  *
177
199
  * @example
178
200
  * Required arguments:
@@ -196,7 +218,8 @@ interface ArgSchema {
196
218
  *
197
219
  * When `true`, the resolved value becomes an array.
198
220
  * For options: can be specified multiple times (--tag foo --tag bar)
199
- * For positional: collects remaining positional arguments
221
+ * For positional: collects remaining positional arguments after preserving values for
222
+ * later required positional arguments.
200
223
  *
201
224
  * Note: Only `true` is allowed (not `false`) to make intent explicit.
202
225
  *
@@ -276,7 +299,11 @@ interface ArgSchema {
276
299
  * - `boolean` type: boolean default
277
300
  * - `number` type: number default
278
301
  * - `enum` type: must be one of the `choices` values
279
- * - `positional`/`custom` type: any appropriate default
302
+ * - `positional`/`custom` type: string, boolean, or number default
303
+ *
304
+ * For single-value positional arguments, the default is used when the positional
305
+ * value is missing or when the value is preserved for later required positional
306
+ * arguments, unless `required: true` is set.
280
307
  *
281
308
  * @example
282
309
  * Default values by type:
@@ -533,7 +560,8 @@ type FilterArgs<A extends Args, V extends Record<keyof A, unknown>, K extends ke
533
560
  *
534
561
  * @internal
535
562
  */
536
- type FilterPositionalArgs<A extends Args, V extends Record<keyof A, unknown>> = { [Arg in keyof A as A[Arg]['type'] extends 'positional' ? Arg : never]: V[Arg] };
563
+ type FilterPositionalArgs<A extends Args, V extends Record<keyof A, unknown>> = { [Arg in keyof A as IsRequiredPositionalArg<A[Arg]> extends true ? Arg : never]: V[Arg] };
564
+ type IsRequiredPositionalArg<A extends ArgSchema> = A['type'] extends 'positional' ? A['multiple'] extends true ? A['required'] extends true ? true : false : A['required'] extends false ? A['default'] extends {} ? true : false : true : false;
537
565
  /**
538
566
  * An arguments for {@link resolveArgs | resolve arguments}.
539
567
  */
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/args-tokens@0.25.0/node_modules/args-tokens/lib/parser.js
1
+ //#region ../../node_modules/.pnpm/args-tokens@0.27.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.25.0/node_modules/args-tokens/lib/utils.js
206
+ //#region ../../node_modules/.pnpm/args-tokens@0.27.0/node_modules/args-tokens/lib/utils.js
207
207
  /**
208
208
  * Entry point of utils.
209
209
  *
@@ -225,7 +225,7 @@ function kebabnize(str) {
225
225
  return str.replace(/[A-Z]/g, (match, offset) => (offset > 0 ? "-" : "") + match.toLowerCase());
226
226
  }
227
227
  //#endregion
228
- //#region ../../node_modules/.pnpm/args-tokens@0.25.0/node_modules/args-tokens/lib/resolver.js
228
+ //#region ../../node_modules/.pnpm/args-tokens@0.27.0/node_modules/args-tokens/lib/resolver.js
229
229
  /**
230
230
  * Entry point of argument options resolver.
231
231
  *
@@ -368,6 +368,8 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
368
368
  const errors = [];
369
369
  const explicit = Object.create(null);
370
370
  const actualInputNames = /* @__PURE__ */ new Map();
371
+ const argEntries = Object.entries(args);
372
+ let requiredPositionalsAfter;
371
373
  function checkTokenName(option, schema, token) {
372
374
  return token.name === (schema.type === "boolean" ? schema.negatable && token.name?.startsWith("no-") ? `no-${option}` : option : option);
373
375
  }
@@ -375,39 +377,63 @@ function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKI
375
377
  function getPositionalSkipIndex() {
376
378
  return Math.min(skipPositionalIndex, positionalItemCount);
377
379
  }
380
+ function getRequiredPositionalsAfter(rawArg) {
381
+ requiredPositionalsAfter ??= createRequiredPositionalsAfter(argEntries);
382
+ return requiredPositionalsAfter[rawArg] ?? 0;
383
+ }
378
384
  let positionalsCount = 0;
379
- for (const [rawArg, schema] of Object.entries(args)) {
385
+ for (const [rawArg, schema] of argEntries) {
380
386
  const arg = toKebab || schema.toKebab ? kebabnize(rawArg) : rawArg;
381
387
  explicit[rawArg] = false;
382
388
  if (schema.type === "positional") {
383
389
  if (skipPositionalIndex > SKIP_POSITIONAL_DEFAULT) while (positionalsCount <= getPositionalSkipIndex()) positionalsCount++;
384
390
  if (schema.multiple) {
385
- const remainingPositionals = positionalTokens.slice(positionalsCount);
386
- if (remainingPositionals.length > 0) {
387
- if (typeof schema.parse === "function") {
388
- const parsed = [];
389
- for (const p of remainingPositionals) try {
390
- parsed.push(schema.parse(p.value));
391
- } catch (error) {
392
- errors.push(error);
391
+ const availablePositionals = Math.max(positionalTokens.length - positionalsCount, 0);
392
+ if (availablePositionals > 0) {
393
+ const requiredPositionals = getRequiredPositionalsAfter(rawArg);
394
+ const positionalsToConsume = Math.max(availablePositionals - requiredPositionals, 0);
395
+ if (positionalsToConsume > 0) {
396
+ const endPositionals = positionalsCount + positionalsToConsume;
397
+ if (typeof schema.parse === "function") {
398
+ const parsed = [];
399
+ for (let i = positionalsCount; i < endPositionals; i++) {
400
+ const p = positionalTokens[i];
401
+ try {
402
+ parsed.push(schema.parse(p.value));
403
+ } catch (error) {
404
+ errors.push(error);
405
+ }
406
+ }
407
+ values[rawArg] = parsed;
408
+ } else {
409
+ const valuesArray = [];
410
+ for (let i = positionalsCount; i < endPositionals; i++) valuesArray.push(positionalTokens[i].value);
411
+ values[rawArg] = valuesArray;
393
412
  }
394
- values[rawArg] = parsed;
395
- } else values[rawArg] = remainingPositionals.map((p) => p.value);
396
- positionalsCount += remainingPositionals.length;
397
- explicit[rawArg] = true;
413
+ positionalsCount = endPositionals;
414
+ explicit[rawArg] = true;
415
+ } else if (schema.required) errors.push(createRequireError(arg, schema));
398
416
  } else if (schema.required) errors.push(createRequireError(arg, schema));
399
417
  } else {
400
418
  const positional = positionalTokens[positionalsCount];
419
+ if (shouldRequireMissingSinglePositional(schema)) {
420
+ if (positional != null) {
421
+ resolveSinglePositionalValue(values, errors, rawArg, schema, positional);
422
+ explicit[rawArg] = true;
423
+ positionalsCount++;
424
+ } else errors.push(createRequireError(arg, schema));
425
+ continue;
426
+ }
401
427
  if (positional != null) {
402
- if (typeof schema.parse === "function") try {
403
- values[rawArg] = schema.parse(positional.value);
404
- } catch (error) {
405
- errors.push(error);
428
+ const requiredPositionals = getRequiredPositionalsAfter(rawArg);
429
+ if (Math.max(positionalTokens.length - positionalsCount, 0) > requiredPositionals) {
430
+ resolveSinglePositionalValue(values, errors, rawArg, schema, positional);
431
+ explicit[rawArg] = true;
432
+ positionalsCount++;
433
+ continue;
406
434
  }
407
- else values[rawArg] = positional.value;
408
- explicit[rawArg] = true;
409
- } else errors.push(createRequireError(arg, schema));
410
- positionalsCount++;
435
+ }
436
+ if (hasDefault(schema)) values[rawArg] = schema.default;
411
437
  }
412
438
  continue;
413
439
  }
@@ -476,6 +502,38 @@ function parse(token, option, schema) {
476
502
  function createRequireError(option, schema) {
477
503
  return new ArgResolveError(schema.type === "positional" ? `Positional argument '${option}' is required` : `Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}is required`, option, "required", schema);
478
504
  }
505
+ function resolveSinglePositionalValue(values, errors, rawArg, schema, positional) {
506
+ if (typeof schema.parse === "function") try {
507
+ values[rawArg] = schema.parse(positional.value);
508
+ } catch (error) {
509
+ errors.push(error);
510
+ }
511
+ else values[rawArg] = positional.value;
512
+ }
513
+ function hasDefault(schema) {
514
+ return schema.default != null;
515
+ }
516
+ function shouldRequireMissingSinglePositional(schema) {
517
+ if (schema.required === true) return true;
518
+ if (schema.required === false) return false;
519
+ return !hasDefault(schema);
520
+ }
521
+ function getRequiredPositionalInputCount(schema) {
522
+ if (schema.type !== "positional") return 0;
523
+ if (schema.multiple) return schema.required === true ? 1 : 0;
524
+ return shouldRequireMissingSinglePositional(schema) ? 1 : 0;
525
+ }
526
+ function createRequiredPositionalsAfter(argEntries) {
527
+ const requiredPositionalsAfter = Object.create(null);
528
+ let minimumRequiredPositionals = 0;
529
+ for (let i = argEntries.length - 1; i >= 0; i--) {
530
+ const [rawArg, schema] = argEntries[i];
531
+ if (schema.type !== "positional") continue;
532
+ requiredPositionalsAfter[rawArg] = minimumRequiredPositionals;
533
+ minimumRequiredPositionals += getRequiredPositionalInputCount(schema);
534
+ }
535
+ return requiredPositionalsAfter;
536
+ }
479
537
  /**
480
538
  * An error that occurs when resolving arguments.
481
539
  * This error is thrown when the argument is not valid.
@@ -525,7 +583,7 @@ function checkConflicts(args, explicit, toKebab, actualInputNames) {
525
583
  return [];
526
584
  }
527
585
  //#endregion
528
- //#region ../../node_modules/.pnpm/args-tokens@0.25.0/node_modules/args-tokens/lib/index.js
586
+ //#region ../../node_modules/.pnpm/args-tokens@0.27.0/node_modules/args-tokens/lib/index.js
529
587
  /**
530
588
  * @author kazuya kawaguchi (a.k.a. kazupon)
531
589
  * @license MIT
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gunshi/bone",
3
3
  "description": "gunshi minimum",
4
- "version": "0.33.0",
4
+ "version": "0.35.0",
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-renderer": "0.33.0",
60
- "gunshi": "0.33.0",
61
- "@gunshi/plugin-global": "0.33.0",
62
- "@gunshi/definition": "0.33.0"
59
+ "@gunshi/definition": "0.35.0",
60
+ "@gunshi/plugin-global": "0.35.0",
61
+ "gunshi": "0.35.0",
62
+ "@gunshi/plugin-renderer": "0.35.0"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "tsdown",