@optique/core 1.0.0-dev.1778 → 1.0.0-dev.1785

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/modifiers.js CHANGED
@@ -2,6 +2,7 @@ import { annotateFreshArray, annotationKey, getAnnotations, inheritAnnotations,
2
2
  import { formatMessage, message, text } from "./message.js";
3
3
  import { dispatchByMode, dispatchIterableByMode, mapModeValue, wrapForMode } from "./mode-dispatch.js";
4
4
  import { composeDependencyMetadata } from "./dependency-metadata.js";
5
+ import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey } from "./phase2-seed.js";
5
6
  import { defineInheritedAnnotationParser, defineSourceBindingOnlyAnnotationCompletionParser, unmatchedNonCliDependencySourceStateMarker } from "./parser.js";
6
7
 
7
8
  //#region src/modifiers.ts
@@ -79,6 +80,10 @@ function unwrapMultipleItemState(state) {
79
80
  function isPromiseLike(value) {
80
81
  return value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
81
82
  }
83
+ function extractOptionalLikePhase2Seed(parser, state, exec) {
84
+ if (!Array.isArray(state) && !(state != null && typeof state === "object")) return wrapForMode(parser.$mode, null);
85
+ return completeOrExtractPhase2Seed(parser, normalizeOptionalLikeInnerState(state, parser.initialState, parser), exec);
86
+ }
82
87
  /**
83
88
  * Computes the inner state to pass through to the wrapped parser inside
84
89
  * {@link optional} / {@link withDefault}. When the outer state is an
@@ -251,6 +256,9 @@ function optional(parser) {
251
256
  state: innerState
252
257
  }] : []);
253
258
  },
259
+ [extractPhase2SeedKey](state, exec) {
260
+ return extractOptionalLikePhase2Seed(parser, state, exec);
261
+ },
254
262
  parse(context) {
255
263
  return dispatchByMode(parser.$mode, () => parseOptionalStyleSync(context, syncParser), () => parseOptionalStyleAsync(context, parser));
256
264
  },
@@ -416,6 +424,9 @@ function withDefault(parser, defaultValue, options) {
416
424
  state: innerState
417
425
  }] : []);
418
426
  },
427
+ [extractPhase2SeedKey](state, exec) {
428
+ return extractOptionalLikePhase2Seed(parser, state, exec);
429
+ },
419
430
  parse(context) {
420
431
  return dispatchByMode(parser.$mode, () => parseOptionalStyleSync(context, syncParser), () => parseOptionalStyleAsync(context, parser));
421
432
  },
@@ -656,6 +667,23 @@ function map(parser, transform) {
656
667
  ...parser,
657
668
  $valueType: [],
658
669
  complete,
670
+ [extractPhase2SeedKey](state, exec) {
671
+ return mapModeValue(parser.$mode, completeOrExtractPhase2Seed(parser, state, exec), (seed) => {
672
+ if (seed == null) return null;
673
+ if (seed.deferred) try {
674
+ return {
675
+ value: transform(seed.value),
676
+ deferred: true
677
+ };
678
+ } catch {
679
+ return {
680
+ value: void 0,
681
+ deferred: true
682
+ };
683
+ }
684
+ return { value: transform(seed.value) };
685
+ });
686
+ },
659
687
  getSuggestRuntimeNodes(state, path) {
660
688
  if (mappedParser.dependencyMetadata?.source != null) return [{
661
689
  path,
@@ -795,6 +823,26 @@ function multiple(parser, options = {}) {
795
823
  });
796
824
  }
797
825
  };
826
+ const extractPhase2SeedSyncWithUnwrappedFallback = (state, exec) => {
827
+ try {
828
+ const seed = completeOrExtractPhase2Seed(syncParser, state, exec);
829
+ if (seed == null && isInjectedAnnotationWrapper(state)) return completeOrExtractPhase2Seed(syncParser, unwrapInjectedWrapper(state), exec);
830
+ return seed;
831
+ } catch (error) {
832
+ if (!isInjectedAnnotationWrapper(state)) throw error;
833
+ return completeOrExtractPhase2Seed(syncParser, unwrapInjectedWrapper(state), exec);
834
+ }
835
+ };
836
+ const extractPhase2SeedAsyncWithUnwrappedFallback = async (state, exec) => {
837
+ try {
838
+ const seed = await completeOrExtractPhase2Seed(parser, state, exec);
839
+ if (seed == null && isInjectedAnnotationWrapper(state)) return await completeOrExtractPhase2Seed(parser, unwrapInjectedWrapper(state), exec);
840
+ return seed;
841
+ } catch (error) {
842
+ if (!isInjectedAnnotationWrapper(state)) throw error;
843
+ return await completeOrExtractPhase2Seed(parser, unwrapInjectedWrapper(state), exec);
844
+ }
845
+ };
798
846
  const getInnerSuggestRuntimeNodes = (state, path) => parser.getSuggestRuntimeNodes?.(state, path) ?? (parser.dependencyMetadata?.source != null ? [{
799
847
  path,
800
848
  parser,
@@ -1023,6 +1071,53 @@ function multiple(parser, options = {}) {
1023
1071
  return validateMultipleResult(values, deferredIndices, hasDeferred);
1024
1072
  });
1025
1073
  },
1074
+ [extractPhase2SeedKey](state, exec) {
1075
+ return dispatchByMode(parser.$mode, () => {
1076
+ const values = [];
1077
+ const deferredIndices = /* @__PURE__ */ new Map();
1078
+ let hasDeferred = false;
1079
+ let hasAnySeed = false;
1080
+ for (let i = 0; i < state.length; i++) {
1081
+ const seed = extractPhase2SeedSyncWithUnwrappedFallback(state[i], withChildExecPath(exec, i));
1082
+ if (seed == null) continue;
1083
+ hasAnySeed = true;
1084
+ values[i] = seed.value;
1085
+ if (seed.deferred) if (seed.deferredKeys) deferredIndices.set(i, seed.deferredKeys);
1086
+ else if (seed.value == null || typeof seed.value !== "object") deferredIndices.set(i, null);
1087
+ else hasDeferred = true;
1088
+ }
1089
+ if (!hasAnySeed) return null;
1090
+ return {
1091
+ value: values,
1092
+ ...deferredIndices.size > 0 || hasDeferred ? {
1093
+ deferred: true,
1094
+ ...deferredIndices.size > 0 ? { deferredKeys: deferredIndices } : {}
1095
+ } : {}
1096
+ };
1097
+ }, async () => {
1098
+ const values = [];
1099
+ const deferredIndices = /* @__PURE__ */ new Map();
1100
+ let hasDeferred = false;
1101
+ let hasAnySeed = false;
1102
+ for (let i = 0; i < state.length; i++) {
1103
+ const seed = await extractPhase2SeedAsyncWithUnwrappedFallback(state[i], withChildExecPath(exec, i));
1104
+ if (seed == null) continue;
1105
+ hasAnySeed = true;
1106
+ values[i] = seed.value;
1107
+ if (seed.deferred) if (seed.deferredKeys) deferredIndices.set(i, seed.deferredKeys);
1108
+ else if (seed.value == null || typeof seed.value !== "object") deferredIndices.set(i, null);
1109
+ else hasDeferred = true;
1110
+ }
1111
+ if (!hasAnySeed) return null;
1112
+ return {
1113
+ value: values,
1114
+ ...deferredIndices.size > 0 || hasDeferred ? {
1115
+ deferred: true,
1116
+ ...deferredIndices.size > 0 ? { deferredKeys: deferredIndices } : {}
1117
+ } : {}
1118
+ };
1119
+ });
1120
+ },
1026
1121
  suggest(context, prefix) {
1027
1122
  const currentItemState = context.state.at(-1);
1028
1123
  const canExtendCurrent = currentItemState != null && !isTerminalMultipleItemState(currentItemState);
@@ -1365,6 +1460,13 @@ function nonEmpty(parser) {
1365
1460
  configurable: true,
1366
1461
  enumerable: false
1367
1462
  });
1463
+ Object.defineProperty(nonEmptyParser, extractPhase2SeedKey, {
1464
+ value(state, exec) {
1465
+ return extractPhase2Seed(parser, state, exec);
1466
+ },
1467
+ configurable: true,
1468
+ enumerable: false
1469
+ });
1368
1470
  if (typeof parser.normalizeValue === "function") Object.defineProperty(nonEmptyParser, "normalizeValue", {
1369
1471
  value: parser.normalizeValue.bind(parser),
1370
1472
  configurable: true,
@@ -0,0 +1,59 @@
1
+ const require_annotations = require('./annotations.cjs');
2
+ const require_mode_dispatch = require('./mode-dispatch.cjs');
3
+
4
+ //#region src/phase2-seed.ts
5
+ /**
6
+ * Internal parser hook key for phase-two seed extraction.
7
+ *
8
+ * @internal
9
+ */
10
+ const extractPhase2SeedKey = Symbol("@optique/core/extractPhase2Seed");
11
+ /**
12
+ * Converts a successful complete() result into a phase-two seed.
13
+ *
14
+ * @internal
15
+ */
16
+ function phase2SeedFromValueResult(result) {
17
+ return {
18
+ value: require_annotations.unwrapInjectedAnnotationWrapper(result.value),
19
+ ...result.deferred ? { deferred: true } : {},
20
+ ...result.deferredKeys != null ? { deferredKeys: result.deferredKeys } : {}
21
+ };
22
+ }
23
+ /**
24
+ * Invokes a parser's internal phase-two seed hook when present.
25
+ *
26
+ * @internal
27
+ */
28
+ function extractPhase2Seed(parser, state, exec) {
29
+ return require_mode_dispatch.dispatchByMode(parser.$mode, () => {
30
+ const extractor = parser[extractPhase2SeedKey];
31
+ return extractor == null ? null : extractor(state, exec);
32
+ }, async () => {
33
+ const extractor = parser[extractPhase2SeedKey];
34
+ return extractor == null ? null : await extractor(state, exec);
35
+ });
36
+ }
37
+ /**
38
+ * Attempts to complete a parser and falls back to the internal phase-two
39
+ * seed hook when completion returns an unsuccessful result.
40
+ *
41
+ * @internal
42
+ */
43
+ function completeOrExtractPhase2Seed(parser, state, exec) {
44
+ return require_mode_dispatch.dispatchByMode(parser.$mode, () => {
45
+ const result = parser.complete(state, exec);
46
+ if (result.success) return phase2SeedFromValueResult(result);
47
+ return extractPhase2Seed(parser, state, exec);
48
+ }, async () => {
49
+ const result = await parser.complete(state, exec);
50
+ if (result.success) return phase2SeedFromValueResult(result);
51
+ return await extractPhase2Seed(parser, state, exec);
52
+ });
53
+ }
54
+
55
+ //#endregion
56
+ exports.completeOrExtractPhase2Seed = completeOrExtractPhase2Seed;
57
+ exports.extractPhase2Seed = extractPhase2Seed;
58
+ exports.extractPhase2SeedKey = extractPhase2SeedKey;
59
+ exports.phase2SeedFromValueResult = phase2SeedFromValueResult;
@@ -0,0 +1,56 @@
1
+ import { unwrapInjectedAnnotationWrapper } from "./annotations.js";
2
+ import { dispatchByMode } from "./mode-dispatch.js";
3
+
4
+ //#region src/phase2-seed.ts
5
+ /**
6
+ * Internal parser hook key for phase-two seed extraction.
7
+ *
8
+ * @internal
9
+ */
10
+ const extractPhase2SeedKey = Symbol("@optique/core/extractPhase2Seed");
11
+ /**
12
+ * Converts a successful complete() result into a phase-two seed.
13
+ *
14
+ * @internal
15
+ */
16
+ function phase2SeedFromValueResult(result) {
17
+ return {
18
+ value: unwrapInjectedAnnotationWrapper(result.value),
19
+ ...result.deferred ? { deferred: true } : {},
20
+ ...result.deferredKeys != null ? { deferredKeys: result.deferredKeys } : {}
21
+ };
22
+ }
23
+ /**
24
+ * Invokes a parser's internal phase-two seed hook when present.
25
+ *
26
+ * @internal
27
+ */
28
+ function extractPhase2Seed(parser, state, exec) {
29
+ return dispatchByMode(parser.$mode, () => {
30
+ const extractor = parser[extractPhase2SeedKey];
31
+ return extractor == null ? null : extractor(state, exec);
32
+ }, async () => {
33
+ const extractor = parser[extractPhase2SeedKey];
34
+ return extractor == null ? null : await extractor(state, exec);
35
+ });
36
+ }
37
+ /**
38
+ * Attempts to complete a parser and falls back to the internal phase-two
39
+ * seed hook when completion returns an unsuccessful result.
40
+ *
41
+ * @internal
42
+ */
43
+ function completeOrExtractPhase2Seed(parser, state, exec) {
44
+ return dispatchByMode(parser.$mode, () => {
45
+ const result = parser.complete(state, exec);
46
+ if (result.success) return phase2SeedFromValueResult(result);
47
+ return extractPhase2Seed(parser, state, exec);
48
+ }, async () => {
49
+ const result = await parser.complete(state, exec);
50
+ if (result.success) return phase2SeedFromValueResult(result);
51
+ return await extractPhase2Seed(parser, state, exec);
52
+ });
53
+ }
54
+
55
+ //#endregion
56
+ export { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult };
@@ -5,6 +5,7 @@ const require_validate = require('./validate.cjs');
5
5
  const require_usage = require('./usage.cjs');
6
6
  const require_mode_dispatch = require('./mode-dispatch.cjs');
7
7
  const require_dependency_metadata = require('./dependency-metadata.cjs');
8
+ const require_phase2_seed = require('./phase2-seed.cjs');
8
9
  const require_suggestion = require('./suggestion.cjs');
9
10
  const require_usage_internals = require('./usage-internals.cjs');
10
11
  const require_valueparser = require('./valueparser.cjs');
@@ -1342,6 +1343,34 @@ function command(name, parser, options = {}) {
1342
1343
  error: options.errors?.invalidState ?? require_message.message`Invalid command state during completion.`
1343
1344
  };
1344
1345
  },
1346
+ [require_phase2_seed.extractPhase2SeedKey](state, exec) {
1347
+ if (typeof state === "undefined") return require_mode_dispatch.wrapForMode(parser.$mode, null);
1348
+ if (state[0] === "matched") {
1349
+ const childExec = withChildExecPath(exec, name);
1350
+ const childContext = {
1351
+ buffer: [],
1352
+ optionsTerminated: false,
1353
+ usage: parser.usage,
1354
+ state: parser.initialState,
1355
+ ...childExec != null ? {
1356
+ exec: childExec,
1357
+ trace: childExec.trace,
1358
+ dependencyRegistry: childExec.dependencyRegistry
1359
+ } : {}
1360
+ };
1361
+ return require_mode_dispatch.dispatchByMode(parser.$mode, () => {
1362
+ const parseResult = syncInnerParser.parse(childContext);
1363
+ const nextExec = parseResult.success ? mergeChildExec(childExec, parseResult.next.exec) : childExec;
1364
+ return require_phase2_seed.completeOrExtractPhase2Seed(syncInnerParser, parseResult.success ? parseResult.next.state : syncInnerParser.initialState, nextExec);
1365
+ }, async () => {
1366
+ const parseResult = await asyncInnerParser.parse(childContext);
1367
+ const nextExec = parseResult.success ? mergeChildExec(childExec, parseResult.next.exec) : childExec;
1368
+ return await require_phase2_seed.completeOrExtractPhase2Seed(asyncInnerParser, parseResult.success ? parseResult.next.state : parser.initialState, nextExec);
1369
+ });
1370
+ }
1371
+ if (state[0] === "parsing") return require_phase2_seed.completeOrExtractPhase2Seed(parser, state[1], withChildExecPath(exec, name));
1372
+ return require_mode_dispatch.wrapForMode(parser.$mode, null);
1373
+ },
1345
1374
  suggest(context, prefix) {
1346
1375
  if (isAsync) return suggestCommandAsync(context, prefix, name, parser, options);
1347
1376
  return suggestCommandSync(context, prefix, name, parser, options);
@@ -5,6 +5,7 @@ import { validateCommandNames, validateOptionNames } from "./validate.js";
5
5
  import { extractOptionNames, isDocHidden, isSuggestionHidden } from "./usage.js";
6
6
  import { dispatchByMode, dispatchIterableByMode, wrapForMode } from "./mode-dispatch.js";
7
7
  import { extractDependencyMetadata } from "./dependency-metadata.js";
8
+ import { completeOrExtractPhase2Seed, extractPhase2SeedKey } from "./phase2-seed.js";
8
9
  import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, findSimilar } from "./suggestion.js";
9
10
  import { extractLeadingCommandNames } from "./usage-internals.js";
10
11
  import { isValueParser } from "./valueparser.js";
@@ -1342,6 +1343,34 @@ function command(name, parser, options = {}) {
1342
1343
  error: options.errors?.invalidState ?? message`Invalid command state during completion.`
1343
1344
  };
1344
1345
  },
1346
+ [extractPhase2SeedKey](state, exec) {
1347
+ if (typeof state === "undefined") return wrapForMode(parser.$mode, null);
1348
+ if (state[0] === "matched") {
1349
+ const childExec = withChildExecPath(exec, name);
1350
+ const childContext = {
1351
+ buffer: [],
1352
+ optionsTerminated: false,
1353
+ usage: parser.usage,
1354
+ state: parser.initialState,
1355
+ ...childExec != null ? {
1356
+ exec: childExec,
1357
+ trace: childExec.trace,
1358
+ dependencyRegistry: childExec.dependencyRegistry
1359
+ } : {}
1360
+ };
1361
+ return dispatchByMode(parser.$mode, () => {
1362
+ const parseResult = syncInnerParser.parse(childContext);
1363
+ const nextExec = parseResult.success ? mergeChildExec(childExec, parseResult.next.exec) : childExec;
1364
+ return completeOrExtractPhase2Seed(syncInnerParser, parseResult.success ? parseResult.next.state : syncInnerParser.initialState, nextExec);
1365
+ }, async () => {
1366
+ const parseResult = await asyncInnerParser.parse(childContext);
1367
+ const nextExec = parseResult.success ? mergeChildExec(childExec, parseResult.next.exec) : childExec;
1368
+ return await completeOrExtractPhase2Seed(asyncInnerParser, parseResult.success ? parseResult.next.state : parser.initialState, nextExec);
1369
+ });
1370
+ }
1371
+ if (state[0] === "parsing") return completeOrExtractPhase2Seed(parser, state[1], withChildExecPath(exec, name));
1372
+ return wrapForMode(parser.$mode, null);
1373
+ },
1345
1374
  suggest(context, prefix) {
1346
1375
  if (isAsync) return suggestCommandAsync(context, prefix, name, parser, options);
1347
1376
  return suggestCommandSync(context, prefix, name, parser, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.1778+0b813b67",
3
+ "version": "1.0.0-dev.1785+6a8af6b8",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",