@databehave/schema 0.1.3 → 0.1.4
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/dist/dataset/dataset.d.ts +47 -0
- package/dist/dataset/dataset.d.ts.map +1 -0
- package/dist/dataset/dataset.js +96 -0
- package/dist/dataset/dataset.js.map +1 -0
- package/dist/dataset/relate.d.ts +32 -0
- package/dist/dataset/relate.d.ts.map +1 -0
- package/dist/dataset/relate.js +46 -0
- package/dist/dataset/relate.js.map +1 -0
- package/dist/foundation/axes.d.ts +101 -0
- package/dist/foundation/axes.d.ts.map +1 -0
- package/dist/foundation/axes.js +42 -0
- package/dist/foundation/axes.js.map +1 -0
- package/dist/foundation/errors.d.ts +99 -0
- package/dist/foundation/errors.d.ts.map +1 -0
- package/dist/foundation/errors.js +91 -0
- package/dist/foundation/errors.js.map +1 -0
- package/dist/foundation/hash.d.ts +12 -0
- package/dist/foundation/hash.d.ts.map +1 -0
- package/dist/foundation/hash.js +21 -0
- package/dist/foundation/hash.js.map +1 -0
- package/dist/foundation/ir.d.ts +91 -0
- package/dist/foundation/ir.d.ts.map +1 -0
- package/dist/foundation/ir.js +16 -0
- package/dist/foundation/ir.js.map +1 -0
- package/dist/foundation/prng.d.ts +27 -0
- package/dist/foundation/prng.d.ts.map +1 -0
- package/dist/foundation/prng.js +56 -0
- package/dist/foundation/prng.js.map +1 -0
- package/dist/foundation/types.d.ts +116 -0
- package/dist/foundation/types.d.ts.map +1 -0
- package/dist/foundation/types.js +188 -0
- package/dist/foundation/types.js.map +1 -0
- package/dist/foundation/walk.d.ts +72 -0
- package/dist/foundation/walk.d.ts.map +1 -0
- package/dist/foundation/walk.js +265 -0
- package/dist/foundation/walk.js.map +1 -0
- package/dist/generator/engine.d.ts +100 -0
- package/dist/generator/engine.d.ts.map +1 -0
- package/dist/generator/engine.js +575 -0
- package/dist/generator/engine.js.map +1 -0
- package/dist/generator/replay.d.ts +42 -0
- package/dist/generator/replay.d.ts.map +1 -0
- package/dist/generator/replay.js +61 -0
- package/dist/generator/replay.js.map +1 -0
- package/dist/generator/trace.d.ts +49 -0
- package/dist/generator/trace.d.ts.map +1 -0
- package/dist/generator/trace.js +38 -0
- package/dist/generator/trace.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +22 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +25 -0
- package/dist/internal.js.map +1 -0
- package/dist/schema/composites.d.ts +104 -0
- package/dist/schema/composites.d.ts.map +1 -0
- package/dist/schema/composites.js +134 -0
- package/dist/schema/composites.js.map +1 -0
- package/dist/schema/conditional.d.ts +28 -0
- package/dist/schema/conditional.d.ts.map +1 -0
- package/dist/schema/conditional.js +52 -0
- package/dist/schema/conditional.js.map +1 -0
- package/dist/schema/decimal.d.ts +33 -0
- package/dist/schema/decimal.d.ts.map +1 -0
- package/dist/schema/decimal.js +39 -0
- package/dist/schema/decimal.js.map +1 -0
- package/dist/schema/primitives.d.ts +47 -0
- package/dist/schema/primitives.d.ts.map +1 -0
- package/dist/schema/primitives.js +78 -0
- package/dist/schema/primitives.js.map +1 -0
- package/dist/validator/parse.d.ts +22 -0
- package/dist/validator/parse.d.ts.map +1 -0
- package/dist/validator/parse.js +427 -0
- package/dist/validator/parse.js.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal Representation (IR) of a databehave schema.
|
|
3
|
+
*
|
|
4
|
+
* Every schema builder compiles to one of these serializable nodes.
|
|
5
|
+
* The generator and validator operate on IR — never on builder classes —
|
|
6
|
+
* so IR can be inspected, logged, transformed, or transported.
|
|
7
|
+
*/
|
|
8
|
+
export type StringFormat = 'plain' | 'uuid' | 'email' | 'url' | 'ipv4' | 'ipv6' | 'date' | 'datetime' | 'time';
|
|
9
|
+
export type NumberKind = {
|
|
10
|
+
readonly kind: 'number';
|
|
11
|
+
readonly int: boolean;
|
|
12
|
+
readonly bits?: 8 | 16 | 32 | 64;
|
|
13
|
+
readonly unsigned?: boolean;
|
|
14
|
+
readonly min?: number;
|
|
15
|
+
readonly max?: number;
|
|
16
|
+
};
|
|
17
|
+
export type StringKind = {
|
|
18
|
+
readonly kind: 'string';
|
|
19
|
+
readonly format: StringFormat;
|
|
20
|
+
readonly min?: number;
|
|
21
|
+
readonly max?: number;
|
|
22
|
+
readonly pattern?: string;
|
|
23
|
+
};
|
|
24
|
+
export type DecimalKind = {
|
|
25
|
+
readonly kind: 'decimal';
|
|
26
|
+
readonly precision: number;
|
|
27
|
+
readonly scale: number;
|
|
28
|
+
readonly min?: string;
|
|
29
|
+
readonly max?: string;
|
|
30
|
+
};
|
|
31
|
+
export type BooleanKind = {
|
|
32
|
+
readonly kind: 'boolean';
|
|
33
|
+
};
|
|
34
|
+
export type NullKind = {
|
|
35
|
+
readonly kind: 'null';
|
|
36
|
+
};
|
|
37
|
+
export type LiteralKind = {
|
|
38
|
+
readonly kind: 'literal';
|
|
39
|
+
readonly value: string | number | boolean | null;
|
|
40
|
+
};
|
|
41
|
+
export type EnumKind = {
|
|
42
|
+
readonly kind: 'enum';
|
|
43
|
+
readonly values: readonly (string | number)[];
|
|
44
|
+
};
|
|
45
|
+
export type ArrayKind = {
|
|
46
|
+
readonly kind: 'array';
|
|
47
|
+
readonly item: SchemaNode;
|
|
48
|
+
readonly length?: number;
|
|
49
|
+
readonly minLength?: number;
|
|
50
|
+
readonly maxLength?: number;
|
|
51
|
+
};
|
|
52
|
+
export type ObjectKind = {
|
|
53
|
+
readonly kind: 'object';
|
|
54
|
+
readonly fields: Readonly<Record<string, SchemaNode>>;
|
|
55
|
+
};
|
|
56
|
+
export type TupleKind = {
|
|
57
|
+
readonly kind: 'tuple';
|
|
58
|
+
readonly items: readonly SchemaNode[];
|
|
59
|
+
};
|
|
60
|
+
export type UnionKind = {
|
|
61
|
+
readonly kind: 'union';
|
|
62
|
+
readonly options: readonly SchemaNode[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* A discriminated union — selects exactly one branch by the value of `key`.
|
|
66
|
+
*
|
|
67
|
+
* Each entry in `branches` must be an object-kind schema whose `key` field is
|
|
68
|
+
* a `literal(...)` matching the map key. Generator and validator both use
|
|
69
|
+
* the discriminator for O(1) branch selection.
|
|
70
|
+
*/
|
|
71
|
+
export type DiscriminatedKind = {
|
|
72
|
+
readonly kind: 'discriminated';
|
|
73
|
+
readonly key: string;
|
|
74
|
+
readonly branches: Readonly<Record<string, SchemaNode>>;
|
|
75
|
+
};
|
|
76
|
+
import type { Axes } from './axes.js';
|
|
77
|
+
export type Modifiers = {
|
|
78
|
+
readonly nullable?: boolean;
|
|
79
|
+
readonly optional?: boolean;
|
|
80
|
+
readonly hasDefault?: boolean;
|
|
81
|
+
readonly defaultValue?: unknown;
|
|
82
|
+
readonly description?: string;
|
|
83
|
+
readonly axes?: Axes;
|
|
84
|
+
};
|
|
85
|
+
export type SchemaCore = NumberKind | StringKind | DecimalKind | BooleanKind | NullKind | LiteralKind | EnumKind | ArrayKind | ObjectKind | TupleKind | UnionKind | DiscriminatedKind;
|
|
86
|
+
export type SchemaNode = SchemaCore & {
|
|
87
|
+
readonly mods?: Modifiers;
|
|
88
|
+
};
|
|
89
|
+
/** Helper: produce a fresh node with merged modifiers. `axes` are deep-merged. */
|
|
90
|
+
export declare const withMods: (node: SchemaNode, patch: Partial<Modifiers>) => SchemaNode;
|
|
91
|
+
//# sourceMappingURL=ir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../../src/foundation/ir.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal Representation (IR) of a databehave schema.
|
|
3
|
+
*
|
|
4
|
+
* Every schema builder compiles to one of these serializable nodes.
|
|
5
|
+
* The generator and validator operate on IR — never on builder classes —
|
|
6
|
+
* so IR can be inspected, logged, transformed, or transported.
|
|
7
|
+
*/
|
|
8
|
+
import { mergeAxes } from './axes.js';
|
|
9
|
+
/** Helper: produce a fresh node with merged modifiers. `axes` are deep-merged. */
|
|
10
|
+
export const withMods = (node, patch) => {
|
|
11
|
+
const prev = node.mods ?? {};
|
|
12
|
+
const mergedAxes = patch.axes !== undefined ? mergeAxes(prev.axes, patch.axes) : prev.axes;
|
|
13
|
+
const next = mergedAxes !== undefined ? { ...prev, ...patch, axes: mergedAxes } : { ...prev, ...patch };
|
|
14
|
+
return { ...node, mods: next };
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=ir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ir.js","sourceRoot":"","sources":["../../src/foundation/ir.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwFH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AA6BrC,kFAAkF;AAClF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAgB,EAAE,KAAyB,EAAc,EAAE;IAClF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;IAC5B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC1F,MAAM,IAAI,GAAc,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAA;IAClH,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;AAChC,CAAC,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mulberry32 — tiny, fast, deterministic 32-bit PRNG.
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency. Identical seed → identical sequence on every machine.
|
|
5
|
+
* Period ≈ 2^32, ample for mock generation.
|
|
6
|
+
*
|
|
7
|
+
* Reference: https://gist.github.com/tommyettinger/46a3a48c0d7fe27ea3aaa5fa8f1ba0e8
|
|
8
|
+
*/
|
|
9
|
+
export type Rng = {
|
|
10
|
+
/** Next uniformly-distributed float in `[0, 1)`. */
|
|
11
|
+
next(): number;
|
|
12
|
+
/** Next integer in `[min, max]` (inclusive). */
|
|
13
|
+
int(min: number, max: number): number;
|
|
14
|
+
/** Pick one element of `items` uniformly. */
|
|
15
|
+
pick<T>(items: readonly T[]): T;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Create a deterministic PRNG seeded by a 32-bit unsigned integer.
|
|
19
|
+
*
|
|
20
|
+
* For string seeds, use {@link rngFromString}.
|
|
21
|
+
*/
|
|
22
|
+
export declare const mulberry32: (seed: number) => Rng;
|
|
23
|
+
/** Derive a 32-bit unsigned seed from an arbitrary string (FNV-1a 32-bit). */
|
|
24
|
+
export declare const seedFromString: (s: string) => number;
|
|
25
|
+
/** Convenience: build an Rng from a string seed. */
|
|
26
|
+
export declare const rngFromString: (s: string) => Rng;
|
|
27
|
+
//# sourceMappingURL=prng.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prng.d.ts","sourceRoot":"","sources":["../../src/foundation/prng.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,GAAG,GAAG;IAChB,oDAAoD;IACpD,IAAI,IAAI,MAAM,CAAA;IACd,gDAAgD;IAChD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;IACrC,6CAA6C;IAC7C,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAAA;CAChC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,GA8BzC,CAAA;AAED,8EAA8E;AAC9E,eAAO,MAAM,cAAc,GAAI,GAAG,MAAM,KAAG,MAO1C,CAAA;AAED,oDAAoD;AACpD,eAAO,MAAM,aAAa,GAAI,GAAG,MAAM,KAAG,GAAoC,CAAA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mulberry32 — tiny, fast, deterministic 32-bit PRNG.
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency. Identical seed → identical sequence on every machine.
|
|
5
|
+
* Period ≈ 2^32, ample for mock generation.
|
|
6
|
+
*
|
|
7
|
+
* Reference: https://gist.github.com/tommyettinger/46a3a48c0d7fe27ea3aaa5fa8f1ba0e8
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Create a deterministic PRNG seeded by a 32-bit unsigned integer.
|
|
11
|
+
*
|
|
12
|
+
* For string seeds, use {@link rngFromString}.
|
|
13
|
+
*/
|
|
14
|
+
export const mulberry32 = (seed) => {
|
|
15
|
+
// Force u32.
|
|
16
|
+
let state = seed >>> 0;
|
|
17
|
+
const next = () => {
|
|
18
|
+
state = (state + 0x6d2b79f5) >>> 0;
|
|
19
|
+
let t = state;
|
|
20
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
21
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
22
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
next,
|
|
26
|
+
int(min, max) {
|
|
27
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
|
28
|
+
throw new RangeError(`rng.int requires finite bounds, got [${min}, ${max}]`);
|
|
29
|
+
}
|
|
30
|
+
if (min > max)
|
|
31
|
+
throw new RangeError(`rng.int: min (${min}) > max (${max})`);
|
|
32
|
+
const lo = Math.ceil(min);
|
|
33
|
+
const hi = Math.floor(max);
|
|
34
|
+
return lo + Math.floor(next() * (hi - lo + 1));
|
|
35
|
+
},
|
|
36
|
+
pick(items) {
|
|
37
|
+
if (items.length === 0)
|
|
38
|
+
throw new RangeError('rng.pick: empty array');
|
|
39
|
+
const idx = Math.floor(next() * items.length);
|
|
40
|
+
// Safe: idx ∈ [0, items.length-1]
|
|
41
|
+
return items[idx];
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/** Derive a 32-bit unsigned seed from an arbitrary string (FNV-1a 32-bit). */
|
|
46
|
+
export const seedFromString = (s) => {
|
|
47
|
+
let h = 0x811c9dc5;
|
|
48
|
+
for (let i = 0; i < s.length; i += 1) {
|
|
49
|
+
h ^= s.charCodeAt(i);
|
|
50
|
+
h = Math.imul(h, 0x01000193);
|
|
51
|
+
}
|
|
52
|
+
return h >>> 0;
|
|
53
|
+
};
|
|
54
|
+
/** Convenience: build an Rng from a string seed. */
|
|
55
|
+
export const rngFromString = (s) => mulberry32(seedFromString(s));
|
|
56
|
+
//# sourceMappingURL=prng.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prng.js","sourceRoot":"","sources":["../../src/foundation/prng.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAO,EAAE;IAC9C,aAAa;IACb,IAAI,KAAK,GAAG,IAAI,KAAK,CAAC,CAAA;IAEtB,MAAM,IAAI,GAAG,GAAW,EAAE;QACxB,KAAK,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QAClC,IAAI,CAAC,GAAG,KAAK,CAAA;QACb,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;QACpC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;QACzC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,UAAU,CAAA;IAC9C,CAAC,CAAA;IAED,OAAO;QACL,IAAI;QACJ,GAAG,CAAC,GAAG,EAAE,GAAG;YACV,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,UAAU,CAAC,wCAAwC,GAAG,KAAK,GAAG,GAAG,CAAC,CAAA;YAC9E,CAAC;YACD,IAAI,GAAG,GAAG,GAAG;gBAAE,MAAM,IAAI,UAAU,CAAC,iBAAiB,GAAG,YAAY,GAAG,GAAG,CAAC,CAAA;YAC3E,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC1B,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;QAChD,CAAC;QACD,IAAI,CAAI,KAAmB;YACzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,UAAU,CAAC,uBAAuB,CAAC,CAAA;YACrE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;YAC7C,kCAAkC;YAClC,OAAO,KAAK,CAAC,GAAG,CAAM,CAAA;QACxB,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAS,EAAU,EAAE;IAClD,IAAI,CAAC,GAAG,UAAU,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QACpB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IAC9B,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,CAAA;AAChB,CAAC,CAAA;AAED,oDAAoD;AACpD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAS,EAAO,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phantom-typed schema builder + Infer<>.
|
|
3
|
+
*
|
|
4
|
+
* Every builder carries:
|
|
5
|
+
* - `_node`: serializable IR (runtime)
|
|
6
|
+
* - `_type`: phantom TS type parameter for inference (compile-time only)
|
|
7
|
+
*
|
|
8
|
+
* Modifiers (.nullable / .optional / .default / .describe) return a *new*
|
|
9
|
+
* builder with updated phantom type and updated IR.
|
|
10
|
+
*/
|
|
11
|
+
import type { Axes, DerivedFn, Distribution, DomainConstraint, InvariantFn } from './axes.js';
|
|
12
|
+
import type { Modifiers, SchemaNode } from './ir.js';
|
|
13
|
+
/**
|
|
14
|
+
* Module-private capability marker symbol keys.
|
|
15
|
+
*
|
|
16
|
+
* Schemas opt into a capability by `declare`ing the corresponding bracketed
|
|
17
|
+
* property as the literal `true`. Methods like `.weighted` / `.normal` /
|
|
18
|
+
* `.typically` then gate themselves with a `this:` constraint that requires
|
|
19
|
+
* the marker. Symbols (rather than string keys like `_capDiscrete`) keep the
|
|
20
|
+
* markers out of consumer IntelliSense and out of any `Object.keys` loop.
|
|
21
|
+
*
|
|
22
|
+
* Three caps are required to mirror the runtime allow-list cleanly:
|
|
23
|
+
*
|
|
24
|
+
* - `Discrete` — values are enumerable; `.weighted` is meaningful.
|
|
25
|
+
* Carried by `str / int / bool / literal / enum`.
|
|
26
|
+
* - `Numeric` — values are bounded numerics; `.typically(from, to)` is
|
|
27
|
+
* meaningful (the generator clamps and, for integers,
|
|
28
|
+
* rounds). Carried by `num / int / decimal`.
|
|
29
|
+
* - `Continuous` — values are real-valued; `.normal(mean, σ)` is
|
|
30
|
+
* meaningful (Gaussian on integers would silently lose
|
|
31
|
+
* σ to rounding, so int is excluded). Carried by
|
|
32
|
+
* `num / decimal`.
|
|
33
|
+
*
|
|
34
|
+
* The symbols are real runtime values so subclass files can `import` them
|
|
35
|
+
* to redeclare the marker. They are NOT re-exported from the package root
|
|
36
|
+
* or from `@databehave/schema/internal`; the package's `exports` field
|
|
37
|
+
* limits deep-path imports to those two entries.
|
|
38
|
+
*/
|
|
39
|
+
export declare const Discrete: unique symbol;
|
|
40
|
+
export declare const Numeric: unique symbol;
|
|
41
|
+
export declare const Continuous: unique symbol;
|
|
42
|
+
/** Base builder. Subclasses (StringSchema, NumberSchema, …) extend this. */
|
|
43
|
+
export declare class Schema<T = unknown> {
|
|
44
|
+
readonly _type: T;
|
|
45
|
+
readonly _node: SchemaNode;
|
|
46
|
+
readonly [Discrete]: boolean;
|
|
47
|
+
readonly [Numeric]: boolean;
|
|
48
|
+
readonly [Continuous]: boolean;
|
|
49
|
+
constructor(node: SchemaNode);
|
|
50
|
+
nullable(): Schema<T | null>;
|
|
51
|
+
optional(): Schema<T | undefined>;
|
|
52
|
+
default(value: T): Schema<T>;
|
|
53
|
+
describe(text: string): this;
|
|
54
|
+
/** Weighted distribution over discrete values. Weights are relative. */
|
|
55
|
+
weighted(this: this & {
|
|
56
|
+
readonly [Discrete]: true;
|
|
57
|
+
}, weights: ReadonlyArray<readonly [T & (string | number | boolean), number]>): this;
|
|
58
|
+
/** Normal (Gaussian) distribution for numeric schemas. */
|
|
59
|
+
normal(this: this & {
|
|
60
|
+
readonly [Continuous]: true;
|
|
61
|
+
}, mean: number, stddev: number): this;
|
|
62
|
+
/** Typical range — values concentrate uniformly inside [from, to]. */
|
|
63
|
+
typically(this: this & {
|
|
64
|
+
readonly [Numeric]: true;
|
|
65
|
+
}, from: number, to: number): this;
|
|
66
|
+
/** Force `value` with probability `p` (stacks before base distribution). */
|
|
67
|
+
occasionally(value: T, p: number): this;
|
|
68
|
+
/**
|
|
69
|
+
* Force `value` every `every` rows (deterministic, driven by `ctx.index`).
|
|
70
|
+
*
|
|
71
|
+
* Useful for periodic rare events that must hit at a guaranteed cadence
|
|
72
|
+
* (e.g. a recurring reset every N rows). Skipped when `ctx.index` is undefined.
|
|
73
|
+
*/
|
|
74
|
+
eventually(every: number, value: T, opts?: {
|
|
75
|
+
readonly offset?: number;
|
|
76
|
+
}): this;
|
|
77
|
+
/**
|
|
78
|
+
* Field is computed from sibling/root context — generator skips sampling.
|
|
79
|
+
*
|
|
80
|
+
* The generic `U extends T` ensures the function's return type is
|
|
81
|
+
* assignable to the schema's value type. Combined with `relate(rows, field)`
|
|
82
|
+
* (which propagates `R[K]` through `DerivedFn<R[K]>`), this catches
|
|
83
|
+
* FK-type mismatches at compile time
|
|
84
|
+
* (e.g. `int().derivedFrom(relate(rowsWithStringSku, 'sku'))`).
|
|
85
|
+
*/
|
|
86
|
+
derivedFrom<U extends T>(fn: DerivedFn<U>): this;
|
|
87
|
+
/** Single-record predicate. Generator retries up to MAX_ATTEMPTS to satisfy. */
|
|
88
|
+
invariant(fn: InvariantFn): this;
|
|
89
|
+
/** Restrict to a closed candidate set or a lookup-by-sibling-field map. */
|
|
90
|
+
in(constraint: DomainConstraint | readonly unknown[]): this;
|
|
91
|
+
/**
|
|
92
|
+
* Re-apply a complete `Axes` record to this schema. Public so that
|
|
93
|
+
* IR-reconstruction helpers (e.g. `fromIR`) can replay axes without
|
|
94
|
+
* reaching through a protected method via casts. Prefer the fluent axis
|
|
95
|
+
* builders (`.weighted`, `.in`, `.derivedFrom`, ...) in user code.
|
|
96
|
+
*
|
|
97
|
+
* Note: this is a low-level escape hatch — it does NOT run the
|
|
98
|
+
* capability allow-list that `.weighted` / `.normal` / `.typically`
|
|
99
|
+
* apply. Callers that round-trip IR are trusted to keep the IR coherent.
|
|
100
|
+
*/
|
|
101
|
+
_applyAxes(axes: Axes): this;
|
|
102
|
+
protected withAxes(axes: Axes): this;
|
|
103
|
+
protected withModsPreserveType(patch: Partial<Modifiers>): this;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Infer the TypeScript type a schema generates / accepts.
|
|
107
|
+
*
|
|
108
|
+
* ```ts
|
|
109
|
+
* const User = obj({ id: int(), name: str() })
|
|
110
|
+
* type User = Infer<typeof User> // { id: number; name: string }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export type Infer<S> = S extends Schema<infer T> ? T : never;
|
|
114
|
+
/** Re-export modifier shape for advanced consumers. */
|
|
115
|
+
export type { Distribution, DomainConstraint, Modifiers, SchemaNode };
|
|
116
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/foundation/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,gBAAgB,EAAsB,WAAW,EAAsB,MAAM,WAAW,CAAA;AAErI,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGpD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,QAAQ,EAAE,OAAO,MAA0C,CAAA;AACxE,eAAO,MAAM,OAAO,EAAE,OAAO,MAAyC,CAAA;AACtE,eAAO,MAAM,UAAU,EAAE,OAAO,MAA4C,CAAA;AA0D5E,4EAA4E;AAC5E,qBAAa,MAAM,CAAC,CAAC,GAAG,OAAO;IAC7B,SAAiB,KAAK,EAAE,CAAC,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAmB1B,SAAiB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IACpC,SAAiB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IACnC,SAAiB,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;gBAE1B,IAAI,EAAE,UAAU;IAI5B,QAAQ,IAAI,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IAI5B,QAAQ,IAAI,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAIjC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAI5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B,wEAAwE;IACxE,QAAQ,CACN,IAAI,EAAE,IAAI,GAAG;QAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;KAAE,EAC1C,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,GACzE,IAAI;IAUP,0DAA0D;IAC1D,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG;QAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,CAAA;KAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAKxF,sEAAsE;IACtE,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG;QAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,CAAA;KAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAKpF,4EAA4E;IAC5E,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAMvC;;;;;OAKG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAY9E;;;;;;;;OAQG;IACH,WAAW,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAIhD,gFAAgF;IAChF,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAIhC,2EAA2E;IAC3E,EAAE,CAAC,UAAU,EAAE,gBAAgB,GAAG,SAAS,OAAO,EAAE,GAAG,IAAI;IAQ3D;;;;;;;;;OASG;IACH,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAG5B,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIpC,SAAS,CAAC,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;CAOhE;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAE5D,uDAAuD;AACvD,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAAE,CAAA"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phantom-typed schema builder + Infer<>.
|
|
3
|
+
*
|
|
4
|
+
* Every builder carries:
|
|
5
|
+
* - `_node`: serializable IR (runtime)
|
|
6
|
+
* - `_type`: phantom TS type parameter for inference (compile-time only)
|
|
7
|
+
*
|
|
8
|
+
* Modifiers (.nullable / .optional / .default / .describe) return a *new*
|
|
9
|
+
* builder with updated phantom type and updated IR.
|
|
10
|
+
*/
|
|
11
|
+
import { SchemaConflictError } from './errors.js';
|
|
12
|
+
import { withMods } from './ir.js';
|
|
13
|
+
/**
|
|
14
|
+
* Module-private capability marker symbol keys.
|
|
15
|
+
*
|
|
16
|
+
* Schemas opt into a capability by `declare`ing the corresponding bracketed
|
|
17
|
+
* property as the literal `true`. Methods like `.weighted` / `.normal` /
|
|
18
|
+
* `.typically` then gate themselves with a `this:` constraint that requires
|
|
19
|
+
* the marker. Symbols (rather than string keys like `_capDiscrete`) keep the
|
|
20
|
+
* markers out of consumer IntelliSense and out of any `Object.keys` loop.
|
|
21
|
+
*
|
|
22
|
+
* Three caps are required to mirror the runtime allow-list cleanly:
|
|
23
|
+
*
|
|
24
|
+
* - `Discrete` — values are enumerable; `.weighted` is meaningful.
|
|
25
|
+
* Carried by `str / int / bool / literal / enum`.
|
|
26
|
+
* - `Numeric` — values are bounded numerics; `.typically(from, to)` is
|
|
27
|
+
* meaningful (the generator clamps and, for integers,
|
|
28
|
+
* rounds). Carried by `num / int / decimal`.
|
|
29
|
+
* - `Continuous` — values are real-valued; `.normal(mean, σ)` is
|
|
30
|
+
* meaningful (Gaussian on integers would silently lose
|
|
31
|
+
* σ to rounding, so int is excluded). Carried by
|
|
32
|
+
* `num / decimal`.
|
|
33
|
+
*
|
|
34
|
+
* The symbols are real runtime values so subclass files can `import` them
|
|
35
|
+
* to redeclare the marker. They are NOT re-exported from the package root
|
|
36
|
+
* or from `@databehave/schema/internal`; the package's `exports` field
|
|
37
|
+
* limits deep-path imports to those two entries.
|
|
38
|
+
*/
|
|
39
|
+
export const Discrete = Symbol('databehave.cap.discrete');
|
|
40
|
+
export const Numeric = Symbol('databehave.cap.numeric');
|
|
41
|
+
export const Continuous = Symbol('databehave.cap.continuous');
|
|
42
|
+
/**
|
|
43
|
+
* Allow-list for which IR kinds may legally carry each axis distribution.
|
|
44
|
+
*
|
|
45
|
+
* Mirrors the type-system `this:` gating on `.weighted` / `.normal` /
|
|
46
|
+
* `.typically`. Used by the runtime guard in those methods to fail-loud
|
|
47
|
+
* when a caller bypasses TypeScript (`as any`, plain JS, `// @ts-ignore`).
|
|
48
|
+
*
|
|
49
|
+
* Stays in sync with `docs/stability.md` "capability matrix".
|
|
50
|
+
*/
|
|
51
|
+
const CAP_BY_OP = {
|
|
52
|
+
// .weighted: discrete-valued kinds. For `kind:'number'` it is allowed only
|
|
53
|
+
// when `int === true` (further check below).
|
|
54
|
+
weighted: new Set(['number', 'string', 'literal', 'enum', 'boolean']),
|
|
55
|
+
// .normal: continuous-numeric kinds. For `kind:'number'` it is allowed
|
|
56
|
+
// only when `int === false` (further check below).
|
|
57
|
+
normal: new Set(['number', 'decimal']),
|
|
58
|
+
// .typically: any numeric kind (int or float or decimal — for ints the
|
|
59
|
+
// generator clamps and rounds).
|
|
60
|
+
typically: new Set(['number', 'decimal']),
|
|
61
|
+
};
|
|
62
|
+
const checkAxisAllowed = (op, node) => {
|
|
63
|
+
if (!CAP_BY_OP[op].has(node.kind)) {
|
|
64
|
+
throw new SchemaConflictError(`.${op}() is not applicable to schema kind '${node.kind}'`, [], `see docs/stability.md (capability matrix)`);
|
|
65
|
+
}
|
|
66
|
+
// Number-kind is split between `int()` (discrete) and `num()` (continuous).
|
|
67
|
+
if (node.kind === 'number') {
|
|
68
|
+
const isInt = node.int === true;
|
|
69
|
+
if (op === 'weighted' && !isInt) {
|
|
70
|
+
throw new SchemaConflictError(`.weighted() is not applicable to num() (continuous); use int().weighted([...]) for discrete numeric weighting`, [], `see docs/stability.md (capability matrix)`);
|
|
71
|
+
}
|
|
72
|
+
if (op === 'normal' && isInt) {
|
|
73
|
+
throw new SchemaConflictError(`.normal() is not applicable to int() (discrete); use num().normal(...) for a continuous Gaussian`, [], `see docs/stability.md (capability matrix)`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/** Base builder. Subclasses (StringSchema, NumberSchema, …) extend this. */
|
|
78
|
+
export class Schema {
|
|
79
|
+
_node;
|
|
80
|
+
constructor(node) {
|
|
81
|
+
this._node = node;
|
|
82
|
+
}
|
|
83
|
+
nullable() {
|
|
84
|
+
return new Schema(withMods(this._node, { nullable: true }));
|
|
85
|
+
}
|
|
86
|
+
optional() {
|
|
87
|
+
return new Schema(withMods(this._node, { optional: true }));
|
|
88
|
+
}
|
|
89
|
+
default(value) {
|
|
90
|
+
return new Schema(withMods(this._node, { hasDefault: true, defaultValue: value }));
|
|
91
|
+
}
|
|
92
|
+
describe(text) {
|
|
93
|
+
return this.withModsPreserveType({ description: text });
|
|
94
|
+
}
|
|
95
|
+
// ── data-schema axes ──────────────────────────────────────────────────────
|
|
96
|
+
/** Weighted distribution over discrete values. Weights are relative. */
|
|
97
|
+
weighted(weights) {
|
|
98
|
+
checkAxisAllowed('weighted', this._node);
|
|
99
|
+
return this.withAxes({
|
|
100
|
+
distribution: {
|
|
101
|
+
kind: 'weighted',
|
|
102
|
+
weights: weights,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/** Normal (Gaussian) distribution for numeric schemas. */
|
|
107
|
+
normal(mean, stddev) {
|
|
108
|
+
checkAxisAllowed('normal', this._node);
|
|
109
|
+
return this.withAxes({ distribution: { kind: 'normal', mean, stddev } });
|
|
110
|
+
}
|
|
111
|
+
/** Typical range — values concentrate uniformly inside [from, to]. */
|
|
112
|
+
typically(from, to) {
|
|
113
|
+
checkAxisAllowed('typically', this._node);
|
|
114
|
+
return this.withAxes({ distribution: { kind: 'typical', from, to } });
|
|
115
|
+
}
|
|
116
|
+
/** Force `value` with probability `p` (stacks before base distribution). */
|
|
117
|
+
occasionally(value, p) {
|
|
118
|
+
if (!(p >= 0 && p <= 1))
|
|
119
|
+
throw new RangeError(`occasionally: p must be in [0,1], got ${p}`);
|
|
120
|
+
const override = { value, p };
|
|
121
|
+
return this.withAxes({ occasionally: [override] });
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Force `value` every `every` rows (deterministic, driven by `ctx.index`).
|
|
125
|
+
*
|
|
126
|
+
* Useful for periodic rare events that must hit at a guaranteed cadence
|
|
127
|
+
* (e.g. a recurring reset every N rows). Skipped when `ctx.index` is undefined.
|
|
128
|
+
*/
|
|
129
|
+
eventually(every, value, opts) {
|
|
130
|
+
if (!Number.isInteger(every) || every < 1) {
|
|
131
|
+
throw new RangeError(`eventually: every must be a positive integer, got ${every}`);
|
|
132
|
+
}
|
|
133
|
+
const override = {
|
|
134
|
+
value,
|
|
135
|
+
every,
|
|
136
|
+
...(opts?.offset !== undefined ? { offset: opts.offset } : {}),
|
|
137
|
+
};
|
|
138
|
+
return this.withAxes({ eventually: [override] });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Field is computed from sibling/root context — generator skips sampling.
|
|
142
|
+
*
|
|
143
|
+
* The generic `U extends T` ensures the function's return type is
|
|
144
|
+
* assignable to the schema's value type. Combined with `relate(rows, field)`
|
|
145
|
+
* (which propagates `R[K]` through `DerivedFn<R[K]>`), this catches
|
|
146
|
+
* FK-type mismatches at compile time
|
|
147
|
+
* (e.g. `int().derivedFrom(relate(rowsWithStringSku, 'sku'))`).
|
|
148
|
+
*/
|
|
149
|
+
derivedFrom(fn) {
|
|
150
|
+
return this.withAxes({ derived: fn });
|
|
151
|
+
}
|
|
152
|
+
/** Single-record predicate. Generator retries up to MAX_ATTEMPTS to satisfy. */
|
|
153
|
+
invariant(fn) {
|
|
154
|
+
return this.withAxes({ invariants: [fn] });
|
|
155
|
+
}
|
|
156
|
+
/** Restrict to a closed candidate set or a lookup-by-sibling-field map. */
|
|
157
|
+
in(constraint) {
|
|
158
|
+
const dom = Array.isArray(constraint)
|
|
159
|
+
? { kind: 'values', values: constraint }
|
|
160
|
+
: constraint;
|
|
161
|
+
return this.withAxes({ domain: dom });
|
|
162
|
+
}
|
|
163
|
+
// ── internal helpers ──────────────────────────────────────────────────────
|
|
164
|
+
/**
|
|
165
|
+
* Re-apply a complete `Axes` record to this schema. Public so that
|
|
166
|
+
* IR-reconstruction helpers (e.g. `fromIR`) can replay axes without
|
|
167
|
+
* reaching through a protected method via casts. Prefer the fluent axis
|
|
168
|
+
* builders (`.weighted`, `.in`, `.derivedFrom`, ...) in user code.
|
|
169
|
+
*
|
|
170
|
+
* Note: this is a low-level escape hatch — it does NOT run the
|
|
171
|
+
* capability allow-list that `.weighted` / `.normal` / `.typically`
|
|
172
|
+
* apply. Callers that round-trip IR are trusted to keep the IR coherent.
|
|
173
|
+
*/
|
|
174
|
+
_applyAxes(axes) {
|
|
175
|
+
return this.withModsPreserveType({ axes });
|
|
176
|
+
}
|
|
177
|
+
withAxes(axes) {
|
|
178
|
+
return this.withModsPreserveType({ axes });
|
|
179
|
+
}
|
|
180
|
+
withModsPreserveType(patch) {
|
|
181
|
+
const next = Object.create(Object.getPrototypeOf(this));
|
|
182
|
+
Object.assign(next, this, {
|
|
183
|
+
_node: withMods(this._node, patch),
|
|
184
|
+
});
|
|
185
|
+
return next;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/foundation/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extensibility API — IR walker and IR-to-builder reconstruction.
|
|
3
|
+
*
|
|
4
|
+
* databehave intentionally ships no CLI, no OpenAPI ingestion, no zod adapter,
|
|
5
|
+
* no GUI — these belong in *external* packages. This module exposes the
|
|
6
|
+
* minimum surface those packages need:
|
|
7
|
+
*
|
|
8
|
+
* - `walkSchema(node, visitor)` : pre/post-order traversal with paths
|
|
9
|
+
* - `fromIR(node)` : reconstruct a `Schema` builder from IR
|
|
10
|
+
*
|
|
11
|
+
* Combined with the already-public `SchemaNode`, `Modifiers`, `Axes`,
|
|
12
|
+
* `mock`, `parse`, `mockDataset`, `createTrace`, and `seedFromString` /
|
|
13
|
+
* `rngFromString`, this is the full extension contract.
|
|
14
|
+
*
|
|
15
|
+
* Extension authors do NOT subclass `Schema`. They build IR (or compose
|
|
16
|
+
* existing builders) and call `fromIR` to obtain a typed builder back.
|
|
17
|
+
*/
|
|
18
|
+
import { Schema } from './types.js';
|
|
19
|
+
import type { SchemaNode } from './ir.js';
|
|
20
|
+
export type WalkPath = readonly (string | number)[];
|
|
21
|
+
export type SchemaVisitor = {
|
|
22
|
+
/** Called before descending into a node's children. Return false to skip subtree. */
|
|
23
|
+
readonly enter?: (node: SchemaNode, path: WalkPath) => void | boolean;
|
|
24
|
+
/** Called after all children have been visited. */
|
|
25
|
+
readonly leave?: (node: SchemaNode, path: WalkPath) => void;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Depth-first pre/post-order traversal of a schema IR tree.
|
|
29
|
+
*
|
|
30
|
+
* The visitor receives every node (including composites) with its
|
|
31
|
+
* JSON-pointer-style path. Use this to power codegen (OpenAPI, zod, SQL DDL,
|
|
32
|
+
* documentation) without coupling to the builder classes.
|
|
33
|
+
*/
|
|
34
|
+
export declare const walkSchema: (schemaOrNode: Schema | SchemaNode, visitor: SchemaVisitor) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Reconstruct a `Schema` builder from an IR node.
|
|
37
|
+
*
|
|
38
|
+
* Modifiers (`nullable`, `optional`, `default`, `describe`, axes) are
|
|
39
|
+
* preserved. Returns `Schema<unknown>` — extension authors that know the shape
|
|
40
|
+
* statically can cast to a more precise type.
|
|
41
|
+
*/
|
|
42
|
+
export declare const fromIR: (node: SchemaNode) => Schema<unknown>;
|
|
43
|
+
/** Current IR contract version. Bumped on every MAJOR release. */
|
|
44
|
+
export declare const IR_VERSION: 1;
|
|
45
|
+
/** Envelope produced by {@link serializeSchema}. */
|
|
46
|
+
export interface SchemaEnvelope {
|
|
47
|
+
/** Reserved for forward compatibility; do not vary. */
|
|
48
|
+
readonly $databehaveVersion: typeof IR_VERSION;
|
|
49
|
+
readonly node: SchemaNode;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Wrap a schema's IR in a versioned envelope safe for serialisation
|
|
53
|
+
* (JSON, disk, IPC). Pair with {@link deserializeSchema} on the
|
|
54
|
+
* receiving end.
|
|
55
|
+
*
|
|
56
|
+
* Throws {@link SchemaConflictError} (`code: 'serialize.closure-axis'`)
|
|
57
|
+
* when any node in the tree carries a closure-bearing axis — `derived`,
|
|
58
|
+
* `invariants`, or an `occasionally` override whose `value` is a
|
|
59
|
+
* function. Closures cannot survive a JSON round-trip, so encoding such
|
|
60
|
+
* a schema would silently drop the axis on the receiving end and
|
|
61
|
+
* produce subtly wrong values. The check is loud at the encode site so
|
|
62
|
+
* callers reach for {@link replay} or hand-coded carriers instead.
|
|
63
|
+
*/
|
|
64
|
+
export declare const serializeSchema: (schema: Schema<unknown>) => SchemaEnvelope;
|
|
65
|
+
/**
|
|
66
|
+
* Inverse of {@link serializeSchema}. Throws when the envelope was
|
|
67
|
+
* produced by an incompatible MAJOR version — the failure is loud
|
|
68
|
+
* because silently loading a node with a renamed or removed field
|
|
69
|
+
* would manifest as a subtle generation/parse bug far from the cause.
|
|
70
|
+
*/
|
|
71
|
+
export declare const deserializeSchema: (envelope: unknown) => Schema<unknown>;
|
|
72
|
+
//# sourceMappingURL=walk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../../src/foundation/walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;AAEnD,MAAM,MAAM,aAAa,GAAG;IAC1B,qFAAqF;IACrF,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAA;IACrE,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;CAC5D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GACrB,cAAc,MAAM,GAAG,UAAU,EACjC,SAAS,aAAa,KACrB,IAGF,CAAA;AAkCD;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,GAAI,MAAM,UAAU,KAAG,MAAM,CAAC,OAAO,CAGvD,CAAA;AA2FD,kEAAkE;AAClE,eAAO,MAAM,UAAU,EAAG,CAAU,CAAA;AAEpC,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,kBAAkB,EAAE,OAAO,UAAU,CAAA;IAC9C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,CAAC,OAAO,CAAC,KAAG,cAMzD,CAAA;AA+DD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,OAAO,KAAG,MAAM,CAAC,OAAO,CAmBnE,CAAA"}
|