@optique/core 1.0.0-dev.725 → 1.0.0-dev.729

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.
@@ -66,6 +66,7 @@ const suggestWithDependency = Symbol.for("@optique/core/dependency/suggestWithDe
66
66
  * // Create a derived parser that depends on the directory
67
67
  * const branchParser = cwdParser.derive({
68
68
  * metavar: "BRANCH",
69
+ * mode: "sync",
69
70
  * factory: (dir) => gitBranch({ dir }),
70
71
  * defaultValue: () => process.cwd(),
71
72
  * });
@@ -79,7 +80,8 @@ function dependency(parser) {
79
80
  [dependencySourceMarker]: true,
80
81
  [dependencyId]: id,
81
82
  derive(options) {
82
- return createDerivedValueParser(id, parser, options);
83
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("derive() requires an explicit mode field (\"sync\" or \"async\").");
84
+ return createDerivedValueParser(id, parser, options, options.mode);
83
85
  },
84
86
  deriveSync(options) {
85
87
  if (parser.$mode === "async") return createAsyncDerivedParserFromSyncFactory(id, options);
@@ -132,6 +134,7 @@ function isDerivedValueParser(parser) {
132
134
  *
133
135
  * const configParser = deriveFrom({
134
136
  * metavar: "CONFIG",
137
+ * mode: "sync",
135
138
  * dependencies: [dirParser, modeParser] as const,
136
139
  * factory: (dir, mode) =>
137
140
  * choice(mode === "dev"
@@ -140,12 +143,14 @@ function isDerivedValueParser(parser) {
140
143
  * defaultValues: () => ["/config", "dev"],
141
144
  * });
142
145
  * ```
146
+ * @throws {TypeError} If the `mode` field is missing or invalid.
143
147
  * @since 0.10.0
144
148
  */
145
149
  function deriveFrom(options) {
150
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("deriveFrom() requires an explicit mode field (\"sync\" or \"async\").");
146
151
  const depsAsync = options.dependencies.some((dep) => dep.$mode === "async");
147
- const factoryReturnsAsync = determineFactoryModeForDeriveFrom(options);
148
152
  const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
153
+ const factoryReturnsAsync = options.mode === "async";
149
154
  const isAsync = depsAsync || factoryReturnsAsync;
150
155
  if (isAsync) {
151
156
  if (factoryReturnsAsync) return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
@@ -191,14 +196,6 @@ function deriveFromAsync(options) {
191
196
  const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
192
197
  return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
193
198
  }
194
- /**
195
- * Determines if the factory returns an async parser for deriveFrom options.
196
- */
197
- function determineFactoryModeForDeriveFrom(options) {
198
- const defaultValues$1 = options.defaultValues();
199
- const parser = options.factory(...defaultValues$1);
200
- return parser.$mode === "async";
201
- }
202
199
  function isAsyncModeParser(parser) {
203
200
  return parser.$mode === "async";
204
201
  }
@@ -254,7 +251,8 @@ function createSyncDerivedFromParser(sourceId, options) {
254
251
  *suggest(prefix) {
255
252
  const sourceValues = options.defaultValues();
256
253
  const derivedParser = options.factory(...sourceValues);
257
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
254
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
255
+ yield* derivedParser.suggest(prefix);
258
256
  },
259
257
  *[suggestWithDependency](prefix, dependencyValue) {
260
258
  let derivedParser;
@@ -268,7 +266,8 @@ function createSyncDerivedFromParser(sourceId, options) {
268
266
  return;
269
267
  }
270
268
  }
271
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
269
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
270
+ yield* derivedParser.suggest(prefix);
272
271
  }
273
272
  };
274
273
  }
@@ -404,8 +403,8 @@ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
404
403
  }
405
404
  };
406
405
  }
407
- function createDerivedValueParser(sourceId, sourceParser, options) {
408
- const factoryReturnsAsync = determineFactoryMode(options);
406
+ function createDerivedValueParser(sourceId, sourceParser, options, factoryMode) {
407
+ const factoryReturnsAsync = factoryMode === "async";
409
408
  const isAsync = sourceParser.$mode === "async" || factoryReturnsAsync;
410
409
  if (isAsync) {
411
410
  if (factoryReturnsAsync) return createAsyncDerivedParserFromAsyncFactory(sourceId, options);
@@ -413,15 +412,6 @@ function createDerivedValueParser(sourceId, sourceParser, options) {
413
412
  }
414
413
  return createSyncDerivedParser(sourceId, options);
415
414
  }
416
- /**
417
- * Determines if the factory returns an async parser by calling it with
418
- * the default value and checking the mode.
419
- */
420
- function determineFactoryMode(options) {
421
- const defaultValue = options.defaultValue();
422
- const parser = options.factory(defaultValue);
423
- return parser.$mode === "async";
424
- }
425
415
  function createSyncDerivedParser(sourceId, options) {
426
416
  return {
427
417
  $mode: "sync",
@@ -471,7 +461,8 @@ function createSyncDerivedParser(sourceId, options) {
471
461
  *suggest(prefix) {
472
462
  const sourceValue = options.defaultValue();
473
463
  const derivedParser = options.factory(sourceValue);
474
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
464
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
465
+ yield* derivedParser.suggest(prefix);
475
466
  },
476
467
  *[suggestWithDependency](prefix, dependencyValue) {
477
468
  let derivedParser;
@@ -484,7 +475,8 @@ function createSyncDerivedParser(sourceId, options) {
484
475
  return;
485
476
  }
486
477
  }
487
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
478
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
479
+ yield* derivedParser.suggest(prefix);
488
480
  }
489
481
  };
490
482
  }
@@ -77,7 +77,7 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
77
77
  * @param sourceValue The value parsed from the dependency source.
78
78
  * @returns A {@link ValueParser} for the derived value.
79
79
  */
80
- readonly factory: (sourceValue: S) => ValueParser<FM, T>;
80
+ readonly factory: (sourceValue: S) => ValueParser<NoInfer<FM>, T>;
81
81
  /**
82
82
  * Default value to use when the dependency source is not provided.
83
83
  * This allows the derived parser to work even when the dependency
@@ -86,6 +86,14 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
86
86
  * @returns The default value for the dependency source.
87
87
  */
88
88
  readonly defaultValue: () => S;
89
+ /**
90
+ * The execution mode of the factory's returned parser. This tells the
91
+ * runtime whether the factory returns a sync or async parser, avoiding
92
+ * the need to call the factory during parser construction.
93
+ *
94
+ * @since 1.0.0
95
+ */
96
+ readonly mode: FM;
89
97
  }
90
98
  /**
91
99
  * Options for creating a derived value parser with a synchronous factory.
@@ -165,6 +173,7 @@ interface DependencySource<M extends Mode = "sync", T = unknown> extends ValuePa
165
173
  * @template FM The mode of the factory's returned parser.
166
174
  * @param options Configuration for the derived parser.
167
175
  * @returns A {@link DerivedValueParser} that depends on this source.
176
+ * @throws {TypeError} If the `mode` field is missing or invalid.
168
177
  */
169
178
  derive<U, FM extends Mode = "sync">(options: DeriveOptions<T, U, FM>): DerivedValueParser<CombineMode<M, FM>, U, T>;
170
179
  /**
@@ -247,7 +256,7 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
247
256
  * @param values The values parsed from the dependency sources (in order).
248
257
  * @returns A {@link ValueParser} for the derived value.
249
258
  */
250
- readonly factory: (...values: DependencyValues<Deps>) => ValueParser<FM, T>;
259
+ readonly factory: (...values: DependencyValues<Deps>) => ValueParser<NoInfer<FM>, T>;
251
260
  /**
252
261
  * Default values to use when the dependency sources are not provided.
253
262
  * Must return a tuple with the same length and types as the dependencies.
@@ -255,6 +264,14 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
255
264
  * @returns A tuple of default values for each dependency source.
256
265
  */
257
266
  readonly defaultValues: () => DependencyValues<Deps>;
267
+ /**
268
+ * The execution mode of the factory's returned parser. This tells the
269
+ * runtime whether the factory returns a sync or async parser, avoiding
270
+ * the need to call the factory during parser construction.
271
+ *
272
+ * @since 1.0.0
273
+ */
274
+ readonly mode: FM;
258
275
  }
259
276
  /**
260
277
  * Options for creating a derived value parser from multiple dependencies
@@ -390,6 +407,7 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
390
407
  * // Create a derived parser that depends on the directory
391
408
  * const branchParser = cwdParser.derive({
392
409
  * metavar: "BRANCH",
410
+ * mode: "sync",
393
411
  * factory: (dir) => gitBranch({ dir }),
394
412
  * defaultValue: () => process.cwd(),
395
413
  * });
@@ -434,6 +452,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
434
452
  *
435
453
  * const configParser = deriveFrom({
436
454
  * metavar: "CONFIG",
455
+ * mode: "sync",
437
456
  * dependencies: [dirParser, modeParser] as const,
438
457
  * factory: (dir, mode) =>
439
458
  * choice(mode === "dev"
@@ -442,6 +461,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
442
461
  * defaultValues: () => ["/config", "dev"],
443
462
  * });
444
463
  * ```
464
+ * @throws {TypeError} If the `mode` field is missing or invalid.
445
465
  * @since 0.10.0
446
466
  */
447
467
  declare function deriveFrom<Deps extends readonly AnyDependencySource[], T, FM extends Mode = "sync">(options: DeriveFromOptions<Deps, T, FM>): DerivedValueParser<CombineMode<CombinedDependencyMode<Deps>, FM>, T, DependencyValues<Deps>>;
@@ -77,7 +77,7 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
77
77
  * @param sourceValue The value parsed from the dependency source.
78
78
  * @returns A {@link ValueParser} for the derived value.
79
79
  */
80
- readonly factory: (sourceValue: S) => ValueParser<FM, T>;
80
+ readonly factory: (sourceValue: S) => ValueParser<NoInfer<FM>, T>;
81
81
  /**
82
82
  * Default value to use when the dependency source is not provided.
83
83
  * This allows the derived parser to work even when the dependency
@@ -86,6 +86,14 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
86
86
  * @returns The default value for the dependency source.
87
87
  */
88
88
  readonly defaultValue: () => S;
89
+ /**
90
+ * The execution mode of the factory's returned parser. This tells the
91
+ * runtime whether the factory returns a sync or async parser, avoiding
92
+ * the need to call the factory during parser construction.
93
+ *
94
+ * @since 1.0.0
95
+ */
96
+ readonly mode: FM;
89
97
  }
90
98
  /**
91
99
  * Options for creating a derived value parser with a synchronous factory.
@@ -165,6 +173,7 @@ interface DependencySource<M extends Mode = "sync", T = unknown> extends ValuePa
165
173
  * @template FM The mode of the factory's returned parser.
166
174
  * @param options Configuration for the derived parser.
167
175
  * @returns A {@link DerivedValueParser} that depends on this source.
176
+ * @throws {TypeError} If the `mode` field is missing or invalid.
168
177
  */
169
178
  derive<U, FM extends Mode = "sync">(options: DeriveOptions<T, U, FM>): DerivedValueParser<CombineMode<M, FM>, U, T>;
170
179
  /**
@@ -247,7 +256,7 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
247
256
  * @param values The values parsed from the dependency sources (in order).
248
257
  * @returns A {@link ValueParser} for the derived value.
249
258
  */
250
- readonly factory: (...values: DependencyValues<Deps>) => ValueParser<FM, T>;
259
+ readonly factory: (...values: DependencyValues<Deps>) => ValueParser<NoInfer<FM>, T>;
251
260
  /**
252
261
  * Default values to use when the dependency sources are not provided.
253
262
  * Must return a tuple with the same length and types as the dependencies.
@@ -255,6 +264,14 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
255
264
  * @returns A tuple of default values for each dependency source.
256
265
  */
257
266
  readonly defaultValues: () => DependencyValues<Deps>;
267
+ /**
268
+ * The execution mode of the factory's returned parser. This tells the
269
+ * runtime whether the factory returns a sync or async parser, avoiding
270
+ * the need to call the factory during parser construction.
271
+ *
272
+ * @since 1.0.0
273
+ */
274
+ readonly mode: FM;
258
275
  }
259
276
  /**
260
277
  * Options for creating a derived value parser from multiple dependencies
@@ -390,6 +407,7 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
390
407
  * // Create a derived parser that depends on the directory
391
408
  * const branchParser = cwdParser.derive({
392
409
  * metavar: "BRANCH",
410
+ * mode: "sync",
393
411
  * factory: (dir) => gitBranch({ dir }),
394
412
  * defaultValue: () => process.cwd(),
395
413
  * });
@@ -434,6 +452,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
434
452
  *
435
453
  * const configParser = deriveFrom({
436
454
  * metavar: "CONFIG",
455
+ * mode: "sync",
437
456
  * dependencies: [dirParser, modeParser] as const,
438
457
  * factory: (dir, mode) =>
439
458
  * choice(mode === "dev"
@@ -442,6 +461,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
442
461
  * defaultValues: () => ["/config", "dev"],
443
462
  * });
444
463
  * ```
464
+ * @throws {TypeError} If the `mode` field is missing or invalid.
445
465
  * @since 0.10.0
446
466
  */
447
467
  declare function deriveFrom<Deps extends readonly AnyDependencySource[], T, FM extends Mode = "sync">(options: DeriveFromOptions<Deps, T, FM>): DerivedValueParser<CombineMode<CombinedDependencyMode<Deps>, FM>, T, DependencyValues<Deps>>;
@@ -66,6 +66,7 @@ const suggestWithDependency = Symbol.for("@optique/core/dependency/suggestWithDe
66
66
  * // Create a derived parser that depends on the directory
67
67
  * const branchParser = cwdParser.derive({
68
68
  * metavar: "BRANCH",
69
+ * mode: "sync",
69
70
  * factory: (dir) => gitBranch({ dir }),
70
71
  * defaultValue: () => process.cwd(),
71
72
  * });
@@ -79,7 +80,8 @@ function dependency(parser) {
79
80
  [dependencySourceMarker]: true,
80
81
  [dependencyId]: id,
81
82
  derive(options) {
82
- return createDerivedValueParser(id, parser, options);
83
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("derive() requires an explicit mode field (\"sync\" or \"async\").");
84
+ return createDerivedValueParser(id, parser, options, options.mode);
83
85
  },
84
86
  deriveSync(options) {
85
87
  if (parser.$mode === "async") return createAsyncDerivedParserFromSyncFactory(id, options);
@@ -132,6 +134,7 @@ function isDerivedValueParser(parser) {
132
134
  *
133
135
  * const configParser = deriveFrom({
134
136
  * metavar: "CONFIG",
137
+ * mode: "sync",
135
138
  * dependencies: [dirParser, modeParser] as const,
136
139
  * factory: (dir, mode) =>
137
140
  * choice(mode === "dev"
@@ -140,12 +143,14 @@ function isDerivedValueParser(parser) {
140
143
  * defaultValues: () => ["/config", "dev"],
141
144
  * });
142
145
  * ```
146
+ * @throws {TypeError} If the `mode` field is missing or invalid.
143
147
  * @since 0.10.0
144
148
  */
145
149
  function deriveFrom(options) {
150
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("deriveFrom() requires an explicit mode field (\"sync\" or \"async\").");
146
151
  const depsAsync = options.dependencies.some((dep) => dep.$mode === "async");
147
- const factoryReturnsAsync = determineFactoryModeForDeriveFrom(options);
148
152
  const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
153
+ const factoryReturnsAsync = options.mode === "async";
149
154
  const isAsync = depsAsync || factoryReturnsAsync;
150
155
  if (isAsync) {
151
156
  if (factoryReturnsAsync) return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
@@ -191,14 +196,6 @@ function deriveFromAsync(options) {
191
196
  const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
192
197
  return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
193
198
  }
194
- /**
195
- * Determines if the factory returns an async parser for deriveFrom options.
196
- */
197
- function determineFactoryModeForDeriveFrom(options) {
198
- const defaultValues$1 = options.defaultValues();
199
- const parser = options.factory(...defaultValues$1);
200
- return parser.$mode === "async";
201
- }
202
199
  function isAsyncModeParser(parser) {
203
200
  return parser.$mode === "async";
204
201
  }
@@ -254,7 +251,8 @@ function createSyncDerivedFromParser(sourceId, options) {
254
251
  *suggest(prefix) {
255
252
  const sourceValues = options.defaultValues();
256
253
  const derivedParser = options.factory(...sourceValues);
257
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
254
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
255
+ yield* derivedParser.suggest(prefix);
258
256
  },
259
257
  *[suggestWithDependency](prefix, dependencyValue) {
260
258
  let derivedParser;
@@ -268,7 +266,8 @@ function createSyncDerivedFromParser(sourceId, options) {
268
266
  return;
269
267
  }
270
268
  }
271
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
269
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
270
+ yield* derivedParser.suggest(prefix);
272
271
  }
273
272
  };
274
273
  }
@@ -404,8 +403,8 @@ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
404
403
  }
405
404
  };
406
405
  }
407
- function createDerivedValueParser(sourceId, sourceParser, options) {
408
- const factoryReturnsAsync = determineFactoryMode(options);
406
+ function createDerivedValueParser(sourceId, sourceParser, options, factoryMode) {
407
+ const factoryReturnsAsync = factoryMode === "async";
409
408
  const isAsync = sourceParser.$mode === "async" || factoryReturnsAsync;
410
409
  if (isAsync) {
411
410
  if (factoryReturnsAsync) return createAsyncDerivedParserFromAsyncFactory(sourceId, options);
@@ -413,15 +412,6 @@ function createDerivedValueParser(sourceId, sourceParser, options) {
413
412
  }
414
413
  return createSyncDerivedParser(sourceId, options);
415
414
  }
416
- /**
417
- * Determines if the factory returns an async parser by calling it with
418
- * the default value and checking the mode.
419
- */
420
- function determineFactoryMode(options) {
421
- const defaultValue = options.defaultValue();
422
- const parser = options.factory(defaultValue);
423
- return parser.$mode === "async";
424
- }
425
415
  function createSyncDerivedParser(sourceId, options) {
426
416
  return {
427
417
  $mode: "sync",
@@ -471,7 +461,8 @@ function createSyncDerivedParser(sourceId, options) {
471
461
  *suggest(prefix) {
472
462
  const sourceValue = options.defaultValue();
473
463
  const derivedParser = options.factory(sourceValue);
474
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
464
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
465
+ yield* derivedParser.suggest(prefix);
475
466
  },
476
467
  *[suggestWithDependency](prefix, dependencyValue) {
477
468
  let derivedParser;
@@ -484,7 +475,8 @@ function createSyncDerivedParser(sourceId, options) {
484
475
  return;
485
476
  }
486
477
  }
487
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
478
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
479
+ yield* derivedParser.suggest(prefix);
488
480
  }
489
481
  };
490
482
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.725+d12d952b",
3
+ "version": "1.0.0-dev.729+c241821c",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",