@kalada/core 0.0.0 → 0.2.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 (80) hide show
  1. package/README.md +25 -0
  2. package/dist/kalada-v1/canonicalize.cjs +266 -0
  3. package/dist/kalada-v1/canonicalize.cjs.map +1 -0
  4. package/dist/kalada-v1/canonicalize.d.cts +7 -0
  5. package/dist/kalada-v1/canonicalize.d.ts +7 -0
  6. package/dist/kalada-v1/canonicalize.js +264 -0
  7. package/dist/kalada-v1/canonicalize.js.map +1 -0
  8. package/dist/kalada-v1/codec.cjs +149 -0
  9. package/dist/kalada-v1/codec.cjs.map +1 -0
  10. package/dist/kalada-v1/codec.d.cts +27 -0
  11. package/dist/kalada-v1/codec.d.ts +27 -0
  12. package/dist/kalada-v1/codec.js +146 -0
  13. package/dist/kalada-v1/codec.js.map +1 -0
  14. package/dist/kalada-v1/compile.cjs +31 -0
  15. package/dist/kalada-v1/compile.cjs.map +1 -0
  16. package/dist/kalada-v1/compile.d.cts +7 -0
  17. package/dist/kalada-v1/compile.d.ts +7 -0
  18. package/dist/kalada-v1/compile.js +29 -0
  19. package/dist/kalada-v1/compile.js.map +1 -0
  20. package/dist/kalada-v1/dependencies.cjs +52 -0
  21. package/dist/kalada-v1/dependencies.cjs.map +1 -0
  22. package/dist/kalada-v1/dependencies.d.cts +7 -0
  23. package/dist/kalada-v1/dependencies.d.ts +7 -0
  24. package/dist/kalada-v1/dependencies.js +50 -0
  25. package/dist/kalada-v1/dependencies.js.map +1 -0
  26. package/dist/kalada-v1/diagnostics.cjs +44 -0
  27. package/dist/kalada-v1/diagnostics.cjs.map +1 -0
  28. package/dist/kalada-v1/diagnostics.d.cts +13 -0
  29. package/dist/kalada-v1/diagnostics.d.ts +13 -0
  30. package/dist/kalada-v1/diagnostics.js +40 -0
  31. package/dist/kalada-v1/diagnostics.js.map +1 -0
  32. package/dist/kalada-v1/evaluate.cjs +141 -0
  33. package/dist/kalada-v1/evaluate.cjs.map +1 -0
  34. package/dist/kalada-v1/evaluate.d.cts +7 -0
  35. package/dist/kalada-v1/evaluate.d.ts +7 -0
  36. package/dist/kalada-v1/evaluate.js +139 -0
  37. package/dist/kalada-v1/evaluate.js.map +1 -0
  38. package/dist/kalada-v1/factories.cjs +48 -0
  39. package/dist/kalada-v1/factories.cjs.map +1 -0
  40. package/dist/kalada-v1/factories.d.cts +22 -0
  41. package/dist/kalada-v1/factories.d.ts +22 -0
  42. package/dist/kalada-v1/factories.js +46 -0
  43. package/dist/kalada-v1/factories.js.map +1 -0
  44. package/dist/kalada-v1/index.cjs +71 -0
  45. package/dist/kalada-v1/index.cjs.map +1 -0
  46. package/dist/kalada-v1/index.d.cts +10 -0
  47. package/dist/kalada-v1/index.d.ts +10 -0
  48. package/dist/kalada-v1/index.js +10 -0
  49. package/dist/kalada-v1/index.js.map +1 -0
  50. package/dist/kalada-v1/json.cjs +129 -0
  51. package/dist/kalada-v1/json.cjs.map +1 -0
  52. package/dist/kalada-v1/json.d.cts +20 -0
  53. package/dist/kalada-v1/json.d.ts +20 -0
  54. package/dist/kalada-v1/json.js +123 -0
  55. package/dist/kalada-v1/json.js.map +1 -0
  56. package/dist/kalada-v1/limits.cjs +34 -0
  57. package/dist/kalada-v1/limits.cjs.map +1 -0
  58. package/dist/kalada-v1/limits.d.cts +8 -0
  59. package/dist/kalada-v1/limits.d.ts +8 -0
  60. package/dist/kalada-v1/limits.js +31 -0
  61. package/dist/kalada-v1/limits.js.map +1 -0
  62. package/dist/kalada-v1/schemas.cjs +154 -0
  63. package/dist/kalada-v1/schemas.cjs.map +1 -0
  64. package/dist/kalada-v1/schemas.d.cts +5 -0
  65. package/dist/kalada-v1/schemas.d.ts +5 -0
  66. package/dist/kalada-v1/schemas.js +151 -0
  67. package/dist/kalada-v1/schemas.js.map +1 -0
  68. package/dist/kalada-v1/types.cjs +4 -0
  69. package/dist/kalada-v1/types.cjs.map +1 -0
  70. package/dist/kalada-v1/types.d.cts +91 -0
  71. package/dist/kalada-v1/types.d.ts +91 -0
  72. package/dist/kalada-v1/types.js +3 -0
  73. package/dist/kalada-v1/types.js.map +1 -0
  74. package/dist/kalada-v1/values.cjs +100 -0
  75. package/dist/kalada-v1/values.cjs.map +1 -0
  76. package/dist/kalada-v1/values.d.cts +48 -0
  77. package/dist/kalada-v1/values.d.ts +48 -0
  78. package/dist/kalada-v1/values.js +93 -0
  79. package/dist/kalada-v1/values.js.map +1 -0
  80. package/package.json +16 -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,266 @@
1
+ 'use strict';
2
+
3
+ var diagnostics_js = require('./diagnostics.js');
4
+ var json_js = require('./json.js');
5
+ var limits_js = require('./limits.js');
6
+
7
+ const NODE_KEYS = /* @__PURE__ */ new Set(["kind", "value", "ref", "name", "body", "variant", "type", "arms"]);
8
+ const ARM_ORDER = Object.freeze({ Option: ["some", "none"], Result: ["ok", "err"] });
9
+ function canonicalizeKaladaV1Program(input, options = {}) {
10
+ try {
11
+ const limits = limits_js.resolveLimits(options.limits);
12
+ const fields = properties(input, [], /* @__PURE__ */ new Set(["format", "version", "profile", "expression"]));
13
+ if (fields.format !== "kalada-program" || fields.version !== 1 || fields.profile !== "kalada-v1") {
14
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", []);
15
+ }
16
+ const state = {
17
+ limits,
18
+ options,
19
+ active: /* @__PURE__ */ new WeakSet(),
20
+ astNodes: 0,
21
+ valueNodes: 0
22
+ };
23
+ const expression = canonicalNode(fields.expression, ["expression"], 0, state);
24
+ return diagnostics_js.success(
25
+ Object.freeze({ format: "kalada-program", version: 1, profile: "kalada-v1", expression })
26
+ );
27
+ } catch (error) {
28
+ const problem = error instanceof diagnostics_js.KaladaFailure ? error : new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", []);
29
+ return diagnostics_js.failure(problem.code, problem.path);
30
+ }
31
+ }
32
+ function canonicalNode(input, path, depth, state) {
33
+ count(path, depth, state);
34
+ if (typeof input !== "object" || input === null || state.active.has(input)) {
35
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
36
+ }
37
+ state.active.add(input);
38
+ try {
39
+ const raw = properties(input, path, NODE_KEYS, false);
40
+ if (raw.kind === "literal") return canonicalLiteral(raw, path, state);
41
+ if (raw.kind === "ref") return canonicalReference(raw, path, state);
42
+ if (raw.kind === "binding") return canonicalBinding(raw, path, depth, state);
43
+ if (raw.kind === "option") return canonicalOption(raw, path, depth, state);
44
+ if (raw.kind === "result") return canonicalResult(raw, path, depth, state);
45
+ if (raw.kind === "match") return canonicalMatch(raw, path, depth, state);
46
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "kind"]);
47
+ } finally {
48
+ state.active.delete(input);
49
+ }
50
+ }
51
+ function canonicalLiteral(raw, path, state) {
52
+ exact(raw, path, ["kind", "value"]);
53
+ return Object.freeze({
54
+ kind: "literal",
55
+ value: safeJson(raw.value, [...path, "value"], state)
56
+ });
57
+ }
58
+ function canonicalReference(raw, path, state) {
59
+ exact(raw, path, ["kind", "ref"]);
60
+ const refPath = [...path, "ref"];
61
+ const codec = state.options.reference;
62
+ const ref = codec ? inspectJson(raw.ref, refPath, state) : safeJson(raw.ref, refPath, state);
63
+ if (codec ? !safeValidate(codec.validate, ref) : typeof ref !== "string" || ref.length === 0) {
64
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_REFERENCE", refPath);
65
+ }
66
+ const replacement = codec?.canonicalize ? safeCanonicalize(codec.canonicalize, ref, refPath) : ref;
67
+ const output = codec ? safeJson(replacement, refPath, state) : replacement;
68
+ if (codec && !safeValidate(codec.validate, output))
69
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_REFERENCE", refPath);
70
+ if (referenceLength(output) > state.limits.maxReferenceLength)
71
+ throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", refPath);
72
+ return Object.freeze({ kind: "ref", ref: output });
73
+ }
74
+ function canonicalBinding(raw, path, depth, state) {
75
+ exact(raw, path, ["kind", "name", "value", "body"]);
76
+ const name = bindingName(raw.name, [...path, "name"], state.limits);
77
+ return Object.freeze({
78
+ kind: "binding",
79
+ name,
80
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state),
81
+ body: canonicalNode(raw.body, [...path, "body"], depth + 1, state)
82
+ });
83
+ }
84
+ function canonicalOption(raw, path, depth, state) {
85
+ if (raw.variant === "none") {
86
+ exact(raw, path, ["kind", "variant"]);
87
+ return Object.freeze({ kind: "option", variant: "none" });
88
+ }
89
+ if (raw.variant !== "some") throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "variant"]);
90
+ exact(raw, path, ["kind", "variant", "value"]);
91
+ return Object.freeze({
92
+ kind: "option",
93
+ variant: "some",
94
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state)
95
+ });
96
+ }
97
+ function canonicalResult(raw, path, depth, state) {
98
+ if (raw.variant !== "ok" && raw.variant !== "err")
99
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "variant"]);
100
+ exact(raw, path, ["kind", "variant", "value"]);
101
+ return Object.freeze({
102
+ kind: "result",
103
+ variant: raw.variant,
104
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state)
105
+ });
106
+ }
107
+ function canonicalMatch(raw, path, depth, state) {
108
+ exact(raw, path, ["kind", "type", "value", "arms"]);
109
+ if (raw.type !== "Option" && raw.type !== "Result")
110
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "type"]);
111
+ const value = canonicalNode(raw.value, [...path, "value"], depth + 1, state);
112
+ const arms = canonicalArms(raw.arms, raw.type, path, depth, state);
113
+ return Object.freeze({ kind: "match", type: raw.type, value, arms });
114
+ }
115
+ function canonicalArms(input, type, path, depth, state) {
116
+ if (!Array.isArray(input)) throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, "arms"]);
117
+ const entries = strictArray(input, [...path, "arms"]);
118
+ const expected = ARM_ORDER[type];
119
+ const found = /* @__PURE__ */ new Map();
120
+ entries.forEach((entry, index) => {
121
+ addArm(entry, index, type, expected, found, path, depth, state);
122
+ });
123
+ if (found.size !== expected.length)
124
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_MISSING_ARM", [...path, "arms"]);
125
+ return Object.freeze(expected.map((variant) => requiredArm(found, variant, path)));
126
+ }
127
+ function addArm(input, index, type, expected, found, path, depth, state) {
128
+ const armPath = [...path, "arms", index];
129
+ const raw = properties(input, armPath, /* @__PURE__ */ new Set(["variant", "binding", "body"]), false);
130
+ if (found.size === expected.length)
131
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_UNREACHABLE_ARM", armPath);
132
+ if (typeof raw.variant !== "string" || !expected.includes(raw.variant))
133
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_UNKNOWN_ARM", [...armPath, "variant"]);
134
+ if (found.has(raw.variant))
135
+ throw new diagnostics_js.KaladaFailure("KALADA_MATCH_DUPLICATE_ARM", [...armPath, "variant"]);
136
+ const allowsBinding = raw.variant !== "none";
137
+ if (!allowsBinding && "binding" in raw)
138
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...armPath, "binding"]);
139
+ exact(
140
+ raw,
141
+ armPath,
142
+ allowsBinding ? ["variant", "body", "binding"] : ["variant", "body"],
143
+ allowsBinding
144
+ );
145
+ const binding = raw.binding === void 0 ? void 0 : bindingName(raw.binding, [...armPath, "binding"], state.limits);
146
+ const body = canonicalNode(raw.body, [...armPath, "body"], depth + 1, state);
147
+ found.set(
148
+ raw.variant,
149
+ Object.freeze({ variant: raw.variant, ...binding ? { binding } : {}, body })
150
+ );
151
+ }
152
+ function requiredArm(found, variant, path) {
153
+ const arm = found.get(variant);
154
+ if (!arm) throw new diagnostics_js.KaladaFailure("KALADA_MATCH_MISSING_ARM", [...path, "arms"]);
155
+ return arm;
156
+ }
157
+ function properties(input, path, allowed, requireExact = true) {
158
+ if (typeof input !== "object" || input === null || Array.isArray(input))
159
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
160
+ let keys;
161
+ try {
162
+ keys = Reflect.ownKeys(input);
163
+ } catch {
164
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
165
+ }
166
+ const output = {};
167
+ for (const key of keys) {
168
+ if (typeof key !== "string" || !allowed.has(key))
169
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, String(key)]);
170
+ try {
171
+ output[key] = json_js.dataValue(input, key);
172
+ } catch {
173
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
174
+ }
175
+ }
176
+ if (requireExact && keys.length !== allowed.size)
177
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
178
+ return output;
179
+ }
180
+ function exact(raw, path, keys, optionalLast = false) {
181
+ const minimum = optionalLast ? keys.length - 1 : keys.length;
182
+ if (Object.keys(raw).length < minimum || Object.keys(raw).length > keys.length)
183
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
184
+ for (let index = 0; index < minimum; index += 1) {
185
+ const key = keys[index];
186
+ if (key !== void 0 && !(key in raw))
187
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
188
+ }
189
+ for (const key of Object.keys(raw))
190
+ if (!keys.includes(key)) throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
191
+ }
192
+ function strictArray(input, path) {
193
+ let keys;
194
+ try {
195
+ keys = Reflect.ownKeys(input);
196
+ } catch {
197
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
198
+ }
199
+ if (keys.length !== input.length + 1) throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
200
+ return Array.from({ length: input.length }, (_, index) => {
201
+ try {
202
+ return json_js.dataValue(input, String(index));
203
+ } catch {
204
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", [...path, index]);
205
+ }
206
+ });
207
+ }
208
+ function safeJson(input, path, state) {
209
+ try {
210
+ const result = json_js.cloneJsonWithStats(input, {
211
+ maxDepth: state.limits.maxValueDepth,
212
+ maxNodes: state.limits.maxValueNodes - state.valueNodes,
213
+ maxStringLength: state.limits.maxStringLength
214
+ });
215
+ state.valueNodes += result.nodes;
216
+ return result.value;
217
+ } catch (error) {
218
+ if (error instanceof RangeError) throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
219
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
220
+ }
221
+ }
222
+ function inspectJson(input, path, state) {
223
+ try {
224
+ return json_js.cloneJson(input, {
225
+ maxDepth: state.limits.maxValueDepth,
226
+ maxNodes: state.limits.maxValueNodes,
227
+ maxStringLength: state.limits.maxStringLength
228
+ });
229
+ } catch (error) {
230
+ if (error instanceof RangeError) throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
231
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
232
+ }
233
+ }
234
+ function referenceLength(reference) {
235
+ return typeof reference === "string" ? [...reference].length : [...json_js.canonicalJsonIdentity(reference)].length;
236
+ }
237
+ function bindingName(input, path, limits) {
238
+ if (typeof input !== "string" || input.length === 0)
239
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_INPUT", path);
240
+ if ([...input].length > limits.maxReferenceLength)
241
+ throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
242
+ return input;
243
+ }
244
+ function safeValidate(validate, input) {
245
+ try {
246
+ return validate(input) === true;
247
+ } catch {
248
+ return false;
249
+ }
250
+ }
251
+ function safeCanonicalize(canonicalize, input, path) {
252
+ try {
253
+ return canonicalize(input);
254
+ } catch {
255
+ throw new diagnostics_js.KaladaFailure("KALADA_INVALID_REFERENCE", path);
256
+ }
257
+ }
258
+ function count(path, depth, state) {
259
+ state.astNodes += 1;
260
+ if (depth > state.limits.maxAstDepth || state.astNodes > state.limits.maxAstNodes)
261
+ throw new diagnostics_js.KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
262
+ }
263
+
264
+ exports.canonicalizeKaladaV1Program = canonicalizeKaladaV1Program;
265
+ //# sourceMappingURL=canonicalize.cjs.map
266
+ //# sourceMappingURL=canonicalize.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/kalada-v1/canonicalize.ts"],"names":["resolveLimits","KaladaFailure","success","failure","dataValue","cloneJsonWithStats","cloneJson","canonicalJsonIdentity"],"mappings":"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","file":"canonicalize.cjs","sourcesContent":["import { failure, KaladaFailure, success } from \"./diagnostics.js\";\nimport {\n canonicalJsonIdentity,\n cloneJson,\n cloneJsonWithStats,\n dataValue,\n type JsonValue,\n} from \"./json.js\";\nimport { resolveLimits } from \"./limits.js\";\nimport type {\n KaladaV1Expression,\n KaladaV1Limits,\n KaladaV1Options,\n KaladaV1Outcome,\n KaladaV1Program,\n MatchArm,\n} from \"./types.js\";\n\ntype Path = readonly (string | number)[];\ninterface State<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\nconst NODE_KEYS = new Set([\"kind\", \"value\", \"ref\", \"name\", \"body\", \"variant\", \"type\", \"arms\"]);\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 throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, \"kind\"]);\n } finally {\n state.active.delete(input);\n }\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\nfunction 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 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 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 return output;\n}\n\nfunction 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 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 for (const key of Object.keys(raw))\n if (!keys.includes(key)) throw new KaladaFailure(\"KALADA_INVALID_INPUT\", [...path, key]);\n}\n\nfunction 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\nfunction safeJson<R extends JsonValue>(input: unknown, path: Path, state: State<R>): 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\nfunction inspectJson<R extends JsonValue>(input: unknown, path: Path, state: State<R>): 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\nfunction referenceLength(reference: JsonValue): number {\n return typeof reference === \"string\"\n ? [...reference].length\n : [...canonicalJsonIdentity(reference)].length;\n}\n\nfunction 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 if ([...input].length > limits.maxReferenceLength)\n throw new KaladaFailure(\"KALADA_LIMIT_EXCEEDED\", path);\n return input;\n}\n\nfunction safeValidate<R>(validate: (input: unknown) => input is R, input: unknown): input is R {\n try {\n return validate(input) === true;\n } catch {\n return false;\n }\n}\n\nfunction 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\nfunction count<R extends JsonValue>(path: Path, depth: number, state: State<R>): 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"]}
@@ -0,0 +1,7 @@
1
+ import { JsonValue } from './json.cjs';
2
+ import { KaladaV1Options, KaladaV1Outcome, KaladaV1Program } from './types.cjs';
3
+ import './values.cjs';
4
+
5
+ declare function canonicalizeKaladaV1Program<R extends JsonValue = string>(input: unknown, options?: KaladaV1Options<R>): KaladaV1Outcome<KaladaV1Program<R>>;
6
+
7
+ export { canonicalizeKaladaV1Program };
@@ -0,0 +1,7 @@
1
+ import { JsonValue } from './json.js';
2
+ import { KaladaV1Options, KaladaV1Outcome, KaladaV1Program } from './types.js';
3
+ import './values.js';
4
+
5
+ declare function canonicalizeKaladaV1Program<R extends JsonValue = string>(input: unknown, options?: KaladaV1Options<R>): KaladaV1Outcome<KaladaV1Program<R>>;
6
+
7
+ export { canonicalizeKaladaV1Program };
@@ -0,0 +1,264 @@
1
+ import { KaladaFailure, success, failure } from './diagnostics.js';
2
+ import { dataValue, cloneJsonWithStats, cloneJson, canonicalJsonIdentity } from './json.js';
3
+ import { resolveLimits } from './limits.js';
4
+
5
+ const NODE_KEYS = /* @__PURE__ */ new Set(["kind", "value", "ref", "name", "body", "variant", "type", "arms"]);
6
+ const ARM_ORDER = Object.freeze({ Option: ["some", "none"], Result: ["ok", "err"] });
7
+ function canonicalizeKaladaV1Program(input, options = {}) {
8
+ try {
9
+ const limits = resolveLimits(options.limits);
10
+ const fields = properties(input, [], /* @__PURE__ */ new Set(["format", "version", "profile", "expression"]));
11
+ if (fields.format !== "kalada-program" || fields.version !== 1 || fields.profile !== "kalada-v1") {
12
+ throw new KaladaFailure("KALADA_INVALID_INPUT", []);
13
+ }
14
+ const state = {
15
+ limits,
16
+ options,
17
+ active: /* @__PURE__ */ new WeakSet(),
18
+ astNodes: 0,
19
+ valueNodes: 0
20
+ };
21
+ const expression = canonicalNode(fields.expression, ["expression"], 0, state);
22
+ return success(
23
+ Object.freeze({ format: "kalada-program", version: 1, profile: "kalada-v1", expression })
24
+ );
25
+ } catch (error) {
26
+ const problem = error instanceof KaladaFailure ? error : new KaladaFailure("KALADA_INVALID_INPUT", []);
27
+ return failure(problem.code, problem.path);
28
+ }
29
+ }
30
+ function canonicalNode(input, path, depth, state) {
31
+ count(path, depth, state);
32
+ if (typeof input !== "object" || input === null || state.active.has(input)) {
33
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
34
+ }
35
+ state.active.add(input);
36
+ try {
37
+ const raw = properties(input, path, NODE_KEYS, false);
38
+ if (raw.kind === "literal") return canonicalLiteral(raw, path, state);
39
+ if (raw.kind === "ref") return canonicalReference(raw, path, state);
40
+ if (raw.kind === "binding") return canonicalBinding(raw, path, depth, state);
41
+ if (raw.kind === "option") return canonicalOption(raw, path, depth, state);
42
+ if (raw.kind === "result") return canonicalResult(raw, path, depth, state);
43
+ if (raw.kind === "match") return canonicalMatch(raw, path, depth, state);
44
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, "kind"]);
45
+ } finally {
46
+ state.active.delete(input);
47
+ }
48
+ }
49
+ function canonicalLiteral(raw, path, state) {
50
+ exact(raw, path, ["kind", "value"]);
51
+ return Object.freeze({
52
+ kind: "literal",
53
+ value: safeJson(raw.value, [...path, "value"], state)
54
+ });
55
+ }
56
+ function canonicalReference(raw, path, state) {
57
+ exact(raw, path, ["kind", "ref"]);
58
+ const refPath = [...path, "ref"];
59
+ const codec = state.options.reference;
60
+ const ref = codec ? inspectJson(raw.ref, refPath, state) : safeJson(raw.ref, refPath, state);
61
+ if (codec ? !safeValidate(codec.validate, ref) : typeof ref !== "string" || ref.length === 0) {
62
+ throw new KaladaFailure("KALADA_INVALID_REFERENCE", refPath);
63
+ }
64
+ const replacement = codec?.canonicalize ? safeCanonicalize(codec.canonicalize, ref, refPath) : ref;
65
+ const output = codec ? safeJson(replacement, refPath, state) : replacement;
66
+ if (codec && !safeValidate(codec.validate, output))
67
+ throw new KaladaFailure("KALADA_INVALID_REFERENCE", refPath);
68
+ if (referenceLength(output) > state.limits.maxReferenceLength)
69
+ throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", refPath);
70
+ return Object.freeze({ kind: "ref", ref: output });
71
+ }
72
+ function canonicalBinding(raw, path, depth, state) {
73
+ exact(raw, path, ["kind", "name", "value", "body"]);
74
+ const name = bindingName(raw.name, [...path, "name"], state.limits);
75
+ return Object.freeze({
76
+ kind: "binding",
77
+ name,
78
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state),
79
+ body: canonicalNode(raw.body, [...path, "body"], depth + 1, state)
80
+ });
81
+ }
82
+ function canonicalOption(raw, path, depth, state) {
83
+ if (raw.variant === "none") {
84
+ exact(raw, path, ["kind", "variant"]);
85
+ return Object.freeze({ kind: "option", variant: "none" });
86
+ }
87
+ if (raw.variant !== "some") throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, "variant"]);
88
+ exact(raw, path, ["kind", "variant", "value"]);
89
+ return Object.freeze({
90
+ kind: "option",
91
+ variant: "some",
92
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state)
93
+ });
94
+ }
95
+ function canonicalResult(raw, path, depth, state) {
96
+ if (raw.variant !== "ok" && raw.variant !== "err")
97
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, "variant"]);
98
+ exact(raw, path, ["kind", "variant", "value"]);
99
+ return Object.freeze({
100
+ kind: "result",
101
+ variant: raw.variant,
102
+ value: canonicalNode(raw.value, [...path, "value"], depth + 1, state)
103
+ });
104
+ }
105
+ function canonicalMatch(raw, path, depth, state) {
106
+ exact(raw, path, ["kind", "type", "value", "arms"]);
107
+ if (raw.type !== "Option" && raw.type !== "Result")
108
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, "type"]);
109
+ const value = canonicalNode(raw.value, [...path, "value"], depth + 1, state);
110
+ const arms = canonicalArms(raw.arms, raw.type, path, depth, state);
111
+ return Object.freeze({ kind: "match", type: raw.type, value, arms });
112
+ }
113
+ function canonicalArms(input, type, path, depth, state) {
114
+ if (!Array.isArray(input)) throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, "arms"]);
115
+ const entries = strictArray(input, [...path, "arms"]);
116
+ const expected = ARM_ORDER[type];
117
+ const found = /* @__PURE__ */ new Map();
118
+ entries.forEach((entry, index) => {
119
+ addArm(entry, index, type, expected, found, path, depth, state);
120
+ });
121
+ if (found.size !== expected.length)
122
+ throw new KaladaFailure("KALADA_MATCH_MISSING_ARM", [...path, "arms"]);
123
+ return Object.freeze(expected.map((variant) => requiredArm(found, variant, path)));
124
+ }
125
+ function addArm(input, index, type, expected, found, path, depth, state) {
126
+ const armPath = [...path, "arms", index];
127
+ const raw = properties(input, armPath, /* @__PURE__ */ new Set(["variant", "binding", "body"]), false);
128
+ if (found.size === expected.length)
129
+ throw new KaladaFailure("KALADA_MATCH_UNREACHABLE_ARM", armPath);
130
+ if (typeof raw.variant !== "string" || !expected.includes(raw.variant))
131
+ throw new KaladaFailure("KALADA_MATCH_UNKNOWN_ARM", [...armPath, "variant"]);
132
+ if (found.has(raw.variant))
133
+ throw new KaladaFailure("KALADA_MATCH_DUPLICATE_ARM", [...armPath, "variant"]);
134
+ const allowsBinding = raw.variant !== "none";
135
+ if (!allowsBinding && "binding" in raw)
136
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...armPath, "binding"]);
137
+ exact(
138
+ raw,
139
+ armPath,
140
+ allowsBinding ? ["variant", "body", "binding"] : ["variant", "body"],
141
+ allowsBinding
142
+ );
143
+ const binding = raw.binding === void 0 ? void 0 : bindingName(raw.binding, [...armPath, "binding"], state.limits);
144
+ const body = canonicalNode(raw.body, [...armPath, "body"], depth + 1, state);
145
+ found.set(
146
+ raw.variant,
147
+ Object.freeze({ variant: raw.variant, ...binding ? { binding } : {}, body })
148
+ );
149
+ }
150
+ function requiredArm(found, variant, path) {
151
+ const arm = found.get(variant);
152
+ if (!arm) throw new KaladaFailure("KALADA_MATCH_MISSING_ARM", [...path, "arms"]);
153
+ return arm;
154
+ }
155
+ function properties(input, path, allowed, requireExact = true) {
156
+ if (typeof input !== "object" || input === null || Array.isArray(input))
157
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
158
+ let keys;
159
+ try {
160
+ keys = Reflect.ownKeys(input);
161
+ } catch {
162
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
163
+ }
164
+ const output = {};
165
+ for (const key of keys) {
166
+ if (typeof key !== "string" || !allowed.has(key))
167
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, String(key)]);
168
+ try {
169
+ output[key] = dataValue(input, key);
170
+ } catch {
171
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
172
+ }
173
+ }
174
+ if (requireExact && keys.length !== allowed.size)
175
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
176
+ return output;
177
+ }
178
+ function exact(raw, path, keys, optionalLast = false) {
179
+ const minimum = optionalLast ? keys.length - 1 : keys.length;
180
+ if (Object.keys(raw).length < minimum || Object.keys(raw).length > keys.length)
181
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
182
+ for (let index = 0; index < minimum; index += 1) {
183
+ const key = keys[index];
184
+ if (key !== void 0 && !(key in raw))
185
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
186
+ }
187
+ for (const key of Object.keys(raw))
188
+ if (!keys.includes(key)) throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, key]);
189
+ }
190
+ function strictArray(input, path) {
191
+ let keys;
192
+ try {
193
+ keys = Reflect.ownKeys(input);
194
+ } catch {
195
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
196
+ }
197
+ if (keys.length !== input.length + 1) throw new KaladaFailure("KALADA_INVALID_INPUT", path);
198
+ return Array.from({ length: input.length }, (_, index) => {
199
+ try {
200
+ return dataValue(input, String(index));
201
+ } catch {
202
+ throw new KaladaFailure("KALADA_INVALID_INPUT", [...path, index]);
203
+ }
204
+ });
205
+ }
206
+ function safeJson(input, path, state) {
207
+ try {
208
+ const result = cloneJsonWithStats(input, {
209
+ maxDepth: state.limits.maxValueDepth,
210
+ maxNodes: state.limits.maxValueNodes - state.valueNodes,
211
+ maxStringLength: state.limits.maxStringLength
212
+ });
213
+ state.valueNodes += result.nodes;
214
+ return result.value;
215
+ } catch (error) {
216
+ if (error instanceof RangeError) throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
217
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
218
+ }
219
+ }
220
+ function inspectJson(input, path, state) {
221
+ try {
222
+ return cloneJson(input, {
223
+ maxDepth: state.limits.maxValueDepth,
224
+ maxNodes: state.limits.maxValueNodes,
225
+ maxStringLength: state.limits.maxStringLength
226
+ });
227
+ } catch (error) {
228
+ if (error instanceof RangeError) throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
229
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
230
+ }
231
+ }
232
+ function referenceLength(reference) {
233
+ return typeof reference === "string" ? [...reference].length : [...canonicalJsonIdentity(reference)].length;
234
+ }
235
+ function bindingName(input, path, limits) {
236
+ if (typeof input !== "string" || input.length === 0)
237
+ throw new KaladaFailure("KALADA_INVALID_INPUT", path);
238
+ if ([...input].length > limits.maxReferenceLength)
239
+ throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
240
+ return input;
241
+ }
242
+ function safeValidate(validate, input) {
243
+ try {
244
+ return validate(input) === true;
245
+ } catch {
246
+ return false;
247
+ }
248
+ }
249
+ function safeCanonicalize(canonicalize, input, path) {
250
+ try {
251
+ return canonicalize(input);
252
+ } catch {
253
+ throw new KaladaFailure("KALADA_INVALID_REFERENCE", path);
254
+ }
255
+ }
256
+ function count(path, depth, state) {
257
+ state.astNodes += 1;
258
+ if (depth > state.limits.maxAstDepth || state.astNodes > state.limits.maxAstNodes)
259
+ throw new KaladaFailure("KALADA_LIMIT_EXCEEDED", path);
260
+ }
261
+
262
+ export { canonicalizeKaladaV1Program };
263
+ //# sourceMappingURL=canonicalize.js.map
264
+ //# sourceMappingURL=canonicalize.js.map