@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.
- package/README.md +20 -0
- package/dist/evaluator/evaluate-workflow-expression.d.ts +10 -0
- package/dist/evaluator/evaluate-workflow-expression.d.ts.map +1 -1
- package/dist/evaluator/evaluate-workflow-expression.js +13 -0
- package/dist/evaluator/evaluate-workflow-expression.js.map +1 -1
- package/dist/evaluator/index.d.ts +2 -1
- package/dist/evaluator/index.d.ts.map +1 -1
- package/dist/evaluator/index.js +2 -1
- package/dist/evaluator/index.js.map +1 -1
- package/dist/evaluator/range.d.ts +6 -0
- package/dist/evaluator/range.d.ts.map +1 -0
- package/dist/evaluator/range.js +46 -0
- package/dist/evaluator/range.js.map +1 -0
- package/dist/expression/create-workflow-expression.d.ts.map +1 -1
- package/dist/expression/create-workflow-expression.js +12 -3
- package/dist/expression/create-workflow-expression.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/plan/freeze.d.ts +25 -14
- package/dist/plan/freeze.d.ts.map +1 -1
- package/dist/plan/freeze.js +84 -56
- package/dist/plan/freeze.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/plan/freeze.js
CHANGED
|
@@ -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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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:
|
|
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',
|
package/dist/plan/freeze.js.map
CHANGED
|
@@ -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":"AAAA,SACEA,0BAA0B,EAE1BC,iCAAiC,QAC5B,wBAAwB;AAC/B,SAAQC,2BAA2B,QAAO,iDAAiD;AAC3F,SAAQC,+BAA+B,QAAO,wBAAwB;AACtE,SAEEC,8BAA8B,QAEzB,0CAA0C;AACjD,SAAmCC,oBAAoB,QAAO,wBAAwB;AACtF,SAAQC,gBAAgB,QAAO,YAAY;AA8D3C,OAAO,SAASC,0BACdC,MAAgC;IAEhC,IAAIC,QAAQ;IACZ,IAAIC;IACJ,IAAIC,gBAAgB;IACpB,MAAMC,cAA4C,EAAE;IACpD,MAAMC,QAAgC,EAAE;IACxC,MAAMC,+BAA+BC,6BAA6BP;IAElE,KAAK,MAAMQ,WAAWR,OAAOS,KAAK,CAACC,QAAQ,CAAE;QAC3C,IAAIF,QAAQG,IAAI,KAAK,WAAW;YAC9BV,SAASO,QAAQP,KAAK;YACtB;QACF;QAEA,IAAI,CAACH,iBAAiBU,QAAQI,UAAU,EAAEZ,OAAOa,IAAI,GAAG;YACtD,IAAIC,+BAA+Bd,QAAQQ,UAAU;gBACnD,MAAMO,4BAA4BP;YACpC;YACAJ,YAAYY,IAAI,CAACC,sBAAsBT;YACvC;QACF;QAEA,MAAMU,YAAYC,wBAAwBnB,QAAQQ;QAClDH,MAAMW,IAAI,CAACE,UAAUb,KAAK;QAC1B,IAAIa,UAAUP,IAAI,KAAK,YAAY;YACjCP,YAAYY,IAAI,CAACE,UAAUE,UAAU;YACrC;QACF;QAEA,IAAId,8BAA8B;YAChCJ,aAAagB,UAAUjB,KAAK;YAC5BE,gBAAgB;QAClB,OAAO;YACLF,SAASiB,UAAUG,OAAO;QAC5B;IACF;IAEA,OAAO;QACLpB,OAAOK,gCAAgCH,gBAAgBD,aAAaD;QACpEG;QACAC;IACF;AACF;AASA,OAAO,SAASiB,mBAAmBtB,MAAgC;IACjE,IAAIC,QAAQ;IACZ,IAAIC;IACJ,IAAIC,gBAAgB;IACpB,MAAMC,cAA4C,EAAE;IACpD,MAAMC,QAAgC,EAAE;IACxC,MAAMK,WAAmC,EAAE;IAC3C,IAAIa,cAAc;IAClB,MAAMjB,+BAA+BC,6BAA6BP;IAElE,KAAK,MAAMQ,WAAWR,OAAOS,KAAK,CAACC,QAAQ,CAAE;QAC3C,IAAIF,QAAQG,IAAI,KAAK,WAAW;YAC9BV,SAASO,QAAQP,KAAK;YACtBS,SAASM,IAAI,CAACR;YACd;QACF;QAEA,IAAI,CAACV,iBAAiBU,QAAQI,UAAU,EAAEZ,OAAOa,IAAI,GAAG;YACtDU,cAAc;YACdb,SAASM,IAAI,CAACR;YACd;QACF;QAEA,MAAMU,YAAYC,wBAAwBnB,QAAQQ;QAClDH,MAAMW,IAAI,CAACE,UAAUb,KAAK;QAC1B,IAAIa,UAAUP,IAAI,KAAK,YAAY;YACjCP,YAAYY,IAAI,CAACE,UAAUE,UAAU;YACrCV,SAASM,IAAI,CAAC;gBAACL,MAAM;gBAAWV,OAAO;YAAE;YACzC;QACF;QAEA,IAAIK,8BAA8B;YAChCJ,aAAagB,UAAUjB,KAAK;YAC5BE,gBAAgB;QAClB,OAAO;YACLF,SAASiB,UAAUG,OAAO;QAC5B;QACAX,SAASM,IAAI,CAAC;YAACL,MAAM;YAAWV,OAAOiB,UAAUG,OAAO;QAAA;IAC1D;IAEA,IAAIE,aAAa,OAAO;QAACZ,MAAM;QAAYF,OAAO;YAACC;QAAQ;QAAGN;QAAaC;IAAK;IAChF,OAAO;QACLM,MAAM;QACNV,OAAOK,gCAAgCH,gBAAgBD,aAAaD;QACpEG;QACAC;IACF;AACF;AAEA,SAASE,6BAA6BP,MAAgC;IACpE,OACEA,OAAOM,4BAA4B,KAAK,QACxCN,OAAOS,KAAK,CAACC,QAAQ,CAACc,MAAM,KAAK,KACjCxB,OAAOS,KAAK,CAACC,QAAQ,CAAC,EAAE,EAAEC,SAAS;AAEvC;AAeA,SAASQ,wBACPnB,MAAgC,EAChCQ,OAAqC;IAErC,IAAI;QACF,MAAMP,QAAQT,2BAA2BgB,QAAQiB,UAAU,EAAEzB,OAAO0B,OAAO;QAC3E,MAAML,UAAU3B,4BAA4BO;QAC5C,OAAO;YACLU,MAAM;YACNV;YACAoB;YACAhB,OAAOsB,eAAenB,SAASR,OAAOa,IAAI,EAAEQ;QAC9C;IACF,EAAE,OAAOO,OAAO;QACd,IAAIA,iBAAiBnC,qCAAqCmC,MAAMC,MAAM,KAAK,gBAAgB;YACzF,IAAIC,gCAAgC9B,QAAQQ,UAAU;gBACpD,MAAM,IAAIb,gCAAgC;oBACxCoC,QAAQvB,QAAQiB,UAAU,CAACM,MAAM;oBACjCC,OAAOJ;gBACT;YACF;YAEA,OAAO;gBACLjB,MAAM;gBACNS,YAAYH,sBAAsBT;gBAClCH,OAAOsB,eAAenB,SAASR,OAAOa,IAAI,EAAE,IAAI;YAClD;QACF;QAEA,MAAM,IAAIlB,gCAAgC;YACxCoC,QAAQvB,QAAQiB,UAAU,CAACM,MAAM;YACjCC,OAAOJ;QACT;IACF;AACF;AAEA,SAASD,eACPnB,OAAqC,EACrCK,IAAsB,EACtBZ,KAAa,EACbgC,WAAW,KAAK;IAEhB,OAAOpC,qBAAqB;QAC1B4B,YAAYjB,QAAQiB,UAAU,CAACM,MAAM;QACrCG,OAAO1B,QAAQ0B,KAAK;QACpBtB,YAAYJ,QAAQI,UAAU;QAC9BuB,aAAatB;QACbZ;QACA,GAAIgC,WAAW;YAACA,UAAU;QAAI,IAAI,CAAC,CAAC;IACtC;AACF;AAEA,SAASH,gCACP9B,MAAgC,EAChCQ,OAAqC;IAErC,OACE,AAACD,6BAA6BP,WAAWA,OAAOoC,aAAa,KAAK,UAClEC,2BAA2B7B,SAASR,OAAOoC,aAAa,EAAEpC,OAAOa,IAAI;AAEzE;AAEA,SAASC,+BACPd,MAAgC,EAChCQ,OAAqC;IAErC,OACED,6BAA6BP,WAC7BA,OAAOoC,aAAa,KAAK,UACzB5B,QAAQI,UAAU,KAAK;AAE3B;AAEA,SAASG,4BACPP,OAAqC;IAErC,OAAO,IAAIb,gCAAgC;QACzCoC,QAAQvB,QAAQiB,UAAU,CAACM,MAAM;QACjCC,OAAO,IAAIM,MAAM;IACnB;AACF;AAEA,SAASrB,sBAAsBT,OAAqC;IAClE,OAAO;QACLqB,QAAQ;QACRJ,YAAYjB,QAAQiB,UAAU,CAACM,MAAM;QACrCQ,cAAc/B,QAAQ0B,KAAK;IAC7B;AACF;AAEA,SAASG,2BACP7B,OAAqC,EACrC4B,aAAiD,EACjDvB,IAAsB;IAEtB,IAAIuB,kBAAkB,QAAQ,OAAO;IACrC,MAAMI,qBAAqBhC,QAAQ0B,KAAK,CAACO,OAAO,CAAC,CAACC;QAChD,MAAMC,eAAe/C,+BAA+B8C;QACpD,OAAOC,iBAAiBC,YAAY,EAAE,GAAG;YAACD;SAAa;IACzD;IACA,OACEH,mBAAmBhB,MAAM,GAAG,KAC5BgB,mBAAmBK,KAAK,CAAC,CAACF,eAAiB7C,iBAAiB6C,cAAc9B;AAE9E"}
|