@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.
- package/README.md +62 -3
- package/dist/kalada-v1/canonical-input.cjs +133 -0
- package/dist/kalada-v1/canonical-input.cjs.map +1 -0
- package/dist/kalada-v1/canonical-input.d.cts +26 -0
- package/dist/kalada-v1/canonical-input.d.ts +26 -0
- package/dist/kalada-v1/canonical-input.js +122 -0
- package/dist/kalada-v1/canonical-input.js.map +1 -0
- package/dist/kalada-v1/canonicalize.cjs +93 -130
- package/dist/kalada-v1/canonicalize.cjs.map +1 -1
- package/dist/kalada-v1/canonicalize.d.cts +1 -0
- package/dist/kalada-v1/canonicalize.d.ts +1 -0
- package/dist/kalada-v1/canonicalize.js +71 -108
- package/dist/kalada-v1/canonicalize.js.map +1 -1
- package/dist/kalada-v1/codec.cjs +24 -0
- package/dist/kalada-v1/codec.cjs.map +1 -1
- package/dist/kalada-v1/codec.d.cts +5 -0
- package/dist/kalada-v1/codec.d.ts +5 -0
- package/dist/kalada-v1/codec.js +24 -0
- package/dist/kalada-v1/codec.js.map +1 -1
- package/dist/kalada-v1/compile.cjs +24 -1
- package/dist/kalada-v1/compile.cjs.map +1 -1
- package/dist/kalada-v1/compile.d.cts +1 -0
- package/dist/kalada-v1/compile.d.ts +1 -0
- package/dist/kalada-v1/compile.js +25 -2
- package/dist/kalada-v1/compile.js.map +1 -1
- package/dist/kalada-v1/dependencies.cjs +55 -2
- package/dist/kalada-v1/dependencies.cjs.map +1 -1
- package/dist/kalada-v1/dependencies.d.cts +1 -0
- package/dist/kalada-v1/dependencies.d.ts +1 -0
- package/dist/kalada-v1/dependencies.js +55 -2
- package/dist/kalada-v1/dependencies.js.map +1 -1
- package/dist/kalada-v1/diagnostics.cjs +29 -4
- package/dist/kalada-v1/diagnostics.cjs.map +1 -1
- package/dist/kalada-v1/diagnostics.d.cts +5 -3
- package/dist/kalada-v1/diagnostics.d.ts +5 -3
- package/dist/kalada-v1/diagnostics.js +29 -4
- package/dist/kalada-v1/diagnostics.js.map +1 -1
- package/dist/kalada-v1/evaluate.cjs +23 -117
- package/dist/kalada-v1/evaluate.cjs.map +1 -1
- package/dist/kalada-v1/evaluate.d.cts +4 -2
- package/dist/kalada-v1/evaluate.d.ts +4 -2
- package/dist/kalada-v1/evaluate.js +24 -118
- package/dist/kalada-v1/evaluate.js.map +1 -1
- package/dist/kalada-v1/evaluation-delivery.cjs +286 -0
- package/dist/kalada-v1/evaluation-delivery.cjs.map +1 -0
- package/dist/kalada-v1/evaluation-delivery.d.cts +13 -0
- package/dist/kalada-v1/evaluation-delivery.d.ts +13 -0
- package/dist/kalada-v1/evaluation-delivery.js +284 -0
- package/dist/kalada-v1/evaluation-delivery.js.map +1 -0
- package/dist/kalada-v1/evaluation-frames.cjs +16 -0
- package/dist/kalada-v1/evaluation-frames.cjs.map +1 -0
- package/dist/kalada-v1/evaluation-frames.d.cts +83 -0
- package/dist/kalada-v1/evaluation-frames.d.ts +83 -0
- package/dist/kalada-v1/evaluation-frames.js +14 -0
- package/dist/kalada-v1/evaluation-frames.js.map +1 -0
- package/dist/kalada-v1/evaluation-machine.cjs +226 -0
- package/dist/kalada-v1/evaluation-machine.cjs.map +1 -0
- package/dist/kalada-v1/evaluation-machine.d.cts +9 -0
- package/dist/kalada-v1/evaluation-machine.d.ts +9 -0
- package/dist/kalada-v1/evaluation-machine.js +224 -0
- package/dist/kalada-v1/evaluation-machine.js.map +1 -0
- package/dist/kalada-v1/evaluation-resolution.cjs +80 -0
- package/dist/kalada-v1/evaluation-resolution.cjs.map +1 -0
- package/dist/kalada-v1/evaluation-resolution.d.cts +11 -0
- package/dist/kalada-v1/evaluation-resolution.d.ts +11 -0
- package/dist/kalada-v1/evaluation-resolution.js +78 -0
- package/dist/kalada-v1/evaluation-resolution.js.map +1 -0
- package/dist/kalada-v1/evaluation-state.cjs +94 -0
- package/dist/kalada-v1/evaluation-state.cjs.map +1 -0
- package/dist/kalada-v1/evaluation-state.d.cts +38 -0
- package/dist/kalada-v1/evaluation-state.d.ts +38 -0
- package/dist/kalada-v1/evaluation-state.js +81 -0
- package/dist/kalada-v1/evaluation-state.js.map +1 -0
- package/dist/kalada-v1/factories.cjs +46 -0
- package/dist/kalada-v1/factories.cjs.map +1 -1
- package/dist/kalada-v1/factories.d.cts +24 -1
- package/dist/kalada-v1/factories.d.ts +24 -1
- package/dist/kalada-v1/factories.js +46 -0
- package/dist/kalada-v1/factories.js.map +1 -1
- package/dist/kalada-v1/function-contracts.cjs +150 -0
- package/dist/kalada-v1/function-contracts.cjs.map +1 -0
- package/dist/kalada-v1/function-contracts.d.cts +15 -0
- package/dist/kalada-v1/function-contracts.d.ts +15 -0
- package/dist/kalada-v1/function-contracts.js +144 -0
- package/dist/kalada-v1/function-contracts.js.map +1 -0
- package/dist/kalada-v1/index.cjs +30 -0
- package/dist/kalada-v1/index.d.cts +5 -3
- package/dist/kalada-v1/index.d.ts +5 -3
- package/dist/kalada-v1/index.js +4 -2
- package/dist/kalada-v1/limits.cjs +23 -2
- package/dist/kalada-v1/limits.cjs.map +1 -1
- package/dist/kalada-v1/limits.d.cts +6 -3
- package/dist/kalada-v1/limits.d.ts +6 -3
- package/dist/kalada-v1/limits.js +23 -3
- package/dist/kalada-v1/limits.js.map +1 -1
- package/dist/kalada-v1/runtime-values.cjs +112 -0
- package/dist/kalada-v1/runtime-values.cjs.map +1 -0
- package/dist/kalada-v1/runtime-values.d.cts +35 -0
- package/dist/kalada-v1/runtime-values.d.ts +35 -0
- package/dist/kalada-v1/runtime-values.js +105 -0
- package/dist/kalada-v1/runtime-values.js.map +1 -0
- package/dist/kalada-v1/schemas.cjs +136 -3
- package/dist/kalada-v1/schemas.cjs.map +1 -1
- package/dist/kalada-v1/schemas.d.cts +2 -1
- package/dist/kalada-v1/schemas.d.ts +2 -1
- package/dist/kalada-v1/schemas.js +137 -5
- package/dist/kalada-v1/schemas.js.map +1 -1
- package/dist/kalada-v1/static-analysis.cjs +177 -0
- package/dist/kalada-v1/static-analysis.cjs.map +1 -0
- package/dist/kalada-v1/static-analysis.d.cts +9 -0
- package/dist/kalada-v1/static-analysis.d.ts +9 -0
- package/dist/kalada-v1/static-analysis.js +175 -0
- package/dist/kalada-v1/static-analysis.js.map +1 -0
- package/dist/kalada-v1/static-types.cjs +229 -0
- package/dist/kalada-v1/static-types.cjs.map +1 -0
- package/dist/kalada-v1/static-types.d.cts +8 -0
- package/dist/kalada-v1/static-types.d.ts +8 -0
- package/dist/kalada-v1/static-types.js +227 -0
- package/dist/kalada-v1/static-types.js.map +1 -0
- package/dist/kalada-v1/temporal-evaluation.cjs +95 -0
- package/dist/kalada-v1/temporal-evaluation.cjs.map +1 -0
- package/dist/kalada-v1/temporal-evaluation.d.cts +18 -0
- package/dist/kalada-v1/temporal-evaluation.d.ts +18 -0
- package/dist/kalada-v1/temporal-evaluation.js +90 -0
- package/dist/kalada-v1/temporal-evaluation.js.map +1 -0
- package/dist/kalada-v1/temporal.cjs +42 -0
- package/dist/kalada-v1/temporal.cjs.map +1 -0
- package/dist/kalada-v1/temporal.d.cts +22 -0
- package/dist/kalada-v1/temporal.d.ts +22 -0
- package/dist/kalada-v1/temporal.js +37 -0
- package/dist/kalada-v1/temporal.js.map +1 -0
- package/dist/kalada-v1/types.d.cts +108 -5
- package/dist/kalada-v1/types.d.ts +108 -5
- package/dist/kalada-v1/values.cjs +13 -1
- package/dist/kalada-v1/values.cjs.map +1 -1
- package/dist/kalada-v1/values.d.cts +2 -1
- package/dist/kalada-v1/values.d.ts +2 -1
- package/dist/kalada-v1/values.js +13 -1
- package/dist/kalada-v1/values.js.map +1 -1
- 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.
|
|
17
|
-
|
|
18
|
-
|
|
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"]}
|