@optique/config 1.0.0-dev.1616 → 1.0.0-dev.1658

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/dist/index.cjs CHANGED
@@ -23,12 +23,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  //#endregion
24
24
  const node_fs = __toESM(require("node:fs"));
25
25
  const node_path = __toESM(require("node:path"));
26
+ const __optique_core_parser = __toESM(require("@optique/core/parser"));
26
27
  const __optique_core_annotations = __toESM(require("@optique/core/annotations"));
27
28
  const __optique_core_message = __toESM(require("@optique/core/message"));
28
29
  const __optique_core_mode_dispatch = __toESM(require("@optique/core/mode-dispatch"));
29
30
 
30
31
  //#region src/index.ts
31
32
  const phase2UndefinedParsedValueKey = Symbol("@optique/config/phase2UndefinedParsedValue");
33
+ const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
32
34
  /**
33
35
  * Internal registry for active config data during config context execution.
34
36
  * This is a workaround for the limitation that object() doesn't propagate
@@ -298,11 +300,13 @@ function bindConfig(parser, options) {
298
300
  const annotations = (0, __optique_core_annotations.getAnnotations)(state);
299
301
  return annotations?.[options.context.id] === phase1ConfigAnnotationMarker;
300
302
  }
303
+ const getSuggestInnerState = (state) => isConfigBindState(state) ? state.cliState === void 0 ? (0, __optique_core_annotations.inheritAnnotations)(state, parser.initialState) : state.cliState : state;
301
304
  const boundParser = {
302
305
  $mode: parser.$mode,
303
306
  $valueType: parser.$valueType,
304
307
  $stateType: parser.$stateType,
305
308
  priority: parser.priority,
309
+ [__optique_core_parser.unmatchedNonCliDependencySourceStateMarker]: true,
306
310
  usage: options.default !== void 0 ? [{
307
311
  type: "optional",
308
312
  terms: parser.usage
@@ -310,6 +314,15 @@ function bindConfig(parser, options) {
310
314
  leadingNames: parser.leadingNames,
311
315
  acceptingAnyToken: parser.acceptingAnyToken,
312
316
  initialState: parser.initialState,
317
+ getSuggestRuntimeNodes(state, path) {
318
+ const innerState = getSuggestInnerState(state);
319
+ const innerNodes = parser.getSuggestRuntimeNodes?.(innerState, path) ?? [];
320
+ return boundParser.dependencyMetadata?.source != null ? [...innerNodes, {
321
+ path,
322
+ parser: boundParser,
323
+ state
324
+ }] : innerNodes;
325
+ },
313
326
  parse: (context) => {
314
327
  const annotations = (0, __optique_core_annotations.getAnnotations)(context.state);
315
328
  const innerState = isConfigBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
@@ -356,7 +369,14 @@ function bindConfig(parser, options) {
356
369
  if (isConfigBindState(state) && state.hasCliValue) return parser.complete(state.cliState, exec);
357
370
  return (0, __optique_core_mode_dispatch.wrapForMode)(parser.$mode, getConfigOrDefault(state, options));
358
371
  },
359
- suggest: parser.suggest,
372
+ suggest: (context, prefix) => {
373
+ const innerState = getSuggestInnerState(context.state);
374
+ const innerContext = innerState !== context.state ? {
375
+ ...context,
376
+ state: innerState
377
+ } : context;
378
+ return parser.suggest(innerContext, prefix);
379
+ },
360
380
  shouldDeferCompletion: shouldDeferPromptUntilConfigResolves,
361
381
  getDocFragments(state, upperDefaultValue) {
362
382
  const defaultValue = upperDefaultValue ?? options.default;
@@ -375,6 +395,39 @@ function bindConfig(parser, options) {
375
395
  configurable: true,
376
396
  enumerable: false
377
397
  });
398
+ Object.defineProperty(boundParser, inheritParentAnnotationsKey, {
399
+ value: true,
400
+ configurable: true,
401
+ enumerable: false
402
+ });
403
+ const dependencyMetadata = parser.dependencyMetadata;
404
+ if (dependencyMetadata != null) {
405
+ const sourceMetadata = dependencyMetadata.source;
406
+ Object.defineProperty(boundParser, "dependencyMetadata", {
407
+ value: sourceMetadata == null ? dependencyMetadata : {
408
+ ...dependencyMetadata,
409
+ source: {
410
+ ...sourceMetadata,
411
+ getMissingSourceValue: sourceMetadata.preservesSourceValue !== false && options.default !== void 0 ? () => ({
412
+ success: true,
413
+ value: options.default
414
+ }) : void 0,
415
+ extractSourceValue: (state) => {
416
+ if (!isConfigBindState(state)) {
417
+ if (sourceMetadata.preservesSourceValue) return getConfigSourceValue(state, options, state, sourceMetadata.extractSourceValue);
418
+ return sourceMetadata.extractSourceValue(state);
419
+ }
420
+ if (state.hasCliValue) return sourceMetadata.extractSourceValue(state.cliState);
421
+ const fallbackState = state.cliState ?? state;
422
+ if (!sourceMetadata.preservesSourceValue) return sourceMetadata.extractSourceValue(fallbackState);
423
+ return getConfigSourceValue(state, options, fallbackState, sourceMetadata.extractSourceValue);
424
+ }
425
+ }
426
+ },
427
+ configurable: true,
428
+ enumerable: false
429
+ });
430
+ }
378
431
  return boundParser;
379
432
  }
380
433
  /**
@@ -412,6 +465,37 @@ function getConfigOrDefault(state, options) {
412
465
  error: __optique_core_message.message`Missing required configuration value.`
413
466
  };
414
467
  }
468
+ /**
469
+ * Resolves a config-backed dependency source with fallback priority.
470
+ *
471
+ * This first checks annotations or the active config registry via
472
+ * {@link getConfigOrDefault}. If no config-backed value is available, it falls
473
+ * back to `options.default` and finally delegates to the wrapped parser's
474
+ * source extractor.
475
+ *
476
+ * @param state The wrapper state, which may carry config annotations.
477
+ * @param options The binding options with lookup and default settings.
478
+ * @param innerState The unwrapped inner state for delegated extraction.
479
+ * @param extractInnerSourceValue The wrapped parser's source extractor.
480
+ * @returns The resolved source value, an async source value, or `undefined`.
481
+ * @throws {TypeError} If {@link getConfigOrDefault} rejects a thenable-returning
482
+ * key callback.
483
+ */
484
+ function getConfigSourceValue(state, options, innerState, extractInnerSourceValue) {
485
+ const annotations = (0, __optique_core_annotations.getAnnotations)(state);
486
+ const contextId = options.context.id;
487
+ const annotationValue = annotations?.[contextId];
488
+ const configData = annotationValue?.data ?? getActiveConfig(contextId);
489
+ if (configData !== void 0 && configData !== null) {
490
+ const resolved = getConfigOrDefault(state, options);
491
+ if (resolved.success) return resolved;
492
+ }
493
+ if (options.default !== void 0) return {
494
+ success: true,
495
+ value: options.default
496
+ };
497
+ return extractInnerSourceValue(innerState);
498
+ }
415
499
 
416
500
  //#endregion
417
501
  exports.bindConfig = bindConfig;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { Parser } from "@optique/core/parser";
1
2
  import { StandardSchemaV1 } from "@standard-schema/spec";
2
3
  import { ParserValuePlaceholder, SourceContext } from "@optique/core/context";
3
- import { Parser } from "@optique/core/parser";
4
4
 
5
5
  //#region src/index.d.ts
6
6
 
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { dirname, resolve } from "node:path";
3
- import { annotationKey, getAnnotations } from "@optique/core/annotations";
3
+ import { unmatchedNonCliDependencySourceStateMarker } from "@optique/core/parser";
4
+ import { annotationKey, getAnnotations, inheritAnnotations } from "@optique/core/annotations";
4
5
  import { message } from "@optique/core/message";
5
6
  import { mapModeValue, wrapForMode } from "@optique/core/mode-dispatch";
6
7
 
7
8
  //#region src/index.ts
8
9
  const phase2UndefinedParsedValueKey = Symbol("@optique/config/phase2UndefinedParsedValue");
10
+ const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
9
11
  /**
10
12
  * Internal registry for active config data during config context execution.
11
13
  * This is a workaround for the limitation that object() doesn't propagate
@@ -275,11 +277,13 @@ function bindConfig(parser, options) {
275
277
  const annotations = getAnnotations(state);
276
278
  return annotations?.[options.context.id] === phase1ConfigAnnotationMarker;
277
279
  }
280
+ const getSuggestInnerState = (state) => isConfigBindState(state) ? state.cliState === void 0 ? inheritAnnotations(state, parser.initialState) : state.cliState : state;
278
281
  const boundParser = {
279
282
  $mode: parser.$mode,
280
283
  $valueType: parser.$valueType,
281
284
  $stateType: parser.$stateType,
282
285
  priority: parser.priority,
286
+ [unmatchedNonCliDependencySourceStateMarker]: true,
283
287
  usage: options.default !== void 0 ? [{
284
288
  type: "optional",
285
289
  terms: parser.usage
@@ -287,6 +291,15 @@ function bindConfig(parser, options) {
287
291
  leadingNames: parser.leadingNames,
288
292
  acceptingAnyToken: parser.acceptingAnyToken,
289
293
  initialState: parser.initialState,
294
+ getSuggestRuntimeNodes(state, path) {
295
+ const innerState = getSuggestInnerState(state);
296
+ const innerNodes = parser.getSuggestRuntimeNodes?.(innerState, path) ?? [];
297
+ return boundParser.dependencyMetadata?.source != null ? [...innerNodes, {
298
+ path,
299
+ parser: boundParser,
300
+ state
301
+ }] : innerNodes;
302
+ },
290
303
  parse: (context) => {
291
304
  const annotations = getAnnotations(context.state);
292
305
  const innerState = isConfigBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
@@ -333,7 +346,14 @@ function bindConfig(parser, options) {
333
346
  if (isConfigBindState(state) && state.hasCliValue) return parser.complete(state.cliState, exec);
334
347
  return wrapForMode(parser.$mode, getConfigOrDefault(state, options));
335
348
  },
336
- suggest: parser.suggest,
349
+ suggest: (context, prefix) => {
350
+ const innerState = getSuggestInnerState(context.state);
351
+ const innerContext = innerState !== context.state ? {
352
+ ...context,
353
+ state: innerState
354
+ } : context;
355
+ return parser.suggest(innerContext, prefix);
356
+ },
337
357
  shouldDeferCompletion: shouldDeferPromptUntilConfigResolves,
338
358
  getDocFragments(state, upperDefaultValue) {
339
359
  const defaultValue = upperDefaultValue ?? options.default;
@@ -352,6 +372,39 @@ function bindConfig(parser, options) {
352
372
  configurable: true,
353
373
  enumerable: false
354
374
  });
375
+ Object.defineProperty(boundParser, inheritParentAnnotationsKey, {
376
+ value: true,
377
+ configurable: true,
378
+ enumerable: false
379
+ });
380
+ const dependencyMetadata = parser.dependencyMetadata;
381
+ if (dependencyMetadata != null) {
382
+ const sourceMetadata = dependencyMetadata.source;
383
+ Object.defineProperty(boundParser, "dependencyMetadata", {
384
+ value: sourceMetadata == null ? dependencyMetadata : {
385
+ ...dependencyMetadata,
386
+ source: {
387
+ ...sourceMetadata,
388
+ getMissingSourceValue: sourceMetadata.preservesSourceValue !== false && options.default !== void 0 ? () => ({
389
+ success: true,
390
+ value: options.default
391
+ }) : void 0,
392
+ extractSourceValue: (state) => {
393
+ if (!isConfigBindState(state)) {
394
+ if (sourceMetadata.preservesSourceValue) return getConfigSourceValue(state, options, state, sourceMetadata.extractSourceValue);
395
+ return sourceMetadata.extractSourceValue(state);
396
+ }
397
+ if (state.hasCliValue) return sourceMetadata.extractSourceValue(state.cliState);
398
+ const fallbackState = state.cliState ?? state;
399
+ if (!sourceMetadata.preservesSourceValue) return sourceMetadata.extractSourceValue(fallbackState);
400
+ return getConfigSourceValue(state, options, fallbackState, sourceMetadata.extractSourceValue);
401
+ }
402
+ }
403
+ },
404
+ configurable: true,
405
+ enumerable: false
406
+ });
407
+ }
355
408
  return boundParser;
356
409
  }
357
410
  /**
@@ -389,6 +442,37 @@ function getConfigOrDefault(state, options) {
389
442
  error: message`Missing required configuration value.`
390
443
  };
391
444
  }
445
+ /**
446
+ * Resolves a config-backed dependency source with fallback priority.
447
+ *
448
+ * This first checks annotations or the active config registry via
449
+ * {@link getConfigOrDefault}. If no config-backed value is available, it falls
450
+ * back to `options.default` and finally delegates to the wrapped parser's
451
+ * source extractor.
452
+ *
453
+ * @param state The wrapper state, which may carry config annotations.
454
+ * @param options The binding options with lookup and default settings.
455
+ * @param innerState The unwrapped inner state for delegated extraction.
456
+ * @param extractInnerSourceValue The wrapped parser's source extractor.
457
+ * @returns The resolved source value, an async source value, or `undefined`.
458
+ * @throws {TypeError} If {@link getConfigOrDefault} rejects a thenable-returning
459
+ * key callback.
460
+ */
461
+ function getConfigSourceValue(state, options, innerState, extractInnerSourceValue) {
462
+ const annotations = getAnnotations(state);
463
+ const contextId = options.context.id;
464
+ const annotationValue = annotations?.[contextId];
465
+ const configData = annotationValue?.data ?? getActiveConfig(contextId);
466
+ if (configData !== void 0 && configData !== null) {
467
+ const resolved = getConfigOrDefault(state, options);
468
+ if (resolved.success) return resolved;
469
+ }
470
+ if (options.default !== void 0) return {
471
+ success: true,
472
+ value: options.default
473
+ };
474
+ return extractInnerSourceValue(innerState);
475
+ }
392
476
 
393
477
  //#endregion
394
478
  export { bindConfig, clearActiveConfig, clearActiveConfigMeta, createConfigContext, getActiveConfig, getActiveConfigMeta, setActiveConfig, setActiveConfigMeta };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/config",
3
- "version": "1.0.0-dev.1616+17abc525",
3
+ "version": "1.0.0-dev.1658+b57e115b",
4
4
  "description": "Configuration file support for Optique with Standard Schema validation",
5
5
  "keywords": [
6
6
  "CLI",
@@ -59,7 +59,7 @@
59
59
  "@standard-schema/spec": "^1.1.0"
60
60
  },
61
61
  "dependencies": {
62
- "@optique/core": "1.0.0-dev.1616+17abc525"
62
+ "@optique/core": "1.0.0-dev.1658+b57e115b"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@standard-schema/spec": "^1.1.0",
@@ -67,7 +67,7 @@
67
67
  "tsdown": "^0.13.0",
68
68
  "typescript": "^5.8.3",
69
69
  "zod": "^3.25.0 || ^4.0.0",
70
- "@optique/env": "1.0.0-dev.1616+17abc525"
70
+ "@optique/env": "1.0.0-dev.1658+b57e115b"
71
71
  },
72
72
  "scripts": {
73
73
  "build": "tsdown",