@kalada/core 0.2.0 → 0.4.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 (140) hide show
  1. package/README.md +62 -3
  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 +26 -0
  5. package/dist/kalada-v1/canonical-input.d.ts +26 -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 +93 -130
  9. package/dist/kalada-v1/canonicalize.cjs.map +1 -1
  10. package/dist/kalada-v1/canonicalize.d.cts +1 -0
  11. package/dist/kalada-v1/canonicalize.d.ts +1 -0
  12. package/dist/kalada-v1/canonicalize.js +71 -108
  13. package/dist/kalada-v1/canonicalize.js.map +1 -1
  14. package/dist/kalada-v1/codec.cjs +24 -0
  15. package/dist/kalada-v1/codec.cjs.map +1 -1
  16. package/dist/kalada-v1/codec.d.cts +5 -0
  17. package/dist/kalada-v1/codec.d.ts +5 -0
  18. package/dist/kalada-v1/codec.js +24 -0
  19. package/dist/kalada-v1/codec.js.map +1 -1
  20. package/dist/kalada-v1/compile.cjs +24 -1
  21. package/dist/kalada-v1/compile.cjs.map +1 -1
  22. package/dist/kalada-v1/compile.d.cts +1 -0
  23. package/dist/kalada-v1/compile.d.ts +1 -0
  24. package/dist/kalada-v1/compile.js +25 -2
  25. package/dist/kalada-v1/compile.js.map +1 -1
  26. package/dist/kalada-v1/dependencies.cjs +55 -2
  27. package/dist/kalada-v1/dependencies.cjs.map +1 -1
  28. package/dist/kalada-v1/dependencies.d.cts +1 -0
  29. package/dist/kalada-v1/dependencies.d.ts +1 -0
  30. package/dist/kalada-v1/dependencies.js +55 -2
  31. package/dist/kalada-v1/dependencies.js.map +1 -1
  32. package/dist/kalada-v1/diagnostics.cjs +29 -4
  33. package/dist/kalada-v1/diagnostics.cjs.map +1 -1
  34. package/dist/kalada-v1/diagnostics.d.cts +5 -3
  35. package/dist/kalada-v1/diagnostics.d.ts +5 -3
  36. package/dist/kalada-v1/diagnostics.js +29 -4
  37. package/dist/kalada-v1/diagnostics.js.map +1 -1
  38. package/dist/kalada-v1/evaluate.cjs +23 -117
  39. package/dist/kalada-v1/evaluate.cjs.map +1 -1
  40. package/dist/kalada-v1/evaluate.d.cts +4 -2
  41. package/dist/kalada-v1/evaluate.d.ts +4 -2
  42. package/dist/kalada-v1/evaluate.js +24 -118
  43. package/dist/kalada-v1/evaluate.js.map +1 -1
  44. package/dist/kalada-v1/evaluation-delivery.cjs +286 -0
  45. package/dist/kalada-v1/evaluation-delivery.cjs.map +1 -0
  46. package/dist/kalada-v1/evaluation-delivery.d.cts +13 -0
  47. package/dist/kalada-v1/evaluation-delivery.d.ts +13 -0
  48. package/dist/kalada-v1/evaluation-delivery.js +284 -0
  49. package/dist/kalada-v1/evaluation-delivery.js.map +1 -0
  50. package/dist/kalada-v1/evaluation-frames.cjs +16 -0
  51. package/dist/kalada-v1/evaluation-frames.cjs.map +1 -0
  52. package/dist/kalada-v1/evaluation-frames.d.cts +83 -0
  53. package/dist/kalada-v1/evaluation-frames.d.ts +83 -0
  54. package/dist/kalada-v1/evaluation-frames.js +14 -0
  55. package/dist/kalada-v1/evaluation-frames.js.map +1 -0
  56. package/dist/kalada-v1/evaluation-machine.cjs +226 -0
  57. package/dist/kalada-v1/evaluation-machine.cjs.map +1 -0
  58. package/dist/kalada-v1/evaluation-machine.d.cts +9 -0
  59. package/dist/kalada-v1/evaluation-machine.d.ts +9 -0
  60. package/dist/kalada-v1/evaluation-machine.js +224 -0
  61. package/dist/kalada-v1/evaluation-machine.js.map +1 -0
  62. package/dist/kalada-v1/evaluation-resolution.cjs +80 -0
  63. package/dist/kalada-v1/evaluation-resolution.cjs.map +1 -0
  64. package/dist/kalada-v1/evaluation-resolution.d.cts +11 -0
  65. package/dist/kalada-v1/evaluation-resolution.d.ts +11 -0
  66. package/dist/kalada-v1/evaluation-resolution.js +78 -0
  67. package/dist/kalada-v1/evaluation-resolution.js.map +1 -0
  68. package/dist/kalada-v1/evaluation-state.cjs +94 -0
  69. package/dist/kalada-v1/evaluation-state.cjs.map +1 -0
  70. package/dist/kalada-v1/evaluation-state.d.cts +38 -0
  71. package/dist/kalada-v1/evaluation-state.d.ts +38 -0
  72. package/dist/kalada-v1/evaluation-state.js +81 -0
  73. package/dist/kalada-v1/evaluation-state.js.map +1 -0
  74. package/dist/kalada-v1/factories.cjs +46 -0
  75. package/dist/kalada-v1/factories.cjs.map +1 -1
  76. package/dist/kalada-v1/factories.d.cts +24 -1
  77. package/dist/kalada-v1/factories.d.ts +24 -1
  78. package/dist/kalada-v1/factories.js +46 -0
  79. package/dist/kalada-v1/factories.js.map +1 -1
  80. package/dist/kalada-v1/function-contracts.cjs +150 -0
  81. package/dist/kalada-v1/function-contracts.cjs.map +1 -0
  82. package/dist/kalada-v1/function-contracts.d.cts +15 -0
  83. package/dist/kalada-v1/function-contracts.d.ts +15 -0
  84. package/dist/kalada-v1/function-contracts.js +144 -0
  85. package/dist/kalada-v1/function-contracts.js.map +1 -0
  86. package/dist/kalada-v1/index.cjs +30 -0
  87. package/dist/kalada-v1/index.d.cts +5 -3
  88. package/dist/kalada-v1/index.d.ts +5 -3
  89. package/dist/kalada-v1/index.js +4 -2
  90. package/dist/kalada-v1/limits.cjs +23 -2
  91. package/dist/kalada-v1/limits.cjs.map +1 -1
  92. package/dist/kalada-v1/limits.d.cts +6 -3
  93. package/dist/kalada-v1/limits.d.ts +6 -3
  94. package/dist/kalada-v1/limits.js +23 -3
  95. package/dist/kalada-v1/limits.js.map +1 -1
  96. package/dist/kalada-v1/runtime-values.cjs +112 -0
  97. package/dist/kalada-v1/runtime-values.cjs.map +1 -0
  98. package/dist/kalada-v1/runtime-values.d.cts +35 -0
  99. package/dist/kalada-v1/runtime-values.d.ts +35 -0
  100. package/dist/kalada-v1/runtime-values.js +105 -0
  101. package/dist/kalada-v1/runtime-values.js.map +1 -0
  102. package/dist/kalada-v1/schemas.cjs +136 -3
  103. package/dist/kalada-v1/schemas.cjs.map +1 -1
  104. package/dist/kalada-v1/schemas.d.cts +2 -1
  105. package/dist/kalada-v1/schemas.d.ts +2 -1
  106. package/dist/kalada-v1/schemas.js +137 -5
  107. package/dist/kalada-v1/schemas.js.map +1 -1
  108. package/dist/kalada-v1/static-analysis.cjs +177 -0
  109. package/dist/kalada-v1/static-analysis.cjs.map +1 -0
  110. package/dist/kalada-v1/static-analysis.d.cts +9 -0
  111. package/dist/kalada-v1/static-analysis.d.ts +9 -0
  112. package/dist/kalada-v1/static-analysis.js +175 -0
  113. package/dist/kalada-v1/static-analysis.js.map +1 -0
  114. package/dist/kalada-v1/static-types.cjs +229 -0
  115. package/dist/kalada-v1/static-types.cjs.map +1 -0
  116. package/dist/kalada-v1/static-types.d.cts +8 -0
  117. package/dist/kalada-v1/static-types.d.ts +8 -0
  118. package/dist/kalada-v1/static-types.js +227 -0
  119. package/dist/kalada-v1/static-types.js.map +1 -0
  120. package/dist/kalada-v1/temporal-evaluation.cjs +95 -0
  121. package/dist/kalada-v1/temporal-evaluation.cjs.map +1 -0
  122. package/dist/kalada-v1/temporal-evaluation.d.cts +18 -0
  123. package/dist/kalada-v1/temporal-evaluation.d.ts +18 -0
  124. package/dist/kalada-v1/temporal-evaluation.js +90 -0
  125. package/dist/kalada-v1/temporal-evaluation.js.map +1 -0
  126. package/dist/kalada-v1/temporal.cjs +42 -0
  127. package/dist/kalada-v1/temporal.cjs.map +1 -0
  128. package/dist/kalada-v1/temporal.d.cts +22 -0
  129. package/dist/kalada-v1/temporal.d.ts +22 -0
  130. package/dist/kalada-v1/temporal.js +37 -0
  131. package/dist/kalada-v1/temporal.js.map +1 -0
  132. package/dist/kalada-v1/types.d.cts +108 -5
  133. package/dist/kalada-v1/types.d.ts +108 -5
  134. package/dist/kalada-v1/values.cjs +13 -1
  135. package/dist/kalada-v1/values.cjs.map +1 -1
  136. package/dist/kalada-v1/values.d.cts +2 -1
  137. package/dist/kalada-v1/values.d.ts +2 -1
  138. package/dist/kalada-v1/values.js +13 -1
  139. package/dist/kalada-v1/values.js.map +1 -1
  140. package/package.json +1 -1
package/README.md CHANGED
@@ -13,9 +13,15 @@ third-party license declarations are reproduced in `THIRD_PARTY_NOTICES.md`.
13
13
 
14
14
  `@kalada/core/kalada-v1` is an additive, dependency-free native profile. It provides private
15
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.
16
+ program constructors and schemas, static function analysis, and a bounded compiler/evaluator.
17
+ Typed functions are lexical values: they may capture bindings, be passed or returned, and call
18
+ themselves or members of the same function group. Evaluation uses an iterative continuation
19
+ machine, so recursion is bounded by configured limits rather than the JavaScript call stack.
20
+
21
+ JSON values remain opaque. Only `decodeKaladaValue` decodes an encoded envelope, and every JSON
22
+ value is wrapped in a `Json` envelope so a discriminant-shaped object round-trips as ordinary JSON.
23
+ Callable values are evaluation-internal and cannot escape through a top-level result, an ADT, JSON,
24
+ or the value codec.
19
25
 
20
26
  ```ts
21
27
  import { KaladaV1, compileKaladaV1Program } from "@kalada/core/kalada-v1";
@@ -28,6 +34,59 @@ const compiled = compileKaladaV1Program(KaladaV1.program(expression));
28
34
  const value = compiled.ok ? compiled.value.evaluate(() => ({ found: false })) : compiled;
29
35
  ```
30
36
 
37
+ ### Functions and collections
38
+
39
+ Function parameters and returns use `KaladaV1.Type`. Calls validate arity and runtime values, and
40
+ arguments are evaluated left-to-right. The collection functions are first-class callable values;
41
+ callbacks receive `(element, zeroBasedIndex)`, preserve input order, and `some`/`every`
42
+ short-circuit.
43
+
44
+ ```ts
45
+ import { KaladaV1, compileKaladaV1Program } from "@kalada/core/kalada-v1";
46
+
47
+ const json = KaladaV1.Type.primitive("json");
48
+ const number = KaladaV1.Type.primitive("number");
49
+ const indices = KaladaV1.call(KaladaV1.coreFunction("map"), [
50
+ KaladaV1.literal(["a", "b", "c"]),
51
+ KaladaV1.function(
52
+ [KaladaV1.parameter("element", json), KaladaV1.parameter("index", number)],
53
+ json,
54
+ KaladaV1.ref("index"),
55
+ ),
56
+ ]);
57
+ const compiled = compileKaladaV1Program(KaladaV1.program(indices));
58
+ const outcome = compiled.ok ? compiled.value.evaluate(() => ({ found: false })) : compiled;
59
+ // outcome: { ok: true, value: [0, 1, 2] }
60
+ ```
61
+
62
+ Named members of `KaladaV1.functionGroup` support direct and mutual recursion. Closures capture the
63
+ definition scope, not the call scope. `analyzeKaladaV1Functions` exposes frozen capture metadata;
64
+ `compileKaladaV1Program` also includes it in the compiled program's `functions` field.
65
+
66
+ ### Limits and failures
67
+
68
+ `compileKaladaV1Program(program, { limits })` accepts partial overrides for AST/value/string,
69
+ evaluation-step, function-parameter/group, capture, closure, call-depth, continuation, collection
70
+ length, and cumulative collection-iteration limits. Defaults are exported as
71
+ `DEFAULT_KALADA_V1_LIMITS` and `DEFAULT_KALADA_V1_FUNCTION_LIMITS`. Limits are inclusive and a
72
+ failure returns a frozen diagnostic instead of throwing. Nested call diagnostics include at most
73
+ the 32 innermost frozen context frames. A compiled program is reusable after any failure.
74
+
75
+ Resolvers are synchronous and return `{ found: true, value }` or a missing/denied resolution.
76
+ Thrown errors, promises, accessors, hostile proxies, cycles, sparse arrays, and non-JSON values are
77
+ contained as diagnostics. `evaluateWithClock` samples its clock exactly once per evaluation.
78
+
79
+ ### Public entry points and non-goals
80
+
81
+ - `@kalada/core` retains only the versioned program envelope and Kuery adapters.
82
+ - `@kalada/core/kuery-v1` retains the Kuery 2.1 compatibility profile.
83
+ - `@kalada/core/kalada-v1` owns the native factories, types, schemas, analysis, values, codec, and
84
+ compiler/evaluator.
85
+
86
+ The profile has no parser, module loader, imports, I/O, effects, scheduling, host-language function
87
+ interop, or async callbacks. Modules and imports are deferred to
88
+ [#21](https://github.com/surikaterna/kalada/issues/21), not implicitly enabled by function values.
89
+
31
90
  Matches are limited to exactly two canonical arms: `some`, `none` for Option and `ok`, `err` for
32
91
  Result. There are no guards or fallthrough. Bindings are lexical: an initializer is evaluated in
33
92
  the outer scope, a body may shadow an outer binding, and only the selected match arm is evaluated.
@@ -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 { ResolvedKaladaV1Limits } from \"./limits.js\";\nimport type { KaladaV1Limits, KaladaV1Options } from \"./types.js\";\n\nexport type Path = readonly (string | number)[];\nexport interface CanonicalState<R extends JsonValue> {\n readonly limits: ResolvedKaladaV1Limits;\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,26 @@
1
+ import { JsonValue } from './json.cjs';
2
+ import { ResolvedKaladaV1Limits } from './limits.cjs';
3
+ import { KaladaV1Options, KaladaV1Limits } from './types.cjs';
4
+ import './temporal.cjs';
5
+ import './values.cjs';
6
+
7
+ type Path = readonly (string | number)[];
8
+ interface CanonicalState<R extends JsonValue> {
9
+ readonly limits: ResolvedKaladaV1Limits;
10
+ readonly options: KaladaV1Options<R>;
11
+ readonly active: WeakSet<object>;
12
+ astNodes: number;
13
+ valueNodes: number;
14
+ }
15
+ declare function properties(input: unknown, path: Path, allowed: ReadonlySet<string>, requireExact?: boolean): Record<string, unknown>;
16
+ declare function exact(raw: Record<string, unknown>, path: Path, keys: readonly string[], optionalLast?: boolean): void;
17
+ declare function strictArray(input: unknown[], path: Path): unknown[];
18
+ declare function safeJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
19
+ declare function inspectJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
20
+ declare function referenceLength(reference: JsonValue): number;
21
+ declare function bindingName(input: unknown, path: Path, limits: KaladaV1Limits): string;
22
+ declare function safeValidate<R>(validate: (input: unknown) => input is R, input: unknown): input is R;
23
+ declare function safeCanonicalize<R>(canonicalize: (input: R) => R, input: R, path: Path): R;
24
+ declare function count<R extends JsonValue>(path: Path, depth: number, state: CanonicalState<R>): void;
25
+
26
+ export { type CanonicalState, type Path, bindingName, count, exact, inspectJson, properties, referenceLength, safeCanonicalize, safeJson, safeValidate, strictArray };
@@ -0,0 +1,26 @@
1
+ import { JsonValue } from './json.js';
2
+ import { ResolvedKaladaV1Limits } from './limits.js';
3
+ import { KaladaV1Options, KaladaV1Limits } from './types.js';
4
+ import './temporal.js';
5
+ import './values.js';
6
+
7
+ type Path = readonly (string | number)[];
8
+ interface CanonicalState<R extends JsonValue> {
9
+ readonly limits: ResolvedKaladaV1Limits;
10
+ readonly options: KaladaV1Options<R>;
11
+ readonly active: WeakSet<object>;
12
+ astNodes: number;
13
+ valueNodes: number;
14
+ }
15
+ declare function properties(input: unknown, path: Path, allowed: ReadonlySet<string>, requireExact?: boolean): Record<string, unknown>;
16
+ declare function exact(raw: Record<string, unknown>, path: Path, keys: readonly string[], optionalLast?: boolean): void;
17
+ declare function strictArray(input: unknown[], path: Path): unknown[];
18
+ declare function safeJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
19
+ declare function inspectJson<R extends JsonValue>(input: unknown, path: Path, state: CanonicalState<R>): JsonValue;
20
+ declare function referenceLength(reference: JsonValue): number;
21
+ declare function bindingName(input: unknown, path: Path, limits: KaladaV1Limits): string;
22
+ declare function safeValidate<R>(validate: (input: unknown) => input is R, input: unknown): input is R;
23
+ declare function safeCanonicalize<R>(canonicalize: (input: R) => R, input: R, path: Path): R;
24
+ declare function count<R extends JsonValue>(path: Path, depth: number, state: CanonicalState<R>): void;
25
+
26
+ 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 { ResolvedKaladaV1Limits } from \"./limits.js\";\nimport type { KaladaV1Limits, KaladaV1Options } from \"./types.js\";\n\nexport type Path = readonly (string | number)[];\nexport interface CanonicalState<R extends JsonValue> {\n readonly limits: ResolvedKaladaV1Limits;\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"]}