@optique/core 1.3.0-dev.2398 → 1.3.0-dev.2401

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.
@@ -3,6 +3,32 @@ const require_internal_dependency = require('./internal/dependency.cjs');
3
3
  const require_internal_parser = require('./internal/parser.cjs');
4
4
 
5
5
  //#region src/dependency-runtime.ts
6
+ /**
7
+ * Stores the raw token parsed by a derived value parser on structural parser
8
+ * states that can safely carry an in-band annotation.
9
+ *
10
+ * The execution trace remains the canonical diagnostic record. This state
11
+ * marker lets construct-independent dependency resolution replay a derived
12
+ * source before downstream fields complete.
13
+ * @internal
14
+ * @since 1.3.0
15
+ */
16
+ const derivedRawInputKey = Symbol("@optique/core/dependency-runtime/derivedRawInput");
17
+ const derivedRawInputs = /* @__PURE__ */ new WeakMap();
18
+ /**
19
+ * Records a derived parser's raw token without modifying its parse result.
20
+ *
21
+ * Parse results may be frozen or carry class private state, so primitives keep
22
+ * their original identity and associate replay metadata out of band.
23
+ *
24
+ * @param state The original value parser result.
25
+ * @param rawInput The token parsed into that result.
26
+ * @internal
27
+ * @since 1.3.0
28
+ */
29
+ function recordDerivedRawInput(state, rawInput) {
30
+ derivedRawInputs.set(state, rawInput);
31
+ }
6
32
  const symbolIds = /* @__PURE__ */ new WeakMap();
7
33
  let symbolCounter = 0;
8
34
  function stableSymbolKey(sym) {
@@ -19,6 +45,8 @@ var DependencyRuntimeContextImpl = class {
19
45
  registry;
20
46
  #replayCache = /* @__PURE__ */ new Map();
21
47
  #failedSources = /* @__PURE__ */ new Set();
48
+ #sourceMetadata = /* @__PURE__ */ new Map();
49
+ #sourceFailures = /* @__PURE__ */ new Map();
22
50
  constructor(registry) {
23
51
  if (registry instanceof FailedAwareRegistry) {
24
52
  this.registry = registry.rebindFailedSources(this.#failedSources);
@@ -28,6 +56,7 @@ var DependencyRuntimeContextImpl = class {
28
56
  }
29
57
  registerSource(sourceId, value) {
30
58
  this.registry.set(sourceId, value);
59
+ this.#sourceFailures.delete(sourceId);
31
60
  }
32
61
  hasSource(sourceId) {
33
62
  return this.registry.has(sourceId);
@@ -46,6 +75,45 @@ var DependencyRuntimeContextImpl = class {
46
75
  }
47
76
  markSourceFailed(sourceId) {
48
77
  this.#failedSources.add(sourceId);
78
+ const lineage = this.#getSourceLineage(sourceId, /* @__PURE__ */ new Set());
79
+ const failure = {
80
+ chain: lineage.labels,
81
+ participants: lineage.sourceIds,
82
+ diagnosticChain: lineage.labels
83
+ };
84
+ this.#sourceFailures.set(sourceId, failure);
85
+ this.#promoteDiagnosticChain(failure);
86
+ }
87
+ registerSourceMetadata(sourceId, label, dependencyIds = []) {
88
+ this.#sourceMetadata.set(sourceId, {
89
+ label,
90
+ dependencyIds
91
+ });
92
+ }
93
+ propagateSourceFailure(dependencyIds, label, sourceId) {
94
+ const upstream = dependencyIds.filter((id) => this.isSourceFailed(id)).map((id) => this.#sourceFailures.get(id) ?? {
95
+ chain: [this.#getSourceLabel(id)],
96
+ participants: [id],
97
+ diagnosticChain: [this.#getSourceLabel(id)]
98
+ }).sort((left, right) => right.chain.length - left.chain.length)[0];
99
+ if (upstream == null) return false;
100
+ const chain = upstream.chain.at(-1) === label ? upstream.chain : [...upstream.chain, label];
101
+ const participants = sourceId == null || upstream.participants.includes(sourceId) ? upstream.participants : [...upstream.participants, sourceId];
102
+ const failure = {
103
+ chain,
104
+ participants,
105
+ diagnosticChain: chain
106
+ };
107
+ if (sourceId != null) {
108
+ this.#failedSources.add(sourceId);
109
+ this.#sourceFailures.set(sourceId, failure);
110
+ }
111
+ this.#promoteDiagnosticChain(failure);
112
+ return true;
113
+ }
114
+ getSourceFailureChain(sourceId) {
115
+ if (!this.#failedSources.has(sourceId)) return void 0;
116
+ return this.#sourceFailures.get(sourceId)?.diagnosticChain;
49
117
  }
50
118
  isSourceFailed(sourceId) {
51
119
  return this.#failedSources.has(sourceId);
@@ -53,6 +121,31 @@ var DependencyRuntimeContextImpl = class {
53
121
  getSuggestionDependencies(request) {
54
122
  return resolveRequest(this, request);
55
123
  }
124
+ #getSourceLabel(sourceId) {
125
+ return this.#sourceMetadata.get(sourceId)?.label ?? sourceId.description ?? String(sourceId);
126
+ }
127
+ #getSourceLineage(sourceId, visited) {
128
+ if (visited.has(sourceId)) return {
129
+ labels: [this.#getSourceLabel(sourceId)],
130
+ sourceIds: [sourceId]
131
+ };
132
+ visited.add(sourceId);
133
+ const metadata = this.#sourceMetadata.get(sourceId);
134
+ const upstream = (metadata?.dependencyIds ?? []).map((id) => this.#getSourceLineage(id, new Set(visited))).sort((left, right) => right.labels.length - left.labels.length)[0];
135
+ return upstream == null ? {
136
+ labels: [this.#getSourceLabel(sourceId)],
137
+ sourceIds: [sourceId]
138
+ } : {
139
+ labels: [...upstream.labels, this.#getSourceLabel(sourceId)],
140
+ sourceIds: [...upstream.sourceIds, sourceId]
141
+ };
142
+ }
143
+ #promoteDiagnosticChain(failure) {
144
+ for (const sourceId of failure.participants) {
145
+ const current = this.#sourceFailures.get(sourceId);
146
+ if (current != null && current.diagnosticChain.length < failure.diagnosticChain.length) current.diagnosticChain = failure.diagnosticChain;
147
+ }
148
+ }
56
149
  };
57
150
  /**
58
151
  * Registry wrapper that hides values for sources that have failed.
@@ -251,14 +344,17 @@ function createReplayKey(path, rawInput, dependencyValues, replayParse) {
251
344
  * @since 1.0.0
252
345
  */
253
346
  function collectExplicitSourceValues(nodes, runtime) {
347
+ registerRuntimeSourceMetadata(nodes, runtime);
254
348
  for (const node of nodes) {
255
349
  const meta = node.parser.dependencyMetadata;
256
350
  if (meta?.source == null) continue;
257
351
  if (meta.source.extractSourceValue == null) continue;
352
+ if (meta.derived != null && getNodeRawInput(node) != null) continue;
258
353
  const result = meta.source.extractSourceValue(node.state);
259
354
  if (isPromiseLike(result)) throw new TypeError(`collectExplicitSourceValues() received an async extractSourceValue() result for ${String(meta.source.sourceId)}. Use collectExplicitSourceValuesAsync() instead.`);
260
355
  registerExplicitSourceValue(meta.source.sourceId, result, runtime);
261
356
  }
357
+ resolveDerivedSourceValues(nodes, runtime);
262
358
  }
263
359
  function registerExplicitSourceValue(sourceId, result, runtime) {
264
360
  if (result == null) return;
@@ -280,13 +376,192 @@ function isPromiseLike(value) {
280
376
  * @since 1.0.0
281
377
  */
282
378
  async function collectExplicitSourceValuesAsync(nodes, runtime) {
379
+ registerRuntimeSourceMetadata(nodes, runtime);
283
380
  for (const node of nodes) {
284
381
  const meta = node.parser.dependencyMetadata;
285
382
  if (meta?.source == null) continue;
286
383
  if (meta.source.extractSourceValue == null) continue;
384
+ if (meta.derived != null && getNodeRawInput(node) != null) continue;
287
385
  const result = await meta.source.extractSourceValue(node.state);
288
386
  registerExplicitSourceValue(meta.source.sourceId, result, runtime);
289
387
  }
388
+ await resolveDerivedSourceValuesAsync(nodes, runtime);
389
+ }
390
+ /**
391
+ * Orders runtime nodes so every in-scope provider precedes a derived source
392
+ * that consumes it. Independent nodes retain declaration order.
393
+ *
394
+ * Missing providers create no edge because the consumer may use its declared
395
+ * default. Scheduling barriers act as providers for the source IDs their
396
+ * selected subtree may expose and depend on their discriminator source.
397
+ *
398
+ * @param nodes Runtime nodes in declaration order.
399
+ * @returns The same nodes in stable dependency order.
400
+ * @throws {TypeError} If active provider edges contain a cycle.
401
+ * @internal
402
+ * @since 1.3.0
403
+ */
404
+ function orderDependencyNodes(nodes) {
405
+ const providers = /* @__PURE__ */ new Map();
406
+ const addProvider = (sourceId, node) => {
407
+ const existing = providers.get(sourceId);
408
+ if (existing == null) providers.set(sourceId, [node]);
409
+ else existing.push(node);
410
+ };
411
+ for (const node of nodes) {
412
+ const source = node.parser.dependencyMetadata?.source;
413
+ if (source != null) addProvider(source.sourceId, node);
414
+ for (const sourceId of node.providesSourceIds ?? []) addProvider(sourceId, node);
415
+ }
416
+ const outgoing = /* @__PURE__ */ new Map();
417
+ const indegree = /* @__PURE__ */ new Map();
418
+ for (const node of nodes) indegree.set(node, 0);
419
+ const addEdge = (provider, consumer) => {
420
+ const edges = outgoing.get(provider) ?? /* @__PURE__ */ new Set();
421
+ if (edges.has(consumer)) return;
422
+ edges.add(consumer);
423
+ outgoing.set(provider, edges);
424
+ indegree.set(consumer, (indegree.get(consumer) ?? 0) + 1);
425
+ };
426
+ for (const node of nodes) {
427
+ const derived = node.parser.dependencyMetadata?.derived;
428
+ if (derived != null) for (const dependencySourceId of derived.dependencyIds) for (const provider of providers.get(dependencySourceId) ?? []) addEdge(provider, node);
429
+ if (node.requiresSourceId != null) {
430
+ for (const provider of providers.get(node.requiresSourceId) ?? []) if (provider !== node) addEdge(provider, node);
431
+ }
432
+ }
433
+ const declarationOrder = new Map(nodes.map((node, index) => [node, index]));
434
+ const ready = nodes.filter((node) => indegree.get(node) === 0);
435
+ const ordered = [];
436
+ while (ready.length > 0) {
437
+ ready.sort((left, right) => declarationOrder.get(left) - declarationOrder.get(right));
438
+ const node = ready.shift();
439
+ ordered.push(node);
440
+ for (const consumer of outgoing.get(node) ?? []) {
441
+ const next = (indegree.get(consumer) ?? 0) - 1;
442
+ indegree.set(consumer, next);
443
+ if (next === 0) ready.push(consumer);
444
+ }
445
+ }
446
+ if (ordered.length !== nodes.length) {
447
+ const cycle = nodes.filter((node) => (indegree.get(node) ?? 0) > 0);
448
+ const labels = cycle.map(formatDependencyNodeLabel).join(" -> ");
449
+ throw new TypeError(`Circular dependency detected among derived sources: ${labels}.`);
450
+ }
451
+ return ordered;
452
+ }
453
+ /** Resolves and publishes matched derived sources in stable dependency order. */
454
+ function resolveDerivedSourceValues(nodes, runtime, options) {
455
+ resolveDerivedSourceValuesInOrder(orderDependencyNodes(nodes), nodes, runtime, (node, rawInput) => replayDerivedParser(node, rawInput, runtime), options);
456
+ }
457
+ /** Async version of {@link resolveDerivedSourceValues}. */
458
+ async function resolveDerivedSourceValuesAsync(nodes, runtime, options) {
459
+ await resolveDerivedSourceValuesInOrderAsync(orderDependencyNodes(nodes), nodes, runtime, options);
460
+ }
461
+ function resolveDerivedSourceValuesInOrder(ordered, allNodes, runtime, replay, options) {
462
+ const providers = collectSourceProviders(allNodes);
463
+ const settled = /* @__PURE__ */ new Set();
464
+ for (const node of ordered) {
465
+ const metadata = node.parser.dependencyMetadata;
466
+ const rawInput = getNodeRawInput(node);
467
+ if (metadata?.derived == null) continue;
468
+ const label = formatDependencyNodeMetavar(node);
469
+ if (runtime.propagateSourceFailure(metadata.derived.dependencyIds, label, metadata.source?.sourceId)) {
470
+ if (metadata.source != null) settled.add(node);
471
+ continue;
472
+ }
473
+ if (metadata.source == null || rawInput == null) continue;
474
+ if (hasPendingProvider(node, providers, settled, runtime, options)) continue;
475
+ settleDerivedSource(node, rawInput, runtime, replay);
476
+ settled.add(node);
477
+ }
478
+ }
479
+ async function resolveDerivedSourceValuesInOrderAsync(ordered, allNodes, runtime, options) {
480
+ const providers = collectSourceProviders(allNodes);
481
+ const settled = /* @__PURE__ */ new Set();
482
+ for (const node of ordered) {
483
+ const metadata = node.parser.dependencyMetadata;
484
+ const rawInput = getNodeRawInput(node);
485
+ if (metadata?.derived == null) continue;
486
+ const label = formatDependencyNodeMetavar(node);
487
+ if (runtime.propagateSourceFailure(metadata.derived.dependencyIds, label, metadata.source?.sourceId)) {
488
+ if (metadata.source != null) settled.add(node);
489
+ continue;
490
+ }
491
+ if (metadata.source == null || rawInput == null) continue;
492
+ if (hasPendingProvider(node, providers, settled, runtime, options)) continue;
493
+ const result = await replayDerivedParserAsync(node, rawInput, runtime);
494
+ publishDerivedSourceResult(metadata.source.sourceId, result, runtime);
495
+ settled.add(node);
496
+ }
497
+ }
498
+ function settleDerivedSource(node, rawInput, runtime, replay) {
499
+ const metadata = node.parser.dependencyMetadata;
500
+ publishDerivedSourceResult(metadata.source.sourceId, replay(node, rawInput), runtime);
501
+ }
502
+ function publishDerivedSourceResult(sourceId, result, runtime) {
503
+ if (result == null || result.success && result.deferred === true) return;
504
+ if (!result.success) runtime.markSourceFailed(sourceId);
505
+ else runtime.registerSource(sourceId, result.value);
506
+ }
507
+ function collectSourceProviders(nodes) {
508
+ const providers = /* @__PURE__ */ new Map();
509
+ for (const node of nodes) {
510
+ const sourceId = node.parser.dependencyMetadata?.source?.sourceId;
511
+ if (sourceId == null) continue;
512
+ const existing = providers.get(sourceId);
513
+ if (existing == null) providers.set(sourceId, [node]);
514
+ else existing.push(node);
515
+ }
516
+ return providers;
517
+ }
518
+ function hasPendingProvider(node, providers, settled, runtime, options) {
519
+ const derived = node.parser.dependencyMetadata.derived;
520
+ return derived.dependencyIds.some((sourceId) => (providers.get(sourceId) ?? []).some((provider) => {
521
+ if (provider === node || runtime.hasSource(sourceId) || runtime.isSourceFailed(sourceId)) return false;
522
+ const metadata = provider.parser.dependencyMetadata;
523
+ if (metadata?.derived != null && getNodeRawInput(provider) != null) return !settled.has(provider);
524
+ return options?.effectfulProviders !== "inactive" && metadata?.source?.completeSource != null;
525
+ }));
526
+ }
527
+ function getNodeRawInput(node) {
528
+ return node.rawInput ?? extractRawInputFromState(node.state);
529
+ }
530
+ function registerRuntimeSourceMetadata(nodes, runtime) {
531
+ for (const node of nodes) {
532
+ const metadata = node.parser.dependencyMetadata;
533
+ if (metadata?.source == null) continue;
534
+ runtime.registerSourceMetadata(metadata.source.sourceId, formatDependencyNodeMetavar(node), metadata.derived?.dependencyIds);
535
+ }
536
+ }
537
+ function propagateRuntimeSourceFailures(nodes, runtime) {
538
+ for (const node of orderDependencyNodes(nodes)) {
539
+ const metadata = node.parser.dependencyMetadata;
540
+ if (metadata?.derived == null) continue;
541
+ runtime.propagateSourceFailure(metadata.derived.dependencyIds, formatDependencyNodeMetavar(node), metadata.source?.sourceId);
542
+ }
543
+ }
544
+ /**
545
+ * Appends the recorded dependency chain to a source failure.
546
+ *
547
+ * @param error The source failure to annotate.
548
+ * @param sourceId The identifier of the failed source.
549
+ * @param runtime The dependency runtime that recorded the failure chain.
550
+ * @returns The annotated failure, or the original failure when no chain exists.
551
+ * @internal
552
+ * @since 1.3.0
553
+ */
554
+ function includeSourceFailureChain(error, sourceId, runtime) {
555
+ const chain = runtime.getSourceFailureChain(sourceId);
556
+ return chain == null || chain.length < 2 ? error : require_message.message`${error} Dependency chain: ${chain.join(" -> ")}.`;
557
+ }
558
+ function formatDependencyNodeMetavar(node) {
559
+ return node.parser.dependencyMetadata?.derived?.metavar ?? node.parser.dependencyMetadata?.source?.metavar ?? (node.path.map(String).join(".") || "<root>");
560
+ }
561
+ function formatDependencyNodeLabel(node) {
562
+ const metavar = node.parser.dependencyMetadata?.derived?.metavar ?? node.parser.dependencyMetadata?.source?.metavar;
563
+ const path = node.path.map(String).join(".") || "<root>";
564
+ return metavar == null ? path : `${metavar} (${path})`;
290
565
  }
291
566
  /**
292
567
  * Fills missing source defaults for source parsers whose state is
@@ -339,6 +614,7 @@ function fillMissingSourceDefaults(nodes, runtime) {
339
614
  error: result
340
615
  });
341
616
  }
617
+ resolveDerivedSourceValues(nodes, runtime);
342
618
  return failures;
343
619
  }
344
620
  /**
@@ -383,6 +659,7 @@ async function fillMissingSourceDefaultsAsync(nodes, runtime) {
383
659
  error: result
384
660
  });
385
661
  }
662
+ await resolveDerivedSourceValuesAsync(nodes, runtime);
386
663
  return failures;
387
664
  }
388
665
  /**
@@ -414,6 +691,10 @@ function replayDerivedParser(node, rawInput, runtime) {
414
691
  });
415
692
  if (resolution.kind === "missing") return void 0;
416
693
  if (resolution.kind === "partial") return void 0;
694
+ if (resolution.usedDefaults.every((usedDefault) => usedDefault)) {
695
+ const preliminary = extractPreliminaryResultFromState(node.state);
696
+ if (preliminary != null) return preliminary;
697
+ }
417
698
  const key = createReplayKey(node.path, rawInput, resolution.values, meta.derived.replayParse);
418
699
  const cached = runtime.getReplayResult(key);
419
700
  if (cached != null) return cached;
@@ -449,6 +730,10 @@ async function replayDerivedParserAsync(node, rawInput, runtime) {
449
730
  });
450
731
  if (resolution.kind === "missing") return void 0;
451
732
  if (resolution.kind === "partial") return void 0;
733
+ if (resolution.usedDefaults.every((usedDefault) => usedDefault)) {
734
+ const preliminary = extractPreliminaryResultFromState(node.state);
735
+ if (preliminary != null) return preliminary;
736
+ }
452
737
  const key = createReplayKey(node.path, rawInput, resolution.values, meta.derived.replayParse);
453
738
  const cached = runtime.getReplayResult(key);
454
739
  if (cached != null) return cached;
@@ -471,10 +756,60 @@ async function replayDerivedParserAsync(node, rawInput, runtime) {
471
756
  * @since 1.0.0
472
757
  */
473
758
  function extractRawInputFromState(state) {
759
+ return extractRawInputFromStateInner(state, /* @__PURE__ */ new Set());
760
+ }
761
+ function extractRawInputFromStateInner(state, visited) {
474
762
  if (state == null) return void 0;
475
763
  if (typeof state !== "object") return void 0;
764
+ if (visited.has(state)) return void 0;
765
+ visited.add(state);
766
+ const recordedRawInput = getRecordedDerivedRawInput(state);
767
+ if (recordedRawInput != null) return recordedRawInput;
476
768
  if (require_internal_dependency.isDeferredParseState(state)) return state.rawInput;
477
- if (Array.isArray(state) && state.length === 1 && require_internal_dependency.isDeferredParseState(state[0])) return state[0].rawInput;
769
+ if (Array.isArray(state)) {
770
+ for (let index = state.length - 1; index >= 0; index--) {
771
+ const rawInput = extractRawInputFromStateInner(state[index], visited);
772
+ if (rawInput != null) return rawInput;
773
+ }
774
+ return void 0;
775
+ }
776
+ const nested = /* @__PURE__ */ new Set();
777
+ for (const value of Object.values(state)) {
778
+ const rawInput = extractRawInputFromStateInner(value, visited);
779
+ if (rawInput != null) nested.add(rawInput);
780
+ }
781
+ return nested.size === 1 ? nested.values().next().value : void 0;
782
+ }
783
+ function extractPreliminaryResultFromState(state) {
784
+ return extractPreliminaryResultFromStateInner(state, /* @__PURE__ */ new Set());
785
+ }
786
+ function extractPreliminaryResultFromStateInner(state, visited) {
787
+ if (state == null || typeof state !== "object") return void 0;
788
+ if (visited.has(state)) return void 0;
789
+ visited.add(state);
790
+ if (require_internal_dependency.isDeferredParseState(state)) return state.preliminaryResult;
791
+ if (getRecordedDerivedRawInput(state) != null && "success" in state && typeof state.success === "boolean") {
792
+ if (state.success === true && "value" in state) return state;
793
+ if (state.success === false && "error" in state) return state;
794
+ }
795
+ if (Array.isArray(state)) {
796
+ for (let index = state.length - 1; index >= 0; index--) {
797
+ const result = extractPreliminaryResultFromStateInner(state[index], visited);
798
+ if (result != null) return result;
799
+ }
800
+ return void 0;
801
+ }
802
+ const nested = /* @__PURE__ */ new Set();
803
+ for (const value of Object.values(state)) {
804
+ const result = extractPreliminaryResultFromStateInner(value, visited);
805
+ if (result != null) nested.add(result);
806
+ }
807
+ return nested.size === 1 ? nested.values().next().value : void 0;
808
+ }
809
+ function getRecordedDerivedRawInput(state) {
810
+ const recorded = derivedRawInputs.get(state);
811
+ if (recorded != null) return recorded;
812
+ if (derivedRawInputKey in state && typeof state[derivedRawInputKey] === "string") return state[derivedRawInputKey];
478
813
  return void 0;
479
814
  }
480
815
  /**
@@ -658,6 +993,7 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
658
993
  completed: []
659
994
  };
660
995
  if (exec == null || exec.phase !== "complete") return empty;
996
+ registerRuntimeSourceMetadata(nodes, runtime);
661
997
  const session = exec.effectfulCompletionSession;
662
998
  if (session?.policy === "demand-only") {
663
999
  const demandNodes = options?.demandNodes ?? nodes;
@@ -667,6 +1003,12 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
667
1003
  while (demandAdded) {
668
1004
  demandAdded = false;
669
1005
  for (const node of nodes) {
1006
+ const metadata = node.parser.dependencyMetadata;
1007
+ if (metadata?.source != null && metadata.derived != null && session.demanded.has(metadata.source.sourceId)) for (const dependencySourceId of metadata.derived.dependencyIds) {
1008
+ if (session.demanded.has(dependencySourceId)) continue;
1009
+ session.demanded.add(dependencySourceId);
1010
+ demandAdded = true;
1011
+ }
670
1012
  if (node.requiresSourceId == null || node.providesSourceIds == null) continue;
671
1013
  if (session.demanded.has(node.requiresSourceId)) continue;
672
1014
  for (const provided of node.providesSourceIds) if (session.demanded.has(provided)) {
@@ -686,7 +1028,7 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
686
1028
  const schedulable = nodes.filter((node) => node.parser.dependencyMetadata?.source?.completeSource != null || node.prepare != null);
687
1029
  if (schedulable.length === 0 && options?.includeStructural !== true) return empty;
688
1030
  const completed = [];
689
- for (const node of nodes) {
1031
+ for (const node of orderDependencyNodes(nodes)) {
690
1032
  if (node.prepare != null) {
691
1033
  const barrierFailure = await node.prepare({
692
1034
  runtime,
@@ -703,6 +1045,28 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
703
1045
  const source = node.parser.dependencyMetadata?.source;
704
1046
  if (source == null) continue;
705
1047
  if (source.completeSource == null) {
1048
+ const derived = node.parser.dependencyMetadata?.derived;
1049
+ const rawInput = getNodeRawInput(node);
1050
+ if (derived != null && rawInput != null) {
1051
+ if (runtime.propagateSourceFailure(derived.dependencyIds, formatDependencyNodeMetavar(node), source.sourceId)) continue;
1052
+ const replayed = await replayDerivedParserAsync(node, rawInput, runtime);
1053
+ if (replayed == null) continue;
1054
+ if (!replayed.success) {
1055
+ runtime.markSourceFailed(source.sourceId);
1056
+ propagateRuntimeSourceFailures(nodes, runtime);
1057
+ return {
1058
+ success: false,
1059
+ error: includeSourceFailureChain(replayed.error, source.sourceId, runtime)
1060
+ };
1061
+ }
1062
+ if (replayed.deferred === true) continue;
1063
+ runtime.registerSource(source.sourceId, replayed.value);
1064
+ if (source.preservesSourceValue && (options?.isReusable?.(node) ?? true)) completed.push({
1065
+ key: node.path[node.path.length - 1],
1066
+ result: replayed
1067
+ });
1068
+ continue;
1069
+ }
706
1070
  const collected = options?.isCollected?.(node) ?? options?.isReusable?.(node) ?? true;
707
1071
  if (source.extractSourceValue == null || collected === false) continue;
708
1072
  const extracted = await source.extractSourceValue(node.state);
@@ -728,9 +1092,10 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
728
1092
  if (result == null) continue;
729
1093
  if (!result.success) {
730
1094
  runtime.markSourceFailed(source.sourceId);
1095
+ propagateRuntimeSourceFailures(nodes, runtime);
731
1096
  return {
732
1097
  success: false,
733
- error: result.error
1098
+ error: includeSourceFailureChain(result.error, source.sourceId, runtime)
734
1099
  };
735
1100
  }
736
1101
  if (result.deferred === true) continue;
@@ -960,11 +1325,15 @@ function buildRuntimeNodesFromPairs(pairs, state, parentPath) {
960
1325
  const nodes = [];
961
1326
  for (const [field, parser] of pairs) {
962
1327
  const fieldState = Object.hasOwn(state, field) ? state[field] : void 0;
1328
+ const rawInput = extractRawInputFromState(fieldState);
1329
+ const defaultDependencyValues = getDefaultDependencySnapshot(fieldState);
963
1330
  nodes.push({
964
1331
  path: [...prefix, field],
965
1332
  parser,
966
1333
  state: fieldState,
967
- matched: isMatchedState(fieldState, parser)
1334
+ matched: isMatchedState(fieldState, parser),
1335
+ ...rawInput != null ? { rawInput } : {},
1336
+ ...defaultDependencyValues != null ? { defaultDependencyValues } : {}
968
1337
  });
969
1338
  }
970
1339
  return nodes;
@@ -987,15 +1356,42 @@ function buildRuntimeNodesFromArray(parsers, stateArray, parentPath) {
987
1356
  for (let i = 0; i < parsers.length; i++) {
988
1357
  const parser = parsers[i];
989
1358
  const elemState = i < stateArray.length ? stateArray[i] : void 0;
1359
+ const rawInput = extractRawInputFromState(elemState);
1360
+ const defaultDependencyValues = getDefaultDependencySnapshot(elemState);
990
1361
  nodes.push({
991
1362
  path: [...prefix, i],
992
1363
  parser,
993
1364
  state: elemState,
994
- matched: isMatchedState(elemState, parser)
1365
+ matched: isMatchedState(elemState, parser),
1366
+ ...rawInput != null ? { rawInput } : {},
1367
+ ...defaultDependencyValues != null ? { defaultDependencyValues } : {}
995
1368
  });
996
1369
  }
997
1370
  return nodes;
998
1371
  }
1372
+ function getDefaultDependencySnapshot(state) {
1373
+ return getDefaultDependencySnapshotInner(state, /* @__PURE__ */ new Set());
1374
+ }
1375
+ function getDefaultDependencySnapshotInner(state, visited) {
1376
+ if (state == null || typeof state !== "object") return void 0;
1377
+ if (visited.has(state)) return void 0;
1378
+ visited.add(state);
1379
+ const direct = require_internal_dependency.getSnapshottedDefaultDependencyValues(state);
1380
+ if (direct != null) return direct;
1381
+ if (Array.isArray(state)) {
1382
+ for (let index = state.length - 1; index >= 0; index--) {
1383
+ const snapshot = getDefaultDependencySnapshotInner(state[index], visited);
1384
+ if (snapshot != null) return snapshot;
1385
+ }
1386
+ return void 0;
1387
+ }
1388
+ const nested = [];
1389
+ for (const value of Object.values(state)) {
1390
+ const snapshot = getDefaultDependencySnapshotInner(value, visited);
1391
+ if (snapshot != null) nested.push(snapshot);
1392
+ }
1393
+ return nested.length === 1 ? nested[0] : void 0;
1394
+ }
999
1395
 
1000
1396
  //#endregion
1001
1397
  exports.buildRuntimeNodesFromArray = buildRuntimeNodesFromArray;
@@ -1009,12 +1405,18 @@ exports.createDependencyFingerprint = createDependencyFingerprint;
1009
1405
  exports.createDependencyRuntimeContext = createDependencyRuntimeContext;
1010
1406
  exports.createReplayKey = createReplayKey;
1011
1407
  exports.defineForwardedEffectfulSchedulingNodes = defineForwardedEffectfulSchedulingNodes;
1408
+ exports.derivedRawInputKey = derivedRawInputKey;
1012
1409
  exports.effectfulSchedulingNodesKey = effectfulSchedulingNodesKey;
1013
1410
  exports.extractRawInputFromState = extractRawInputFromState;
1014
1411
  exports.fillMissingSourceDefaults = fillMissingSourceDefaults;
1015
1412
  exports.fillMissingSourceDefaultsAsync = fillMissingSourceDefaultsAsync;
1413
+ exports.includeSourceFailureChain = includeSourceFailureChain;
1414
+ exports.orderDependencyNodes = orderDependencyNodes;
1415
+ exports.recordDerivedRawInput = recordDerivedRawInput;
1016
1416
  exports.replayDerivedParser = replayDerivedParser;
1017
1417
  exports.replayDerivedParserAsync = replayDerivedParserAsync;
1418
+ exports.resolveDerivedSourceValues = resolveDerivedSourceValues;
1419
+ exports.resolveDerivedSourceValuesAsync = resolveDerivedSourceValuesAsync;
1018
1420
  exports.resolveStateWithRuntime = resolveStateWithRuntime;
1019
1421
  exports.resolveStateWithRuntimeAsync = resolveStateWithRuntimeAsync;
1020
1422
  exports.serializeSchedulingPath = serializeSchedulingPath;