@optique/core 0.10.0-dev.292 → 0.10.0-dev.294

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.
@@ -541,32 +541,145 @@ async function* suggestObjectAsync(context, prefix, parserPairs) {
541
541
  * @returns The field states with deferred states resolved to their actual values
542
542
  * @internal
543
543
  */
544
+ /**
545
+ * Recursively collects dependency values from DependencySourceState objects
546
+ * found anywhere in the state tree.
547
+ */
548
+ function collectDependencies(state, registry) {
549
+ if (state === null || state === void 0) return;
550
+ if (require_dependency.isDependencySourceState(state)) {
551
+ const depId = state[require_dependency.DependencyId];
552
+ const result = state.result;
553
+ if (result.success) registry.set(depId, result.value);
554
+ return;
555
+ }
556
+ if (Array.isArray(state)) {
557
+ for (const item of state) collectDependencies(item, registry);
558
+ return;
559
+ }
560
+ if (typeof state === "object" && !require_dependency.isDeferredParseState(state)) for (const key of Reflect.ownKeys(state)) collectDependencies(state[key], registry);
561
+ }
562
+ /**
563
+ * Checks if a value is a plain object (created with `{}` or `Object.create(null)`).
564
+ * Class instances like `Temporal.PlainDate`, `URL`, `Date`, etc. return false.
565
+ * This is used to determine whether to recursively traverse an object when
566
+ * resolving deferred parse states - we only want to traverse plain objects
567
+ * that are part of the parser state structure, not user values.
568
+ */
569
+ function isPlainObject(value) {
570
+ if (typeof value !== "object" || value === null) return false;
571
+ const proto = Object.getPrototypeOf(value);
572
+ return proto === Object.prototype || proto === null;
573
+ }
574
+ /**
575
+ * Recursively resolves DeferredParseState objects found anywhere in the state tree.
576
+ * Returns the resolved state (sync version).
577
+ *
578
+ * Only traverses:
579
+ * - DeferredParseState (to resolve it)
580
+ * - DependencySourceState (skipped, kept as-is)
581
+ * - Arrays (to find nested deferred states)
582
+ * - Plain objects (to find nested deferred states in parser state structures)
583
+ *
584
+ * Does NOT traverse class instances (e.g., Temporal.PlainDate, URL) since these
585
+ * are user values that should be preserved as-is.
586
+ */
587
+ function resolveDeferred(state, registry) {
588
+ if (state === null || state === void 0) return state;
589
+ if (require_dependency.isDeferredParseState(state)) {
590
+ const deferredState = state;
591
+ const parser = deferredState.parser;
592
+ const depIds = deferredState.dependencyIds;
593
+ if (depIds && depIds.length > 0) {
594
+ const dependencyValues = [];
595
+ let allDepsAvailable = true;
596
+ for (const depId$1 of depIds) if (registry.has(depId$1)) dependencyValues.push(registry.get(depId$1));
597
+ else {
598
+ allDepsAvailable = false;
599
+ break;
600
+ }
601
+ if (allDepsAvailable) {
602
+ const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValues);
603
+ if (reParseResult instanceof Promise) return deferredState.preliminaryResult;
604
+ return reParseResult;
605
+ }
606
+ return deferredState.preliminaryResult;
607
+ }
608
+ const depId = deferredState.dependencyId;
609
+ if (registry.has(depId)) {
610
+ const dependencyValue = registry.get(depId);
611
+ const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValue);
612
+ if (reParseResult instanceof Promise) return deferredState.preliminaryResult;
613
+ return reParseResult;
614
+ }
615
+ return deferredState.preliminaryResult;
616
+ }
617
+ if (require_dependency.isDependencySourceState(state)) return state;
618
+ if (Array.isArray(state)) return state.map((item) => resolveDeferred(item, registry));
619
+ if (isPlainObject(state)) {
620
+ const resolved = {};
621
+ for (const key of Reflect.ownKeys(state)) resolved[key] = resolveDeferred(state[key], registry);
622
+ return resolved;
623
+ }
624
+ return state;
625
+ }
544
626
  function resolveDeferredParseStates(fieldStates) {
545
627
  const registry = new require_dependency.DependencyRegistry();
546
- for (const key of Reflect.ownKeys(fieldStates)) {
547
- const fieldState = fieldStates[key];
548
- if (require_dependency.isDependencySourceState(fieldState)) {
549
- const depId = fieldState[require_dependency.DependencyId];
550
- const result = fieldState.result;
551
- if (result.success) registry.set(depId, result.value);
628
+ collectDependencies(fieldStates, registry);
629
+ return resolveDeferred(fieldStates, registry);
630
+ }
631
+ /**
632
+ * Recursively resolves DeferredParseState objects found anywhere in the state tree.
633
+ * Returns the resolved state (async version).
634
+ *
635
+ * Only traverses:
636
+ * - DeferredParseState (to resolve it)
637
+ * - DependencySourceState (skipped, kept as-is)
638
+ * - Arrays (to find nested deferred states)
639
+ * - Plain objects (to find nested deferred states in parser state structures)
640
+ *
641
+ * Does NOT traverse class instances (e.g., Temporal.PlainDate, URL) since these
642
+ * are user values that should be preserved as-is.
643
+ */
644
+ async function resolveDeferredAsync(state, registry) {
645
+ if (state === null || state === void 0) return state;
646
+ if (require_dependency.isDeferredParseState(state)) {
647
+ const deferredState = state;
648
+ const parser = deferredState.parser;
649
+ const depIds = deferredState.dependencyIds;
650
+ if (depIds && depIds.length > 0) {
651
+ const dependencyValues = [];
652
+ let allDepsAvailable = true;
653
+ for (const depId$1 of depIds) if (registry.has(depId$1)) dependencyValues.push(registry.get(depId$1));
654
+ else {
655
+ allDepsAvailable = false;
656
+ break;
657
+ }
658
+ if (allDepsAvailable) {
659
+ const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValues);
660
+ return Promise.resolve(reParseResult);
661
+ }
662
+ return deferredState.preliminaryResult;
552
663
  }
553
- }
554
- const resolvedStates = { ...fieldStates };
555
- for (const key of Reflect.ownKeys(fieldStates)) {
556
- const fieldState = fieldStates[key];
557
- if (require_dependency.isDeferredParseState(fieldState)) {
558
- const deferredState = fieldState;
559
- const depId = deferredState.dependencyId;
560
- if (registry.has(depId)) {
561
- const dependencyValue = registry.get(depId);
562
- const parser = deferredState.parser;
563
- const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValue);
564
- if (reParseResult instanceof Promise) resolvedStates[key] = deferredState.preliminaryResult;
565
- else resolvedStates[key] = reParseResult;
566
- } else resolvedStates[key] = deferredState.preliminaryResult;
664
+ const depId = deferredState.dependencyId;
665
+ if (registry.has(depId)) {
666
+ const dependencyValue = registry.get(depId);
667
+ const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValue);
668
+ return Promise.resolve(reParseResult);
567
669
  }
670
+ return deferredState.preliminaryResult;
671
+ }
672
+ if (require_dependency.isDependencySourceState(state)) return state;
673
+ if (Array.isArray(state)) return Promise.all(state.map((item) => resolveDeferredAsync(item, registry)));
674
+ if (isPlainObject(state)) {
675
+ const resolved = {};
676
+ const keys = Reflect.ownKeys(state);
677
+ await Promise.all(keys.map(async (key) => {
678
+ resolved[key] = await resolveDeferredAsync(state[key], registry);
679
+ }));
680
+ return resolved;
568
681
  }
569
- return resolvedStates;
682
+ return state;
570
683
  }
571
684
  /**
572
685
  * Async version of resolveDeferredParseStates for async parsers.
@@ -574,29 +687,8 @@ function resolveDeferredParseStates(fieldStates) {
574
687
  */
575
688
  async function resolveDeferredParseStatesAsync(fieldStates) {
576
689
  const registry = new require_dependency.DependencyRegistry();
577
- for (const key of Reflect.ownKeys(fieldStates)) {
578
- const fieldState = fieldStates[key];
579
- if (require_dependency.isDependencySourceState(fieldState)) {
580
- const depId = fieldState[require_dependency.DependencyId];
581
- const result = fieldState.result;
582
- if (result.success) registry.set(depId, result.value);
583
- }
584
- }
585
- const resolvedStates = { ...fieldStates };
586
- for (const key of Reflect.ownKeys(fieldStates)) {
587
- const fieldState = fieldStates[key];
588
- if (require_dependency.isDeferredParseState(fieldState)) {
589
- const deferredState = fieldState;
590
- const depId = deferredState.dependencyId;
591
- if (registry.has(depId)) {
592
- const dependencyValue = registry.get(depId);
593
- const parser = deferredState.parser;
594
- const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValue);
595
- resolvedStates[key] = await Promise.resolve(reParseResult);
596
- } else resolvedStates[key] = deferredState.preliminaryResult;
597
- }
598
- }
599
- return resolvedStates;
690
+ collectDependencies(fieldStates, registry);
691
+ return await resolveDeferredAsync(fieldStates, registry);
600
692
  }
601
693
  function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
602
694
  const label = typeof labelOrParsers === "string" ? labelOrParsers : void 0;
@@ -1220,15 +1312,15 @@ function merge(...args) {
1220
1312
  return parseSync(context);
1221
1313
  },
1222
1314
  complete(state) {
1223
- const extractCompleteState = (parser, index) => {
1315
+ const extractCompleteState = (parser, resolvedState, index) => {
1224
1316
  if (parser.initialState === void 0) {
1225
1317
  const key = `__parser_${index}`;
1226
- if (state && typeof state === "object" && key in state) return state[key];
1318
+ if (resolvedState && typeof resolvedState === "object" && key in resolvedState) return resolvedState[key];
1227
1319
  return void 0;
1228
1320
  } else if (parser.initialState && typeof parser.initialState === "object") {
1229
- if (state && typeof state === "object") {
1321
+ if (resolvedState && typeof resolvedState === "object") {
1230
1322
  const extractedState = {};
1231
- for (const field in parser.initialState) extractedState[field] = field in state ? state[field] : parser.initialState[field];
1323
+ for (const field in parser.initialState) extractedState[field] = field in resolvedState ? resolvedState[field] : parser.initialState[field];
1232
1324
  return extractedState;
1233
1325
  }
1234
1326
  return parser.initialState;
@@ -1236,10 +1328,11 @@ function merge(...args) {
1236
1328
  return parser.initialState;
1237
1329
  };
1238
1330
  if (!isAsync) {
1331
+ const resolvedState = resolveDeferredParseStates(state);
1239
1332
  const object$1 = {};
1240
1333
  for (let i = 0; i < syncParsers.length; i++) {
1241
1334
  const parser = syncParsers[i];
1242
- const parserState = extractCompleteState(parser, i);
1335
+ const parserState = extractCompleteState(parser, resolvedState, i);
1243
1336
  const result = parser.complete(parserState);
1244
1337
  if (!result.success) return result;
1245
1338
  for (const field in result.value) object$1[field] = result.value[field];
@@ -1250,10 +1343,11 @@ function merge(...args) {
1250
1343
  };
1251
1344
  }
1252
1345
  return (async () => {
1346
+ const resolvedState = await resolveDeferredParseStatesAsync(state);
1253
1347
  const object$1 = {};
1254
1348
  for (let i = 0; i < parsers.length; i++) {
1255
1349
  const parser = parsers[i];
1256
- const parserState = extractCompleteState(parser, i);
1350
+ const parserState = extractCompleteState(parser, resolvedState, i);
1257
1351
  const result = await parser.complete(parserState);
1258
1352
  if (!result.success) return result;
1259
1353
  for (const field in result.value) object$1[field] = result.value[field];
@@ -541,32 +541,145 @@ async function* suggestObjectAsync(context, prefix, parserPairs) {
541
541
  * @returns The field states with deferred states resolved to their actual values
542
542
  * @internal
543
543
  */
544
+ /**
545
+ * Recursively collects dependency values from DependencySourceState objects
546
+ * found anywhere in the state tree.
547
+ */
548
+ function collectDependencies(state, registry) {
549
+ if (state === null || state === void 0) return;
550
+ if (isDependencySourceState(state)) {
551
+ const depId = state[DependencyId];
552
+ const result = state.result;
553
+ if (result.success) registry.set(depId, result.value);
554
+ return;
555
+ }
556
+ if (Array.isArray(state)) {
557
+ for (const item of state) collectDependencies(item, registry);
558
+ return;
559
+ }
560
+ if (typeof state === "object" && !isDeferredParseState(state)) for (const key of Reflect.ownKeys(state)) collectDependencies(state[key], registry);
561
+ }
562
+ /**
563
+ * Checks if a value is a plain object (created with `{}` or `Object.create(null)`).
564
+ * Class instances like `Temporal.PlainDate`, `URL`, `Date`, etc. return false.
565
+ * This is used to determine whether to recursively traverse an object when
566
+ * resolving deferred parse states - we only want to traverse plain objects
567
+ * that are part of the parser state structure, not user values.
568
+ */
569
+ function isPlainObject(value) {
570
+ if (typeof value !== "object" || value === null) return false;
571
+ const proto = Object.getPrototypeOf(value);
572
+ return proto === Object.prototype || proto === null;
573
+ }
574
+ /**
575
+ * Recursively resolves DeferredParseState objects found anywhere in the state tree.
576
+ * Returns the resolved state (sync version).
577
+ *
578
+ * Only traverses:
579
+ * - DeferredParseState (to resolve it)
580
+ * - DependencySourceState (skipped, kept as-is)
581
+ * - Arrays (to find nested deferred states)
582
+ * - Plain objects (to find nested deferred states in parser state structures)
583
+ *
584
+ * Does NOT traverse class instances (e.g., Temporal.PlainDate, URL) since these
585
+ * are user values that should be preserved as-is.
586
+ */
587
+ function resolveDeferred(state, registry) {
588
+ if (state === null || state === void 0) return state;
589
+ if (isDeferredParseState(state)) {
590
+ const deferredState = state;
591
+ const parser = deferredState.parser;
592
+ const depIds = deferredState.dependencyIds;
593
+ if (depIds && depIds.length > 0) {
594
+ const dependencyValues = [];
595
+ let allDepsAvailable = true;
596
+ for (const depId$1 of depIds) if (registry.has(depId$1)) dependencyValues.push(registry.get(depId$1));
597
+ else {
598
+ allDepsAvailable = false;
599
+ break;
600
+ }
601
+ if (allDepsAvailable) {
602
+ const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValues);
603
+ if (reParseResult instanceof Promise) return deferredState.preliminaryResult;
604
+ return reParseResult;
605
+ }
606
+ return deferredState.preliminaryResult;
607
+ }
608
+ const depId = deferredState.dependencyId;
609
+ if (registry.has(depId)) {
610
+ const dependencyValue = registry.get(depId);
611
+ const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValue);
612
+ if (reParseResult instanceof Promise) return deferredState.preliminaryResult;
613
+ return reParseResult;
614
+ }
615
+ return deferredState.preliminaryResult;
616
+ }
617
+ if (isDependencySourceState(state)) return state;
618
+ if (Array.isArray(state)) return state.map((item) => resolveDeferred(item, registry));
619
+ if (isPlainObject(state)) {
620
+ const resolved = {};
621
+ for (const key of Reflect.ownKeys(state)) resolved[key] = resolveDeferred(state[key], registry);
622
+ return resolved;
623
+ }
624
+ return state;
625
+ }
544
626
  function resolveDeferredParseStates(fieldStates) {
545
627
  const registry = new DependencyRegistry();
546
- for (const key of Reflect.ownKeys(fieldStates)) {
547
- const fieldState = fieldStates[key];
548
- if (isDependencySourceState(fieldState)) {
549
- const depId = fieldState[DependencyId];
550
- const result = fieldState.result;
551
- if (result.success) registry.set(depId, result.value);
628
+ collectDependencies(fieldStates, registry);
629
+ return resolveDeferred(fieldStates, registry);
630
+ }
631
+ /**
632
+ * Recursively resolves DeferredParseState objects found anywhere in the state tree.
633
+ * Returns the resolved state (async version).
634
+ *
635
+ * Only traverses:
636
+ * - DeferredParseState (to resolve it)
637
+ * - DependencySourceState (skipped, kept as-is)
638
+ * - Arrays (to find nested deferred states)
639
+ * - Plain objects (to find nested deferred states in parser state structures)
640
+ *
641
+ * Does NOT traverse class instances (e.g., Temporal.PlainDate, URL) since these
642
+ * are user values that should be preserved as-is.
643
+ */
644
+ async function resolveDeferredAsync(state, registry) {
645
+ if (state === null || state === void 0) return state;
646
+ if (isDeferredParseState(state)) {
647
+ const deferredState = state;
648
+ const parser = deferredState.parser;
649
+ const depIds = deferredState.dependencyIds;
650
+ if (depIds && depIds.length > 0) {
651
+ const dependencyValues = [];
652
+ let allDepsAvailable = true;
653
+ for (const depId$1 of depIds) if (registry.has(depId$1)) dependencyValues.push(registry.get(depId$1));
654
+ else {
655
+ allDepsAvailable = false;
656
+ break;
657
+ }
658
+ if (allDepsAvailable) {
659
+ const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValues);
660
+ return Promise.resolve(reParseResult);
661
+ }
662
+ return deferredState.preliminaryResult;
552
663
  }
553
- }
554
- const resolvedStates = { ...fieldStates };
555
- for (const key of Reflect.ownKeys(fieldStates)) {
556
- const fieldState = fieldStates[key];
557
- if (isDeferredParseState(fieldState)) {
558
- const deferredState = fieldState;
559
- const depId = deferredState.dependencyId;
560
- if (registry.has(depId)) {
561
- const dependencyValue = registry.get(depId);
562
- const parser = deferredState.parser;
563
- const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValue);
564
- if (reParseResult instanceof Promise) resolvedStates[key] = deferredState.preliminaryResult;
565
- else resolvedStates[key] = reParseResult;
566
- } else resolvedStates[key] = deferredState.preliminaryResult;
664
+ const depId = deferredState.dependencyId;
665
+ if (registry.has(depId)) {
666
+ const dependencyValue = registry.get(depId);
667
+ const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValue);
668
+ return Promise.resolve(reParseResult);
567
669
  }
670
+ return deferredState.preliminaryResult;
671
+ }
672
+ if (isDependencySourceState(state)) return state;
673
+ if (Array.isArray(state)) return Promise.all(state.map((item) => resolveDeferredAsync(item, registry)));
674
+ if (isPlainObject(state)) {
675
+ const resolved = {};
676
+ const keys = Reflect.ownKeys(state);
677
+ await Promise.all(keys.map(async (key) => {
678
+ resolved[key] = await resolveDeferredAsync(state[key], registry);
679
+ }));
680
+ return resolved;
568
681
  }
569
- return resolvedStates;
682
+ return state;
570
683
  }
571
684
  /**
572
685
  * Async version of resolveDeferredParseStates for async parsers.
@@ -574,29 +687,8 @@ function resolveDeferredParseStates(fieldStates) {
574
687
  */
575
688
  async function resolveDeferredParseStatesAsync(fieldStates) {
576
689
  const registry = new DependencyRegistry();
577
- for (const key of Reflect.ownKeys(fieldStates)) {
578
- const fieldState = fieldStates[key];
579
- if (isDependencySourceState(fieldState)) {
580
- const depId = fieldState[DependencyId];
581
- const result = fieldState.result;
582
- if (result.success) registry.set(depId, result.value);
583
- }
584
- }
585
- const resolvedStates = { ...fieldStates };
586
- for (const key of Reflect.ownKeys(fieldStates)) {
587
- const fieldState = fieldStates[key];
588
- if (isDeferredParseState(fieldState)) {
589
- const deferredState = fieldState;
590
- const depId = deferredState.dependencyId;
591
- if (registry.has(depId)) {
592
- const dependencyValue = registry.get(depId);
593
- const parser = deferredState.parser;
594
- const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValue);
595
- resolvedStates[key] = await Promise.resolve(reParseResult);
596
- } else resolvedStates[key] = deferredState.preliminaryResult;
597
- }
598
- }
599
- return resolvedStates;
690
+ collectDependencies(fieldStates, registry);
691
+ return await resolveDeferredAsync(fieldStates, registry);
600
692
  }
601
693
  function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
602
694
  const label = typeof labelOrParsers === "string" ? labelOrParsers : void 0;
@@ -1220,15 +1312,15 @@ function merge(...args) {
1220
1312
  return parseSync(context);
1221
1313
  },
1222
1314
  complete(state) {
1223
- const extractCompleteState = (parser, index) => {
1315
+ const extractCompleteState = (parser, resolvedState, index) => {
1224
1316
  if (parser.initialState === void 0) {
1225
1317
  const key = `__parser_${index}`;
1226
- if (state && typeof state === "object" && key in state) return state[key];
1318
+ if (resolvedState && typeof resolvedState === "object" && key in resolvedState) return resolvedState[key];
1227
1319
  return void 0;
1228
1320
  } else if (parser.initialState && typeof parser.initialState === "object") {
1229
- if (state && typeof state === "object") {
1321
+ if (resolvedState && typeof resolvedState === "object") {
1230
1322
  const extractedState = {};
1231
- for (const field in parser.initialState) extractedState[field] = field in state ? state[field] : parser.initialState[field];
1323
+ for (const field in parser.initialState) extractedState[field] = field in resolvedState ? resolvedState[field] : parser.initialState[field];
1232
1324
  return extractedState;
1233
1325
  }
1234
1326
  return parser.initialState;
@@ -1236,10 +1328,11 @@ function merge(...args) {
1236
1328
  return parser.initialState;
1237
1329
  };
1238
1330
  if (!isAsync) {
1331
+ const resolvedState = resolveDeferredParseStates(state);
1239
1332
  const object$1 = {};
1240
1333
  for (let i = 0; i < syncParsers.length; i++) {
1241
1334
  const parser = syncParsers[i];
1242
- const parserState = extractCompleteState(parser, i);
1335
+ const parserState = extractCompleteState(parser, resolvedState, i);
1243
1336
  const result = parser.complete(parserState);
1244
1337
  if (!result.success) return result;
1245
1338
  for (const field in result.value) object$1[field] = result.value[field];
@@ -1250,10 +1343,11 @@ function merge(...args) {
1250
1343
  };
1251
1344
  }
1252
1345
  return (async () => {
1346
+ const resolvedState = await resolveDeferredParseStatesAsync(state);
1253
1347
  const object$1 = {};
1254
1348
  for (let i = 0; i < parsers.length; i++) {
1255
1349
  const parser = parsers[i];
1256
- const parserState = extractCompleteState(parser, i);
1350
+ const parserState = extractCompleteState(parser, resolvedState, i);
1257
1351
  const result = await parser.complete(parserState);
1258
1352
  if (!result.success) return result;
1259
1353
  for (const field in result.value) object$1[field] = result.value[field];