@etohq/workflows-input-schema-runtime 0.0.1-next-20260318155517

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.
Files changed (63) hide show
  1. package/README.md +71 -0
  2. package/dist/__tests__/rules-array-operators.spec.d.ts +2 -0
  3. package/dist/__tests__/rules-array-operators.spec.d.ts.map +1 -0
  4. package/dist/__tests__/rules-array-operators.spec.js +43 -0
  5. package/dist/__tests__/rules-array-operators.spec.js.map +1 -0
  6. package/dist/__tests__/rules-date-interaction.spec.d.ts +2 -0
  7. package/dist/__tests__/rules-date-interaction.spec.d.ts.map +1 -0
  8. package/dist/__tests__/rules-date-interaction.spec.js +33 -0
  9. package/dist/__tests__/rules-date-interaction.spec.js.map +1 -0
  10. package/dist/__tests__/rules-variables.spec.d.ts +2 -0
  11. package/dist/__tests__/rules-variables.spec.d.ts.map +1 -0
  12. package/dist/__tests__/rules-variables.spec.js +93 -0
  13. package/dist/__tests__/rules-variables.spec.js.map +1 -0
  14. package/dist/__tests__/schema-dead-ends.spec.d.ts +2 -0
  15. package/dist/__tests__/schema-dead-ends.spec.d.ts.map +1 -0
  16. package/dist/__tests__/schema-dead-ends.spec.js +60 -0
  17. package/dist/__tests__/schema-dead-ends.spec.js.map +1 -0
  18. package/dist/__tests__/schema-reachability.spec.d.ts +2 -0
  19. package/dist/__tests__/schema-reachability.spec.d.ts.map +1 -0
  20. package/dist/__tests__/schema-reachability.spec.js +77 -0
  21. package/dist/__tests__/schema-reachability.spec.js.map +1 -0
  22. package/dist/__tests__/schema-rule-refs.spec.d.ts +2 -0
  23. package/dist/__tests__/schema-rule-refs.spec.d.ts.map +1 -0
  24. package/dist/__tests__/schema-rule-refs.spec.js +113 -0
  25. package/dist/__tests__/schema-rule-refs.spec.js.map +1 -0
  26. package/dist/__tests__/schema-skipto-cycles.spec.d.ts +2 -0
  27. package/dist/__tests__/schema-skipto-cycles.spec.d.ts.map +1 -0
  28. package/dist/__tests__/schema-skipto-cycles.spec.js +78 -0
  29. package/dist/__tests__/schema-skipto-cycles.spec.js.map +1 -0
  30. package/dist/__tests__/schema-unscoped-control-flow.spec.d.ts +2 -0
  31. package/dist/__tests__/schema-unscoped-control-flow.spec.d.ts.map +1 -0
  32. package/dist/__tests__/schema-unscoped-control-flow.spec.js +28 -0
  33. package/dist/__tests__/schema-unscoped-control-flow.spec.js.map +1 -0
  34. package/dist/__tests__/schema-validation.spec.d.ts +2 -0
  35. package/dist/__tests__/schema-validation.spec.d.ts.map +1 -0
  36. package/dist/__tests__/schema-validation.spec.js +71 -0
  37. package/dist/__tests__/schema-validation.spec.js.map +1 -0
  38. package/dist/__tests__/submission-validation.spec.d.ts +2 -0
  39. package/dist/__tests__/submission-validation.spec.d.ts.map +1 -0
  40. package/dist/__tests__/submission-validation.spec.js +63 -0
  41. package/dist/__tests__/submission-validation.spec.js.map +1 -0
  42. package/dist/index.d.ts +5 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +21 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/rules.d.ts +23 -0
  47. package/dist/rules.d.ts.map +1 -0
  48. package/dist/rules.js +336 -0
  49. package/dist/rules.js.map +1 -0
  50. package/dist/schema.d.ts +3 -0
  51. package/dist/schema.d.ts.map +1 -0
  52. package/dist/schema.js +629 -0
  53. package/dist/schema.js.map +1 -0
  54. package/dist/transforms.d.ts +10 -0
  55. package/dist/transforms.d.ts.map +1 -0
  56. package/dist/transforms.js +45 -0
  57. package/dist/transforms.js.map +1 -0
  58. package/dist/tsconfig.tsbuildinfo +1 -0
  59. package/dist/validation.d.ts +11 -0
  60. package/dist/validation.d.ts.map +1 -0
  61. package/dist/validation.js +227 -0
  62. package/dist/validation.js.map +1 -0
  63. package/package.json +30 -0
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # @etohq/workflows-input-schema-runtime
2
+
3
+ Cross-platform runtime utilities for `@etohq/workflows-input-schema`:
4
+
5
+ - Schema validation (static analysis)
6
+ - Submission validation (type coercion, transforms, constraints)
7
+ - Rule evaluation (visibility/required/value overrides, variables, skip/end decisions)
8
+
9
+ ## API
10
+
11
+ ```ts
12
+ import { validateSchemaSpec } from "@etohq/workflows-input-schema-runtime"
13
+ import { validateSubmission } from "@etohq/workflows-input-schema-runtime"
14
+ import { evaluateRules } from "@etohq/workflows-input-schema-runtime"
15
+ ```
16
+
17
+ ## Validate A Schema
18
+
19
+ ```ts
20
+ import type { InputSchemaSpec } from "@etohq/workflows-input-schema"
21
+ import { validateSchemaSpec } from "@etohq/workflows-input-schema-runtime"
22
+
23
+ const schema: InputSchemaSpec = {
24
+ id: "schema_1",
25
+ version: 1,
26
+ name: "Example",
27
+ fields: [{ key: "name", value_type: "string", required: true }],
28
+ layout: [
29
+ { type: "section", id: "s1", children: [{ type: "field", field_key: "name" }] },
30
+ { type: "ending", id: "done", title: { default: "Done" } },
31
+ ],
32
+ }
33
+
34
+ const result = validateSchemaSpec(schema)
35
+ // result.status: valid | warning | invalid
36
+ // result.issues: ValidationIssue[]
37
+ ```
38
+
39
+ ## Validate A Submission
40
+
41
+ ```ts
42
+ import { validateSubmission } from "@etohq/workflows-input-schema-runtime"
43
+
44
+ const submission = {
45
+ schema_id: "schema_1",
46
+ schema_version: 1,
47
+ values: { name: " Alice " },
48
+ }
49
+
50
+ const res = validateSubmission(schema, submission)
51
+ // res.enriched_values contains coerced/transformed values when no type errors occurred.
52
+ ```
53
+
54
+ ## Evaluate Rules
55
+
56
+ ```ts
57
+ import { evaluateRules } from "@etohq/workflows-input-schema-runtime"
58
+
59
+ const runtime = evaluateRules(schema, submission)
60
+ // runtime.field_state: required/visible per field
61
+ // runtime.value_overrides: rule-set values per field
62
+ // runtime.variable_overrides: computed variables by id
63
+ // runtime.end / runtime.skip_to: control flow directives
64
+ ```
65
+
66
+ ## Runtime Semantics Notes
67
+
68
+ - Endings are terminal in the implicit layout flow.
69
+ - `skip_to` must target a non-ending node (use `end` to terminate).
70
+ - Static analysis (cycles, reachability) is strongest when control-flow rules are scoped (`rule.scope.node_id`).
71
+
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rules-array-operators.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-array-operators.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/rules-array-operators.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rules_1 = require("../rules");
4
+ function submission(values) {
5
+ return {
6
+ schema_id: "schema_1",
7
+ schema_version: 1,
8
+ values,
9
+ context: null,
10
+ };
11
+ }
12
+ describe("evaluatePredicate (array wrappers)", () => {
13
+ test("includes_one_of works with { type: \"array\" } wrappers", () => {
14
+ const pred = {
15
+ type: "op",
16
+ op: "includes_one_of",
17
+ left: { type: "field", field_key: "tags" },
18
+ right: { type: "const", value: { type: "array", value: ["b"] } },
19
+ };
20
+ const ok = (0, rules_1.evaluatePredicate)(submission({ tags: { type: "array", value: ["a", "b"] } }), pred);
21
+ expect(ok).toBe(true);
22
+ });
23
+ test("equals_one_of works with { type: \"array\" } wrappers", () => {
24
+ const pred = {
25
+ type: "op",
26
+ op: "equals_one_of",
27
+ left: { type: "field", field_key: "name" },
28
+ right: { type: "const", value: { type: "array", value: ["alice", "bob"] } },
29
+ };
30
+ const ok = (0, rules_1.evaluatePredicate)(submission({ name: "bob" }), pred);
31
+ expect(ok).toBe(true);
32
+ });
33
+ test("is_submitted treats empty array wrapper as empty", () => {
34
+ const pred = {
35
+ type: "op",
36
+ op: "is_submitted",
37
+ left: { type: "field", field_key: "tags" },
38
+ };
39
+ const ok = (0, rules_1.evaluatePredicate)(submission({ tags: { type: "array", value: [] } }), pred);
40
+ expect(ok).toBe(false);
41
+ });
42
+ });
43
+ //# sourceMappingURL=rules-array-operators.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-array-operators.spec.js","sourceRoot":"","sources":["../../src/__tests__/rules-array-operators.spec.ts"],"names":[],"mappings":";;AACA,oCAA4C;AAE5C,SAAS,UAAU,CAAC,MAAiC;IACnD,OAAO;QACL,SAAS,EAAE,UAAU;QACrB,cAAc,EAAE,CAAC;QACjB,MAAM;QACN,OAAO,EAAE,IAAI;KACd,CAAA;AACH,CAAC;AAED,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACnE,MAAM,IAAI,GAAkB;YAC1B,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,iBAAiB;YACrB,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE;YAC1C,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE;SACjE,CAAA;QAED,MAAM,EAAE,GAAG,IAAA,yBAAiB,EAC1B,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAC1D,IAAI,CACL,CAAA;QACD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;QACjE,MAAM,IAAI,GAAkB;YAC1B,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,eAAe;YACnB,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE;YAC1C,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE;SAC5E,CAAA;QAED,MAAM,EAAE,GAAG,IAAA,yBAAiB,EAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;QAC/D,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC5D,MAAM,IAAI,GAAkB;YAC1B,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,cAAc;YAClB,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE;SAC3C,CAAA;QAED,MAAM,EAAE,GAAG,IAAA,yBAAiB,EAC1B,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,EAClD,IAAI,CACL,CAAA;QACD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rules-date-interaction.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-date-interaction.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/rules-date-interaction.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rules_1 = require("../rules");
4
+ function submission(params) {
5
+ return {
6
+ schema_id: "schema_1",
7
+ schema_version: 1,
8
+ values: params.values ?? {},
9
+ context: params.context ?? null,
10
+ };
11
+ }
12
+ describe("evaluatePredicate (date + interaction operators)", () => {
13
+ test("is_before compares ISO date wrappers", () => {
14
+ const pred = {
15
+ type: "op",
16
+ op: "is_before",
17
+ left: { type: "field", field_key: "dob" },
18
+ right: { type: "const", value: { type: "date", value: "2020-01-01" } },
19
+ };
20
+ const ok = (0, rules_1.evaluatePredicate)(submission({ values: { dob: { type: "date", value: "2019-12-31" } } }), pred);
21
+ expect(ok).toBe(true);
22
+ });
23
+ test("interaction operator resolves from context convention", () => {
24
+ const pred = {
25
+ type: "op",
26
+ op: "is_clicked",
27
+ left: { type: "field", field_key: "cta" },
28
+ };
29
+ const ok = (0, rules_1.evaluatePredicate)(submission({ context: { "interaction.cta.is_clicked": true } }), pred);
30
+ expect(ok).toBe(true);
31
+ });
32
+ });
33
+ //# sourceMappingURL=rules-date-interaction.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-date-interaction.spec.js","sourceRoot":"","sources":["../../src/__tests__/rules-date-interaction.spec.ts"],"names":[],"mappings":";;AACA,oCAA4C;AAE5C,SAAS,UAAU,CAAC,MAGnB;IACC,OAAO;QACL,SAAS,EAAE,UAAU;QACrB,cAAc,EAAE,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;KAChC,CAAA;AACH,CAAC;AAED,QAAQ,CAAC,kDAAkD,EAAE,GAAG,EAAE;IAChE,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAChD,MAAM,IAAI,GAAkB;YAC1B,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,WAAW;YACf,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE;YACzC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE;SACvE,CAAA;QAED,MAAM,EAAE,GAAG,IAAA,yBAAiB,EAC1B,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,EACtE,IAAI,CACL,CAAA;QACD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;QACjE,MAAM,IAAI,GAAkB;YAC1B,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,YAAY;YAChB,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE;SAC1C,CAAA;QAED,MAAM,EAAE,GAAG,IAAA,yBAAiB,EAC1B,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,4BAA4B,EAAE,IAAI,EAAE,EAAE,CAAC,EAC/D,IAAI,CACL,CAAA;QACD,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rules-variables.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-variables.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/rules-variables.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rules_1 = require("../rules");
4
+ describe("runtime variables (PredicateRef.variable/var)", () => {
5
+ test("evaluatePredicate can compare variables via env", () => {
6
+ const submission = {
7
+ schema_id: "schema_1",
8
+ schema_version: 1,
9
+ values: {},
10
+ context: null,
11
+ };
12
+ const pred = {
13
+ type: "op",
14
+ op: "is_greater_than",
15
+ left: { type: "variable", variable_id: "v" },
16
+ right: { type: "const", value: 1 },
17
+ };
18
+ const ok = (0, rules_1.evaluatePredicate)(submission, pred, {
19
+ variables_by_id: { v: 2 },
20
+ variable_id_by_name: {},
21
+ });
22
+ expect(ok).toBe(true);
23
+ });
24
+ test("calculate_variable can reference variables", () => {
25
+ const schema = {
26
+ id: "schema_1",
27
+ version: 1,
28
+ name: "Test Schema",
29
+ fields: [{ key: "name", value_type: "string", required: false }],
30
+ variables: [{ id: "v", name: "score", value_type: "number", default_value: 2 }],
31
+ rules: [
32
+ {
33
+ id: "r1",
34
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
35
+ then: [
36
+ // Double the variable: v = v + v
37
+ {
38
+ type: "calculate_variable",
39
+ variable_id: "v",
40
+ operator: "add",
41
+ value: { type: "variable", variable_id: "v" },
42
+ },
43
+ ],
44
+ },
45
+ ],
46
+ };
47
+ const submission = {
48
+ schema_id: "schema_1",
49
+ schema_version: 1,
50
+ values: { name: "x" },
51
+ context: null,
52
+ };
53
+ const res = (0, rules_1.evaluateRules)(schema, submission);
54
+ expect(res.variable_overrides.v).toBe(4);
55
+ });
56
+ test("var(name) resolves via schema variable names", () => {
57
+ const schema = {
58
+ id: "schema_1",
59
+ version: 1,
60
+ name: "Test Schema",
61
+ fields: [{ key: "name", value_type: "string", required: false }],
62
+ variables: [{ id: "v", name: "score", value_type: "number", default_value: 2 }],
63
+ rules: [
64
+ {
65
+ id: "r1",
66
+ when: {
67
+ type: "op",
68
+ op: "equals",
69
+ left: { type: "var", name: "score" },
70
+ right: { type: "const", value: 2 },
71
+ },
72
+ then: [
73
+ {
74
+ type: "calculate_variable",
75
+ variable_id: "v",
76
+ operator: "add",
77
+ value: { type: "const", value: 1 },
78
+ },
79
+ ],
80
+ },
81
+ ],
82
+ };
83
+ const submission = {
84
+ schema_id: "schema_1",
85
+ schema_version: 1,
86
+ values: { name: "x" },
87
+ context: null,
88
+ };
89
+ const res = (0, rules_1.evaluateRules)(schema, submission);
90
+ expect(res.variable_overrides.v).toBe(3);
91
+ });
92
+ });
93
+ //# sourceMappingURL=rules-variables.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-variables.spec.js","sourceRoot":"","sources":["../../src/__tests__/rules-variables.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema-dead-ends.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-dead-ends.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema-dead-ends.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schema_1 = require("../schema");
4
+ describe("validateSchemaSpec (dead-end nodes)", () => {
5
+ test("rejects reachable non-ending node that cannot reach an ending", () => {
6
+ const schema = {
7
+ id: "schema_1",
8
+ version: 1,
9
+ name: "Test Schema",
10
+ fields: [{ key: "name", value_type: "string", required: false }],
11
+ layout: [
12
+ { type: "section", id: "A", children: [] },
13
+ { type: "ending", id: "END", title: { default: "Done" } },
14
+ { type: "section", id: "B", children: [] },
15
+ ],
16
+ rules: [
17
+ // Make B reachable, but B still can't reach any ending because endings are terminal.
18
+ {
19
+ id: "rA",
20
+ scope: { node_id: "A" },
21
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
22
+ then: [{ type: "skip_to", node_id: "B" }],
23
+ },
24
+ ],
25
+ };
26
+ const res = (0, schema_1.validateSchemaSpec)(schema);
27
+ expect(res.status).toBe("invalid");
28
+ expect(res.issues.some((i) => i.code === "dead_end")).toBe(true);
29
+ });
30
+ test("accepts a node that can reach an ending via an end effect", () => {
31
+ const schema = {
32
+ id: "schema_1",
33
+ version: 1,
34
+ name: "Test Schema",
35
+ fields: [{ key: "name", value_type: "string", required: false }],
36
+ layout: [
37
+ { type: "section", id: "A", children: [] },
38
+ { type: "ending", id: "END", title: { default: "Done" } },
39
+ { type: "section", id: "B", children: [] },
40
+ ],
41
+ rules: [
42
+ {
43
+ id: "rA",
44
+ scope: { node_id: "A" },
45
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
46
+ then: [{ type: "skip_to", node_id: "B" }],
47
+ },
48
+ {
49
+ id: "rB",
50
+ scope: { node_id: "B" },
51
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
52
+ then: [{ type: "end", ending_id: "END" }],
53
+ },
54
+ ],
55
+ };
56
+ const res = (0, schema_1.validateSchemaSpec)(schema);
57
+ expect(res.status).toBe("valid");
58
+ });
59
+ });
60
+ //# sourceMappingURL=schema-dead-ends.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-dead-ends.spec.js","sourceRoot":"","sources":["../../src/__tests__/schema-dead-ends.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema-reachability.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-reachability.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema-reachability.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schema_1 = require("../schema");
4
+ describe("validateSchemaSpec (reachability + skip_to targets)", () => {
5
+ test("rejects schemas with no ending reachable from start", () => {
6
+ const schema = {
7
+ id: "schema_1",
8
+ version: 1,
9
+ name: "Test Schema",
10
+ fields: [{ key: "name", value_type: "string", required: false }],
11
+ layout: [
12
+ { type: "section", id: "A", children: [] },
13
+ { type: "section", id: "B", children: [] },
14
+ ],
15
+ rules: [],
16
+ };
17
+ const res = (0, schema_1.validateSchemaSpec)(schema);
18
+ expect(res.status).toBe("invalid");
19
+ expect(res.issues.some((i) => i.code === "reachability")).toBe(true);
20
+ });
21
+ test("accepts schemas where an ending is reachable via layout progression", () => {
22
+ const schema = {
23
+ id: "schema_1",
24
+ version: 1,
25
+ name: "Test Schema",
26
+ fields: [{ key: "name", value_type: "string", required: false }],
27
+ layout: [
28
+ { type: "section", id: "A", children: [] },
29
+ { type: "ending", id: "END", title: { default: "Done" } },
30
+ ],
31
+ rules: [],
32
+ };
33
+ const res = (0, schema_1.validateSchemaSpec)(schema);
34
+ expect(res.status).toBe("valid");
35
+ });
36
+ test("warns on unreachable nodes (e.g. nodes after an ending)", () => {
37
+ const schema = {
38
+ id: "schema_1",
39
+ version: 1,
40
+ name: "Test Schema",
41
+ fields: [{ key: "name", value_type: "string", required: false }],
42
+ layout: [
43
+ { type: "section", id: "A", children: [] },
44
+ { type: "ending", id: "END", title: { default: "Done" } },
45
+ { type: "section", id: "B", children: [] },
46
+ ],
47
+ rules: [],
48
+ };
49
+ const res = (0, schema_1.validateSchemaSpec)(schema);
50
+ expect(res.status).toBe("warning");
51
+ expect(res.issues.some((i) => i.code === "unreachable")).toBe(true);
52
+ });
53
+ test("rejects skip_to that targets an ending id", () => {
54
+ const schema = {
55
+ id: "schema_1",
56
+ version: 1,
57
+ name: "Test Schema",
58
+ fields: [{ key: "name", value_type: "string", required: false }],
59
+ layout: [
60
+ { type: "section", id: "A", children: [] },
61
+ { type: "ending", id: "END", title: { default: "Done" } },
62
+ ],
63
+ rules: [
64
+ {
65
+ id: "r1",
66
+ scope: { node_id: "A" },
67
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
68
+ then: [{ type: "skip_to", node_id: "END" }],
69
+ },
70
+ ],
71
+ };
72
+ const res = (0, schema_1.validateSchemaSpec)(schema);
73
+ expect(res.status).toBe("invalid");
74
+ expect(res.issues.some((i) => i.code === "rule" && i.message.includes("skip_to must not target an ending"))).toBe(true);
75
+ });
76
+ });
77
+ //# sourceMappingURL=schema-reachability.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-reachability.spec.js","sourceRoot":"","sources":["../../src/__tests__/schema-reachability.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema-rule-refs.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-rule-refs.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema-rule-refs.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schema_1 = require("../schema");
4
+ describe("validateSchemaSpec (rule/effect references)", () => {
5
+ test("rejects unknown scope node_id", () => {
6
+ const schema = {
7
+ id: "schema_1",
8
+ version: 1,
9
+ name: "Test Schema",
10
+ fields: [{ key: "name", value_type: "string", required: false }],
11
+ layout: [{ type: "section", id: "s1", children: [] }],
12
+ rules: [
13
+ {
14
+ id: "r1",
15
+ scope: { node_id: "missing" },
16
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
17
+ then: [],
18
+ },
19
+ ],
20
+ };
21
+ const res = (0, schema_1.validateSchemaSpec)(schema);
22
+ expect(res.status).toBe("invalid");
23
+ expect(res.issues.some((i) => i.message.includes("Unknown scope node_id"))).toBe(true);
24
+ });
25
+ test("rejects scope node_id when it points to an ending", () => {
26
+ const schema = {
27
+ id: "schema_1",
28
+ version: 1,
29
+ name: "Test Schema",
30
+ fields: [{ key: "name", value_type: "string", required: false }],
31
+ layout: [
32
+ { type: "section", id: "s1", children: [] },
33
+ { type: "ending", id: "END", title: { default: "Done" } },
34
+ ],
35
+ rules: [
36
+ {
37
+ id: "r1",
38
+ scope: { node_id: "END" },
39
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
40
+ then: [],
41
+ },
42
+ ],
43
+ };
44
+ const res = (0, schema_1.validateSchemaSpec)(schema);
45
+ expect(res.status).toBe("invalid");
46
+ expect(res.issues.some((i) => i.message.includes("scope.node_id must not be an ending"))).toBe(true);
47
+ });
48
+ test("rejects unknown node_id in skip_to", () => {
49
+ const schema = {
50
+ id: "schema_1",
51
+ version: 1,
52
+ name: "Test Schema",
53
+ fields: [{ key: "name", value_type: "string", required: false }],
54
+ layout: [{ type: "section", id: "s1", children: [] }],
55
+ rules: [
56
+ {
57
+ id: "r1",
58
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
59
+ then: [{ type: "skip_to", node_id: "missing" }],
60
+ },
61
+ ],
62
+ };
63
+ const res = (0, schema_1.validateSchemaSpec)(schema);
64
+ expect(res.status).toBe("invalid");
65
+ expect(res.issues.some((i) => i.message.includes("Unknown node_id"))).toBe(true);
66
+ });
67
+ test("rejects unknown ending_id in end", () => {
68
+ const schema = {
69
+ id: "schema_1",
70
+ version: 1,
71
+ name: "Test Schema",
72
+ fields: [{ key: "name", value_type: "string", required: false }],
73
+ layout: [{ type: "section", id: "s1", children: [] }],
74
+ rules: [
75
+ {
76
+ id: "r1",
77
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
78
+ then: [{ type: "end", ending_id: "missing" }],
79
+ },
80
+ ],
81
+ };
82
+ const res = (0, schema_1.validateSchemaSpec)(schema);
83
+ expect(res.status).toBe("invalid");
84
+ expect(res.issues.some((i) => i.message.includes("Unknown ending_id"))).toBe(true);
85
+ });
86
+ test("rejects unknown variable_id in calculate_variable", () => {
87
+ const schema = {
88
+ id: "schema_1",
89
+ version: 1,
90
+ name: "Test Schema",
91
+ fields: [{ key: "name", value_type: "string", required: false }],
92
+ layout: [{ type: "section", id: "s1", children: [] }],
93
+ rules: [
94
+ {
95
+ id: "r1",
96
+ when: { type: "op", op: "is_present", left: { type: "field", field_key: "name" } },
97
+ then: [
98
+ {
99
+ type: "calculate_variable",
100
+ variable_id: "v_missing",
101
+ operator: "assign",
102
+ value: { type: "const", value: 1 },
103
+ },
104
+ ],
105
+ },
106
+ ],
107
+ };
108
+ const res = (0, schema_1.validateSchemaSpec)(schema);
109
+ expect(res.status).toBe("invalid");
110
+ expect(res.issues.some((i) => i.message.includes("Unknown variable_id"))).toBe(true);
111
+ });
112
+ });
113
+ //# sourceMappingURL=schema-rule-refs.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-rule-refs.spec.js","sourceRoot":"","sources":["../../src/__tests__/schema-rule-refs.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema-skipto-cycles.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-skipto-cycles.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema-skipto-cycles.spec.ts"],"names":[],"mappings":""}