@adcp/sdk 14.0.0-beta.12 → 14.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/index.d.mts +3 -3
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +3 -1
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +2 -2
- package/dist/lib/server/create-adcp-server.d.ts +2 -2
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +6 -1
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +6 -1
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.d.mts +3 -3
- package/dist/lib/server/decisioning/index.d.ts +3 -3
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +24 -17
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +24 -17
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +71 -42
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +75 -43
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.mts +15 -21
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +15 -21
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +100 -30
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +100 -30
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.d.mts +30 -16
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts +30 -16
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.js +40 -20
- package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +38 -19
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.d.mts +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.d.ts +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.js +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.mts +3 -2
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +3 -2
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.d.mts +10 -10
- package/dist/lib/server/decisioning/specialisms/creative.d.ts +10 -10
- package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.js +11 -2
- package/dist/lib/testing/storyboard/default-invariants.js.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +11 -2
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.d.mts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/loader.js +14 -0
- package/dist/lib/testing/storyboard/loader.js.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +14 -0
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/phase-condition.d.mts +41 -0
- package/dist/lib/testing/storyboard/phase-condition.d.ts +42 -0
- package/dist/lib/testing/storyboard/phase-condition.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/phase-condition.js +215 -0
- package/dist/lib/testing/storyboard/phase-condition.js.map +1 -0
- package/dist/lib/testing/storyboard/phase-condition.mjs +189 -0
- package/dist/lib/testing/storyboard/phase-condition.mjs.map +1 -0
- package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.js +15 -2
- package/dist/lib/testing/storyboard/request-builder.js.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +15 -2
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +57 -23
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +57 -23
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/task-map.js +6 -2
- package/dist/lib/testing/storyboard/task-map.js.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +6 -2
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.d.mts +5 -4
- package/dist/lib/testing/storyboard/types.d.ts +5 -4
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.js +60 -4
- package/dist/lib/testing/storyboard/webhook-assertions.js.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +60 -4
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.d.mts +15 -0
- package/dist/lib/testing/storyboard/webhook-receiver.d.ts +15 -0
- package/dist/lib/testing/storyboard/webhook-receiver.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.js +57 -6
- package/dist/lib/testing/storyboard/webhook-receiver.js.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +57 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/types.d.mts +2 -0
- package/dist/lib/testing/types.d.ts +2 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/testing/types.js.map +1 -1
- package/dist/lib/types/core.generated.d.mts +5 -2
- package/dist/lib/types/core.generated.d.ts +5 -2
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js.map +1 -1
- package/dist/lib/types/index.d.mts +1 -1
- package/dist/lib/types/index.d.ts +1 -1
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/list-transformers.d.ts +9 -5
- package/dist/lib/types/schemas.generated.d.ts +21 -298
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +5 -2
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +4 -2
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.d.mts +2 -1
- package/dist/lib/types/server-payload-aliases.d.ts +2 -1
- package/dist/lib/types/server-payload-aliases.d.ts.map +1 -1
- package/dist/lib/types/server-payload-aliases.js.map +1 -1
- package/dist/lib/types/tools.generated.d.mts +5 -2
- package/dist/lib/types/tools.generated.d.ts +5 -2
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.d.mts +5 -1
- package/dist/lib/utils/build-creative-return-builders.d.ts +5 -1
- package/dist/lib/utils/build-creative-return-builders.d.ts.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.js +9 -3
- package/dist/lib/utils/build-creative-return-builders.js.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +7 -2
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.js +1 -1
- package/dist/lib/utils/response-unwrapper.js.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +1 -1
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.d.ts.map +1 -1
- package/dist/lib/validation/schema-loader.js +16 -7
- package/dist/lib/validation/schema-loader.js.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +16 -7
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/llms.txt +2 -2
- package/docs/migration-5.x-to-6.x.md +3 -2
- package/docs/migration-task-registry-scoping.md +61 -0
- package/examples/hello_seller_adapter_guaranteed.ts +1 -1
- package/package.json +4 -4
- package/skills/build-decisioning-creative-template/SKILL.md +2 -2
- package/skills/build-decisioning-platform/SKILL.md +4 -2
- package/skills/build-decisioning-platform/advanced/REFERENCE.md +7 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-condition.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/phase-condition.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AACzF,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAChE,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAC9D,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B,CAAC;AACF,KAAK,MAAM,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAAC;AAC7D,KAAK,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAC7C,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAO/E,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAsD1E;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAE9F;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAErE"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var phase_condition_exports = {};
|
|
20
|
+
__export(phase_condition_exports, {
|
|
21
|
+
evaluatePhaseCondition: () => evaluatePhaseCondition,
|
|
22
|
+
parsePhaseCondition: () => parsePhaseCondition,
|
|
23
|
+
phaseConditionUsesContext: () => phaseConditionUsesContext
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(phase_condition_exports);
|
|
26
|
+
function parsePhaseCondition(expression) {
|
|
27
|
+
const tokens = tokenize(expression);
|
|
28
|
+
if (tokens.length === 0) throw syntaxError(expression, 0, "expression must not be empty");
|
|
29
|
+
let cursor = 0;
|
|
30
|
+
const peek = () => tokens[cursor];
|
|
31
|
+
const take = () => tokens[cursor++];
|
|
32
|
+
const parseValue = () => {
|
|
33
|
+
const token = peek();
|
|
34
|
+
if (token?.kind === "reference") {
|
|
35
|
+
take();
|
|
36
|
+
return token.value;
|
|
37
|
+
}
|
|
38
|
+
if (token?.kind === "literal") {
|
|
39
|
+
take();
|
|
40
|
+
return { kind: "literal", value: token.value };
|
|
41
|
+
}
|
|
42
|
+
throw syntaxError(expression, token?.offset ?? expression.length, "expected a runtime reference or literal");
|
|
43
|
+
};
|
|
44
|
+
const parseUnary = () => {
|
|
45
|
+
const token = peek();
|
|
46
|
+
if (token?.kind === "not") {
|
|
47
|
+
take();
|
|
48
|
+
return { kind: "not", operand: parseUnary() };
|
|
49
|
+
}
|
|
50
|
+
return parseValue();
|
|
51
|
+
};
|
|
52
|
+
const parseEquality = () => {
|
|
53
|
+
const left = parseUnary();
|
|
54
|
+
const operator = peek();
|
|
55
|
+
if (operator?.kind !== "equals" && operator?.kind !== "not_equals") return left;
|
|
56
|
+
take();
|
|
57
|
+
const right = parseUnary();
|
|
58
|
+
return {
|
|
59
|
+
kind: "equality",
|
|
60
|
+
operator: operator.kind === "equals" ? "==" : "!=",
|
|
61
|
+
left,
|
|
62
|
+
right
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
const operands = [parseEquality()];
|
|
66
|
+
while (peek()?.kind === "or") {
|
|
67
|
+
take();
|
|
68
|
+
operands.push(parseEquality());
|
|
69
|
+
}
|
|
70
|
+
const trailing = peek();
|
|
71
|
+
if (trailing) {
|
|
72
|
+
throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);
|
|
73
|
+
}
|
|
74
|
+
return operands.length === 1 ? operands[0] : { kind: "or", operands };
|
|
75
|
+
}
|
|
76
|
+
function evaluatePhaseCondition(expression, scope) {
|
|
77
|
+
return Boolean(evaluateNode(parsePhaseCondition(expression), scope));
|
|
78
|
+
}
|
|
79
|
+
function phaseConditionUsesContext(expression) {
|
|
80
|
+
return nodeUsesContext(parsePhaseCondition(expression));
|
|
81
|
+
}
|
|
82
|
+
function evaluateNode(node, scope) {
|
|
83
|
+
switch (node.kind) {
|
|
84
|
+
case "literal":
|
|
85
|
+
return node.value;
|
|
86
|
+
case "reference":
|
|
87
|
+
return resolveReference(node, scope);
|
|
88
|
+
case "not":
|
|
89
|
+
return !Boolean(evaluateNode(node.operand, scope));
|
|
90
|
+
case "equality": {
|
|
91
|
+
const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);
|
|
92
|
+
return node.operator === "==" ? equal : !equal;
|
|
93
|
+
}
|
|
94
|
+
case "or":
|
|
95
|
+
return node.operands.some((operand) => Boolean(evaluateNode(operand, scope)));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function resolveReference(reference, scope) {
|
|
99
|
+
let value = scope[reference.root];
|
|
100
|
+
for (const segment of reference.path) {
|
|
101
|
+
if (value === null || typeof value !== "object" || !Object.prototype.hasOwnProperty.call(value, segment)) {
|
|
102
|
+
return void 0;
|
|
103
|
+
}
|
|
104
|
+
value = value[segment];
|
|
105
|
+
}
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
function nodeUsesContext(node) {
|
|
109
|
+
switch (node.kind) {
|
|
110
|
+
case "literal":
|
|
111
|
+
return false;
|
|
112
|
+
case "reference":
|
|
113
|
+
return node.root === "context";
|
|
114
|
+
case "not":
|
|
115
|
+
return nodeUsesContext(node.operand);
|
|
116
|
+
case "equality":
|
|
117
|
+
return nodeUsesContext(node.left) || nodeUsesContext(node.right);
|
|
118
|
+
case "or":
|
|
119
|
+
return node.operands.some(nodeUsesContext);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function tokenize(expression) {
|
|
123
|
+
const tokens = [];
|
|
124
|
+
let offset = 0;
|
|
125
|
+
while (offset < expression.length) {
|
|
126
|
+
const char = expression[offset];
|
|
127
|
+
if (/\s/.test(char)) {
|
|
128
|
+
offset++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (expression.startsWith("||", offset)) {
|
|
132
|
+
tokens.push({ kind: "or", offset });
|
|
133
|
+
offset += 2;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (expression.startsWith("==", offset)) {
|
|
137
|
+
tokens.push({ kind: "equals", offset });
|
|
138
|
+
offset += 2;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (expression.startsWith("!=", offset)) {
|
|
142
|
+
tokens.push({ kind: "not_equals", offset });
|
|
143
|
+
offset += 2;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (char === "!") {
|
|
147
|
+
tokens.push({ kind: "not", offset });
|
|
148
|
+
offset++;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (char === "'" || char === '"') {
|
|
152
|
+
const literal = readStringLiteral(expression, offset, char);
|
|
153
|
+
tokens.push({ kind: "literal", value: literal.value, offset });
|
|
154
|
+
offset = literal.nextOffset;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const rest = expression.slice(offset);
|
|
158
|
+
const reference = /^(context|test_kit)((?:\.[A-Za-z0-9_]+)+)/.exec(rest);
|
|
159
|
+
if (reference) {
|
|
160
|
+
const full = reference[0];
|
|
161
|
+
const next = rest[full.length];
|
|
162
|
+
if (next && /[A-Za-z0-9_.]/.test(next)) {
|
|
163
|
+
throw syntaxError(expression, offset + full.length, "invalid runtime reference");
|
|
164
|
+
}
|
|
165
|
+
tokens.push({
|
|
166
|
+
kind: "reference",
|
|
167
|
+
value: {
|
|
168
|
+
kind: "reference",
|
|
169
|
+
root: reference[1],
|
|
170
|
+
path: reference[2].slice(1).split(".")
|
|
171
|
+
},
|
|
172
|
+
offset
|
|
173
|
+
});
|
|
174
|
+
offset += full.length;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const boolean = /^(true|false)\b/.exec(rest);
|
|
178
|
+
if (boolean) {
|
|
179
|
+
tokens.push({ kind: "literal", value: boolean[1] === "true", offset });
|
|
180
|
+
offset += boolean[0].length;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);
|
|
184
|
+
}
|
|
185
|
+
return tokens;
|
|
186
|
+
}
|
|
187
|
+
function readStringLiteral(expression, start, quote) {
|
|
188
|
+
let value = "";
|
|
189
|
+
for (let offset = start + 1; offset < expression.length; offset++) {
|
|
190
|
+
const char = expression[offset];
|
|
191
|
+
if (char === quote) return { value, nextOffset: offset + 1 };
|
|
192
|
+
if (char === "\\") {
|
|
193
|
+
const escaped = expression[offset + 1];
|
|
194
|
+
if (escaped !== quote && escaped !== "\\") {
|
|
195
|
+
throw syntaxError(expression, offset, "string literals only support escaped quotes and backslashes");
|
|
196
|
+
}
|
|
197
|
+
value += escaped;
|
|
198
|
+
offset++;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (char === "\n" || char === "\r") throw syntaxError(expression, offset, "string literals must stay on one line");
|
|
202
|
+
value += char;
|
|
203
|
+
}
|
|
204
|
+
throw syntaxError(expression, start, "unterminated string literal");
|
|
205
|
+
}
|
|
206
|
+
function syntaxError(expression, offset, detail) {
|
|
207
|
+
return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);
|
|
208
|
+
}
|
|
209
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
210
|
+
0 && (module.exports = {
|
|
211
|
+
evaluatePhaseCondition,
|
|
212
|
+
parsePhaseCondition,
|
|
213
|
+
phaseConditionUsesContext
|
|
214
|
+
});
|
|
215
|
+
//# sourceMappingURL=phase-condition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/phase-condition.ts"],"sourcesContent":["/**\n * Closed, side-effect-free grammar for storyboard phase `skip_if` guards.\n *\n * Supported forms are deliberately small: runtime references rooted at\n * `context` or `test_kit`, truthiness/negation, `==` / `!=`, boolean and\n * quoted string literals, and logical OR. Anything else is an authoring\n * error rather than an expression that silently falls through to \"run\".\n */\n\nexport type PhaseConditionScope = {\n context?: Record<string, unknown>;\n test_kit?: unknown;\n};\n\ntype ReferenceNode = { kind: 'reference'; root: 'context' | 'test_kit'; path: string[] };\ntype LiteralNode = { kind: 'literal'; value: boolean | string };\ntype UnaryNode = { kind: 'not'; operand: PhaseConditionNode };\ntype EqualityNode = {\n kind: 'equality';\n operator: '==' | '!=';\n left: ValueNode | UnaryNode;\n right: ValueNode | UnaryNode;\n};\ntype OrNode = { kind: 'or'; operands: PhaseConditionNode[] };\ntype ValueNode = ReferenceNode | LiteralNode;\nexport type PhaseConditionNode = ValueNode | UnaryNode | EqualityNode | OrNode;\n\ntype Token =\n | { kind: 'reference'; value: ReferenceNode; offset: number }\n | { kind: 'literal'; value: boolean | string; offset: number }\n | { kind: 'not' | 'equals' | 'not_equals' | 'or'; offset: number };\n\nexport function parsePhaseCondition(expression: string): PhaseConditionNode {\n const tokens = tokenize(expression);\n if (tokens.length === 0) throw syntaxError(expression, 0, 'expression must not be empty');\n\n let cursor = 0;\n const peek = (): Token | undefined => tokens[cursor];\n const take = (): Token => tokens[cursor++]!;\n\n const parseValue = (): ValueNode => {\n const token = peek();\n if (token?.kind === 'reference') {\n take();\n return token.value;\n }\n if (token?.kind === 'literal') {\n take();\n return { kind: 'literal', value: token.value };\n }\n throw syntaxError(expression, token?.offset ?? expression.length, 'expected a runtime reference or literal');\n };\n\n const parseUnary = (): ValueNode | UnaryNode => {\n const token = peek();\n if (token?.kind === 'not') {\n take();\n return { kind: 'not', operand: parseUnary() };\n }\n return parseValue();\n };\n\n const parseEquality = (): PhaseConditionNode => {\n const left = parseUnary();\n const operator = peek();\n if (operator?.kind !== 'equals' && operator?.kind !== 'not_equals') return left;\n take();\n const right = parseUnary();\n return {\n kind: 'equality',\n operator: operator.kind === 'equals' ? '==' : '!=',\n left,\n right,\n };\n };\n\n const operands = [parseEquality()];\n while (peek()?.kind === 'or') {\n take();\n operands.push(parseEquality());\n }\n const trailing = peek();\n if (trailing) {\n throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);\n }\n return operands.length === 1 ? operands[0]! : { kind: 'or', operands };\n}\n\nexport function evaluatePhaseCondition(expression: string, scope: PhaseConditionScope): boolean {\n return Boolean(evaluateNode(parsePhaseCondition(expression), scope));\n}\n\nexport function phaseConditionUsesContext(expression: string): boolean {\n return nodeUsesContext(parsePhaseCondition(expression));\n}\n\nfunction evaluateNode(node: PhaseConditionNode, scope: PhaseConditionScope): unknown {\n switch (node.kind) {\n case 'literal':\n return node.value;\n case 'reference':\n return resolveReference(node, scope);\n case 'not':\n return !Boolean(evaluateNode(node.operand, scope));\n case 'equality': {\n const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);\n return node.operator === '==' ? equal : !equal;\n }\n case 'or':\n return node.operands.some(operand => Boolean(evaluateNode(operand, scope)));\n }\n}\n\nfunction resolveReference(reference: ReferenceNode, scope: PhaseConditionScope): unknown {\n let value: unknown = scope[reference.root];\n for (const segment of reference.path) {\n if (value === null || typeof value !== 'object' || !Object.prototype.hasOwnProperty.call(value, segment)) {\n return undefined;\n }\n value = (value as Record<string, unknown>)[segment];\n }\n return value;\n}\n\nfunction nodeUsesContext(node: PhaseConditionNode): boolean {\n switch (node.kind) {\n case 'literal':\n return false;\n case 'reference':\n return node.root === 'context';\n case 'not':\n return nodeUsesContext(node.operand);\n case 'equality':\n return nodeUsesContext(node.left) || nodeUsesContext(node.right);\n case 'or':\n return node.operands.some(nodeUsesContext);\n }\n}\n\nfunction tokenize(expression: string): Token[] {\n const tokens: Token[] = [];\n let offset = 0;\n while (offset < expression.length) {\n const char = expression[offset]!;\n if (/\\s/.test(char)) {\n offset++;\n continue;\n }\n if (expression.startsWith('||', offset)) {\n tokens.push({ kind: 'or', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('==', offset)) {\n tokens.push({ kind: 'equals', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('!=', offset)) {\n tokens.push({ kind: 'not_equals', offset });\n offset += 2;\n continue;\n }\n if (char === '!') {\n tokens.push({ kind: 'not', offset });\n offset++;\n continue;\n }\n if (char === \"'\" || char === '\"') {\n const literal = readStringLiteral(expression, offset, char);\n tokens.push({ kind: 'literal', value: literal.value, offset });\n offset = literal.nextOffset;\n continue;\n }\n\n const rest = expression.slice(offset);\n // Preserve the original test-kit path compatibility: authored fixture\n // maps may use numeric-leading keys such as format dimensions (`300x250`).\n const reference = /^(context|test_kit)((?:\\.[A-Za-z0-9_]+)+)/.exec(rest);\n if (reference) {\n const full = reference[0]!;\n const next = rest[full.length];\n if (next && /[A-Za-z0-9_.]/.test(next)) {\n throw syntaxError(expression, offset + full.length, 'invalid runtime reference');\n }\n tokens.push({\n kind: 'reference',\n value: {\n kind: 'reference',\n root: reference[1] as 'context' | 'test_kit',\n path: reference[2]!.slice(1).split('.'),\n },\n offset,\n });\n offset += full.length;\n continue;\n }\n\n const boolean = /^(true|false)\\b/.exec(rest);\n if (boolean) {\n tokens.push({ kind: 'literal', value: boolean[1] === 'true', offset });\n offset += boolean[0].length;\n continue;\n }\n throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);\n }\n return tokens;\n}\n\nfunction readStringLiteral(expression: string, start: number, quote: \"'\" | '\"'): { value: string; nextOffset: number } {\n let value = '';\n for (let offset = start + 1; offset < expression.length; offset++) {\n const char = expression[offset]!;\n if (char === quote) return { value, nextOffset: offset + 1 };\n if (char === '\\\\') {\n const escaped = expression[offset + 1];\n if (escaped !== quote && escaped !== '\\\\') {\n throw syntaxError(expression, offset, 'string literals only support escaped quotes and backslashes');\n }\n value += escaped;\n offset++;\n continue;\n }\n if (char === '\\n' || char === '\\r') throw syntaxError(expression, offset, 'string literals must stay on one line');\n value += char;\n }\n throw syntaxError(expression, start, 'unterminated string literal');\n}\n\nfunction syntaxError(expression: string, offset: number, detail: string): Error {\n return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
function parsePhaseCondition(expression) {
|
|
2
|
+
const tokens = tokenize(expression);
|
|
3
|
+
if (tokens.length === 0) throw syntaxError(expression, 0, "expression must not be empty");
|
|
4
|
+
let cursor = 0;
|
|
5
|
+
const peek = () => tokens[cursor];
|
|
6
|
+
const take = () => tokens[cursor++];
|
|
7
|
+
const parseValue = () => {
|
|
8
|
+
const token = peek();
|
|
9
|
+
if (token?.kind === "reference") {
|
|
10
|
+
take();
|
|
11
|
+
return token.value;
|
|
12
|
+
}
|
|
13
|
+
if (token?.kind === "literal") {
|
|
14
|
+
take();
|
|
15
|
+
return { kind: "literal", value: token.value };
|
|
16
|
+
}
|
|
17
|
+
throw syntaxError(expression, token?.offset ?? expression.length, "expected a runtime reference or literal");
|
|
18
|
+
};
|
|
19
|
+
const parseUnary = () => {
|
|
20
|
+
const token = peek();
|
|
21
|
+
if (token?.kind === "not") {
|
|
22
|
+
take();
|
|
23
|
+
return { kind: "not", operand: parseUnary() };
|
|
24
|
+
}
|
|
25
|
+
return parseValue();
|
|
26
|
+
};
|
|
27
|
+
const parseEquality = () => {
|
|
28
|
+
const left = parseUnary();
|
|
29
|
+
const operator = peek();
|
|
30
|
+
if (operator?.kind !== "equals" && operator?.kind !== "not_equals") return left;
|
|
31
|
+
take();
|
|
32
|
+
const right = parseUnary();
|
|
33
|
+
return {
|
|
34
|
+
kind: "equality",
|
|
35
|
+
operator: operator.kind === "equals" ? "==" : "!=",
|
|
36
|
+
left,
|
|
37
|
+
right
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
const operands = [parseEquality()];
|
|
41
|
+
while (peek()?.kind === "or") {
|
|
42
|
+
take();
|
|
43
|
+
operands.push(parseEquality());
|
|
44
|
+
}
|
|
45
|
+
const trailing = peek();
|
|
46
|
+
if (trailing) {
|
|
47
|
+
throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);
|
|
48
|
+
}
|
|
49
|
+
return operands.length === 1 ? operands[0] : { kind: "or", operands };
|
|
50
|
+
}
|
|
51
|
+
function evaluatePhaseCondition(expression, scope) {
|
|
52
|
+
return Boolean(evaluateNode(parsePhaseCondition(expression), scope));
|
|
53
|
+
}
|
|
54
|
+
function phaseConditionUsesContext(expression) {
|
|
55
|
+
return nodeUsesContext(parsePhaseCondition(expression));
|
|
56
|
+
}
|
|
57
|
+
function evaluateNode(node, scope) {
|
|
58
|
+
switch (node.kind) {
|
|
59
|
+
case "literal":
|
|
60
|
+
return node.value;
|
|
61
|
+
case "reference":
|
|
62
|
+
return resolveReference(node, scope);
|
|
63
|
+
case "not":
|
|
64
|
+
return !Boolean(evaluateNode(node.operand, scope));
|
|
65
|
+
case "equality": {
|
|
66
|
+
const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);
|
|
67
|
+
return node.operator === "==" ? equal : !equal;
|
|
68
|
+
}
|
|
69
|
+
case "or":
|
|
70
|
+
return node.operands.some((operand) => Boolean(evaluateNode(operand, scope)));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function resolveReference(reference, scope) {
|
|
74
|
+
let value = scope[reference.root];
|
|
75
|
+
for (const segment of reference.path) {
|
|
76
|
+
if (value === null || typeof value !== "object" || !Object.prototype.hasOwnProperty.call(value, segment)) {
|
|
77
|
+
return void 0;
|
|
78
|
+
}
|
|
79
|
+
value = value[segment];
|
|
80
|
+
}
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
function nodeUsesContext(node) {
|
|
84
|
+
switch (node.kind) {
|
|
85
|
+
case "literal":
|
|
86
|
+
return false;
|
|
87
|
+
case "reference":
|
|
88
|
+
return node.root === "context";
|
|
89
|
+
case "not":
|
|
90
|
+
return nodeUsesContext(node.operand);
|
|
91
|
+
case "equality":
|
|
92
|
+
return nodeUsesContext(node.left) || nodeUsesContext(node.right);
|
|
93
|
+
case "or":
|
|
94
|
+
return node.operands.some(nodeUsesContext);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function tokenize(expression) {
|
|
98
|
+
const tokens = [];
|
|
99
|
+
let offset = 0;
|
|
100
|
+
while (offset < expression.length) {
|
|
101
|
+
const char = expression[offset];
|
|
102
|
+
if (/\s/.test(char)) {
|
|
103
|
+
offset++;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (expression.startsWith("||", offset)) {
|
|
107
|
+
tokens.push({ kind: "or", offset });
|
|
108
|
+
offset += 2;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (expression.startsWith("==", offset)) {
|
|
112
|
+
tokens.push({ kind: "equals", offset });
|
|
113
|
+
offset += 2;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (expression.startsWith("!=", offset)) {
|
|
117
|
+
tokens.push({ kind: "not_equals", offset });
|
|
118
|
+
offset += 2;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (char === "!") {
|
|
122
|
+
tokens.push({ kind: "not", offset });
|
|
123
|
+
offset++;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (char === "'" || char === '"') {
|
|
127
|
+
const literal = readStringLiteral(expression, offset, char);
|
|
128
|
+
tokens.push({ kind: "literal", value: literal.value, offset });
|
|
129
|
+
offset = literal.nextOffset;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const rest = expression.slice(offset);
|
|
133
|
+
const reference = /^(context|test_kit)((?:\.[A-Za-z0-9_]+)+)/.exec(rest);
|
|
134
|
+
if (reference) {
|
|
135
|
+
const full = reference[0];
|
|
136
|
+
const next = rest[full.length];
|
|
137
|
+
if (next && /[A-Za-z0-9_.]/.test(next)) {
|
|
138
|
+
throw syntaxError(expression, offset + full.length, "invalid runtime reference");
|
|
139
|
+
}
|
|
140
|
+
tokens.push({
|
|
141
|
+
kind: "reference",
|
|
142
|
+
value: {
|
|
143
|
+
kind: "reference",
|
|
144
|
+
root: reference[1],
|
|
145
|
+
path: reference[2].slice(1).split(".")
|
|
146
|
+
},
|
|
147
|
+
offset
|
|
148
|
+
});
|
|
149
|
+
offset += full.length;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const boolean = /^(true|false)\b/.exec(rest);
|
|
153
|
+
if (boolean) {
|
|
154
|
+
tokens.push({ kind: "literal", value: boolean[1] === "true", offset });
|
|
155
|
+
offset += boolean[0].length;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);
|
|
159
|
+
}
|
|
160
|
+
return tokens;
|
|
161
|
+
}
|
|
162
|
+
function readStringLiteral(expression, start, quote) {
|
|
163
|
+
let value = "";
|
|
164
|
+
for (let offset = start + 1; offset < expression.length; offset++) {
|
|
165
|
+
const char = expression[offset];
|
|
166
|
+
if (char === quote) return { value, nextOffset: offset + 1 };
|
|
167
|
+
if (char === "\\") {
|
|
168
|
+
const escaped = expression[offset + 1];
|
|
169
|
+
if (escaped !== quote && escaped !== "\\") {
|
|
170
|
+
throw syntaxError(expression, offset, "string literals only support escaped quotes and backslashes");
|
|
171
|
+
}
|
|
172
|
+
value += escaped;
|
|
173
|
+
offset++;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (char === "\n" || char === "\r") throw syntaxError(expression, offset, "string literals must stay on one line");
|
|
177
|
+
value += char;
|
|
178
|
+
}
|
|
179
|
+
throw syntaxError(expression, start, "unterminated string literal");
|
|
180
|
+
}
|
|
181
|
+
function syntaxError(expression, offset, detail) {
|
|
182
|
+
return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);
|
|
183
|
+
}
|
|
184
|
+
export {
|
|
185
|
+
evaluatePhaseCondition,
|
|
186
|
+
parsePhaseCondition,
|
|
187
|
+
phaseConditionUsesContext
|
|
188
|
+
};
|
|
189
|
+
//# sourceMappingURL=phase-condition.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/phase-condition.ts"],"sourcesContent":["/**\n * Closed, side-effect-free grammar for storyboard phase `skip_if` guards.\n *\n * Supported forms are deliberately small: runtime references rooted at\n * `context` or `test_kit`, truthiness/negation, `==` / `!=`, boolean and\n * quoted string literals, and logical OR. Anything else is an authoring\n * error rather than an expression that silently falls through to \"run\".\n */\n\nexport type PhaseConditionScope = {\n context?: Record<string, unknown>;\n test_kit?: unknown;\n};\n\ntype ReferenceNode = { kind: 'reference'; root: 'context' | 'test_kit'; path: string[] };\ntype LiteralNode = { kind: 'literal'; value: boolean | string };\ntype UnaryNode = { kind: 'not'; operand: PhaseConditionNode };\ntype EqualityNode = {\n kind: 'equality';\n operator: '==' | '!=';\n left: ValueNode | UnaryNode;\n right: ValueNode | UnaryNode;\n};\ntype OrNode = { kind: 'or'; operands: PhaseConditionNode[] };\ntype ValueNode = ReferenceNode | LiteralNode;\nexport type PhaseConditionNode = ValueNode | UnaryNode | EqualityNode | OrNode;\n\ntype Token =\n | { kind: 'reference'; value: ReferenceNode; offset: number }\n | { kind: 'literal'; value: boolean | string; offset: number }\n | { kind: 'not' | 'equals' | 'not_equals' | 'or'; offset: number };\n\nexport function parsePhaseCondition(expression: string): PhaseConditionNode {\n const tokens = tokenize(expression);\n if (tokens.length === 0) throw syntaxError(expression, 0, 'expression must not be empty');\n\n let cursor = 0;\n const peek = (): Token | undefined => tokens[cursor];\n const take = (): Token => tokens[cursor++]!;\n\n const parseValue = (): ValueNode => {\n const token = peek();\n if (token?.kind === 'reference') {\n take();\n return token.value;\n }\n if (token?.kind === 'literal') {\n take();\n return { kind: 'literal', value: token.value };\n }\n throw syntaxError(expression, token?.offset ?? expression.length, 'expected a runtime reference or literal');\n };\n\n const parseUnary = (): ValueNode | UnaryNode => {\n const token = peek();\n if (token?.kind === 'not') {\n take();\n return { kind: 'not', operand: parseUnary() };\n }\n return parseValue();\n };\n\n const parseEquality = (): PhaseConditionNode => {\n const left = parseUnary();\n const operator = peek();\n if (operator?.kind !== 'equals' && operator?.kind !== 'not_equals') return left;\n take();\n const right = parseUnary();\n return {\n kind: 'equality',\n operator: operator.kind === 'equals' ? '==' : '!=',\n left,\n right,\n };\n };\n\n const operands = [parseEquality()];\n while (peek()?.kind === 'or') {\n take();\n operands.push(parseEquality());\n }\n const trailing = peek();\n if (trailing) {\n throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);\n }\n return operands.length === 1 ? operands[0]! : { kind: 'or', operands };\n}\n\nexport function evaluatePhaseCondition(expression: string, scope: PhaseConditionScope): boolean {\n return Boolean(evaluateNode(parsePhaseCondition(expression), scope));\n}\n\nexport function phaseConditionUsesContext(expression: string): boolean {\n return nodeUsesContext(parsePhaseCondition(expression));\n}\n\nfunction evaluateNode(node: PhaseConditionNode, scope: PhaseConditionScope): unknown {\n switch (node.kind) {\n case 'literal':\n return node.value;\n case 'reference':\n return resolveReference(node, scope);\n case 'not':\n return !Boolean(evaluateNode(node.operand, scope));\n case 'equality': {\n const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);\n return node.operator === '==' ? equal : !equal;\n }\n case 'or':\n return node.operands.some(operand => Boolean(evaluateNode(operand, scope)));\n }\n}\n\nfunction resolveReference(reference: ReferenceNode, scope: PhaseConditionScope): unknown {\n let value: unknown = scope[reference.root];\n for (const segment of reference.path) {\n if (value === null || typeof value !== 'object' || !Object.prototype.hasOwnProperty.call(value, segment)) {\n return undefined;\n }\n value = (value as Record<string, unknown>)[segment];\n }\n return value;\n}\n\nfunction nodeUsesContext(node: PhaseConditionNode): boolean {\n switch (node.kind) {\n case 'literal':\n return false;\n case 'reference':\n return node.root === 'context';\n case 'not':\n return nodeUsesContext(node.operand);\n case 'equality':\n return nodeUsesContext(node.left) || nodeUsesContext(node.right);\n case 'or':\n return node.operands.some(nodeUsesContext);\n }\n}\n\nfunction tokenize(expression: string): Token[] {\n const tokens: Token[] = [];\n let offset = 0;\n while (offset < expression.length) {\n const char = expression[offset]!;\n if (/\\s/.test(char)) {\n offset++;\n continue;\n }\n if (expression.startsWith('||', offset)) {\n tokens.push({ kind: 'or', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('==', offset)) {\n tokens.push({ kind: 'equals', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('!=', offset)) {\n tokens.push({ kind: 'not_equals', offset });\n offset += 2;\n continue;\n }\n if (char === '!') {\n tokens.push({ kind: 'not', offset });\n offset++;\n continue;\n }\n if (char === \"'\" || char === '\"') {\n const literal = readStringLiteral(expression, offset, char);\n tokens.push({ kind: 'literal', value: literal.value, offset });\n offset = literal.nextOffset;\n continue;\n }\n\n const rest = expression.slice(offset);\n // Preserve the original test-kit path compatibility: authored fixture\n // maps may use numeric-leading keys such as format dimensions (`300x250`).\n const reference = /^(context|test_kit)((?:\\.[A-Za-z0-9_]+)+)/.exec(rest);\n if (reference) {\n const full = reference[0]!;\n const next = rest[full.length];\n if (next && /[A-Za-z0-9_.]/.test(next)) {\n throw syntaxError(expression, offset + full.length, 'invalid runtime reference');\n }\n tokens.push({\n kind: 'reference',\n value: {\n kind: 'reference',\n root: reference[1] as 'context' | 'test_kit',\n path: reference[2]!.slice(1).split('.'),\n },\n offset,\n });\n offset += full.length;\n continue;\n }\n\n const boolean = /^(true|false)\\b/.exec(rest);\n if (boolean) {\n tokens.push({ kind: 'literal', value: boolean[1] === 'true', offset });\n offset += boolean[0].length;\n continue;\n }\n throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);\n }\n return tokens;\n}\n\nfunction readStringLiteral(expression: string, start: number, quote: \"'\" | '\"'): { value: string; nextOffset: number } {\n let value = '';\n for (let offset = start + 1; offset < expression.length; offset++) {\n const char = expression[offset]!;\n if (char === quote) return { value, nextOffset: offset + 1 };\n if (char === '\\\\') {\n const escaped = expression[offset + 1];\n if (escaped !== quote && escaped !== '\\\\') {\n throw syntaxError(expression, offset, 'string literals only support escaped quotes and backslashes');\n }\n value += escaped;\n offset++;\n continue;\n }\n if (char === '\\n' || char === '\\r') throw syntaxError(expression, offset, 'string literals must stay on one line');\n value += char;\n }\n throw syntaxError(expression, start, 'unterminated string literal');\n}\n\nfunction syntaxError(expression: string, offset: number, detail: string): Error {\n return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-builder.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/request-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"request-builder.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/request-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AA+/BhE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,WAAW,EACpB,UAAU,CAAC,EAAE,eAAe,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4BzB;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAQD,6DAA6D;AAC7D,eAAO,MAAM,YAAY,sBAAgB,CAAC;AAE1C,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,2BAAqB,CAAC"}
|
|
@@ -34,6 +34,8 @@ const FIXTURE_AWARE_ENRICHERS = /* @__PURE__ */ new Set([
|
|
|
34
34
|
// merges discovery-derived product_id / pricing_option_id INTO fixture packages[0]
|
|
35
35
|
"comply_test_controller",
|
|
36
36
|
// forces account.sandbox: true regardless of fixture
|
|
37
|
+
"check_governance",
|
|
38
|
+
// preserves the authored intent-vs-delivery request shape
|
|
37
39
|
"get_products",
|
|
38
40
|
// preserves wholesale fixture fields while keeping resolved account scope authoritative
|
|
39
41
|
"update_media_buy",
|
|
@@ -491,8 +493,18 @@ const REQUEST_ENRICHERS = {
|
|
|
491
493
|
]
|
|
492
494
|
};
|
|
493
495
|
},
|
|
494
|
-
check_governance(step, context, options) {
|
|
495
|
-
|
|
496
|
+
check_governance(step, context, options, runnerVars) {
|
|
497
|
+
const fixture = step.sample_request !== void 0 ? omitEnvelopeFields(
|
|
498
|
+
(0, import_context.injectContext)({ ...step.sample_request }, context, runnerVars)
|
|
499
|
+
) : void 0;
|
|
500
|
+
const isDelivery = fixture?.phase === "delivery" || fixture?.planned_delivery !== void 0 || fixture?.delivery_metrics !== void 0 || fixture?.governance_context !== void 0;
|
|
501
|
+
if (fixture && isDelivery) {
|
|
502
|
+
return {
|
|
503
|
+
...fixture,
|
|
504
|
+
caller: fixture.caller ?? FALLBACK_CALLER_AGENT_URL
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
const fallback = {
|
|
496
508
|
plan_id: context.plan_id ?? "unknown",
|
|
497
509
|
caller: FALLBACK_CALLER_AGENT_URL,
|
|
498
510
|
tool: "get_products",
|
|
@@ -504,6 +516,7 @@ const REQUEST_ENRICHERS = {
|
|
|
504
516
|
total_budget: options.budget ?? 1e4
|
|
505
517
|
}
|
|
506
518
|
};
|
|
519
|
+
return fixture ? { ...fallback, ...fixture } : fallback;
|
|
507
520
|
},
|
|
508
521
|
get_account_financials(_step, context, options) {
|
|
509
522
|
return {
|