@ghostry/fabricator 0.0.1 → 0.0.3
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 +18 -12
- package/dist/esm/Adapter/Core.js +3 -3
- package/dist/esm/Enumeration/Enumerate.js +16 -13
- package/dist/esm/Error/index.js +16 -8
- package/dist/esm/Fabricator/Constructor.js +12 -14
- package/dist/esm/Harnessing/Core.js +30 -0
- package/dist/esm/Harnessing/Salt.js +12 -0
- package/dist/esm/Harnessing/Types.js +1 -0
- package/dist/esm/Instance/Core.js +25 -41
- package/dist/esm/Instance/Stack/Async.js +10 -0
- package/dist/esm/Instance/Stack/Sync.js +16 -0
- package/dist/esm/Primitive/bigint/Registry.js +12 -12
- package/dist/esm/Primitive/boolean/Registry.js +2 -1
- package/dist/esm/Primitive/date/Registry.js +15 -14
- package/dist/esm/Primitive/null/Registry.js +2 -1
- package/dist/esm/Primitive/number/Registry.js +18 -17
- package/dist/esm/Primitive/recursive/Fabricator.js +1 -1
- package/dist/esm/Primitive/symbol/Registry.js +2 -1
- package/dist/esm/Primitive/undefined/Registry.js +2 -1
- package/dist/esm/Random/index.js +24 -79
- package/dist/esm/Utility/Core.js +6 -1
- package/dist/esm/adapting.js +2 -0
- package/dist/esm/harnessing.js +1 -0
- package/dist/esm/index.js +5 -4
- package/dist/esm/internal.js +2 -2
- package/dist/types/Adapter/Core.d.ts +30 -33
- package/dist/types/Adapter/Types.d.ts +78 -88
- package/dist/types/Bound.d.ts +15 -15
- package/dist/types/Distribution/index.d.ts +54 -61
- package/dist/types/Enumeration/Enumerate.d.ts +24 -24
- package/dist/types/Enumeration/Plan.d.ts +22 -26
- package/dist/types/Enumeration/Types.d.ts +38 -43
- package/dist/types/Error/index.d.ts +103 -89
- package/dist/types/Fabricator/Constructor.d.ts +24 -26
- package/dist/types/Fabricator/Types.d.ts +73 -81
- package/dist/types/Harnessing/Core.d.ts +43 -0
- package/dist/types/Harnessing/Salt.d.ts +31 -0
- package/dist/types/Harnessing/Types.d.ts +79 -0
- package/dist/types/Instance/Core.d.ts +38 -74
- package/dist/types/Instance/Stack/Async.d.ts +14 -0
- package/dist/types/Instance/Stack/Sync.d.ts +14 -0
- package/dist/types/Instance/Types.d.ts +98 -102
- package/dist/types/Primitive/always/Schema.d.ts +8 -8
- package/dist/types/Primitive/always/Types.d.ts +7 -7
- package/dist/types/Primitive/array/Registry.d.ts +10 -8
- package/dist/types/Primitive/array/Schema.d.ts +4 -5
- package/dist/types/Primitive/array/Types.d.ts +6 -6
- package/dist/types/Primitive/bigint/Registry.d.ts +6 -6
- package/dist/types/Primitive/bigint/Schema.d.ts +8 -8
- package/dist/types/Primitive/bigint/Types.d.ts +5 -5
- package/dist/types/Primitive/boolean/Outcomes.d.ts +8 -8
- package/dist/types/Primitive/boolean/Registry.d.ts +2 -12
- package/dist/types/Primitive/boolean/Schema.d.ts +8 -8
- package/dist/types/Primitive/boolean/Types.d.ts +3 -3
- package/dist/types/Primitive/choice/Fabricator.d.ts +6 -7
- package/dist/types/Primitive/choice/Registry.d.ts +13 -13
- package/dist/types/Primitive/choice/Schema.d.ts +6 -6
- package/dist/types/Primitive/choice/Types.d.ts +11 -11
- package/dist/types/Primitive/date/Registry.d.ts +25 -48
- package/dist/types/Primitive/date/Schema.d.ts +9 -10
- package/dist/types/Primitive/date/Types.d.ts +4 -4
- package/dist/types/Primitive/enum/Registry.d.ts +13 -13
- package/dist/types/Primitive/enum/Schema.d.ts +5 -5
- package/dist/types/Primitive/enum/Types.d.ts +17 -19
- package/dist/types/Primitive/namespace.d.ts +10 -10
- package/dist/types/Primitive/null/Registry.d.ts +2 -2
- package/dist/types/Primitive/null/Schema.d.ts +2 -2
- package/dist/types/Primitive/null/Types.d.ts +3 -3
- package/dist/types/Primitive/nullable/Fabricator.d.ts +7 -7
- package/dist/types/Primitive/nullable/Schema.d.ts +13 -13
- package/dist/types/Primitive/nullable/Types.d.ts +9 -10
- package/dist/types/Primitive/nullish/Fabricator.d.ts +12 -13
- package/dist/types/Primitive/nullish/Schema.d.ts +8 -8
- package/dist/types/Primitive/nullish/Types.d.ts +12 -13
- package/dist/types/Primitive/number/Registry.d.ts +20 -38
- package/dist/types/Primitive/number/Schema.d.ts +11 -12
- package/dist/types/Primitive/number/Types.d.ts +13 -13
- package/dist/types/Primitive/number/defaults.d.ts +3 -3
- package/dist/types/Primitive/object/Fabricator.d.ts +15 -15
- package/dist/types/Primitive/object/Registry.d.ts +8 -8
- package/dist/types/Primitive/object/Schema.d.ts +10 -10
- package/dist/types/Primitive/object/Types.d.ts +20 -22
- package/dist/types/Primitive/object/compute/Fabricator.d.ts +4 -5
- package/dist/types/Primitive/object/compute/Schema.d.ts +4 -4
- package/dist/types/Primitive/object/compute/Types.d.ts +19 -20
- package/dist/types/Primitive/object/omittable/Fabricator.d.ts +10 -10
- package/dist/types/Primitive/object/omittable/Outcomes.d.ts +2 -2
- package/dist/types/Primitive/object/omittable/Schema.d.ts +11 -11
- package/dist/types/Primitive/object/omittable/Types.d.ts +14 -15
- package/dist/types/Primitive/object/optional/Fabricator.d.ts +16 -18
- package/dist/types/Primitive/object/optional/Outcomes.d.ts +2 -2
- package/dist/types/Primitive/object/optional/Schema.d.ts +4 -4
- package/dist/types/Primitive/object/optional/Types.d.ts +17 -17
- package/dist/types/Primitive/opaque/Registry.d.ts +3 -3
- package/dist/types/Primitive/opaque/Schema.d.ts +8 -9
- package/dist/types/Primitive/record/Registry.d.ts +8 -6
- package/dist/types/Primitive/record/Schema.d.ts +9 -11
- package/dist/types/Primitive/record/Types.d.ts +25 -25
- package/dist/types/Primitive/recursive/Fabricator.d.ts +20 -21
- package/dist/types/Primitive/recursive/Registry.d.ts +6 -7
- package/dist/types/Primitive/recursive/Schema.d.ts +8 -8
- package/dist/types/Primitive/recursive/Terminate.d.ts +13 -14
- package/dist/types/Primitive/recursive/Types.d.ts +31 -31
- package/dist/types/Primitive/recursive/self/Fabricator.d.ts +11 -12
- package/dist/types/Primitive/recursive/self/Schema.d.ts +10 -10
- package/dist/types/Primitive/recursive/self/Types.d.ts +7 -8
- package/dist/types/Primitive/string/Constants.d.ts +12 -13
- package/dist/types/Primitive/string/Fabricator.d.ts +2 -2
- package/dist/types/Primitive/string/Registry.d.ts +10 -16
- package/dist/types/Primitive/string/Schema.d.ts +5 -5
- package/dist/types/Primitive/string/Types.d.ts +17 -17
- package/dist/types/Primitive/symbol/Fabricator.d.ts +2 -2
- package/dist/types/Primitive/symbol/Registry.d.ts +4 -11
- package/dist/types/Primitive/symbol/Schema.d.ts +6 -6
- package/dist/types/Primitive/symbol/Types.d.ts +2 -2
- package/dist/types/Primitive/tuple/Fabricator.d.ts +7 -8
- package/dist/types/Primitive/tuple/Schema.d.ts +5 -5
- package/dist/types/Primitive/tuple/Types.d.ts +24 -25
- package/dist/types/Primitive/undefinable/Fabricator.d.ts +7 -7
- package/dist/types/Primitive/undefinable/Schema.d.ts +13 -13
- package/dist/types/Primitive/undefinable/Types.d.ts +10 -10
- package/dist/types/Primitive/undefined/Registry.d.ts +2 -2
- package/dist/types/Primitive/undefined/Schema.d.ts +4 -4
- package/dist/types/Primitive/undefined/Types.d.ts +3 -3
- package/dist/types/Random/Generator/sfc32.d.ts +4 -4
- package/dist/types/Random/Types.d.ts +151 -293
- package/dist/types/Random/index.d.ts +56 -81
- package/dist/types/Schema/Core.d.ts +19 -21
- package/dist/types/Schema/Registry.d.ts +3 -3
- package/dist/types/Schema/Types.d.ts +41 -48
- package/dist/types/Types.d.ts +39 -45
- package/dist/types/Utility/Core.d.ts +18 -9
- package/dist/types/adapting.d.ts +32 -0
- package/dist/types/harnessing.d.ts +30 -0
- package/dist/types/index.d.ts +95 -128
- package/dist/types/internal.d.ts +53 -40
- package/package.json +39 -7
- package/dist/esm/Random/CallSite.js +0 -56
- package/dist/types/Random/CallSite.d.ts +0 -59
|
@@ -5,37 +5,37 @@ import { Produces, type Adaptation, type Kind, type Meta } from "../../Types";
|
|
|
5
5
|
/**
|
|
6
6
|
* A Schema usable as a record's keys: any Schema whose fabricated value is a
|
|
7
7
|
* legal JS property key. Constrained through the phantom `[Produces]` marker
|
|
8
|
-
* rather than by enumerating kinds, so any current or future key-producing
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* rather than by enumerating kinds, so any current or future key-producing kind
|
|
9
|
+
* qualifies — `T.string.whereby(...)`, `T.symbol`, `T.enum.uniform([...])` of
|
|
10
|
+
* strings, `T.always("k")`, a string `T.choice` — while `T.number`/`T.date` are
|
|
11
|
+
* rejected at the call site.
|
|
12
12
|
*
|
|
13
|
-
* `symbol` is included deliberately: symbols are legal property keys.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* `symbol` is included deliberately: symbols are legal property keys. Excluding
|
|
14
|
+
* them would arbitrarily narrow what a record can describe. They do not survive
|
|
15
|
+
* `Adapter/TypeBox` — see its `record` case.
|
|
16
16
|
*/
|
|
17
17
|
export type Key = AnySchema & {
|
|
18
18
|
readonly [Produces]?: string | symbol;
|
|
19
19
|
};
|
|
20
20
|
export type Value = AnySchema;
|
|
21
21
|
/**
|
|
22
|
-
* Whether a key type spans a whole primitive key type rather than a finite
|
|
23
|
-
*
|
|
22
|
+
* Whether a key type spans a whole primitive key type rather than a finite set
|
|
23
|
+
* of literals — i.e. whether the record's keyspace is open-ended.
|
|
24
24
|
*/
|
|
25
25
|
type IsKeyspaceOpen<$Key> = string extends $Key ? true : symbol extends $Key ? true : false;
|
|
26
26
|
/**
|
|
27
|
-
* Split is
|
|
27
|
+
* Split is _open keyspace vs. finite_, not string vs. symbol.
|
|
28
28
|
*
|
|
29
29
|
* An open key (`string`, `symbol`, or both) is a plain index signature: no
|
|
30
30
|
* `Partial` — an index signature never guarantees a key is present, and
|
|
31
31
|
* wrapping one would only add a spurious `| undefined`. Carrying
|
|
32
|
-
* `ValueOf<$Key>` rather than hardcoding `string` keeps a mixed
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* `ValueOf<$Key>` rather than hardcoding `string` keeps a mixed `string |
|
|
33
|
+
* symbol` key as `Record<string | symbol, ...>` instead of silently dropping
|
|
34
|
+
* the symbol half.
|
|
35
35
|
*
|
|
36
36
|
* A finite literal key set (`enum`/`always`/`choice`) is `Partial`: size is
|
|
37
|
-
* drawn from `whereby.size`, and colliding keys collapse (`Fabricator.ts`),
|
|
38
|
-
*
|
|
37
|
+
* drawn from `whereby.size`, and colliding keys collapse (`Fabricator.ts`), so
|
|
38
|
+
* a two-member key schema may produce only one. Every key present wants
|
|
39
39
|
* `T.object({ ... })` — what a record over a finite key set degenerates to.
|
|
40
40
|
*/
|
|
41
41
|
export type Fabricated<$Key extends Key = Key, $Value extends Value = Value, $Bindings extends unknown[] = []> = IsKeyspaceOpen<ValueOf<$Key, $Bindings>> extends true ? Record<ValueOf<$Key, $Bindings> & PropertyKey, ValueOf<$Value, $Bindings>> : Partial<Record<ValueOf<$Key, $Bindings> & PropertyKey, ValueOf<$Value, $Bindings>>>;
|
|
@@ -43,13 +43,13 @@ export type Fabricated<$Key extends Key = Key, $Value extends Value = Value, $Bi
|
|
|
43
43
|
* How many entries to attempt, uniformly across `[minTried, max]`.
|
|
44
44
|
*
|
|
45
45
|
* Asymmetric naming is the point. Colliding keys collapse rather than being
|
|
46
|
-
* redrawn, so surviving count is only ever
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* `
|
|
46
|
+
* redrawn, so surviving count is only ever _at most_ what was attempted: `max`
|
|
47
|
+
* is a real upper bound; the lower bound is not guaranteed and the field says
|
|
48
|
+
* so. `minTried` is optional, default `0`, matching `string`'s
|
|
49
|
+
* `whereby.length.min`.
|
|
50
50
|
*
|
|
51
|
-
* No bare-number form (unlike `array`'s `length`): "exactly N" is a promise
|
|
52
|
-
*
|
|
51
|
+
* No bare-number form (unlike `array`'s `length`): "exactly N" is a promise a
|
|
52
|
+
* collapsing key set cannot keep.
|
|
53
53
|
*/
|
|
54
54
|
export type Whereby = {
|
|
55
55
|
size: {
|
|
@@ -59,10 +59,10 @@ export type Whereby = {
|
|
|
59
59
|
};
|
|
60
60
|
/**
|
|
61
61
|
* `key`/`value` stay required regardless of `produce` — both are known at
|
|
62
|
-
* `T.record(...)` call time and describe the shape TypeBox derives either
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* `
|
|
62
|
+
* `T.record(...)` call time and describe the shape TypeBox derives either way.
|
|
63
|
+
* `produce` is carried _alongside_ `whereby` rather than replacing it, so a
|
|
64
|
+
* prior size spec survives `as` for future validation — same as `array`'s
|
|
65
|
+
* `Meta`.
|
|
66
66
|
*/
|
|
67
67
|
export type Meta<$Key extends Key = Key, $Value extends Value = Value> = {
|
|
68
68
|
key: $Key;
|
|
@@ -21,27 +21,26 @@ export type Fabricator<$Schema extends {
|
|
|
21
21
|
/**
|
|
22
22
|
* Expansion is lazy — one dispatch per `self` at fabricate time, not unrolled
|
|
23
23
|
* to `depth.max` at build. This is the only place dispatch (assigning a node
|
|
24
|
-
* its private stream) happens
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* (`
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* `initialize()` instance.
|
|
24
|
+
* its private stream) happens _inside_ `fabricate()`, not at `new
|
|
25
|
+
* Fabricator(...)`. Safe because of isolation, not memoization: every other
|
|
26
|
+
* kind's dispatch count is a function of schema shape, so structural path
|
|
27
|
+
* keying already identifies it. A recursive node's count is data-dependent —
|
|
28
|
+
* how deep this `fabricate()` goes — so no structural path distinguishes
|
|
29
|
+
* sibling expansions at the same depth (an `array` of three `self` children
|
|
30
|
+
* calls `fabricateAt` three times on one shared element Fabricator; the schema
|
|
31
|
+
* does not tell them apart). Each expansion gets its own _root_: `forkSource`
|
|
32
|
+
* mints an isolated `RandomSource` salted from this node's draw, and each
|
|
33
|
+
* `fabricateAt` resolves an ordinary construction root on it
|
|
34
|
+
* (`RandomSource.toRoot`), recorded on each expansion's `trace`. The private
|
|
35
|
+
* source's construction counter orders expansions; nothing to increment here.
|
|
36
|
+
* Isolation also keeps this node's data-dependent draws from perturbing (or
|
|
37
|
+
* being perturbed by) an unrelated Fabricator from the same `initialize()`
|
|
38
|
+
* instance.
|
|
40
39
|
*
|
|
41
40
|
* Each `self` gets its own independently-dispatched expansion — calling
|
|
42
|
-
* `context.self` twice (two array slots) is two `fabricateAt` calls, each
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
41
|
+
* `context.self` twice (two array slots) is two `fabricateAt` calls, each with
|
|
42
|
+
* its own scope and stream space — `tuple`'s per-slot convention, not `array`'s
|
|
43
|
+
* shared-element one. Sibling tree branches therefore draw independently, not a
|
|
44
|
+
* correlated shared sequence.
|
|
46
45
|
*/
|
|
47
|
-
export declare function Fabricator<$Body>(context: FabricatorContext<Schema<$Body>>, forkSource: (
|
|
46
|
+
export declare function Fabricator<$Body>(context: FabricatorContext<Schema<$Body>>, forkSource: (salt: string) => RandomSource, make: (schema: unknown, path: ReadonlyArray<string>, context: ConstructionContext) => NaiveFabricator<unknown>): Fabricator<Schema<$Body>>;
|
|
@@ -9,13 +9,12 @@ import type { Whereby } from "./Types";
|
|
|
9
9
|
*
|
|
10
10
|
* `body` is called exactly once, here, with a single freshly-minted `self`
|
|
11
11
|
* placeholder — eagerly, the same timing `array`/`record` normalize their
|
|
12
|
-
* nested definitions at call time, not deferred to `.whereby()`. Every
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* wrong schema object elsewhere isn't.
|
|
12
|
+
* nested definitions at call time, not deferred to `.whereby()`. Every `self`
|
|
13
|
+
* in the returned schema is this same placeholder; `Constructor.ts`'s `make`
|
|
14
|
+
* matches it only by `[Kind]`, never by identity, so a `self` captured out of
|
|
15
|
+
* its callback and reused elsewhere silently resolves against whichever
|
|
16
|
+
* recursion is currently active rather than erroring — a misuse this library
|
|
17
|
+
* doesn't guard, the same way passing the wrong schema object elsewhere isn't.
|
|
19
18
|
*/
|
|
20
19
|
export default function <const $Body extends AnySchema>(body: (self: SelfSchema) => $Body): {
|
|
21
20
|
whereby(config: Whereby<$Body>): Schema<$Body>;
|
|
@@ -2,19 +2,19 @@ import { type AdaptationEntry } from "../../Adapter/Core";
|
|
|
2
2
|
import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
|
|
3
3
|
import type { Core } from "./Types";
|
|
4
4
|
/**
|
|
5
|
-
* A recursive schema, produced by `.whereby({ depth })` — see
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* A recursive schema, produced by `.whereby({ depth })` — see `Registry.ts` for
|
|
6
|
+
* the builder `T.recursive(body)` itself returns. `terminal` is optional there;
|
|
7
|
+
* omitted, it is derived from `body`.
|
|
8
8
|
*
|
|
9
9
|
* No `.as()`, unlike `array`/`record`: a fully custom whole-value producer
|
|
10
|
-
* would need to be reproducible per depth on its own terms, which is
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* would need to be reproducible per depth on its own terms, which is exactly
|
|
11
|
+
* the problem `depth`/`terminal` already solve — deferred rather than ruled
|
|
12
|
+
* out, since adding it later is non-breaking.
|
|
13
13
|
*/
|
|
14
14
|
export interface Schema<$Body = unknown, $Adaptations extends Adaptations = {}> extends Core<$Body, $Adaptations> {
|
|
15
15
|
/**
|
|
16
|
-
* Override what this schema maps to in one or more external schema
|
|
17
|
-
*
|
|
16
|
+
* Override what this schema maps to in one or more external schema libraries
|
|
17
|
+
* — see `string/Schema.ts`'s `adapt` for the full contract.
|
|
18
18
|
*/
|
|
19
19
|
adapt: <const $Adapter extends Adapter, $Returnable extends ReturnType<$Adapter["convert"]>>(adapter: $Adapter, produce: (adapting: Adapting<Schema<$Body, $Adaptations>>) => $Returnable) => Schema<$Body, WithAdaptations<$Adaptations, AdaptationEntry<$Adapter, $Returnable>>>;
|
|
20
20
|
}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import type { AnySchema } from "../../Schema/Types";
|
|
2
2
|
/**
|
|
3
|
-
* Derive the schema that `fabricateAt` swaps in at `depth.max` when the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
3
|
+
* Derive the schema that `fabricateAt` swaps in at `depth.max` when the caller
|
|
4
|
+
* omits `terminal`. Walks `body` and rewrites every `self` site into a
|
|
5
|
+
* declining state so the result contains _no_ `recursive.self` nodes —
|
|
6
|
+
* `Constructor.ts`'s `make` still dispatches nested schemas eagerly, and
|
|
7
|
+
* `recursive.self` throws when `context.self` is missing (which it is, at the
|
|
8
|
+
* ceiling).
|
|
9
9
|
*
|
|
10
|
-
* Empty collections are `opaque(() => [])` / `opaque(() => ({}))`,
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* would still construct that inner node.
|
|
10
|
+
* Empty collections are `opaque(() => [])` / `opaque(() => ({}))`, never
|
|
11
|
+
* `always([])`: each leaf must get its own reference (see `Recursive.test.ts`).
|
|
12
|
+
* Presence wrappers become a self-free schema that always declines (`null` /
|
|
13
|
+
* `undefined` / `Omitted`), rather than keeping the inner `self` behind a
|
|
14
|
+
* produce short-circuit — `make` would still construct that inner node.
|
|
16
15
|
*
|
|
17
|
-
* Nested `T.recursive` is its own fixed point and is treated as a
|
|
18
|
-
*
|
|
16
|
+
* Nested `T.recursive` is its own fixed point and is treated as a leaf; its
|
|
17
|
+
* inner `self` is not this walk's `self`.
|
|
19
18
|
*/
|
|
20
19
|
export declare function terminate(body: AnySchema): AnySchema;
|
|
@@ -3,11 +3,11 @@ import type { AnySchema, ValueOf } from "../../Schema/Types";
|
|
|
3
3
|
import { Produces, type Adaptation, type Kind, type Meta } from "../../Types";
|
|
4
4
|
/**
|
|
5
5
|
* Fixed point of a recursive schema. A self-referential alias, normally
|
|
6
|
-
* `TS2456` ("`RecursiveValue` circularly references itself") — legal
|
|
6
|
+
* `TS2456` ("`RecursiveValue` circularly references itself") — legal _only_
|
|
7
7
|
* because `ValueOf`'s second argument is read through an interface member
|
|
8
|
-
* (`this["bindings"]` on every composite `Core`), which TypeScript defers.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* (`this["bindings"]` on every composite `Core`), which TypeScript defers. Do
|
|
9
|
+
* not rewrite as a conditional; that reintroduces the error. See `CLAUDE.md`'s
|
|
10
|
+
* "`ValueOf`'s `$Bindings`".
|
|
11
11
|
*
|
|
12
12
|
* Wherever `self` sits in `$Body` (nested through `array`/`object`/`tuple`/
|
|
13
13
|
* etc., each forwarding `this["bindings"]`), it reads `bindings[0]` —
|
|
@@ -19,33 +19,33 @@ export type Fabricated<$Body> = RecursiveValue<$Body>;
|
|
|
19
19
|
* `terminal` is what `self` expands into at `depth.max`, in place of `body`.
|
|
20
20
|
* Expansion is lazy (per `self`, at fabricate time) — see `Fabricator.ts`.
|
|
21
21
|
*
|
|
22
|
-
* Constraining `terminal` against `RecursiveValue<$Body>` as a plain field
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
22
|
+
* Constraining `terminal` against `RecursiveValue<$Body>` as a plain field type
|
|
23
|
+
* (not `terminal`'s own type parameter) is enough: structural assignability
|
|
24
|
+
* already rejects a wrong terminal (e.g. missing a required field `body` has),
|
|
25
|
+
* and nothing downstream needs `terminal`'s precise type (`Core`'s `[Produces]`
|
|
26
|
+
* depends only on `$Body`). A bare-vs-generic comparison rejects the same wrong
|
|
27
|
+
* terminal either way.
|
|
28
28
|
*
|
|
29
29
|
* Omitted, `terminal` is derived from `body` (`Terminate.ts`): every `self`
|
|
30
30
|
* behind a declining kind is rewritten into a stop (empty array/record,
|
|
31
|
-
* remaining non-`self` choice arms, `null`/`undefined`/`Omitted`). A
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* leaf
|
|
31
|
+
* remaining non-`self` choice arms, `null`/`undefined`/`Omitted`). A required
|
|
32
|
+
* `self` cannot be derived — `.whereby()` throws `UnterminableRecursiveError`,
|
|
33
|
+
* and an explicit `terminal` is the way out. A provided `terminal` is a
|
|
34
|
+
* wholesale override of that derivation (custom leaf values, a narrower JSON
|
|
35
|
+
* leaf), not a patch of `self` sites.
|
|
36
36
|
*
|
|
37
|
-
* `depth.max` is a ceiling, not a target: `fabricateAt` (`Fabricator.ts`)
|
|
38
|
-
*
|
|
39
|
-
* `array`/`record`/`string`'s `{min, max}`, there is no drawn count for a
|
|
40
|
-
*
|
|
41
|
-
*
|
|
37
|
+
* `depth.max` is a ceiling, not a target: `fabricateAt` (`Fabricator.ts`) only
|
|
38
|
+
* _compares_ a counter against it, never draws one — unlike
|
|
39
|
+
* `array`/`record`/`string`'s `{min, max}`, there is no drawn count for a `min`
|
|
40
|
+
* to constrain. Realized depth is emergent: intervening kinds decline to
|
|
41
|
+
* recurse (an `array`/`record` rolling 0, a `choice` picking a non-`self`
|
|
42
42
|
* option, an `omittable`/`optional`/`undefinable` resolving absent). The
|
|
43
|
-
* recursive node has no say. "Force `body` while `depth` is below some
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* `
|
|
48
|
-
*
|
|
43
|
+
* recursive node has no say. "Force `body` while `depth` is below some `min`"
|
|
44
|
+
* is a no-op: that already happens below `depth.max`. A genuine floor would
|
|
45
|
+
* coerce those intervening kinds' draws — a different feature than a second
|
|
46
|
+
* number here. The derived terminal may empty a collection whose `body` said
|
|
47
|
+
* `length.min > 0`: the ceiling has to stop somehow, and an explicit `terminal`
|
|
48
|
+
* already did the same with `T.opaque(() => [])`.
|
|
49
49
|
*/
|
|
50
50
|
export type Whereby<$Body> = {
|
|
51
51
|
depth: {
|
|
@@ -68,11 +68,11 @@ export type Meta<$Body = unknown> = {
|
|
|
68
68
|
terminal: AnySchema;
|
|
69
69
|
};
|
|
70
70
|
/**
|
|
71
|
-
* A `type` alias, not an `interface` — unlike every composite that
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
71
|
+
* A `type` alias, not an `interface` — unlike every composite that _contains_ a
|
|
72
|
+
* `self`, `recursive` is where the fixed point _closes_, so `[Produces]` never
|
|
73
|
+
* needs `this["bindings"]`: `RecursiveValue` is already concrete once `$Body`
|
|
74
|
+
* is, regardless of bindings this schema sits inside (a nested `T.recursive` is
|
|
75
|
+
* its own independent fixed point).
|
|
76
76
|
*/
|
|
77
77
|
export type Core<$Body = unknown, $Adaptations extends Adaptations = {}> = {
|
|
78
78
|
[Kind]: "recursive";
|
|
@@ -6,9 +6,8 @@ import type { Fabricated, Meta as ThisMeta } from "./Types";
|
|
|
6
6
|
export type Fabrication<$Fabricator extends Fabricator> = $Fabricator extends Fabricator<infer $Bindings> ? $Bindings[0] : never;
|
|
7
7
|
/**
|
|
8
8
|
* Deliberately not parameterized by a Schema the way every other kind's
|
|
9
|
-
* Fabricator type is — `self` carries no config to read a shape from
|
|
10
|
-
*
|
|
11
|
-
* against.
|
|
9
|
+
* Fabricator type is — `self` carries no config to read a shape from (`[Meta]`
|
|
10
|
+
* is always `{}`), only whatever `$Bindings` its position resolves against.
|
|
12
11
|
*/
|
|
13
12
|
export type Fabricator<$Bindings extends unknown[] = []> = NaiveFabricator<Fabricated<$Bindings>> & {
|
|
14
13
|
[Kind]: "recursive.self";
|
|
@@ -16,14 +15,14 @@ export type Fabricator<$Bindings extends unknown[] = []> = NaiveFabricator<Fabri
|
|
|
16
15
|
readonly trace: Trace;
|
|
17
16
|
};
|
|
18
17
|
/**
|
|
19
|
-
* A transient passthrough, unlike every other kind's Fabricator — it draws
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
18
|
+
* A transient passthrough, unlike every other kind's Fabricator — it draws no
|
|
19
|
+
* randomness of its own: a `self` node stands for wherever `T.recursive`'s
|
|
20
|
+
* current expansion is, and `resolve` _is_ that expansion, one level deeper —
|
|
21
|
+
* the same closure `recursive/Fabricator.ts` hands to every `self` in its body
|
|
22
|
+
* via `Constructor.ts`'s `make` context (`case "recursive.self"`). Calling
|
|
23
|
+
* `resolve` is what actually recurses; this function only wraps it in the shape
|
|
24
|
+
* `make` expects back. Absent `resolve` (a `self` rebuilt from its schema plus
|
|
25
|
+
* trace, without the enclosing recursive parent), `.fabricate()` throws
|
|
26
|
+
* `DetachedSelfError`.
|
|
28
27
|
*/
|
|
29
28
|
export declare function Fabricator<$Bindings extends unknown[]>(context: FabricatorContext<Schema>, resolve?: (() => Fabricated<$Bindings>) | undefined): Fabricator<$Bindings>;
|
|
@@ -2,17 +2,17 @@ import { type AdaptationEntry } from "../../../Adapter/Core";
|
|
|
2
2
|
import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../../Adapter/Types";
|
|
3
3
|
import type { Core } from "./Types";
|
|
4
4
|
/**
|
|
5
|
-
* The placeholder `T.recursive`'s body callback receives in place of the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* The placeholder `T.recursive`'s body callback receives in place of the schema
|
|
6
|
+
* being defined — everywhere `self` appears, it stands for "recurse one level
|
|
7
|
+
* deeper here." Never constructed directly: `T.recursive` is the only thing
|
|
8
|
+
* that mints one, and only ever hands it to its own callback, so there is no
|
|
9
|
+
* bare `T.self`.
|
|
10
10
|
*
|
|
11
|
-
* No `.as()` — unlike `always`, not because there's nothing left to
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* No `.as()` — unlike `always`, not because there's nothing left to override,
|
|
12
|
+
* but because there is nothing here _to_ produce: a `self` node carries no
|
|
13
|
+
* value of its own, only a reference to whatever the enclosing recursion
|
|
14
|
+
* currently binds it to. `adapt` still applies, on the same footing as every
|
|
15
|
+
* other kind.
|
|
16
16
|
*/
|
|
17
17
|
export interface Schema<$Adaptations extends Adaptations = {}> extends Core<$Adaptations> {
|
|
18
18
|
adapt: <const $Adapter extends Adapter, $Returnable extends ReturnType<$Adapter["convert"]>>(adapter: $Adapter, produce: (adapting: Adapting<Schema<$Adaptations>>) => $Returnable) => Schema<WithAdaptations<$Adaptations, AdaptationEntry<$Adapter, $Returnable>>>;
|
|
@@ -2,15 +2,14 @@ import type { Adaptations } from "../../../Adapter/Types";
|
|
|
2
2
|
import { Produces, type Adaptation, type Kind, type Meta } from "../../../Types";
|
|
3
3
|
/**
|
|
4
4
|
* The value a `self` reference resolves to at this position — whatever the
|
|
5
|
-
* enclosing `T.recursive`'s current expansion binds it to. Reads
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
8
|
-
* `bindings` is and why it's a tuple.
|
|
5
|
+
* enclosing `T.recursive`'s current expansion binds it to. Reads `bindings[0]`,
|
|
6
|
+
* the analogue of TypeBox's `TThis` reading `this['params'][0]`; see
|
|
7
|
+
* `Schema/Types.ts`'s `ValueOf` for what `bindings` is and why it's a tuple.
|
|
9
8
|
*
|
|
10
|
-
* Unlike every other kind, `self` has no type parameter of its own — its
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* Unlike every other kind, `self` has no type parameter of its own — its whole
|
|
10
|
+
* value comes from outside, threaded in structurally by whatever composite
|
|
11
|
+
* kinds wrap it (`recursive/Types.ts`'s `RecursiveValue` is what ultimately
|
|
12
|
+
* supplies `bindings[0]`).
|
|
14
13
|
*/
|
|
15
14
|
export type Fabricated<$Bindings extends unknown[] = []> = $Bindings[0];
|
|
16
15
|
export type Meta = Record<string, never>;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { CodepointRange } from "./Types";
|
|
2
2
|
/**
|
|
3
|
-
* Unicode code point ranges for spanning the codespace — a fuzzing aid
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Unicode code point ranges for spanning the codespace — a fuzzing aid for
|
|
4
|
+
* exercising input far outside ordinary text. Use a preset or build an
|
|
5
|
+
* arbitrary inclusive range with `range(from, to)`.
|
|
6
6
|
*
|
|
7
|
-
* Lives here rather than `Types.ts` so that file stays type-only. A
|
|
8
|
-
*
|
|
9
|
-
* module
|
|
10
|
-
* `
|
|
11
|
-
* a cycle that drops `[Kind]`/`[Meta]` off `Core`.
|
|
7
|
+
* Lives here rather than `Types.ts` so that file stays type-only. A value
|
|
8
|
+
* export alongside `export type Fabricated = string` makes the module a value
|
|
9
|
+
* module, and `export * as string` in `Primitive/namespace.ts` then resolves
|
|
10
|
+
* `string` to the namespace — a cycle that drops `[Kind]`/`[Meta]` off `Core`.
|
|
12
11
|
*/
|
|
13
12
|
export declare const unicode: {
|
|
14
13
|
/**
|
|
@@ -24,8 +23,8 @@ export declare const unicode: {
|
|
|
24
23
|
}[];
|
|
25
24
|
/**
|
|
26
25
|
* The entire Unicode codespace, U+0000–U+10FFFF, including the surrogate
|
|
27
|
-
* block — so it can yield lone surrogates and thus ill-formed UTF-16.
|
|
28
|
-
*
|
|
26
|
+
* block — so it can yield lone surrogates and thus ill-formed UTF-16. Opt in
|
|
27
|
+
* for lone surrogates and other ill-formed UTF-16 when fuzzing.
|
|
29
28
|
*/
|
|
30
29
|
codespace: {
|
|
31
30
|
from: number;
|
|
@@ -45,9 +44,9 @@ export declare const unicode: {
|
|
|
45
44
|
range: (from: number, to: number) => CodepointRange;
|
|
46
45
|
};
|
|
47
46
|
/**
|
|
48
|
-
* The built-in character classes as code point ranges, each an alias for
|
|
49
|
-
*
|
|
50
|
-
*
|
|
47
|
+
* The built-in character classes as code point ranges, each an alias for the
|
|
48
|
+
* code point ranges it spans. For use in the `[weight, source]` form of
|
|
49
|
+
* `composition` (e.g. mixing a class with a Unicode range).
|
|
51
50
|
*/
|
|
52
51
|
export declare const classes: {
|
|
53
52
|
lowercase: ReadonlyArray<CodepointRange>;
|
|
@@ -18,7 +18,7 @@ export type Fabricator<$Schema extends {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Turn a `string` Schema into a live Fabricator — the one place this kind's
|
|
21
|
-
* character-generation logic actually runs. `Constructor.ts` calls this once
|
|
22
|
-
* `construct()`, never from inside the returned `fabricate`.
|
|
21
|
+
* character-generation logic actually runs. `Constructor.ts` calls this once
|
|
22
|
+
* per `construct()`, never from inside the returned `fabricate`.
|
|
23
23
|
*/
|
|
24
24
|
export declare function Fabricator(context: FabricatorContext<Schema>): Fabricator;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Produce } from "../../Random/Types";
|
|
2
2
|
import { Kind } from "../../Types";
|
|
3
3
|
import { Schema } from "./Schema";
|
|
4
|
-
import type { Fabricated, InputWhereby, JsonSchema } from "./Types";
|
|
4
|
+
import type { Fabricated, InputWhereby, JsonSchema, Whereby } from "./Types";
|
|
5
5
|
declare const _default: {
|
|
6
6
|
/**
|
|
7
|
-
* The builder carries the primitive's `[Kind]` so it can be named directly
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* The builder carries the primitive's `[Kind]` so it can be named directly as
|
|
8
|
+
* a `compute` source — which derives its schema by kind — without first
|
|
9
|
+
* satisfying a `whereby`.
|
|
10
10
|
*/
|
|
11
11
|
[Kind]: "string";
|
|
12
12
|
/**
|
|
@@ -15,9 +15,9 @@ declare const _default: {
|
|
|
15
15
|
* (e.g. `toTypeBox`) read.
|
|
16
16
|
*/
|
|
17
17
|
as: (produce: Produce<Fabricated>, hints?: JsonSchema) => Schema<{
|
|
18
|
-
produce: Produce<
|
|
18
|
+
produce: Produce<Fabricated>;
|
|
19
19
|
hints: JsonSchema | undefined;
|
|
20
|
-
}
|
|
20
|
+
}>;
|
|
21
21
|
/**
|
|
22
22
|
* A string whose length falls uniformly within `[length.min, length.max]`;
|
|
23
23
|
* `length.min` defaults to inclusive 0. Exclusive ends use a Bound object.
|
|
@@ -28,17 +28,11 @@ declare const _default: {
|
|
|
28
28
|
* `length` counts UTF-16 code units, so the result's `.length` equals the
|
|
29
29
|
* chosen length exactly. When the composition cannot fill the final code
|
|
30
30
|
* units — e.g. only astral, two-unit characters remain for a one-unit gap —
|
|
31
|
-
* the gap is topped up with a well-formed BMP character outside the
|
|
32
|
-
*
|
|
31
|
+
* the gap is topped up with a well-formed BMP character outside the requested
|
|
32
|
+
* `composition`, inserted at a random character boundary.
|
|
33
33
|
*/
|
|
34
34
|
whereby: (whereby: InputWhereby) => Schema<{
|
|
35
|
-
whereby:
|
|
36
|
-
|
|
37
|
-
min: import("../..").Bound<number>;
|
|
38
|
-
max: import("../..").Bound<number>;
|
|
39
|
-
};
|
|
40
|
-
composition?: import("./Types").Composition;
|
|
41
|
-
};
|
|
42
|
-
}, {}>;
|
|
35
|
+
whereby: Whereby;
|
|
36
|
+
}>;
|
|
43
37
|
};
|
|
44
38
|
export default _default;
|
|
@@ -4,13 +4,13 @@ import type { Produce } from "../../Random/Types";
|
|
|
4
4
|
import type { Core, Fabricated, JsonSchema, Meta as ThisMeta } from "./Types";
|
|
5
5
|
/**
|
|
6
6
|
* Buildable `string` recipe: length/composition (`whereby` — required, unlike
|
|
7
|
-
* `number`/`date`; no natural bound to fuzz a length to), or opaque
|
|
8
|
-
*
|
|
7
|
+
* `number`/`date`; no natural bound to fuzz a length to), or opaque production
|
|
8
|
+
* via `as`.
|
|
9
9
|
*
|
|
10
10
|
* `$Meta` is generic (defaulting to the full `Meta` union) so builder return
|
|
11
|
-
* types stay narrow — see `number/Schema.ts`. `$Adaptations` is generic for
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* types stay narrow — see `number/Schema.ts`. `$Adaptations` is generic for the
|
|
12
|
+
* same reason, threaded through every builder method so an adaptation survives
|
|
13
|
+
* chaining (see `adapt`).
|
|
14
14
|
*/
|
|
15
15
|
export interface Schema<$Meta extends ThisMeta = ThisMeta, $Adaptations extends Adaptations = {}> extends Core<$Meta, $Adaptations> {
|
|
16
16
|
/**
|
|
@@ -9,19 +9,19 @@ export type CodepointRange = {
|
|
|
9
9
|
to: number;
|
|
10
10
|
};
|
|
11
11
|
/**
|
|
12
|
-
* The single mechanism every character is drawn from: one or more code
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* The single mechanism every character is drawn from: one or more code point
|
|
13
|
+
* ranges. A literal string is accepted as shorthand for the ranges of its
|
|
14
|
+
* individual characters, so custom pools, the built-in classes, and the Unicode
|
|
15
|
+
* codespace are all the same thing under the hood.
|
|
16
16
|
*/
|
|
17
17
|
export type CharacterSource = string | CodepointRange | ReadonlyArray<CodepointRange>;
|
|
18
18
|
export type CharacterClass = keyof typeof classes;
|
|
19
19
|
/**
|
|
20
|
-
* How a string's characters should be composed: a weighting over the
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
20
|
+
* How a string's characters should be composed: a weighting over the built-in
|
|
21
|
+
* classes by name, or explicit `[weight, source]` pairs over arbitrary
|
|
22
|
+
* character sources. Each character independently picks a source by weight,
|
|
23
|
+
* then a code point uniformly across that source's ranges — so the weights
|
|
24
|
+
* describe expected composition, not per-character uniformity.
|
|
25
25
|
*/
|
|
26
26
|
export type Composition = Partial<Record<CharacterClass, number>> | ReadonlyArray<[number, CharacterSource]>;
|
|
27
27
|
export type InputWhereby = {
|
|
@@ -41,9 +41,9 @@ export type Whereby = {
|
|
|
41
41
|
export type Fabricated = string;
|
|
42
42
|
/**
|
|
43
43
|
* JSON-Schema keywords that constrain a string value — carried as neutral,
|
|
44
|
-
* schema-library-agnostic hints (see the builder's `as`). Adapters forward
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* schema-library-agnostic hints (see the builder's `as`). Adapters forward them
|
|
45
|
+
* to their target: `toTypeBox` to `Type.String(...)`, a future `toZod` to
|
|
46
|
+
* `z.string()` refinements, etc.
|
|
47
47
|
*
|
|
48
48
|
* Length lives on `whereby` as Bound pairs, which adapters forward as
|
|
49
49
|
* `minLength`/`maxLength`; `hints` never duplicates it — these are the
|
|
@@ -54,11 +54,11 @@ export type JsonSchema = {
|
|
|
54
54
|
pattern?: string;
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
|
-
* A length/composition, drawn via `whereby` — no natural bound to fuzz to,
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
57
|
+
* A length/composition, drawn via `whereby` — no natural bound to fuzz to, so
|
|
58
|
+
* unlike `number`/`date` there's no bare form — optionally overridden by an
|
|
59
|
+
* opaque `as` production, carried alongside `whereby` rather than replacing it
|
|
60
|
+
* (when `whereby` was already set) so a prior length/composition survives `as`
|
|
61
|
+
* for future validation.
|
|
62
62
|
*/
|
|
63
63
|
export type Meta = {
|
|
64
64
|
whereby: Whereby;
|
|
@@ -18,7 +18,7 @@ export type Fabricator<$Schema extends {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* A bare symbol draws no randomness at all — `Symbol(meta.key)` is
|
|
21
|
-
* deterministic — so only the `.as(...)`-overridden path ever obtains a
|
|
22
|
-
*
|
|
21
|
+
* deterministic — so only the `.as(...)`-overridden path ever obtains a stream.
|
|
22
|
+
* The bare path still records `trace`, like every other node.
|
|
23
23
|
*/
|
|
24
24
|
export declare function Fabricator(context: FabricatorContext<Schema>): Fabricator;
|