@shipfox/expression 1.1.5 → 1.2.1

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.
@@ -4,61 +4,53 @@ import { WorkflowTemplateResolutionError } from '../resolver/errors.js';
4
4
  import { resolveContextRootAvailability } from '../workflow-context/workflow-context.js';
5
5
  import { evaluationTraceEntry } from './evaluation-trace.js';
6
6
  import { shouldFillAtSite } from './fill.js';
7
- /**
8
- * Segment lifecycle:
9
- *
10
- * `{expr}` -> plan -> `{deferred, fillTarget}` -> freeze at a site at or after
11
- * `fillTarget` -> `{literal}`. Runner-fill segments are never filled server-side.
12
- *
13
- * Value fields follow their declared policy at their fill target. Predicates use
14
- * the planned predicate entry point and fail closed when evaluation is deferred.
15
- */ export function freezeResolvedFieldAtSite(params) {
7
+ export function freezeResolvedFieldAtSite(params) {
16
8
  let value = '';
9
+ let typedValue;
10
+ let hasTypedValue = false;
17
11
  const diagnostics = [];
18
12
  const trace = [];
13
+ const preserveSingleExpressionType = isExactSingleExpressionField(params);
19
14
  for (const segment of params.field.segments){
20
15
  if (segment.kind === 'literal') {
21
16
  value += segment.value;
22
17
  continue;
23
18
  }
24
19
  if (!shouldFillAtSite(segment.fillTarget, params.site)) {
20
+ if (exactTypedFieldRequiresFailure(params, segment)) {
21
+ throw typedFieldNotFillableAtSite(segment);
22
+ }
25
23
  diagnostics.push(missingPathDiagnostic(segment));
26
24
  continue;
27
25
  }
28
- try {
29
- const literal = coerceWorkflowValueToString(evaluateWorkflowExpression(segment.expression, params.context));
30
- value += literal;
31
- trace.push(fillTraceEntry(segment, params.site, literal));
32
- } catch (error) {
33
- if (error instanceof WorkflowExpressionEvaluationError && error.reason === 'missing-path') {
34
- if (missingPathRequiresFailure(segment, params.failurePolicy, params.site)) {
35
- throw new WorkflowTemplateResolutionError({
36
- source: segment.expression.source,
37
- cause: error
38
- });
39
- }
40
- diagnostics.push(missingPathDiagnostic(segment));
41
- trace.push(fillTraceEntry(segment, params.site, '', true));
42
- continue;
43
- }
44
- throw new WorkflowTemplateResolutionError({
45
- source: segment.expression.source,
46
- cause: error
47
- });
26
+ const evaluated = evaluateFillableSegment(params, segment);
27
+ trace.push(evaluated.trace);
28
+ if (evaluated.kind === 'degraded') {
29
+ diagnostics.push(evaluated.diagnostic);
30
+ continue;
31
+ }
32
+ if (preserveSingleExpressionType) {
33
+ typedValue = evaluated.value;
34
+ hasTypedValue = true;
35
+ } else {
36
+ value += evaluated.literal;
48
37
  }
49
38
  }
50
39
  return {
51
- value,
40
+ value: preserveSingleExpressionType && hasTypedValue ? typedValue : value,
52
41
  diagnostics,
53
42
  trace
54
43
  };
55
44
  }
56
45
  export function resolveFieldAtSite(params) {
57
46
  let value = '';
47
+ let typedValue;
48
+ let hasTypedValue = false;
58
49
  const diagnostics = [];
59
50
  const trace = [];
60
51
  const segments = [];
61
52
  let hasResidual = false;
53
+ const preserveSingleExpressionType = isExactSingleExpressionField(params);
62
54
  for (const segment of params.field.segments){
63
55
  if (segment.kind === 'literal') {
64
56
  value += segment.value;
@@ -70,35 +62,26 @@ export function resolveFieldAtSite(params) {
70
62
  segments.push(segment);
71
63
  continue;
72
64
  }
73
- try {
74
- const literal = coerceWorkflowValueToString(evaluateWorkflowExpression(segment.expression, params.context));
75
- value += literal;
65
+ const evaluated = evaluateFillableSegment(params, segment);
66
+ trace.push(evaluated.trace);
67
+ if (evaluated.kind === 'degraded') {
68
+ diagnostics.push(evaluated.diagnostic);
76
69
  segments.push({
77
70
  kind: 'literal',
78
- value: literal
79
- });
80
- trace.push(fillTraceEntry(segment, params.site, literal));
81
- } catch (error) {
82
- if (error instanceof WorkflowExpressionEvaluationError && error.reason === 'missing-path') {
83
- if (missingPathRequiresFailure(segment, params.failurePolicy, params.site)) {
84
- throw new WorkflowTemplateResolutionError({
85
- source: segment.expression.source,
86
- cause: error
87
- });
88
- }
89
- diagnostics.push(missingPathDiagnostic(segment));
90
- segments.push({
91
- kind: 'literal',
92
- value: ''
93
- });
94
- trace.push(fillTraceEntry(segment, params.site, '', true));
95
- continue;
96
- }
97
- throw new WorkflowTemplateResolutionError({
98
- source: segment.expression.source,
99
- cause: error
71
+ value: ''
100
72
  });
73
+ continue;
74
+ }
75
+ if (preserveSingleExpressionType) {
76
+ typedValue = evaluated.value;
77
+ hasTypedValue = true;
78
+ } else {
79
+ value += evaluated.literal;
101
80
  }
81
+ segments.push({
82
+ kind: 'literal',
83
+ value: evaluated.literal
84
+ });
102
85
  }
103
86
  if (hasResidual) return {
104
87
  kind: 'residual',
@@ -110,11 +93,44 @@ export function resolveFieldAtSite(params) {
110
93
  };
111
94
  return {
112
95
  kind: 'frozen',
113
- value,
96
+ value: preserveSingleExpressionType && hasTypedValue ? typedValue : value,
114
97
  diagnostics,
115
98
  trace
116
99
  };
117
100
  }
101
+ function isExactSingleExpressionField(params) {
102
+ return params.preserveSingleExpressionType === true && params.field.segments.length === 1 && params.field.segments[0]?.kind === 'deferred';
103
+ }
104
+ function evaluateFillableSegment(params, segment) {
105
+ try {
106
+ const value = evaluateWorkflowExpression(segment.expression, params.context);
107
+ const literal = coerceWorkflowValueToString(value);
108
+ return {
109
+ kind: 'evaluated',
110
+ value,
111
+ literal,
112
+ trace: fillTraceEntry(segment, params.site, literal)
113
+ };
114
+ } catch (error) {
115
+ if (error instanceof WorkflowExpressionEvaluationError && error.reason === 'missing-path') {
116
+ if (fieldMissingPathRequiresFailure(params, segment)) {
117
+ throw new WorkflowTemplateResolutionError({
118
+ source: segment.expression.source,
119
+ cause: error
120
+ });
121
+ }
122
+ return {
123
+ kind: 'degraded',
124
+ diagnostic: missingPathDiagnostic(segment),
125
+ trace: fillTraceEntry(segment, params.site, '', true)
126
+ };
127
+ }
128
+ throw new WorkflowTemplateResolutionError({
129
+ source: segment.expression.source,
130
+ cause: error
131
+ });
132
+ }
133
+ }
118
134
  function fillTraceEntry(segment, site, value, degraded = false) {
119
135
  return evaluationTraceEntry({
120
136
  expression: segment.expression.source,
@@ -127,6 +143,18 @@ function fillTraceEntry(segment, site, value, degraded = false) {
127
143
  } : {}
128
144
  });
129
145
  }
146
+ function fieldMissingPathRequiresFailure(params, segment) {
147
+ return isExactSingleExpressionField(params) && params.failurePolicy === 'fail' || missingPathRequiresFailure(segment, params.failurePolicy, params.site);
148
+ }
149
+ function exactTypedFieldRequiresFailure(params, segment) {
150
+ return isExactSingleExpressionField(params) && params.failurePolicy === 'fail' && segment.fillTarget !== 'runner-fill';
151
+ }
152
+ function typedFieldNotFillableAtSite(segment) {
153
+ return new WorkflowTemplateResolutionError({
154
+ source: segment.expression.source,
155
+ cause: new Error('Typed field is not fillable at this site.')
156
+ });
157
+ }
130
158
  function missingPathDiagnostic(segment) {
131
159
  return {
132
160
  reason: 'missing-path',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plan/freeze.ts"],"sourcesContent":["import {\n evaluateWorkflowExpression,\n type WorkflowExpressionEvaluationContext,\n WorkflowExpressionEvaluationError,\n} from '../evaluator/index.js';\nimport {coerceWorkflowValueToString} from '../resolver/coerce-workflow-value-to-string.js';\nimport {WorkflowTemplateResolutionError} from '../resolver/errors.js';\nimport {\n type AvailabilitySite,\n resolveContextRootAvailability,\n type WorkflowInterpolationFailurePolicy,\n} from '../workflow-context/workflow-context.js';\nimport {type EvaluationTraceEntry, evaluationTraceEntry} from './evaluation-trace.js';\nimport {shouldFillAtSite} from './fill.js';\nimport type {\n ResolvedField,\n ResolvedFieldDeferredSegment,\n ResolvedFieldSegment,\n} from './resolved-field.js';\n\nexport type WorkflowTemplateFailurePolicy = WorkflowInterpolationFailurePolicy;\n\nexport interface WorkflowTemplateDiagnostic {\n readonly reason: 'missing-path';\n readonly expression: string;\n readonly contextRoots: readonly string[];\n}\n\nexport interface FrozenResolvedField {\n readonly value: string;\n readonly diagnostics: readonly WorkflowTemplateDiagnostic[];\n readonly trace: readonly EvaluationTraceEntry[];\n}\n\nexport type SiteResolvedField =\n | {\n readonly kind: 'frozen';\n readonly value: string;\n readonly diagnostics: readonly WorkflowTemplateDiagnostic[];\n readonly trace: readonly EvaluationTraceEntry[];\n }\n | {\n readonly kind: 'residual';\n readonly field: ResolvedField;\n readonly diagnostics: readonly WorkflowTemplateDiagnostic[];\n readonly trace: readonly EvaluationTraceEntry[];\n };\n\n/**\n * Segment lifecycle:\n *\n * `{expr}` -> plan -> `{deferred, fillTarget}` -> freeze at a site at or after\n * `fillTarget` -> `{literal}`. Runner-fill segments are never filled server-side.\n *\n * Value fields follow their declared policy at their fill target. Predicates use\n * the planned predicate entry point and fail closed when evaluation is deferred.\n */\nexport function freezeResolvedFieldAtSite(params: {\n readonly field: ResolvedField;\n readonly failurePolicy: WorkflowInterpolationFailurePolicy;\n readonly site: AvailabilitySite;\n readonly context: WorkflowExpressionEvaluationContext;\n}): FrozenResolvedField {\n let value = '';\n const diagnostics: WorkflowTemplateDiagnostic[] = [];\n const trace: EvaluationTraceEntry[] = [];\n\n for (const segment of params.field.segments) {\n if (segment.kind === 'literal') {\n value += segment.value;\n continue;\n }\n\n if (!shouldFillAtSite(segment.fillTarget, params.site)) {\n diagnostics.push(missingPathDiagnostic(segment));\n continue;\n }\n\n try {\n const literal = coerceWorkflowValueToString(\n evaluateWorkflowExpression(segment.expression, params.context),\n );\n value += literal;\n trace.push(fillTraceEntry(segment, params.site, literal));\n } catch (error) {\n if (error instanceof WorkflowExpressionEvaluationError && error.reason === 'missing-path') {\n if (missingPathRequiresFailure(segment, params.failurePolicy, params.site)) {\n throw new WorkflowTemplateResolutionError({\n source: segment.expression.source,\n cause: error,\n });\n }\n\n diagnostics.push(missingPathDiagnostic(segment));\n trace.push(fillTraceEntry(segment, params.site, '', true));\n continue;\n }\n\n throw new WorkflowTemplateResolutionError({\n source: segment.expression.source,\n cause: error,\n });\n }\n }\n\n return {value, diagnostics, trace};\n}\n\nexport function resolveFieldAtSite(params: {\n readonly field: ResolvedField;\n readonly failurePolicy: WorkflowInterpolationFailurePolicy;\n readonly site: AvailabilitySite;\n readonly context: WorkflowExpressionEvaluationContext;\n}): SiteResolvedField {\n let value = '';\n const diagnostics: WorkflowTemplateDiagnostic[] = [];\n const trace: EvaluationTraceEntry[] = [];\n const segments: ResolvedFieldSegment[] = [];\n let hasResidual = false;\n\n for (const segment of params.field.segments) {\n if (segment.kind === 'literal') {\n value += segment.value;\n segments.push(segment);\n continue;\n }\n\n if (!shouldFillAtSite(segment.fillTarget, params.site)) {\n hasResidual = true;\n segments.push(segment);\n continue;\n }\n\n try {\n const literal = coerceWorkflowValueToString(\n evaluateWorkflowExpression(segment.expression, params.context),\n );\n value += literal;\n segments.push({kind: 'literal', value: literal});\n trace.push(fillTraceEntry(segment, params.site, literal));\n } catch (error) {\n if (error instanceof WorkflowExpressionEvaluationError && error.reason === 'missing-path') {\n if (missingPathRequiresFailure(segment, params.failurePolicy, params.site)) {\n throw new WorkflowTemplateResolutionError({\n source: segment.expression.source,\n cause: error,\n });\n }\n\n diagnostics.push(missingPathDiagnostic(segment));\n segments.push({kind: 'literal', value: ''});\n trace.push(fillTraceEntry(segment, params.site, '', true));\n continue;\n }\n\n throw new WorkflowTemplateResolutionError({\n source: segment.expression.source,\n cause: error,\n });\n }\n }\n\n if (hasResidual) return {kind: 'residual', field: {segments}, diagnostics, trace};\n return {kind: 'frozen', value, diagnostics, trace};\n}\n\nfunction fillTraceEntry(\n segment: ResolvedFieldDeferredSegment,\n site: AvailabilitySite,\n value: string,\n degraded = false,\n): EvaluationTraceEntry {\n return evaluationTraceEntry({\n expression: segment.expression.source,\n roots: segment.roots,\n fillTarget: segment.fillTarget,\n evaluatedAt: site,\n value,\n ...(degraded ? {degraded: true} : {}),\n });\n}\n\nfunction missingPathDiagnostic(segment: ResolvedFieldDeferredSegment): WorkflowTemplateDiagnostic {\n return {\n reason: 'missing-path',\n expression: segment.expression.source,\n contextRoots: segment.roots,\n };\n}\n\nfunction missingPathRequiresFailure(\n segment: ResolvedFieldDeferredSegment,\n failurePolicy: WorkflowInterpolationFailurePolicy,\n site: AvailabilitySite,\n): boolean {\n if (failurePolicy !== 'fail') return false;\n const rootAvailabilities = segment.roots.flatMap((root) => {\n const availability = resolveContextRootAvailability(root);\n return availability === undefined ? [] : [availability];\n });\n return (\n rootAvailabilities.length > 0 &&\n rootAvailabilities.every((availability) => shouldFillAtSite(availability, site))\n );\n}\n"],"names":["evaluateWorkflowExpression","WorkflowExpressionEvaluationError","coerceWorkflowValueToString","WorkflowTemplateResolutionError","resolveContextRootAvailability","evaluationTraceEntry","shouldFillAtSite","freezeResolvedFieldAtSite","params","value","diagnostics","trace","segment","field","segments","kind","fillTarget","site","push","missingPathDiagnostic","literal","expression","context","fillTraceEntry","error","reason","missingPathRequiresFailure","failurePolicy","source","cause","resolveFieldAtSite","hasResidual","degraded","roots","evaluatedAt","contextRoots","rootAvailabilities","flatMap","root","availability","undefined","length","every"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/plan/freeze.ts"],"sourcesContent":["import {\n evaluateWorkflowExpression,\n type WorkflowExpressionEvaluationContext,\n WorkflowExpressionEvaluationError,\n} from '../evaluator/index.js';\nimport {coerceWorkflowValueToString} from '../resolver/coerce-workflow-value-to-string.js';\nimport {WorkflowTemplateResolutionError} from '../resolver/errors.js';\nimport {\n type AvailabilitySite,\n resolveContextRootAvailability,\n type WorkflowInterpolationFailurePolicy,\n} from '../workflow-context/workflow-context.js';\nimport {type EvaluationTraceEntry, evaluationTraceEntry} from './evaluation-trace.js';\nimport {shouldFillAtSite} from './fill.js';\nimport type {\n ResolvedField,\n ResolvedFieldDeferredSegment,\n ResolvedFieldSegment,\n} from './resolved-field.js';\n\nexport type WorkflowTemplateFailurePolicy = WorkflowInterpolationFailurePolicy;\n\nexport interface WorkflowTemplateDiagnostic {\n readonly reason: 'missing-path';\n readonly expression: string;\n readonly contextRoots: readonly string[];\n}\n\nexport interface FrozenResolvedField<Value = string> {\n readonly value: Value;\n readonly diagnostics: readonly WorkflowTemplateDiagnostic[];\n readonly trace: readonly EvaluationTraceEntry[];\n}\n\nexport type SiteResolvedField<Value = string> =\n | {\n readonly kind: 'frozen';\n readonly value: Value;\n readonly diagnostics: readonly WorkflowTemplateDiagnostic[];\n readonly trace: readonly EvaluationTraceEntry[];\n }\n | {\n readonly kind: 'residual';\n readonly field: ResolvedField;\n readonly diagnostics: readonly WorkflowTemplateDiagnostic[];\n readonly trace: readonly EvaluationTraceEntry[];\n };\n\ninterface ResolveFieldAtSiteParams {\n readonly field: ResolvedField;\n readonly failurePolicy: WorkflowInterpolationFailurePolicy;\n readonly site: AvailabilitySite;\n readonly context: WorkflowExpressionEvaluationContext;\n /** Preserve the value of an exact single expression instead of stringifying it. */\n readonly preserveSingleExpressionType?: boolean;\n}\n\n/**\n * Segment lifecycle:\n *\n * `{expr}` -> plan -> `{deferred, fillTarget}` -> freeze at a site at or after\n * `fillTarget` -> `{literal}`. Runner-fill segments are never filled server-side.\n *\n * Value fields follow their declared policy at their fill target. Predicates use\n * the planned predicate entry point and fail closed when evaluation is deferred.\n */\nexport function freezeResolvedFieldAtSite(\n params: ResolveFieldAtSiteParams & {readonly preserveSingleExpressionType: true},\n): FrozenResolvedField<unknown>;\nexport function freezeResolvedFieldAtSite(\n params: ResolveFieldAtSiteParams & {readonly preserveSingleExpressionType?: false},\n): FrozenResolvedField;\nexport function freezeResolvedFieldAtSite(\n params: ResolveFieldAtSiteParams,\n): FrozenResolvedField<unknown>;\nexport function freezeResolvedFieldAtSite(\n params: ResolveFieldAtSiteParams,\n): FrozenResolvedField<unknown> {\n let value = '';\n let typedValue: unknown;\n let hasTypedValue = false;\n const diagnostics: WorkflowTemplateDiagnostic[] = [];\n const trace: EvaluationTraceEntry[] = [];\n const preserveSingleExpressionType = isExactSingleExpressionField(params);\n\n for (const segment of params.field.segments) {\n if (segment.kind === 'literal') {\n value += segment.value;\n continue;\n }\n\n if (!shouldFillAtSite(segment.fillTarget, params.site)) {\n if (exactTypedFieldRequiresFailure(params, segment)) {\n throw typedFieldNotFillableAtSite(segment);\n }\n diagnostics.push(missingPathDiagnostic(segment));\n continue;\n }\n\n const evaluated = evaluateFillableSegment(params, segment);\n trace.push(evaluated.trace);\n if (evaluated.kind === 'degraded') {\n diagnostics.push(evaluated.diagnostic);\n continue;\n }\n\n if (preserveSingleExpressionType) {\n typedValue = evaluated.value;\n hasTypedValue = true;\n } else {\n value += evaluated.literal;\n }\n }\n\n return {\n value: preserveSingleExpressionType && hasTypedValue ? typedValue : value,\n diagnostics,\n trace,\n };\n}\n\nexport function resolveFieldAtSite(\n params: ResolveFieldAtSiteParams & {readonly preserveSingleExpressionType: true},\n): SiteResolvedField<unknown>;\nexport function resolveFieldAtSite(\n params: ResolveFieldAtSiteParams & {readonly preserveSingleExpressionType?: false},\n): SiteResolvedField;\nexport function resolveFieldAtSite(params: ResolveFieldAtSiteParams): SiteResolvedField<unknown>;\nexport function resolveFieldAtSite(params: ResolveFieldAtSiteParams): SiteResolvedField<unknown> {\n let value = '';\n let typedValue: unknown;\n let hasTypedValue = false;\n const diagnostics: WorkflowTemplateDiagnostic[] = [];\n const trace: EvaluationTraceEntry[] = [];\n const segments: ResolvedFieldSegment[] = [];\n let hasResidual = false;\n const preserveSingleExpressionType = isExactSingleExpressionField(params);\n\n for (const segment of params.field.segments) {\n if (segment.kind === 'literal') {\n value += segment.value;\n segments.push(segment);\n continue;\n }\n\n if (!shouldFillAtSite(segment.fillTarget, params.site)) {\n hasResidual = true;\n segments.push(segment);\n continue;\n }\n\n const evaluated = evaluateFillableSegment(params, segment);\n trace.push(evaluated.trace);\n if (evaluated.kind === 'degraded') {\n diagnostics.push(evaluated.diagnostic);\n segments.push({kind: 'literal', value: ''});\n continue;\n }\n\n if (preserveSingleExpressionType) {\n typedValue = evaluated.value;\n hasTypedValue = true;\n } else {\n value += evaluated.literal;\n }\n segments.push({kind: 'literal', value: evaluated.literal});\n }\n\n if (hasResidual) return {kind: 'residual', field: {segments}, diagnostics, trace};\n return {\n kind: 'frozen',\n value: preserveSingleExpressionType && hasTypedValue ? typedValue : value,\n diagnostics,\n trace,\n };\n}\n\nfunction isExactSingleExpressionField(params: ResolveFieldAtSiteParams): boolean {\n return (\n params.preserveSingleExpressionType === true &&\n params.field.segments.length === 1 &&\n params.field.segments[0]?.kind === 'deferred'\n );\n}\n\ntype FilledFieldSegment =\n | {\n readonly kind: 'evaluated';\n readonly value: unknown;\n readonly literal: string;\n readonly trace: EvaluationTraceEntry;\n }\n | {\n readonly kind: 'degraded';\n readonly diagnostic: WorkflowTemplateDiagnostic;\n readonly trace: EvaluationTraceEntry;\n };\n\nfunction evaluateFillableSegment(\n params: ResolveFieldAtSiteParams,\n segment: ResolvedFieldDeferredSegment,\n): FilledFieldSegment {\n try {\n const value = evaluateWorkflowExpression(segment.expression, params.context);\n const literal = coerceWorkflowValueToString(value);\n return {\n kind: 'evaluated',\n value,\n literal,\n trace: fillTraceEntry(segment, params.site, literal),\n };\n } catch (error) {\n if (error instanceof WorkflowExpressionEvaluationError && error.reason === 'missing-path') {\n if (fieldMissingPathRequiresFailure(params, segment)) {\n throw new WorkflowTemplateResolutionError({\n source: segment.expression.source,\n cause: error,\n });\n }\n\n return {\n kind: 'degraded',\n diagnostic: missingPathDiagnostic(segment),\n trace: fillTraceEntry(segment, params.site, '', true),\n };\n }\n\n throw new WorkflowTemplateResolutionError({\n source: segment.expression.source,\n cause: error,\n });\n }\n}\n\nfunction fillTraceEntry(\n segment: ResolvedFieldDeferredSegment,\n site: AvailabilitySite,\n value: string,\n degraded = false,\n): EvaluationTraceEntry {\n return evaluationTraceEntry({\n expression: segment.expression.source,\n roots: segment.roots,\n fillTarget: segment.fillTarget,\n evaluatedAt: site,\n value,\n ...(degraded ? {degraded: true} : {}),\n });\n}\n\nfunction fieldMissingPathRequiresFailure(\n params: ResolveFieldAtSiteParams,\n segment: ResolvedFieldDeferredSegment,\n): boolean {\n return (\n (isExactSingleExpressionField(params) && params.failurePolicy === 'fail') ||\n missingPathRequiresFailure(segment, params.failurePolicy, params.site)\n );\n}\n\nfunction exactTypedFieldRequiresFailure(\n params: ResolveFieldAtSiteParams,\n segment: ResolvedFieldDeferredSegment,\n): boolean {\n return (\n isExactSingleExpressionField(params) &&\n params.failurePolicy === 'fail' &&\n segment.fillTarget !== 'runner-fill'\n );\n}\n\nfunction typedFieldNotFillableAtSite(\n segment: ResolvedFieldDeferredSegment,\n): WorkflowTemplateResolutionError {\n return new WorkflowTemplateResolutionError({\n source: segment.expression.source,\n cause: new Error('Typed field is not fillable at this site.'),\n });\n}\n\nfunction missingPathDiagnostic(segment: ResolvedFieldDeferredSegment): WorkflowTemplateDiagnostic {\n return {\n reason: 'missing-path',\n expression: segment.expression.source,\n contextRoots: segment.roots,\n };\n}\n\nfunction missingPathRequiresFailure(\n segment: ResolvedFieldDeferredSegment,\n failurePolicy: WorkflowInterpolationFailurePolicy,\n site: AvailabilitySite,\n): boolean {\n if (failurePolicy !== 'fail') return false;\n const rootAvailabilities = segment.roots.flatMap((root) => {\n const availability = resolveContextRootAvailability(root);\n return availability === undefined ? [] : [availability];\n });\n return (\n rootAvailabilities.length > 0 &&\n rootAvailabilities.every((availability) => shouldFillAtSite(availability, site))\n );\n}\n"],"names":["evaluateWorkflowExpression","WorkflowExpressionEvaluationError","coerceWorkflowValueToString","WorkflowTemplateResolutionError","resolveContextRootAvailability","evaluationTraceEntry","shouldFillAtSite","freezeResolvedFieldAtSite","params","value","typedValue","hasTypedValue","diagnostics","trace","preserveSingleExpressionType","isExactSingleExpressionField","segment","field","segments","kind","fillTarget","site","exactTypedFieldRequiresFailure","typedFieldNotFillableAtSite","push","missingPathDiagnostic","evaluated","evaluateFillableSegment","diagnostic","literal","resolveFieldAtSite","hasResidual","length","expression","context","fillTraceEntry","error","reason","fieldMissingPathRequiresFailure","source","cause","degraded","roots","evaluatedAt","failurePolicy","missingPathRequiresFailure","Error","contextRoots","rootAvailabilities","flatMap","root","availability","undefined","every"],"mappings":"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"}