@kalada/core 0.1.0 → 0.3.0

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 (98) hide show
  1. package/README.md +25 -0
  2. package/dist/kalada-v1/canonical-input.cjs +133 -0
  3. package/dist/kalada-v1/canonical-input.cjs.map +1 -0
  4. package/dist/kalada-v1/canonical-input.d.cts +25 -0
  5. package/dist/kalada-v1/canonical-input.d.ts +25 -0
  6. package/dist/kalada-v1/canonical-input.js +122 -0
  7. package/dist/kalada-v1/canonical-input.js.map +1 -0
  8. package/dist/kalada-v1/canonicalize.cjs +214 -0
  9. package/dist/kalada-v1/canonicalize.cjs.map +1 -0
  10. package/dist/kalada-v1/canonicalize.d.cts +8 -0
  11. package/dist/kalada-v1/canonicalize.d.ts +8 -0
  12. package/dist/kalada-v1/canonicalize.js +212 -0
  13. package/dist/kalada-v1/canonicalize.js.map +1 -0
  14. package/dist/kalada-v1/codec.cjs +173 -0
  15. package/dist/kalada-v1/codec.cjs.map +1 -0
  16. package/dist/kalada-v1/codec.d.cts +32 -0
  17. package/dist/kalada-v1/codec.d.ts +32 -0
  18. package/dist/kalada-v1/codec.js +170 -0
  19. package/dist/kalada-v1/codec.js.map +1 -0
  20. package/dist/kalada-v1/compile.cjs +45 -0
  21. package/dist/kalada-v1/compile.cjs.map +1 -0
  22. package/dist/kalada-v1/compile.d.cts +8 -0
  23. package/dist/kalada-v1/compile.d.ts +8 -0
  24. package/dist/kalada-v1/compile.js +43 -0
  25. package/dist/kalada-v1/compile.js.map +1 -0
  26. package/dist/kalada-v1/dependencies.cjs +58 -0
  27. package/dist/kalada-v1/dependencies.cjs.map +1 -0
  28. package/dist/kalada-v1/dependencies.d.cts +8 -0
  29. package/dist/kalada-v1/dependencies.d.ts +8 -0
  30. package/dist/kalada-v1/dependencies.js +56 -0
  31. package/dist/kalada-v1/dependencies.js.map +1 -0
  32. package/dist/kalada-v1/diagnostics.cjs +49 -0
  33. package/dist/kalada-v1/diagnostics.cjs.map +1 -0
  34. package/dist/kalada-v1/diagnostics.d.cts +14 -0
  35. package/dist/kalada-v1/diagnostics.d.ts +14 -0
  36. package/dist/kalada-v1/diagnostics.js +45 -0
  37. package/dist/kalada-v1/diagnostics.js.map +1 -0
  38. package/dist/kalada-v1/evaluate.cjs +176 -0
  39. package/dist/kalada-v1/evaluate.cjs.map +1 -0
  40. package/dist/kalada-v1/evaluate.d.cts +8 -0
  41. package/dist/kalada-v1/evaluate.d.ts +8 -0
  42. package/dist/kalada-v1/evaluate.js +174 -0
  43. package/dist/kalada-v1/evaluate.js.map +1 -0
  44. package/dist/kalada-v1/factories.cjs +66 -0
  45. package/dist/kalada-v1/factories.cjs.map +1 -0
  46. package/dist/kalada-v1/factories.d.cts +30 -0
  47. package/dist/kalada-v1/factories.d.ts +30 -0
  48. package/dist/kalada-v1/factories.js +64 -0
  49. package/dist/kalada-v1/factories.js.map +1 -0
  50. package/dist/kalada-v1/index.cjs +88 -0
  51. package/dist/kalada-v1/index.cjs.map +1 -0
  52. package/dist/kalada-v1/index.d.cts +11 -0
  53. package/dist/kalada-v1/index.d.ts +11 -0
  54. package/dist/kalada-v1/index.js +11 -0
  55. package/dist/kalada-v1/index.js.map +1 -0
  56. package/dist/kalada-v1/json.cjs +129 -0
  57. package/dist/kalada-v1/json.cjs.map +1 -0
  58. package/dist/kalada-v1/json.d.cts +20 -0
  59. package/dist/kalada-v1/json.d.ts +20 -0
  60. package/dist/kalada-v1/json.js +123 -0
  61. package/dist/kalada-v1/json.js.map +1 -0
  62. package/dist/kalada-v1/limits.cjs +34 -0
  63. package/dist/kalada-v1/limits.cjs.map +1 -0
  64. package/dist/kalada-v1/limits.d.cts +9 -0
  65. package/dist/kalada-v1/limits.d.ts +9 -0
  66. package/dist/kalada-v1/limits.js +31 -0
  67. package/dist/kalada-v1/limits.js.map +1 -0
  68. package/dist/kalada-v1/schemas.cjs +182 -0
  69. package/dist/kalada-v1/schemas.cjs.map +1 -0
  70. package/dist/kalada-v1/schemas.d.cts +5 -0
  71. package/dist/kalada-v1/schemas.d.ts +5 -0
  72. package/dist/kalada-v1/schemas.js +179 -0
  73. package/dist/kalada-v1/schemas.js.map +1 -0
  74. package/dist/kalada-v1/temporal-evaluation.cjs +74 -0
  75. package/dist/kalada-v1/temporal-evaluation.cjs.map +1 -0
  76. package/dist/kalada-v1/temporal-evaluation.d.cts +13 -0
  77. package/dist/kalada-v1/temporal-evaluation.d.ts +13 -0
  78. package/dist/kalada-v1/temporal-evaluation.js +71 -0
  79. package/dist/kalada-v1/temporal-evaluation.js.map +1 -0
  80. package/dist/kalada-v1/temporal.cjs +42 -0
  81. package/dist/kalada-v1/temporal.cjs.map +1 -0
  82. package/dist/kalada-v1/temporal.d.cts +22 -0
  83. package/dist/kalada-v1/temporal.d.ts +22 -0
  84. package/dist/kalada-v1/temporal.js +37 -0
  85. package/dist/kalada-v1/temporal.js.map +1 -0
  86. package/dist/kalada-v1/types.cjs +4 -0
  87. package/dist/kalada-v1/types.cjs.map +1 -0
  88. package/dist/kalada-v1/types.d.cts +120 -0
  89. package/dist/kalada-v1/types.d.ts +120 -0
  90. package/dist/kalada-v1/types.js +3 -0
  91. package/dist/kalada-v1/types.js.map +1 -0
  92. package/dist/kalada-v1/values.cjs +112 -0
  93. package/dist/kalada-v1/values.cjs.map +1 -0
  94. package/dist/kalada-v1/values.d.cts +49 -0
  95. package/dist/kalada-v1/values.d.ts +49 -0
  96. package/dist/kalada-v1/values.js +105 -0
  97. package/dist/kalada-v1/values.js.map +1 -0
  98. package/package.json +11 -1
package/README.md CHANGED
@@ -8,3 +8,28 @@ scheduling semantics.
8
8
  The exact Kuery 2.1 strict-expression compatibility API is available only from
9
9
  `@kalada/core/kuery-v1`. Provenance is recorded in the shipped `provenance/kuery-2.1.0.json`, and
10
10
  third-party license declarations are reproduced in `THIRD_PARTY_NOTICES.md`.
11
+
12
+ ## Native `kalada-v1` profile
13
+
14
+ `@kalada/core/kalada-v1` is an additive, dependency-free native profile. It provides private
15
+ WeakSet-branded `Option`/`Result` runtime values, explicit `kalada-value` v1 encoding, canonical
16
+ program constructors and schemas, and a bounded compiler/evaluator. JSON values remain opaque:
17
+ only `decodeKaladaValue` decodes an encoded envelope, and every JSON value is wrapped in a `Json`
18
+ envelope so a discriminant-shaped object round-trips as ordinary JSON.
19
+
20
+ ```ts
21
+ import { KaladaV1, compileKaladaV1Program } from "@kalada/core/kalada-v1";
22
+
23
+ const expression = KaladaV1.match("Option", KaladaV1.Option.some(KaladaV1.literal("Ada")), [
24
+ KaladaV1.arm("some", KaladaV1.ref("name"), "name"),
25
+ KaladaV1.arm("none", KaladaV1.literal("unknown")),
26
+ ]);
27
+ const compiled = compileKaladaV1Program(KaladaV1.program(expression));
28
+ const value = compiled.ok ? compiled.value.evaluate(() => ({ found: false })) : compiled;
29
+ ```
30
+
31
+ Matches are limited to exactly two canonical arms: `some`, `none` for Option and `ok`, `err` for
32
+ Result. There are no guards or fallthrough. Bindings are lexical: an initializer is evaluated in
33
+ the outer scope, a body may shadow an outer binding, and only the selected match arm is evaluated.
34
+ Each evaluated expression node costs one step. Runtime ADT identity never survives object copying
35
+ or JSON serialization; use `encodeKaladaValue`/`decodeKaladaValue` at an interchange boundary.
@@ -0,0 +1,133 @@
1
+ 'use strict';
2
+
3
+ var diagnostics_js = require('./diagnostics.js');
4
+ var json_js = require('./json.js');
5
+
6
+ function properties(input, path, allowed, requireExact = true) {
7
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
8
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
9
+ }
10
+ let keys;
11
+ try {
12
+ keys = Reflect.ownKeys(input);
13
+ } catch {
14
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
15
+ }
16
+ const output = {};
17
+ for (const key of keys) {
18
+ if (typeof key !== "string" || !allowed.has(key)) {
19
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, String(key)]);
20
+ }
21
+ try {
22
+ output[key] = json_js.dataValue(input, key);
23
+ } catch {
24
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
25
+ }
26
+ }
27
+ if (requireExact && keys.length !== allowed.size) {
28
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
29
+ }
30
+ return output;
31
+ }
32
+ function exact(raw, path, keys, optionalLast = false) {
33
+ const minimum = optionalLast ? keys.length - 1 : keys.length;
34
+ if (Object.keys(raw).length < minimum || Object.keys(raw).length > keys.length) {
35
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
36
+ }
37
+ for (let index = 0; index < minimum; index += 1) {
38
+ const key = keys[index];
39
+ if (key !== void 0 && !(key in raw)) {
40
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
41
+ }
42
+ }
43
+ for (const key of Object.keys(raw)) {
44
+ if (!keys.includes(key)) throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
45
+ }
46
+ }
47
+ function strictArray(input, path) {
48
+ let keys;
49
+ try {
50
+ keys = Reflect.ownKeys(input);
51
+ } catch {
52
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
53
+ }
54
+ if (keys.length !== input.length + 1) throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
55
+ return Array.from({ length: input.length }, (_, index) => {
56
+ try {
57
+ return json_js.dataValue(input, String(index));
58
+ } catch {
59
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, index]);
60
+ }
61
+ });
62
+ }
63
+ function safeJson(input, path, state) {
64
+ try {
65
+ const result = json_js.cloneJsonWithStats(input, {
66
+ maxDepth: state.limits.maxValueDepth,
67
+ maxNodes: state.limits.maxValueNodes - state.valueNodes,
68
+ maxStringLength: state.limits.maxStringLength
69
+ });
70
+ state.valueNodes += result.nodes;
71
+ return result.value;
72
+ } catch (error) {
73
+ if (error instanceof RangeError) throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
74
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
75
+ }
76
+ }
77
+ function inspectJson(input, path, state) {
78
+ try {
79
+ return json_js.cloneJson(input, {
80
+ maxDepth: state.limits.maxValueDepth,
81
+ maxNodes: state.limits.maxValueNodes,
82
+ maxStringLength: state.limits.maxStringLength
83
+ });
84
+ } catch (error) {
85
+ if (error instanceof RangeError) throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
86
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
87
+ }
88
+ }
89
+ function referenceLength(reference) {
90
+ return typeof reference === "string" ? [...reference].length : [...json_js.canonicalJsonIdentity(reference)].length;
91
+ }
92
+ function bindingName(input, path, limits) {
93
+ if (typeof input !== "string" || input.length === 0) {
94
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
95
+ }
96
+ if ([...input].length > limits.maxReferenceLength) {
97
+ throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
98
+ }
99
+ return input;
100
+ }
101
+ function safeValidate(validate, input) {
102
+ try {
103
+ return validate(input) === true;
104
+ } catch {
105
+ return false;
106
+ }
107
+ }
108
+ function safeCanonicalize(canonicalize, input, path) {
109
+ try {
110
+ return canonicalize(input);
111
+ } catch {
112
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_REFERENCE", path);
113
+ }
114
+ }
115
+ function count(path, depth, state) {
116
+ state.astNodes += 1;
117
+ if (depth > state.limits.maxAstDepth || state.astNodes > state.limits.maxAstNodes) {
118
+ throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
119
+ }
120
+ }
121
+
122
+ exports.bindingName = bindingName;
123
+ exports.count = count;
124
+ exports.exact = exact;
125
+ exports.inspectJson = inspectJson;
126
+ exports.properties = properties;
127
+ exports.referenceLength = referenceLength;
128
+ exports.safeCanonicalize = safeCanonicalize;
129
+ exports.safeJson = safeJson;
130
+ exports.safeValidate = safeValidate;
131
+ exports.strictArray = strictArray;
132
+ //# sourceMappingURL=canonical-input.cjs.map
133
+ //# sourceMappingURL=canonical-input.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/kalada-v1/canonical-input.ts"],"names":["KaladaFailure","dataValue","cloneJsonWithStats","cloneJson","canonicalJsonIdentity"],"mappings":"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","file":"canonical-input.cjs","sourcesContent":["import { KaladaFailure } from \"./diagnostics.js\";\nimport {\n canonicalJsonIdentity,\n cloneJson,\n cloneJsonWithStats,\n dataValue,\n type JsonValue,\n} from \"./json.js\";\nimport type { KaladaV1Limits, KaladaV1Options } from \"./types.js\";\n\nexport type Path = readonly (string | number)[];\nexport interface CanonicalState<R extends JsonValue> {\n readonly limits: KaladaV1Limits;\n readonly options: KaladaV1Options<R>;\n readonly active: WeakSet<object>;\n astNodes: number;\n valueNodes: number;\n}\n\nexport function properties(\n input: unknown,\n path: Path,\n allowed: ReadonlySet<string>,\n requireExact = true,\n): Record<string, unknown> {\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n let keys: PropertyKey[];\n try {\n keys = Reflect.ownKeys(input);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n const output: Record<string, unknown> = {};\n for (const key of keys) {\n if (typeof key !== \"string\" || !allowed.has(key)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, String(key)]);\n }\n try {\n output[key] = dataValue(input, key);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, key]);\n }\n }\n if (requireExact && keys.length !== allowed.size) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n return output;\n}\n\nexport function exact(\n raw: Record<string, unknown>,\n path: Path,\n keys: readonly string[],\n optionalLast = false,\n): void {\n const minimum = optionalLast ? keys.length - 1 : keys.length;\n if (Object.keys(raw).length < minimum || Object.keys(raw).length > keys.length) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n for (let index = 0; index < minimum; index += 1) {\n const key = keys[index];\n if (key !== undefined && !(key in raw)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, key]);\n }\n }\n for (const key of Object.keys(raw)) {\n if (!keys.includes(key)) throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, key]);\n }\n}\n\nexport function strictArray(input: unknown[], path: Path): unknown[] {\n let keys: PropertyKey[];\n try {\n keys = Reflect.ownKeys(input);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n if (keys.length !== input.length + 1) throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n return Array.from({ length: input.length }, (_, index) => {\n try {\n return dataValue(input, String(index));\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, index]);\n }\n });\n}\n\nexport function safeJson<R extends JsonValue>(\n input: unknown,\n path: Path,\n state: CanonicalState<R>,\n): JsonValue {\n try {\n const result = cloneJsonWithStats(input, {\n maxDepth: state.limits.maxValueDepth,\n maxNodes: state.limits.maxValueNodes - state.valueNodes,\n maxStringLength: state.limits.maxStringLength,\n });\n state.valueNodes += result.nodes;\n return result.value;\n } catch (error) {\n if (error instanceof RangeError) throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n}\n\nexport function inspectJson<R extends JsonValue>(\n input: unknown,\n path: Path,\n state: CanonicalState<R>,\n): JsonValue {\n try {\n return cloneJson(input, {\n maxDepth: state.limits.maxValueDepth,\n maxNodes: state.limits.maxValueNodes,\n maxStringLength: state.limits.maxStringLength,\n });\n } catch (error) {\n if (error instanceof RangeError) throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n}\n\nexport function referenceLength(reference: JsonValue): number {\n return typeof reference === \"string\"\n ? [...reference].length\n : [...canonicalJsonIdentity(reference)].length;\n}\n\nexport function bindingName(input: unknown, path: Path, limits: KaladaV1Limits): string {\n if (typeof input !== \"string\" || input.length === 0) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n if ([...input].length > limits.maxReferenceLength) {\n throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n }\n return input;\n}\n\nexport function safeValidate<R>(\n validate: (input: unknown) => input is R,\n input: unknown,\n): input is R {\n try {\n return validate(input) === true;\n } catch {\n return false;\n }\n}\n\nexport function safeCanonicalize<R>(canonicalize: (input: R) => R, input: R, path: Path): R {\n try {\n return canonicalize(input);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_REFERENCE\", path);\n }\n}\n\nexport function count<R extends JsonValue>(\n path: Path,\n depth: number,\n state: CanonicalState<R>,\n): void {\n state.astNodes += 1;\n if (depth > state.limits.maxAstDepth || state.astNodes > state.limits.maxAstNodes) {\n throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import { JsonValue } from './json.cjs';
2
+ import { KaladaV1Limits, KaladaV1Options } from './types.cjs';
3
+ import './temporal.cjs';
4
+ import './values.cjs';
5
+
6
+ type Path = readonly (string | number)[];
7
+ interface CanonicalState<R extends JsonValue> {
8
+ readonly limits: KaladaV1Limits;
9
+ readonly options: KaladaV1Options<R>;
10
+ readonly active: WeakSet<object>;
11
+ astNodes: number;
12
+ valueNodes: number;
13
+ }
14
+ declare function properties(input: unknown, path: Path, allowed: ReadonlySet<string>, requireExact?: boolean): Record<string, unknown>;
15
+ declare function exact(raw: Record<string, unknown>, path: Path, keys: readonly string[], optionalLast?: boolean): void;
16
+ declare function strictArray(input: unknown[], path: Path): unknown[];
17
+ declare function safeJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
18
+ declare function inspectJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
19
+ declare function referenceLength(reference: JsonValue): number;
20
+ declare function bindingName(input: unknown, path: Path, limits: KaladaV1Limits): string;
21
+ declare function safeValidate<R>(validate: (input: unknown) => input is R, input: unknown): input is R;
22
+ declare function safeCanonicalize<R>(canonicalize: (input: R) => R, input: R, path: Path): R;
23
+ declare function count<R extends JsonValue>(path: Path, depth: number, state: CanonicalState<R>): void;
24
+
25
+ export { type CanonicalState, type Path, bindingName, count, exact, inspectJson, properties, referenceLength, safeCanonicalize, safeJson, safeValidate, strictArray };
@@ -0,0 +1,25 @@
1
+ import { JsonValue } from './json.js';
2
+ import { KaladaV1Limits, KaladaV1Options } from './types.js';
3
+ import './temporal.js';
4
+ import './values.js';
5
+
6
+ type Path = readonly (string | number)[];
7
+ interface CanonicalState<R extends JsonValue> {
8
+ readonly limits: KaladaV1Limits;
9
+ readonly options: KaladaV1Options<R>;
10
+ readonly active: WeakSet<object>;
11
+ astNodes: number;
12
+ valueNodes: number;
13
+ }
14
+ declare function properties(input: unknown, path: Path, allowed: ReadonlySet<string>, requireExact?: boolean): Record<string, unknown>;
15
+ declare function exact(raw: Record<string, unknown>, path: Path, keys: readonly string[], optionalLast?: boolean): void;
16
+ declare function strictArray(input: unknown[], path: Path): unknown[];
17
+ declare function safeJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
18
+ declare function inspectJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
19
+ declare function referenceLength(reference: JsonValue): number;
20
+ declare function bindingName(input: unknown, path: Path, limits: KaladaV1Limits): string;
21
+ declare function safeValidate<R>(validate: (input: unknown) => input is R, input: unknown): input is R;
22
+ declare function safeCanonicalize<R>(canonicalize: (input: R) => R, input: R, path: Path): R;
23
+ declare function count<R extends JsonValue>(path: Path, depth: number, state: CanonicalState<R>): void;
24
+
25
+ export { type CanonicalState, type Path, bindingName, count, exact, inspectJson, properties, referenceLength, safeCanonicalize, safeJson, safeValidate, strictArray };
@@ -0,0 +1,122 @@
1
+ import { KaladaFailure } from './diagnostics.js';
2
+ import { dataValue, cloneJsonWithStats, cloneJson, canonicalJsonIdentity } from './json.js';
3
+
4
+ function properties(input, path, allowed, requireExact = true) {
5
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
6
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
7
+ }
8
+ let keys;
9
+ try {
10
+ keys = Reflect.ownKeys(input);
11
+ } catch {
12
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
13
+ }
14
+ const output = {};
15
+ for (const key of keys) {
16
+ if (typeof key !== "string" || !allowed.has(key)) {
17
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, String(key)]);
18
+ }
19
+ try {
20
+ output[key] = dataValue(input, key);
21
+ } catch {
22
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
23
+ }
24
+ }
25
+ if (requireExact && keys.length !== allowed.size) {
26
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
27
+ }
28
+ return output;
29
+ }
30
+ function exact(raw, path, keys, optionalLast = false) {
31
+ const minimum = optionalLast ? keys.length - 1 : keys.length;
32
+ if (Object.keys(raw).length < minimum || Object.keys(raw).length > keys.length) {
33
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
34
+ }
35
+ for (let index = 0; index < minimum; index += 1) {
36
+ const key = keys[index];
37
+ if (key !== void 0 && !(key in raw)) {
38
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
39
+ }
40
+ }
41
+ for (const key of Object.keys(raw)) {
42
+ if (!keys.includes(key)) throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
43
+ }
44
+ }
45
+ function strictArray(input, path) {
46
+ let keys;
47
+ try {
48
+ keys = Reflect.ownKeys(input);
49
+ } catch {
50
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
51
+ }
52
+ if (keys.length !== input.length + 1) throw new KaladaFailure("KALADA_INVALID_INPUT", path);
53
+ return Array.from({ length: input.length }, (_, index) => {
54
+ try {
55
+ return dataValue(input, String(index));
56
+ } catch {
57
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, index]);
58
+ }
59
+ });
60
+ }
61
+ function safeJson(input, path, state) {
62
+ try {
63
+ const result = cloneJsonWithStats(input, {
64
+ maxDepth: state.limits.maxValueDepth,
65
+ maxNodes: state.limits.maxValueNodes - state.valueNodes,
66
+ maxStringLength: state.limits.maxStringLength
67
+ });
68
+ state.valueNodes += result.nodes;
69
+ return result.value;
70
+ } catch (error) {
71
+ if (error instanceof RangeError) throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
72
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
73
+ }
74
+ }
75
+ function inspectJson(input, path, state) {
76
+ try {
77
+ return cloneJson(input, {
78
+ maxDepth: state.limits.maxValueDepth,
79
+ maxNodes: state.limits.maxValueNodes,
80
+ maxStringLength: state.limits.maxStringLength
81
+ });
82
+ } catch (error) {
83
+ if (error instanceof RangeError) throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
84
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
85
+ }
86
+ }
87
+ function referenceLength(reference) {
88
+ return typeof reference === "string" ? [...reference].length : [...canonicalJsonIdentity(reference)].length;
89
+ }
90
+ function bindingName(input, path, limits) {
91
+ if (typeof input !== "string" || input.length === 0) {
92
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
93
+ }
94
+ if ([...input].length > limits.maxReferenceLength) {
95
+ throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
96
+ }
97
+ return input;
98
+ }
99
+ function safeValidate(validate, input) {
100
+ try {
101
+ return validate(input) === true;
102
+ } catch {
103
+ return false;
104
+ }
105
+ }
106
+ function safeCanonicalize(canonicalize, input, path) {
107
+ try {
108
+ return canonicalize(input);
109
+ } catch {
110
+ throw new KaladaFailure("KALADA_INVALID_REFERENCE", path);
111
+ }
112
+ }
113
+ function count(path, depth, state) {
114
+ state.astNodes += 1;
115
+ if (depth > state.limits.maxAstDepth || state.astNodes > state.limits.maxAstNodes) {
116
+ throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
117
+ }
118
+ }
119
+
120
+ export { bindingName, count, exact, inspectJson, properties, referenceLength, safeCanonicalize, safeJson, safeValidate, strictArray };
121
+ //# sourceMappingURL=canonical-input.js.map
122
+ //# sourceMappingURL=canonical-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/kalada-v1/canonical-input.ts"],"names":[],"mappings":"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","file":"canonical-input.js","sourcesContent":["import { KaladaFailure } from \"./diagnostics.js\";\nimport {\n canonicalJsonIdentity,\n cloneJson,\n cloneJsonWithStats,\n dataValue,\n type JsonValue,\n} from \"./json.js\";\nimport type { KaladaV1Limits, KaladaV1Options } from \"./types.js\";\n\nexport type Path = readonly (string | number)[];\nexport interface CanonicalState<R extends JsonValue> {\n readonly limits: KaladaV1Limits;\n readonly options: KaladaV1Options<R>;\n readonly active: WeakSet<object>;\n astNodes: number;\n valueNodes: number;\n}\n\nexport function properties(\n input: unknown,\n path: Path,\n allowed: ReadonlySet<string>,\n requireExact = true,\n): Record<string, unknown> {\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n let keys: PropertyKey[];\n try {\n keys = Reflect.ownKeys(input);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n const output: Record<string, unknown> = {};\n for (const key of keys) {\n if (typeof key !== \"string\" || !allowed.has(key)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, String(key)]);\n }\n try {\n output[key] = dataValue(input, key);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, key]);\n }\n }\n if (requireExact && keys.length !== allowed.size) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n return output;\n}\n\nexport function exact(\n raw: Record<string, unknown>,\n path: Path,\n keys: readonly string[],\n optionalLast = false,\n): void {\n const minimum = optionalLast ? keys.length - 1 : keys.length;\n if (Object.keys(raw).length < minimum || Object.keys(raw).length > keys.length) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n for (let index = 0; index < minimum; index += 1) {\n const key = keys[index];\n if (key !== undefined && !(key in raw)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, key]);\n }\n }\n for (const key of Object.keys(raw)) {\n if (!keys.includes(key)) throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, key]);\n }\n}\n\nexport function strictArray(input: unknown[], path: Path): unknown[] {\n let keys: PropertyKey[];\n try {\n keys = Reflect.ownKeys(input);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n if (keys.length !== input.length + 1) throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n return Array.from({ length: input.length }, (_, index) => {\n try {\n return dataValue(input, String(index));\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, index]);\n }\n });\n}\n\nexport function safeJson<R extends JsonValue>(\n input: unknown,\n path: Path,\n state: CanonicalState<R>,\n): JsonValue {\n try {\n const result = cloneJsonWithStats(input, {\n maxDepth: state.limits.maxValueDepth,\n maxNodes: state.limits.maxValueNodes - state.valueNodes,\n maxStringLength: state.limits.maxStringLength,\n });\n state.valueNodes += result.nodes;\n return result.value;\n } catch (error) {\n if (error instanceof RangeError) throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n}\n\nexport function inspectJson<R extends JsonValue>(\n input: unknown,\n path: Path,\n state: CanonicalState<R>,\n): JsonValue {\n try {\n return cloneJson(input, {\n maxDepth: state.limits.maxValueDepth,\n maxNodes: state.limits.maxValueNodes,\n maxStringLength: state.limits.maxStringLength,\n });\n } catch (error) {\n if (error instanceof RangeError) throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n}\n\nexport function referenceLength(reference: JsonValue): number {\n return typeof reference === \"string\"\n ? [...reference].length\n : [...canonicalJsonIdentity(reference)].length;\n}\n\nexport function bindingName(input: unknown, path: Path, limits: KaladaV1Limits): string {\n if (typeof input !== \"string\" || input.length === 0) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n if ([...input].length > limits.maxReferenceLength) {\n throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n }\n return input;\n}\n\nexport function safeValidate<R>(\n validate: (input: unknown) => input is R,\n input: unknown,\n): input is R {\n try {\n return validate(input) === true;\n } catch {\n return false;\n }\n}\n\nexport function safeCanonicalize<R>(canonicalize: (input: R) => R, input: R, path: Path): R {\n try {\n return canonicalize(input);\n } catch {\n throw new KaladaFailure(\"KALADA_INVALID_REFERENCE\", path);\n }\n}\n\nexport function count<R extends JsonValue>(\n path: Path,\n depth: number,\n state: CanonicalState<R>,\n): void {\n state.astNodes += 1;\n if (depth > state.limits.maxAstDepth || state.astNodes > state.limits.maxAstNodes) {\n throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n }\n}\n"]}
@@ -0,0 +1,214 @@
1
+ 'use strict';
2
+
3
+ var canonicalInput_js = require('./canonical-input.js');
4
+ var diagnostics_js = require('./diagnostics.js');
5
+ var limits_js = require('./limits.js');
6
+
7
+ const NODE_KEYS = /* @__PURE__ */ new Set([
8
+ "kind",
9
+ "value",
10
+ "ref",
11
+ "name",
12
+ "body",
13
+ "variant",
14
+ "type",
15
+ "arms",
16
+ "milliseconds",
17
+ "operator",
18
+ "left",
19
+ "right"
20
+ ]);
21
+ const ARM_ORDER = Object.freeze({ Option: ["some", "none"], Result: ["ok", "err"] });
22
+ function canonicalizeKaladaV1Program(input, options = {}) {
23
+ try {
24
+ const limits = limits_js.resolveLimits(options.limits);
25
+ const fields = canonicalInput_js.properties(input, [], /* @__PURE__ */ new Set(["format", "version", "profile", "expression"]));
26
+ if (fields.format !== "kalada-program" || fields.version !== 1 || fields.profile !== "kalada-v1") {
27
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", []);
28
+ }
29
+ const state = {
30
+ limits,
31
+ options,
32
+ active: /* @__PURE__ */ new WeakSet(),
33
+ astNodes: 0,
34
+ valueNodes: 0
35
+ };
36
+ const expression = canonicalNode(fields.expression, ["expression"], 0, state);
37
+ return diagnostics_js.success(
38
+ Object.freeze({ format: "kalada-program", version: 1, profile: "kalada-v1", expression })
39
+ );
40
+ } catch (error) {
41
+ const problem = error instanceof diagnostics_js.KaladaFailure ? error : new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", []);
42
+ return diagnostics_js.failure(problem.code, problem.path);
43
+ }
44
+ }
45
+ function canonicalNode(input, path, depth, state) {
46
+ canonicalInput_js.count(path, depth, state);
47
+ if (typeof input !== "object" || input === null || state.active.has(input)) {
48
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
49
+ }
50
+ state.active.add(input);
51
+ try {
52
+ const raw = canonicalInput_js.properties(input, path, NODE_KEYS, false);
53
+ if (raw.kind === "literal") return canonicalLiteral(raw, path, state);
54
+ if (raw.kind === "ref") return canonicalReference(raw, path, state);
55
+ if (raw.kind === "binding") return canonicalBinding(raw, path, depth, state);
56
+ if (raw.kind === "option") return canonicalOption(raw, path, depth, state);
57
+ if (raw.kind === "result") return canonicalResult(raw, path, depth, state);
58
+ if (raw.kind === "match") return canonicalMatch(raw, path, depth, state);
59
+ if (raw.kind === "instant" || raw.kind === "duration") return canonicalTemporal(raw, path);
60
+ if (raw.kind === "current-instant") return canonicalCurrentInstant(raw, path);
61
+ if (raw.kind === "temporal-arithmetic") {
62
+ return canonicalTemporalOperation(raw, path, depth, state, ["add", "subtract"]);
63
+ }
64
+ if (raw.kind === "temporal-comparison") {
65
+ return canonicalTemporalOperation(raw, path, depth, state, [
66
+ "equal",
67
+ "not-equal",
68
+ "less-than",
69
+ "less-than-or-equal",
70
+ "greater-than",
71
+ "greater-than-or-equal"
72
+ ]);
73
+ }
74
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "kind"]);
75
+ } finally {
76
+ state.active.delete(input);
77
+ }
78
+ }
79
+ function canonicalTemporal(raw, path) {
80
+ canonicalInput_js.exact(raw, path, ["kind", "milliseconds"]);
81
+ if (!Number.isSafeInteger(raw.milliseconds)) {
82
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "milliseconds"]);
83
+ }
84
+ return Object.freeze({
85
+ kind: raw.kind,
86
+ milliseconds: Object.is(raw.milliseconds, -0) ? 0 : raw.milliseconds
87
+ });
88
+ }
89
+ function canonicalCurrentInstant(raw, path) {
90
+ canonicalInput_js.exact(raw, path, ["kind"]);
91
+ return Object.freeze({ kind: "current-instant" });
92
+ }
93
+ function canonicalTemporalOperation(raw, path, depth, state, operators) {
94
+ canonicalInput_js.exact(raw, path, ["kind", "operator", "left", "right"]);
95
+ if (typeof raw.operator !== "string" || !operators.includes(raw.operator)) {
96
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "operator"]);
97
+ }
98
+ return Object.freeze({
99
+ kind: raw.kind,
100
+ operator: raw.operator,
101
+ left: canonicalNode(raw.left, [...path, "left"], depth + 1, state),
102
+ right: canonicalNode(raw.right, [...path, "right"], depth + 1, state)
103
+ });
104
+ }
105
+ function canonicalLiteral(raw, path, state) {
106
+ canonicalInput_js.exact(raw, path, ["kind", "value"]);
107
+ return Object.freeze({
108
+ kind: "literal",
109
+ value: canonicalInput_js.safeJson(raw.value, [...path, "value"], state)
110
+ });
111
+ }
112
+ function canonicalReference(raw, path, state) {
113
+ canonicalInput_js.exact(raw, path, ["kind", "ref"]);
114
+ const refPath = [...path, "ref"];
115
+ const codec = state.options.reference;
116
+ const ref = codec ? canonicalInput_js.inspectJson(raw.ref, refPath, state) : canonicalInput_js.safeJson(raw.ref, refPath, state);
117
+ if (codec ? !canonicalInput_js.safeValidate(codec.validate, ref) : typeof ref !== "string" || ref.length === 0) {
118
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_REFERENCE", refPath);
119
+ }
120
+ const replacement = codec?.canonicalize ? canonicalInput_js.safeCanonicalize(codec.canonicalize, ref, refPath) : ref;
121
+ const output = codec ? canonicalInput_js.safeJson(replacement, refPath, state) : replacement;
122
+ if (codec && !canonicalInput_js.safeValidate(codec.validate, output))
123
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_REFERENCE", refPath);
124
+ if (canonicalInput_js.referenceLength(output) > state.limits.maxReferenceLength)
125
+ throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", refPath);
126
+ return Object.freeze({ kind: "ref", ref: output });
127
+ }
128
+ function canonicalBinding(raw, path, depth, state) {
129
+ canonicalInput_js.exact(raw, path, ["kind", "name", "value", "body"]);
130
+ const name = canonicalInput_js.bindingName(raw.name, [...path, "name"], state.limits);
131
+ return Object.freeze({
132
+ kind: "binding",
133
+ name,
134
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state),
135
+ body: canonicalNode(raw.body, [...path, "body"], depth + 1, state)
136
+ });
137
+ }
138
+ function canonicalOption(raw, path, depth, state) {
139
+ if (raw.variant === "none") {
140
+ canonicalInput_js.exact(raw, path, ["kind", "variant"]);
141
+ return Object.freeze({ kind: "option", variant: "none" });
142
+ }
143
+ if (raw.variant !== "some") throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "variant"]);
144
+ canonicalInput_js.exact(raw, path, ["kind", "variant", "value"]);
145
+ return Object.freeze({
146
+ kind: "option",
147
+ variant: "some",
148
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state)
149
+ });
150
+ }
151
+ function canonicalResult(raw, path, depth, state) {
152
+ if (raw.variant !== "ok" && raw.variant !== "err")
153
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "variant"]);
154
+ canonicalInput_js.exact(raw, path, ["kind", "variant", "value"]);
155
+ return Object.freeze({
156
+ kind: "result",
157
+ variant: raw.variant,
158
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state)
159
+ });
160
+ }
161
+ function canonicalMatch(raw, path, depth, state) {
162
+ canonicalInput_js.exact(raw, path, ["kind", "type", "value", "arms"]);
163
+ if (raw.type !== "Option" && raw.type !== "Result")
164
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "type"]);
165
+ const value = canonicalNode(raw.value, [...path, "value"], depth + 1, state);
166
+ const arms = canonicalArms(raw.arms, raw.type, path, depth, state);
167
+ return Object.freeze({ kind: "match", type: raw.type, value, arms });
168
+ }
169
+ function canonicalArms(input, type, path, depth, state) {
170
+ if (!Array.isArray(input)) throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "arms"]);
171
+ const entries = canonicalInput_js.strictArray(input, [...path, "arms"]);
172
+ const expected = ARM_ORDER[type];
173
+ const found = /* @__PURE__ */ new Map();
174
+ entries.forEach((entry, index) => {
175
+ addArm(entry, index, type, expected, found, path, depth, state);
176
+ });
177
+ if (found.size !== expected.length)
178
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_MISSING_ARM", [...path, "arms"]);
179
+ return Object.freeze(expected.map((variant) => requiredArm(found, variant, path)));
180
+ }
181
+ function addArm(input, index, type, expected, found, path, depth, state) {
182
+ const armPath = [...path, "arms", index];
183
+ const raw = canonicalInput_js.properties(input, armPath, /* @__PURE__ */ new Set(["variant", "binding", "body"]), false);
184
+ if (found.size === expected.length)
185
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_UNREACHABLE_ARM", armPath);
186
+ if (typeof raw.variant !== "string" || !expected.includes(raw.variant))
187
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_UNKNOWN_ARM", [...armPath, "variant"]);
188
+ if (found.has(raw.variant))
189
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_DUPLICATE_ARM", [...armPath, "variant"]);
190
+ const allowsBinding = raw.variant !== "none";
191
+ if (!allowsBinding && "binding" in raw)
192
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...armPath, "binding"]);
193
+ canonicalInput_js.exact(
194
+ raw,
195
+ armPath,
196
+ allowsBinding ? ["variant", "body", "binding"] : ["variant", "body"],
197
+ allowsBinding
198
+ );
199
+ const binding = raw.binding === void 0 ? void 0 : canonicalInput_js.bindingName(raw.binding, [...armPath, "binding"], state.limits);
200
+ const body = canonicalNode(raw.body, [...armPath, "body"], depth + 1, state);
201
+ found.set(
202
+ raw.variant,
203
+ Object.freeze({ variant: raw.variant, ...binding ? { binding } : {}, body })
204
+ );
205
+ }
206
+ function requiredArm(found, variant, path) {
207
+ const arm = found.get(variant);
208
+ if (!arm) throw new diagnostics_js.KaladaFailure("KALADA_MATCH_MISSING_ARM", [...path, "arms"]);
209
+ return arm;
210
+ }
211
+
212
+ exports.canonicalizeKaladaV1Program = canonicalizeKaladaV1Program;
213
+ //# sourceMappingURL=canonicalize.cjs.map
214
+ //# sourceMappingURL=canonicalize.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/kalada-v1/canonicalize.ts"],"names":["resolveLimits","properties","KaladaFailure","success","failure","count","exact","safeJson","inspectJson","safeValidate","safeCanonicalize","referenceLength","bindingName","strictArray"],"mappings":"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","file":"canonicalize.cjs","sourcesContent":["import {\n bindingName,\n count,\n exact,\n inspectJson,\n type Path,\n properties,\n referenceLength,\n type CanonicalState as State,\n safeCanonicalize,\n safeJson,\n safeValidate,\n strictArray,\n} from \"./canonical-input.js\";\nimport { failure, KaladaFailure, success } from \"./diagnostics.js\";\nimport type { JsonValue } from \"./json.js\";\nimport { resolveLimits } from \"./limits.js\";\nimport type {\n KaladaV1Expression,\n KaladaV1Options,\n KaladaV1Outcome,\n KaladaV1Program,\n MatchArm,\n} from \"./types.js\";\n\nconst NODE_KEYS = new Set([\n \"kind\",\n \"value\",\n \"ref\",\n \"name\",\n \"body\",\n \"variant\",\n \"type\",\n \"arms\",\n \"milliseconds\",\n \"operator\",\n \"left\",\n \"right\",\n]);\nconst ARM_ORDER = Object.freeze({ Option: [\"some\", \"none\"], Result: [\"ok\", \"err\"] } as const);\n\nexport function canonicalizeKaladaV1Program<R extends JsonValue = string>(\n input: unknown,\n options: KaladaV1Options<R> = {},\n): KaladaV1Outcome<KaladaV1Program<R>> {\n try {\n const limits = resolveLimits(options.limits);\n const fields = properties(input, [], new Set([\"format\", \"version\", \"profile\", \"expression\"]));\n if (\n fields.format !== \"kalada-program\" ||\n fields.version !== 1 ||\n fields.profile !== \"kalada-v1\"\n ) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", []);\n }\n const state: State<R> = {\n limits,\n options,\n active: new WeakSet(),\n astNodes: 0,\n valueNodes: 0,\n };\n const expression = canonicalNode(fields.expression, [\"expression\"], 0, state);\n return success(\n Object.freeze({ format: \"kalada-program\", version: 1, profile: \"kalada-v1\", expression }),\n );\n } catch (error) {\n const problem =\n error instanceof KaladaFailure ? error : new KaladaFailure(\"KALADA_INVALID_INPUT\", []);\n return failure(problem.code, problem.path);\n }\n}\n\nfunction canonicalNode<R extends JsonValue>(\n input: unknown,\n path: Path,\n depth: number,\n state: State<R>,\n): KaladaV1Expression<R> {\n count(path, depth, state);\n if (typeof input !== \"object\" || input === null || state.active.has(input)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", path);\n }\n state.active.add(input);\n try {\n const raw = properties(input, path, NODE_KEYS, false);\n if (raw.kind === \"literal\") return canonicalLiteral(raw, path, state);\n if (raw.kind === \"ref\") return canonicalReference(raw, path, state);\n if (raw.kind === \"binding\") return canonicalBinding(raw, path, depth, state);\n if (raw.kind === \"option\") return canonicalOption(raw, path, depth, state);\n if (raw.kind === \"result\") return canonicalResult(raw, path, depth, state);\n if (raw.kind === \"match\") return canonicalMatch(raw, path, depth, state);\n if (raw.kind === \"instant\" || raw.kind === \"duration\") return canonicalTemporal(raw, path);\n if (raw.kind === \"current-instant\") return canonicalCurrentInstant(raw, path);\n if (raw.kind === \"temporal-arithmetic\") {\n return canonicalTemporalOperation(raw, path, depth, state, [\"add\", \"subtract\"]);\n }\n if (raw.kind === \"temporal-comparison\") {\n return canonicalTemporalOperation(raw, path, depth, state, [\n \"equal\",\n \"not-equal\",\n \"less-than\",\n \"less-than-or-equal\",\n \"greater-than\",\n \"greater-than-or-equal\",\n ]);\n }\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"kind\"]);\n } finally {\n state.active.delete(input);\n }\n}\n\nfunction canonicalTemporal(\n raw: Record<string, unknown>,\n path: Path,\n): Extract<KaladaV1Expression, { kind: \"instant\" | \"duration\" }> {\n exact(raw, path, [\"kind\", \"milliseconds\"]);\n if (!Number.isSafeInteger(raw.milliseconds)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"milliseconds\"]);\n }\n return Object.freeze({\n kind: raw.kind,\n milliseconds: Object.is(raw.milliseconds, -0) ? 0 : raw.milliseconds,\n }) as Extract<KaladaV1Expression, { kind: \"instant\" | \"duration\" }>;\n}\n\nfunction canonicalCurrentInstant(\n raw: Record<string, unknown>,\n path: Path,\n): Extract<KaladaV1Expression, { kind: \"current-instant\" }> {\n exact(raw, path, [\"kind\"]);\n return Object.freeze({ kind: \"current-instant\" });\n}\n\nfunction canonicalTemporalOperation<R extends JsonValue>(\n raw: Record<string, unknown>,\n path: Path,\n depth: number,\n state: State<R>,\n operators: readonly string[],\n): KaladaV1Expression<R> {\n exact(raw, path, [\"kind\", \"operator\", \"left\", \"right\"]);\n if (typeof raw.operator !== \"string\" || !operators.includes(raw.operator)) {\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"operator\"]);\n }\n return Object.freeze({\n kind: raw.kind,\n operator: raw.operator,\n left: canonicalNode(raw.left, [...path, \"left\"], depth + 1, state),\n right: canonicalNode(raw.right, [...path, \"right\"], depth + 1, state),\n }) as KaladaV1Expression<R>;\n}\n\nfunction canonicalLiteral<R extends JsonValue>(\n raw: Record<string, unknown>,\n path: Path,\n state: State<R>,\n): KaladaV1Expression<R> {\n exact(raw, path, [\"kind\", \"value\"]);\n return Object.freeze({\n kind: \"literal\",\n value: safeJson(raw.value, [...path, \"value\"], state),\n });\n}\n\nfunction canonicalReference<R extends JsonValue>(\n raw: Record<string, unknown>,\n path: Path,\n state: State<R>,\n): KaladaV1Expression<R> {\n exact(raw, path, [\"kind\", \"ref\"]);\n const refPath = [...path, \"ref\"];\n const codec = state.options.reference;\n const ref = (\n codec ? inspectJson(raw.ref, refPath, state) : safeJson(raw.ref, refPath, state)\n ) as R;\n if (codec ? !safeValidate(codec.validate, ref) : typeof ref !== \"string\" || ref.length === 0) {\n throw new KaladaFailure(\"KALADA_INVALID_REFERENCE\", refPath);\n }\n const replacement = codec?.canonicalize\n ? safeCanonicalize(codec.canonicalize, ref, refPath)\n : ref;\n const output = (codec ? safeJson(replacement, refPath, state) : replacement) as R;\n if (codec && !safeValidate(codec.validate, output))\n throw new KaladaFailure(\"KALADA_INVALID_REFERENCE\", refPath);\n if (referenceLength(output) > state.limits.maxReferenceLength)\n throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", refPath);\n return Object.freeze({ kind: \"ref\", ref: output });\n}\n\nfunction canonicalBinding<R extends JsonValue>(\n raw: Record<string, unknown>,\n path: Path,\n depth: number,\n state: State<R>,\n): KaladaV1Expression<R> {\n exact(raw, path, [\"kind\", \"name\", \"value\", \"body\"]);\n const name = bindingName(raw.name, [...path, \"name\"], state.limits);\n return Object.freeze({\n kind: \"binding\",\n name,\n value: canonicalNode(raw.value, [...path, \"value\"], depth + 1, state),\n body: canonicalNode(raw.body, [...path, \"body\"], depth + 1, state),\n });\n}\n\nfunction canonicalOption<R extends JsonValue>(\n raw: Record<string, unknown>,\n path: Path,\n depth: number,\n state: State<R>,\n): KaladaV1Expression<R> {\n if (raw.variant === \"none\") {\n exact(raw, path, [\"kind\", \"variant\"]);\n return Object.freeze({ kind: \"option\", variant: \"none\" });\n }\n if (raw.variant !== \"some\") throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"variant\"]);\n exact(raw, path, [\"kind\", \"variant\", \"value\"]);\n return Object.freeze({\n kind: \"option\",\n variant: \"some\",\n value: canonicalNode(raw.value, [...path, \"value\"], depth + 1, state),\n });\n}\n\nfunction canonicalResult<R extends JsonValue>(\n raw: Record<string, unknown>,\n path: Path,\n depth: number,\n state: State<R>,\n): KaladaV1Expression<R> {\n if (raw.variant !== \"ok\" && raw.variant !== \"err\")\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"variant\"]);\n exact(raw, path, [\"kind\", \"variant\", \"value\"]);\n return Object.freeze({\n kind: \"result\",\n variant: raw.variant,\n value: canonicalNode(raw.value, [...path, \"value\"], depth + 1, state),\n });\n}\n\nfunction canonicalMatch<R extends JsonValue>(\n raw: Record<string, unknown>,\n path: Path,\n depth: number,\n state: State<R>,\n): KaladaV1Expression<R> {\n exact(raw, path, [\"kind\", \"type\", \"value\", \"arms\"]);\n if (raw.type !== \"Option\" && raw.type !== \"Result\")\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"type\"]);\n const value = canonicalNode(raw.value, [...path, \"value\"], depth + 1, state);\n const arms = canonicalArms(raw.arms, raw.type, path, depth, state);\n return Object.freeze({ kind: \"match\", type: raw.type, value, arms });\n}\n\nfunction canonicalArms<R extends JsonValue>(\n input: unknown,\n type: \"Option\" | \"Result\",\n path: Path,\n depth: number,\n state: State<R>,\n): readonly MatchArm<R>[] {\n if (!Array.isArray(input)) throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"arms\"]);\n const entries = strictArray(input, [...path, \"arms\"]);\n const expected: readonly string[] = ARM_ORDER[type];\n const found = new Map<string, MatchArm<R>>();\n entries.forEach((entry, index) => {\n addArm(entry, index, type, expected, found, path, depth, state);\n });\n if (found.size !== expected.length)\n throw new KaladaFailure(\"KALADA_MATCH_MISSING_ARM\", [...path, \"arms\"]);\n return Object.freeze(expected.map((variant) => requiredArm(found, variant, path)));\n}\n\nfunction addArm<R extends JsonValue>(\n input: unknown,\n index: number,\n type: \"Option\" | \"Result\",\n expected: readonly string[],\n found: Map<string, MatchArm<R>>,\n path: Path,\n depth: number,\n state: State<R>,\n): void {\n const armPath = [...path, \"arms\", index];\n const raw = properties(input, armPath, new Set([\"variant\", \"binding\", \"body\"]), false);\n if (found.size === expected.length)\n throw new KaladaFailure(\"KALADA_MATCH_UNREACHABLE_ARM\", armPath);\n if (typeof raw.variant !== \"string\" || !expected.includes(raw.variant))\n throw new KaladaFailure(\"KALADA_MATCH_UNKNOWN_ARM\", [...armPath, \"variant\"]);\n if (found.has(raw.variant))\n throw new KaladaFailure(\"KALADA_MATCH_DUPLICATE_ARM\", [...armPath, \"variant\"]);\n const allowsBinding = raw.variant !== \"none\";\n if (!allowsBinding && \"binding\" in raw)\n throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...armPath, \"binding\"]);\n exact(\n raw,\n armPath,\n allowsBinding ? [\"variant\", \"body\", \"binding\"] : [\"variant\", \"body\"],\n allowsBinding,\n );\n const binding =\n raw.binding === undefined\n ? undefined\n : bindingName(raw.binding, [...armPath, \"binding\"], state.limits);\n const body = canonicalNode(raw.body, [...armPath, \"body\"], depth + 1, state);\n found.set(\n raw.variant,\n Object.freeze({ variant: raw.variant, ...(binding ? { binding } : {}), body }) as MatchArm<R>,\n );\n void type;\n}\n\nfunction requiredArm<R extends JsonValue>(\n found: Map<string, MatchArm<R>>,\n variant: string,\n path: Path,\n): MatchArm<R> {\n const arm = found.get(variant);\n if (!arm) throw new KaladaFailure(\"KALADA_MATCH_MISSING_ARM\", [...path, \"arms\"]);\n return arm;\n}\n"]}