@ghostry/fabricator 0.0.1
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/LICENSE +21 -0
- package/README.md +47 -0
- package/dist/esm/Adapter/Core.js +47 -0
- package/dist/esm/Adapter/Types.js +1 -0
- package/dist/esm/Bound.js +81 -0
- package/dist/esm/Distribution/index.js +200 -0
- package/dist/esm/Enumeration/Enumerate.js +103 -0
- package/dist/esm/Enumeration/Plan.js +286 -0
- package/dist/esm/Enumeration/Types.js +1 -0
- package/dist/esm/Error/index.js +201 -0
- package/dist/esm/Fabricator/Constructor.js +328 -0
- package/dist/esm/Fabricator/Types.js +1 -0
- package/dist/esm/Instance/Core.js +119 -0
- package/dist/esm/Instance/Types.js +1 -0
- package/dist/esm/Primitive/always/Fabricator.js +13 -0
- package/dist/esm/Primitive/always/Registry.js +11 -0
- package/dist/esm/Primitive/always/Schema.js +10 -0
- package/dist/esm/Primitive/always/Types.js +1 -0
- package/dist/esm/Primitive/always/index.js +5 -0
- package/dist/esm/Primitive/array/Fabricator.js +45 -0
- package/dist/esm/Primitive/array/Registry.js +26 -0
- package/dist/esm/Primitive/array/Schema.js +17 -0
- package/dist/esm/Primitive/array/Types.js +1 -0
- package/dist/esm/Primitive/array/index.js +5 -0
- package/dist/esm/Primitive/bigint/Fabricator.js +54 -0
- package/dist/esm/Primitive/bigint/Registry.js +31 -0
- package/dist/esm/Primitive/bigint/Schema.js +17 -0
- package/dist/esm/Primitive/bigint/Types.js +1 -0
- package/dist/esm/Primitive/bigint/index.js +5 -0
- package/dist/esm/Primitive/boolean/Fabricator.js +44 -0
- package/dist/esm/Primitive/boolean/Outcomes.js +5 -0
- package/dist/esm/Primitive/boolean/Registry.js +11 -0
- package/dist/esm/Primitive/boolean/Schema.js +33 -0
- package/dist/esm/Primitive/boolean/Types.js +1 -0
- package/dist/esm/Primitive/boolean/index.js +6 -0
- package/dist/esm/Primitive/choice/Fabricator.js +37 -0
- package/dist/esm/Primitive/choice/Registry.js +38 -0
- package/dist/esm/Primitive/choice/Schema.js +17 -0
- package/dist/esm/Primitive/choice/Types.js +1 -0
- package/dist/esm/Primitive/choice/index.js +5 -0
- package/dist/esm/Primitive/date/Fabricator.js +86 -0
- package/dist/esm/Primitive/date/Registry.js +61 -0
- package/dist/esm/Primitive/date/Schema.js +17 -0
- package/dist/esm/Primitive/date/Types.js +1 -0
- package/dist/esm/Primitive/date/index.js +5 -0
- package/dist/esm/Primitive/enum/Fabricator.js +33 -0
- package/dist/esm/Primitive/enum/Registry.js +33 -0
- package/dist/esm/Primitive/enum/Schema.js +17 -0
- package/dist/esm/Primitive/enum/Types.js +1 -0
- package/dist/esm/Primitive/enum/index.js +5 -0
- package/dist/esm/Primitive/index.js +24 -0
- package/dist/esm/Primitive/namespace.js +21 -0
- package/dist/esm/Primitive/null/Fabricator.js +14 -0
- package/dist/esm/Primitive/null/Registry.js +8 -0
- package/dist/esm/Primitive/null/Schema.js +10 -0
- package/dist/esm/Primitive/null/Types.js +1 -0
- package/dist/esm/Primitive/null/index.js +5 -0
- package/dist/esm/Primitive/nullable/Fabricator.js +58 -0
- package/dist/esm/Primitive/nullable/Outcomes.js +5 -0
- package/dist/esm/Primitive/nullable/Registry.js +13 -0
- package/dist/esm/Primitive/nullable/Schema.js +36 -0
- package/dist/esm/Primitive/nullable/Types.js +1 -0
- package/dist/esm/Primitive/nullable/index.js +6 -0
- package/dist/esm/Primitive/nullish/Fabricator.js +64 -0
- package/dist/esm/Primitive/nullish/Outcomes.js +6 -0
- package/dist/esm/Primitive/nullish/Registry.js +13 -0
- package/dist/esm/Primitive/nullish/Schema.js +36 -0
- package/dist/esm/Primitive/nullish/Types.js +1 -0
- package/dist/esm/Primitive/nullish/index.js +6 -0
- package/dist/esm/Primitive/number/Fabricator.js +73 -0
- package/dist/esm/Primitive/number/Registry.js +59 -0
- package/dist/esm/Primitive/number/Schema.js +18 -0
- package/dist/esm/Primitive/number/Types.js +1 -0
- package/dist/esm/Primitive/number/defaults.js +21 -0
- package/dist/esm/Primitive/number/index.js +5 -0
- package/dist/esm/Primitive/object/Fabricator.js +77 -0
- package/dist/esm/Primitive/object/Registry.js +146 -0
- package/dist/esm/Primitive/object/Schema.js +18 -0
- package/dist/esm/Primitive/object/Types.js +1 -0
- package/dist/esm/Primitive/object/compute/Fabricator.js +24 -0
- package/dist/esm/Primitive/object/compute/Registry.js +15 -0
- package/dist/esm/Primitive/object/compute/Schema.js +13 -0
- package/dist/esm/Primitive/object/compute/Types.js +1 -0
- package/dist/esm/Primitive/object/compute/index.js +5 -0
- package/dist/esm/Primitive/object/index.js +9 -0
- package/dist/esm/Primitive/object/omittable/Fabricator.js +57 -0
- package/dist/esm/Primitive/object/omittable/Outcomes.js +5 -0
- package/dist/esm/Primitive/object/omittable/Registry.js +13 -0
- package/dist/esm/Primitive/object/omittable/Schema.js +36 -0
- package/dist/esm/Primitive/object/omittable/Types.js +1 -0
- package/dist/esm/Primitive/object/omittable/index.js +6 -0
- package/dist/esm/Primitive/object/optional/Fabricator.js +55 -0
- package/dist/esm/Primitive/object/optional/Outcomes.js +6 -0
- package/dist/esm/Primitive/object/optional/Registry.js +13 -0
- package/dist/esm/Primitive/object/optional/Schema.js +36 -0
- package/dist/esm/Primitive/object/optional/Types.js +1 -0
- package/dist/esm/Primitive/object/optional/index.js +6 -0
- package/dist/esm/Primitive/opaque/Fabricator.js +19 -0
- package/dist/esm/Primitive/opaque/Registry.js +11 -0
- package/dist/esm/Primitive/opaque/Schema.js +10 -0
- package/dist/esm/Primitive/opaque/Types.js +1 -0
- package/dist/esm/Primitive/opaque/index.js +5 -0
- package/dist/esm/Primitive/record/Fabricator.js +55 -0
- package/dist/esm/Primitive/record/Registry.js +26 -0
- package/dist/esm/Primitive/record/Schema.js +17 -0
- package/dist/esm/Primitive/record/Types.js +1 -0
- package/dist/esm/Primitive/record/index.js +5 -0
- package/dist/esm/Primitive/recursive/Fabricator.js +33 -0
- package/dist/esm/Primitive/recursive/Registry.js +20 -0
- package/dist/esm/Primitive/recursive/Schema.js +10 -0
- package/dist/esm/Primitive/recursive/Terminate.js +236 -0
- package/dist/esm/Primitive/recursive/Types.js +1 -0
- package/dist/esm/Primitive/recursive/index.js +7 -0
- package/dist/esm/Primitive/recursive/self/Fabricator.js +15 -0
- package/dist/esm/Primitive/recursive/self/Registry.js +9 -0
- package/dist/esm/Primitive/recursive/self/Schema.js +10 -0
- package/dist/esm/Primitive/recursive/self/Types.js +1 -0
- package/dist/esm/Primitive/recursive/self/index.js +5 -0
- package/dist/esm/Primitive/string/Constants.js +73 -0
- package/dist/esm/Primitive/string/Fabricator.js +109 -0
- package/dist/esm/Primitive/string/Registry.js +25 -0
- package/dist/esm/Primitive/string/Schema.js +18 -0
- package/dist/esm/Primitive/string/Types.js +1 -0
- package/dist/esm/Primitive/string/index.js +6 -0
- package/dist/esm/Primitive/symbol/Fabricator.js +33 -0
- package/dist/esm/Primitive/symbol/Registry.js +17 -0
- package/dist/esm/Primitive/symbol/Schema.js +17 -0
- package/dist/esm/Primitive/symbol/Types.js +1 -0
- package/dist/esm/Primitive/symbol/index.js +5 -0
- package/dist/esm/Primitive/tuple/Fabricator.js +33 -0
- package/dist/esm/Primitive/tuple/Registry.js +13 -0
- package/dist/esm/Primitive/tuple/Schema.js +17 -0
- package/dist/esm/Primitive/tuple/Types.js +1 -0
- package/dist/esm/Primitive/tuple/index.js +5 -0
- package/dist/esm/Primitive/undefinable/Fabricator.js +58 -0
- package/dist/esm/Primitive/undefinable/Outcomes.js +5 -0
- package/dist/esm/Primitive/undefinable/Registry.js +13 -0
- package/dist/esm/Primitive/undefinable/Schema.js +36 -0
- package/dist/esm/Primitive/undefinable/Types.js +1 -0
- package/dist/esm/Primitive/undefinable/index.js +6 -0
- package/dist/esm/Primitive/undefined/Fabricator.js +16 -0
- package/dist/esm/Primitive/undefined/Registry.js +8 -0
- package/dist/esm/Primitive/undefined/Schema.js +10 -0
- package/dist/esm/Primitive/undefined/Types.js +1 -0
- package/dist/esm/Primitive/undefined/index.js +5 -0
- package/dist/esm/Random/CallSite.js +56 -0
- package/dist/esm/Random/Generator/sfc32.js +16 -0
- package/dist/esm/Random/Types.js +1 -0
- package/dist/esm/Random/index.js +151 -0
- package/dist/esm/Schema/Core.js +68 -0
- package/dist/esm/Schema/Registry.js +17 -0
- package/dist/esm/Schema/Types.js +1 -0
- package/dist/esm/Types.js +11 -0
- package/dist/esm/Utility/Core.js +36 -0
- package/dist/esm/Utility/DeepMerge.js +18 -0
- package/dist/esm/Utility/Digest.js +28 -0
- package/dist/esm/Utility/ShallowMerge.js +13 -0
- package/dist/esm/Utility/Types.js +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/internal.js +5 -0
- package/dist/types/Adapter/Core.d.ts +64 -0
- package/dist/types/Adapter/Types.d.ts +145 -0
- package/dist/types/Bound.d.ts +68 -0
- package/dist/types/Distribution/index.d.ts +157 -0
- package/dist/types/Enumeration/Enumerate.d.ts +35 -0
- package/dist/types/Enumeration/Plan.d.ts +44 -0
- package/dist/types/Enumeration/Types.d.ts +86 -0
- package/dist/types/Error/index.d.ts +541 -0
- package/dist/types/Fabricator/Constructor.d.ts +43 -0
- package/dist/types/Fabricator/Types.d.ts +150 -0
- package/dist/types/Instance/Core.d.ts +98 -0
- package/dist/types/Instance/Types.d.ts +167 -0
- package/dist/types/Primitive/always/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/always/Registry.d.ts +3 -0
- package/dist/types/Primitive/always/Schema.d.ts +19 -0
- package/dist/types/Primitive/always/Types.d.ts +23 -0
- package/dist/types/Primitive/always/index.d.ts +5 -0
- package/dist/types/Primitive/array/Fabricator.d.ts +22 -0
- package/dist/types/Primitive/array/Registry.d.ts +18 -0
- package/dist/types/Primitive/array/Schema.d.ts +23 -0
- package/dist/types/Primitive/array/Types.d.ts +44 -0
- package/dist/types/Primitive/array/index.d.ts +5 -0
- package/dist/types/Primitive/bigint/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/bigint/Registry.d.ts +19 -0
- package/dist/types/Primitive/bigint/Schema.d.ts +27 -0
- package/dist/types/Primitive/bigint/Types.d.ts +33 -0
- package/dist/types/Primitive/bigint/index.d.ts +5 -0
- package/dist/types/Primitive/boolean/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/boolean/Outcomes.d.ts +12 -0
- package/dist/types/Primitive/boolean/Registry.d.ts +14 -0
- package/dist/types/Primitive/boolean/Schema.d.ts +28 -0
- package/dist/types/Primitive/boolean/Types.d.ts +26 -0
- package/dist/types/Primitive/boolean/index.d.ts +6 -0
- package/dist/types/Primitive/choice/Fabricator.d.ts +32 -0
- package/dist/types/Primitive/choice/Registry.d.ts +38 -0
- package/dist/types/Primitive/choice/Schema.d.ts +24 -0
- package/dist/types/Primitive/choice/Types.d.ts +35 -0
- package/dist/types/Primitive/choice/index.d.ts +5 -0
- package/dist/types/Primitive/date/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/date/Registry.d.ts +82 -0
- package/dist/types/Primitive/date/Schema.d.ts +28 -0
- package/dist/types/Primitive/date/Types.d.ts +34 -0
- package/dist/types/Primitive/date/index.d.ts +5 -0
- package/dist/types/Primitive/enum/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/enum/Registry.d.ts +39 -0
- package/dist/types/Primitive/enum/Schema.d.ts +23 -0
- package/dist/types/Primitive/enum/Types.d.ts +44 -0
- package/dist/types/Primitive/enum/index.d.ts +5 -0
- package/dist/types/Primitive/index.d.ts +28 -0
- package/dist/types/Primitive/namespace.d.ts +38 -0
- package/dist/types/Primitive/null/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/null/Registry.d.ts +3 -0
- package/dist/types/Primitive/null/Schema.d.ts +16 -0
- package/dist/types/Primitive/null/Types.d.ts +15 -0
- package/dist/types/Primitive/null/index.d.ts +5 -0
- package/dist/types/Primitive/nullable/Fabricator.d.ts +31 -0
- package/dist/types/Primitive/nullable/Outcomes.d.ts +9 -0
- package/dist/types/Primitive/nullable/Registry.d.ts +3 -0
- package/dist/types/Primitive/nullable/Schema.d.ts +36 -0
- package/dist/types/Primitive/nullable/Types.d.ts +48 -0
- package/dist/types/Primitive/nullable/index.d.ts +6 -0
- package/dist/types/Primitive/nullish/Fabricator.d.ts +36 -0
- package/dist/types/Primitive/nullish/Outcomes.d.ts +9 -0
- package/dist/types/Primitive/nullish/Registry.d.ts +3 -0
- package/dist/types/Primitive/nullish/Schema.d.ts +36 -0
- package/dist/types/Primitive/nullish/Types.d.ts +58 -0
- package/dist/types/Primitive/nullish/index.d.ts +6 -0
- package/dist/types/Primitive/number/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/number/Registry.d.ts +52 -0
- package/dist/types/Primitive/number/Schema.d.ts +32 -0
- package/dist/types/Primitive/number/Types.d.ts +56 -0
- package/dist/types/Primitive/number/defaults.d.ts +18 -0
- package/dist/types/Primitive/number/index.d.ts +5 -0
- package/dist/types/Primitive/object/Fabricator.d.ts +56 -0
- package/dist/types/Primitive/object/Registry.d.ts +23 -0
- package/dist/types/Primitive/object/Schema.d.ts +41 -0
- package/dist/types/Primitive/object/Types.d.ts +85 -0
- package/dist/types/Primitive/object/compute/Fabricator.d.ts +31 -0
- package/dist/types/Primitive/object/compute/Registry.d.ts +4 -0
- package/dist/types/Primitive/object/compute/Schema.d.ts +21 -0
- package/dist/types/Primitive/object/compute/Types.d.ts +56 -0
- package/dist/types/Primitive/object/compute/index.d.ts +5 -0
- package/dist/types/Primitive/object/index.d.ts +8 -0
- package/dist/types/Primitive/object/omittable/Fabricator.d.ts +37 -0
- package/dist/types/Primitive/object/omittable/Outcomes.d.ts +9 -0
- package/dist/types/Primitive/object/omittable/Registry.d.ts +3 -0
- package/dist/types/Primitive/object/omittable/Schema.d.ts +32 -0
- package/dist/types/Primitive/object/omittable/Types.d.ts +57 -0
- package/dist/types/Primitive/object/omittable/index.d.ts +6 -0
- package/dist/types/Primitive/object/optional/Fabricator.d.ts +45 -0
- package/dist/types/Primitive/object/optional/Outcomes.d.ts +9 -0
- package/dist/types/Primitive/object/optional/Registry.d.ts +3 -0
- package/dist/types/Primitive/object/optional/Schema.d.ts +32 -0
- package/dist/types/Primitive/object/optional/Types.d.ts +72 -0
- package/dist/types/Primitive/object/optional/index.d.ts +6 -0
- package/dist/types/Primitive/opaque/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/opaque/Registry.d.ts +12 -0
- package/dist/types/Primitive/opaque/Schema.d.ts +22 -0
- package/dist/types/Primitive/opaque/Types.d.ts +18 -0
- package/dist/types/Primitive/opaque/index.d.ts +5 -0
- package/dist/types/Primitive/record/Fabricator.d.ts +25 -0
- package/dist/types/Primitive/record/Registry.d.ts +17 -0
- package/dist/types/Primitive/record/Schema.d.ts +27 -0
- package/dist/types/Primitive/record/Types.d.ts +85 -0
- package/dist/types/Primitive/record/index.d.ts +5 -0
- package/dist/types/Primitive/recursive/Fabricator.d.ts +47 -0
- package/dist/types/Primitive/recursive/Registry.d.ts +22 -0
- package/dist/types/Primitive/recursive/Schema.d.ts +21 -0
- package/dist/types/Primitive/recursive/Terminate.d.ts +20 -0
- package/dist/types/Primitive/recursive/Types.d.ts +82 -0
- package/dist/types/Primitive/recursive/index.d.ts +6 -0
- package/dist/types/Primitive/recursive/self/Fabricator.d.ts +29 -0
- package/dist/types/Primitive/recursive/self/Registry.d.ts +7 -0
- package/dist/types/Primitive/recursive/self/Schema.d.ts +20 -0
- package/dist/types/Primitive/recursive/self/Types.d.ts +28 -0
- package/dist/types/Primitive/recursive/self/index.d.ts +5 -0
- package/dist/types/Primitive/string/Constants.d.ts +58 -0
- package/dist/types/Primitive/string/Fabricator.d.ts +24 -0
- package/dist/types/Primitive/string/Registry.d.ts +44 -0
- package/dist/types/Primitive/string/Schema.d.ts +65 -0
- package/dist/types/Primitive/string/Types.d.ts +77 -0
- package/dist/types/Primitive/string/index.d.ts +6 -0
- package/dist/types/Primitive/symbol/Fabricator.d.ts +24 -0
- package/dist/types/Primitive/symbol/Registry.d.ts +16 -0
- package/dist/types/Primitive/symbol/Schema.d.ts +24 -0
- package/dist/types/Primitive/symbol/Types.d.ts +19 -0
- package/dist/types/Primitive/symbol/index.d.ts +5 -0
- package/dist/types/Primitive/tuple/Fabricator.d.ts +37 -0
- package/dist/types/Primitive/tuple/Registry.d.ts +3 -0
- package/dist/types/Primitive/tuple/Schema.d.ts +24 -0
- package/dist/types/Primitive/tuple/Types.d.ts +53 -0
- package/dist/types/Primitive/tuple/index.d.ts +5 -0
- package/dist/types/Primitive/undefinable/Fabricator.d.ts +31 -0
- package/dist/types/Primitive/undefinable/Outcomes.d.ts +9 -0
- package/dist/types/Primitive/undefinable/Registry.d.ts +3 -0
- package/dist/types/Primitive/undefinable/Schema.d.ts +36 -0
- package/dist/types/Primitive/undefinable/Types.d.ts +48 -0
- package/dist/types/Primitive/undefinable/index.d.ts +6 -0
- package/dist/types/Primitive/undefined/Fabricator.d.ts +19 -0
- package/dist/types/Primitive/undefined/Registry.d.ts +3 -0
- package/dist/types/Primitive/undefined/Schema.d.ts +16 -0
- package/dist/types/Primitive/undefined/Types.d.ts +15 -0
- package/dist/types/Primitive/undefined/index.d.ts +5 -0
- package/dist/types/Random/CallSite.d.ts +59 -0
- package/dist/types/Random/Generator/sfc32.d.ts +10 -0
- package/dist/types/Random/Types.d.ts +384 -0
- package/dist/types/Random/index.d.ts +107 -0
- package/dist/types/Schema/Core.d.ts +44 -0
- package/dist/types/Schema/Registry.d.ts +20 -0
- package/dist/types/Schema/Types.d.ts +70 -0
- package/dist/types/Types.d.ts +78 -0
- package/dist/types/Utility/Core.d.ts +35 -0
- package/dist/types/Utility/DeepMerge.d.ts +14 -0
- package/dist/types/Utility/Digest.d.ts +9 -0
- package/dist/types/Utility/ShallowMerge.d.ts +6 -0
- package/dist/types/Utility/Types.d.ts +4 -0
- package/dist/types/index.d.ts +186 -0
- package/dist/types/internal.d.ts +64 -0
- package/package.json +53 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Adaptations } from "../../../Adapter/Types";
|
|
2
|
+
import type { Produce } from "../../../Random/Types";
|
|
3
|
+
import type { AnySchema, ValueOf } from "../../../Schema/Types";
|
|
4
|
+
import { Kind, Meta, Omitted, type Adaptation, type Produces } from "../../../Types";
|
|
5
|
+
/**
|
|
6
|
+
* The wrapped field's Schema — the value type when the roll is
|
|
7
|
+
* present-with-a-value.
|
|
8
|
+
*/
|
|
9
|
+
export type Definition = AnySchema;
|
|
10
|
+
/**
|
|
11
|
+
* The value an optional field's key holds when present at all — the wrapped
|
|
12
|
+
* value, or `undefined` (present-as-`undefined` is one of three outcomes,
|
|
13
|
+
* distinct from the key not appearing). Flows through `[Produces]` into
|
|
14
|
+
* `object/Types.ts`'s per-field type, so a `T.optional`-wrapped field types
|
|
15
|
+
* as `{ a?: T | undefined }` — a real `?:` (from `OmittableKeys`, which also
|
|
16
|
+
* covers this kind) *and* a real `| undefined`.
|
|
17
|
+
*/
|
|
18
|
+
export type Fabricated<$Definition extends Definition, $Bindings extends unknown[] = []> = ValueOf<$Definition, $Bindings> | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* What an optional field's Fabricator returns: the wrapped value,
|
|
21
|
+
* `undefined`, or `Omitted` when the key should not appear — whether from
|
|
22
|
+
* the built-in three-way roll or, via `.as(...)`, an opaque producer.
|
|
23
|
+
*/
|
|
24
|
+
export type Resolved<$Definition extends Definition> = Fabricated<$Definition> | typeof Omitted;
|
|
25
|
+
export type { Outcome } from "./Outcomes";
|
|
26
|
+
/**
|
|
27
|
+
* Relative weights for `.weighted(...)`, keyed by `Outcome`. Keys optional —
|
|
28
|
+
* an omitted key falls back to baseline `1`, the same weight the uniform
|
|
29
|
+
* 1/3 split already uses. Values are relative, exactly like `weighted()`
|
|
30
|
+
* (`Distribution/index.ts`) — they need not sum to one, and are fed to
|
|
31
|
+
* `weighted()` unchanged alongside each unspecified key's baseline `1`.
|
|
32
|
+
*
|
|
33
|
+
* Specifying one outcome's weight shifts *every* outcome's resulting
|
|
34
|
+
* probability, not just the named one — unspecified ones stay at weight `1`
|
|
35
|
+
* but their share of the total still moves, since the total changed.
|
|
36
|
+
* `.weighted({ omitted: 0.1 })` on `T.optional` is not "10% omitted, other
|
|
37
|
+
* two still 33%" — with `undefined`/`value` at default `1`, the split is
|
|
38
|
+
* `0.1 / 2.1 ≈ 4.8%` omitted and `≈47.6%` each for the other two. No
|
|
39
|
+
* independent "absolute probability" mode; weights are only meaningful
|
|
40
|
+
* relative to the full set in play.
|
|
41
|
+
*/
|
|
42
|
+
export type Weights = {
|
|
43
|
+
omitted: number;
|
|
44
|
+
undefined?: number | undefined;
|
|
45
|
+
value?: number | undefined;
|
|
46
|
+
} | {
|
|
47
|
+
omitted?: number | undefined;
|
|
48
|
+
undefined: number;
|
|
49
|
+
value?: number | undefined;
|
|
50
|
+
} | {
|
|
51
|
+
omitted?: number | undefined;
|
|
52
|
+
undefined?: number | undefined;
|
|
53
|
+
value: number;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* `definition` stays required regardless of `produce` — an opaque `as`
|
|
57
|
+
* production layers on top rather than replacing it, so a prior definition
|
|
58
|
+
* survives `as` for future validation of `produce` (and so `ToTypeBox`'s
|
|
59
|
+
* structural derivation of the wrapped shape keeps working either way).
|
|
60
|
+
*/
|
|
61
|
+
export type Meta<$Definition extends Definition = Definition> = {
|
|
62
|
+
definition: $Definition;
|
|
63
|
+
produce?: Produce<Resolved<$Definition>>;
|
|
64
|
+
weights?: Weights;
|
|
65
|
+
};
|
|
66
|
+
export interface Core<$Definition extends Definition = Definition, $Adaptations extends Adaptations = {}> {
|
|
67
|
+
[Kind]: "object.optional";
|
|
68
|
+
[Meta]: Meta<$Definition>;
|
|
69
|
+
bindings?: unknown[];
|
|
70
|
+
readonly [Produces]?: Fabricated<$Definition, NonNullable<this["bindings"]>>;
|
|
71
|
+
readonly [Adaptation]?: $Adaptations;
|
|
72
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AdaptationsOf } from "../../Adapter/Types";
|
|
2
|
+
import type { FabricatorContext, NaiveFabricator } from "../../Fabricator/Types";
|
|
3
|
+
import type { Trace } from "../../Random/Types";
|
|
4
|
+
import { Kind, Meta, type Adaptation } from "../../Types";
|
|
5
|
+
import { Schema } from "./Schema";
|
|
6
|
+
import type { Fabricated, Meta as ThisMeta } from "./Types";
|
|
7
|
+
export type Fabrication<$Fabricator extends Fabricator> = $Fabricator extends Fabricator<infer $Schema> ? $Schema[typeof Meta] extends ThisMeta<infer $T> ? Fabricated<$T> : never : never;
|
|
8
|
+
export type Fabricator<$Schema extends {
|
|
9
|
+
[Meta]: ThisMeta<any>;
|
|
10
|
+
} = {
|
|
11
|
+
[Meta]: ThisMeta;
|
|
12
|
+
}> = NaiveFabricator<$Schema[typeof Meta] extends ThisMeta<infer $T> ? Fabricated<$T> : never> & {
|
|
13
|
+
[Kind]: "opaque";
|
|
14
|
+
[Meta]: $Schema[typeof Meta];
|
|
15
|
+
readonly trace: Trace;
|
|
16
|
+
readonly [Adaptation]?: AdaptationsOf<$Schema>;
|
|
17
|
+
schema: $Schema[typeof Meta] extends ThisMeta<infer $T> ? Schema<$T, AdaptationsOf<$Schema>> : never;
|
|
18
|
+
};
|
|
19
|
+
export declare function Fabricator<$T>(context: FabricatorContext<Schema<$T>>): Fabricator<Schema<$T>>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Produce } from "../../Random/Types";
|
|
2
|
+
import { Schema } from "./Schema";
|
|
3
|
+
/**
|
|
4
|
+
* A value this library has no kind for — a `Map`, a `Set`, a `URL`, a class
|
|
5
|
+
* instance — produced by `produce` and typed as whatever it returns, so
|
|
6
|
+
* `T.opaque((random) => new Map<string, number>())` needs no annotation.
|
|
7
|
+
*
|
|
8
|
+
* `produce` receives this schema's own seeded stream, so an opaque value
|
|
9
|
+
* still replays from a seed; see `Types.ts`'s `Produce`. No bare form and
|
|
10
|
+
* no `.as()` — `produce` is the whole schema.
|
|
11
|
+
*/
|
|
12
|
+
export default function <$T>(produce: Produce<$T>): Schema<$T>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AdaptationEntry } from "../../Adapter/Core";
|
|
2
|
+
import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
|
|
3
|
+
import type { Core } from "./Types";
|
|
4
|
+
/**
|
|
5
|
+
* Escape hatch for values no kind models — a `Map`, a `Set`, a `URL`, a
|
|
6
|
+
* class instance, a branded type. `produce` is supplied at construction and
|
|
7
|
+
* receives the schema's own seeded stream (`Types.ts`'s `Produce`).
|
|
8
|
+
*
|
|
9
|
+
* No `.as()`, for `always`'s reason: the constructor argument already fully
|
|
10
|
+
* determines production. `adapt` matters more here than for any other kind
|
|
11
|
+
* — an opaque value maps to TypeBox's `Unknown`, which is honest but
|
|
12
|
+
* maximally imprecise, and `.adapt(typebox, ...)` is the only way to say
|
|
13
|
+
* more.
|
|
14
|
+
*/
|
|
15
|
+
export interface Schema<$T = unknown, $Adaptations extends Adaptations = {}> extends Core<$T, $Adaptations> {
|
|
16
|
+
/**
|
|
17
|
+
* Override what this schema maps to in one or more external schema
|
|
18
|
+
* libraries — see `string/Schema.ts`'s `adapt` for the full contract.
|
|
19
|
+
*/
|
|
20
|
+
adapt: <const $Adapter extends Adapter, $Returnable extends ReturnType<$Adapter["convert"]>>(adapter: $Adapter, produce: (adapting: Adapting<Schema<$T, $Adaptations>>) => $Returnable) => Schema<$T, WithAdaptations<$Adaptations, AdaptationEntry<$Adapter, $Returnable>>>;
|
|
21
|
+
}
|
|
22
|
+
export declare function Schema<$T, $Adaptations extends Adaptations = {}>(schema: Core<$T, $Adaptations>): Schema<$T, $Adaptations>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Adaptations } from "../../Adapter/Types";
|
|
2
|
+
import type { Produce } from "../../Random/Types";
|
|
3
|
+
import { Produces, type Adaptation, type Kind, type Meta } from "../../Types";
|
|
4
|
+
export type Fabricated<$T> = $T;
|
|
5
|
+
/**
|
|
6
|
+
* A single required member, unlike the two-arm unions kinds with a `whereby`
|
|
7
|
+
* carry: there is no configuration for an opaque value to layer `produce` on
|
|
8
|
+
* top of — `produce` is the entire schema.
|
|
9
|
+
*/
|
|
10
|
+
export type Meta<$T = unknown> = {
|
|
11
|
+
produce: Produce<$T>;
|
|
12
|
+
};
|
|
13
|
+
export type Core<$T = unknown, $Adaptations extends Adaptations = {}> = {
|
|
14
|
+
[Kind]: "opaque";
|
|
15
|
+
[Meta]: Meta<$T>;
|
|
16
|
+
readonly [Produces]?: Fabricated<$T>;
|
|
17
|
+
readonly [Adaptation]?: $Adaptations;
|
|
18
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AdaptationsOf } from "../../Adapter/Types";
|
|
2
|
+
import type { FabricatorContext, NaiveFabricator } from "../../Fabricator/Types";
|
|
3
|
+
import type { Trace } from "../../Random/Types";
|
|
4
|
+
import { Children, Kind, Meta, type Adaptation } from "../../Types";
|
|
5
|
+
import { Schema } from "./Schema";
|
|
6
|
+
import type { Fabricated, Key, Meta as ThisMeta, Value } from "./Types";
|
|
7
|
+
export type Fabrication<$Fabricator extends Fabricator> = $Fabricator extends Fabricator<infer $Schema extends {
|
|
8
|
+
[Meta]: ThisMeta;
|
|
9
|
+
}> ? Fabricated<$Schema[typeof Meta]["key"], $Schema[typeof Meta]["value"]> : never;
|
|
10
|
+
export type Fabricator<$Schema extends {
|
|
11
|
+
[Meta]: ThisMeta;
|
|
12
|
+
} = {
|
|
13
|
+
[Meta]: ThisMeta;
|
|
14
|
+
}> = NaiveFabricator<Fabricated<$Schema[typeof Meta]["key"], $Schema[typeof Meta]["value"]>> & {
|
|
15
|
+
[Kind]: "record";
|
|
16
|
+
[Meta]: $Schema[typeof Meta];
|
|
17
|
+
readonly trace: Trace;
|
|
18
|
+
[Children]: {
|
|
19
|
+
key: NaiveFabricator<any>;
|
|
20
|
+
value: NaiveFabricator<any>;
|
|
21
|
+
};
|
|
22
|
+
readonly [Adaptation]?: AdaptationsOf<$Schema>;
|
|
23
|
+
schema: Schema<$Schema[typeof Meta]["key"], $Schema[typeof Meta]["value"], AdaptationsOf<$Schema>>;
|
|
24
|
+
};
|
|
25
|
+
export declare function Fabricator<$Key extends Key, $Value extends Value>(context: FabricatorContext<Schema<$Key, $Value>>, key: NaiveFabricator<any>, value: NaiveFabricator<any>): Fabricator<Schema<$Key, $Value>>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Produce } from "../../Random/Types";
|
|
2
|
+
import { Schema } from "./Schema";
|
|
3
|
+
import type { Fabricated, Key, Value, Whereby } from "./Types";
|
|
4
|
+
export default function <const $Key extends Key, const $Value extends Value>(key: $Key, value: $Value): {
|
|
5
|
+
/**
|
|
6
|
+
* A record of `value` keyed by `key`, attempted `whereby.size` times —
|
|
7
|
+
* uniformly across `[size.minTried, size.max]` (with `minTried`
|
|
8
|
+
* defaulting to 0). Colliding keys collapse, so the result holds *at
|
|
9
|
+
* most* that many entries; see `Types.ts`'s `Whereby`.
|
|
10
|
+
*/
|
|
11
|
+
whereby: (whereby: Whereby) => Schema<$Key, $Value>;
|
|
12
|
+
/**
|
|
13
|
+
* A record whose production is `produce`, in full, instead of drawn
|
|
14
|
+
* entry by entry.
|
|
15
|
+
*/
|
|
16
|
+
as: (produce: Produce<Fabricated<$Key, $Value>>) => Schema<$Key, $Value>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type AdaptationEntry } from "../../Adapter/Core";
|
|
2
|
+
import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
|
|
3
|
+
import type { Produce } from "../../Random/Types";
|
|
4
|
+
import type { Core, Fabricated, Key, Value } from "./Types";
|
|
5
|
+
/**
|
|
6
|
+
* The buildable recipe for a `record`: a key Schema and a value Schema,
|
|
7
|
+
* drawn `whereby.size` times. `array`'s sibling — one repeated value shape
|
|
8
|
+
* and a fuzzed count — but keyed rather than indexed.
|
|
9
|
+
*/
|
|
10
|
+
export interface Schema<$Key extends Key = Key, $Value extends Value = Value, $Adaptations extends Adaptations = {}> extends Core<$Key, $Value, $Adaptations> {
|
|
11
|
+
/**
|
|
12
|
+
* Layer an opaque production on this schema's existing `[Meta]` — carrying
|
|
13
|
+
* `whereby`/`key`/`value` forward, not discarding them, so a later
|
|
14
|
+
* `.as(...)` (or future validation of `produce`) still has them to check
|
|
15
|
+
* against.
|
|
16
|
+
*/
|
|
17
|
+
as: (produce: Produce<Fabricated<$Key, $Value>>) => Schema<$Key, $Value, $Adaptations>;
|
|
18
|
+
/**
|
|
19
|
+
* Override what this schema maps to in one or more external schema
|
|
20
|
+
* libraries — see `string/Schema.ts`'s `adapt`. Particularly relevant
|
|
21
|
+
* here: a symbol-keyed record has no TypeBox counterpart
|
|
22
|
+
* (`Adapter/TypeBox`'s `record` case), so this is the only way to give
|
|
23
|
+
* one a mapping.
|
|
24
|
+
*/
|
|
25
|
+
adapt: <const $Adapter extends Adapter, $Returnable extends ReturnType<$Adapter["convert"]>>(adapter: $Adapter, produce: (adapting: Adapting<Schema<$Key, $Value, $Adaptations>>) => $Returnable) => Schema<$Key, $Value, WithAdaptations<$Adaptations, AdaptationEntry<$Adapter, $Returnable>>>;
|
|
26
|
+
}
|
|
27
|
+
export declare function Schema<$Key extends Key, $Value extends Value, $Adaptations extends Adaptations = {}>(schema: Core<$Key, $Value, $Adaptations>): Schema<$Key, $Value, $Adaptations>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { Adaptations } from "../../Adapter/Types";
|
|
2
|
+
import type { Produce } from "../../Random/Types";
|
|
3
|
+
import type { AnySchema, ValueOf } from "../../Schema/Types";
|
|
4
|
+
import { Produces, type Adaptation, type Kind, type Meta } from "../../Types";
|
|
5
|
+
/**
|
|
6
|
+
* A Schema usable as a record's keys: any Schema whose fabricated value is a
|
|
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
|
+
* kind qualifies — `T.string.whereby(...)`, `T.symbol`,
|
|
10
|
+
* `T.enum.uniform([...])` of strings, `T.always("k")`, a string `T.choice` —
|
|
11
|
+
* while `T.number`/`T.date` are rejected at the call site.
|
|
12
|
+
*
|
|
13
|
+
* `symbol` is included deliberately: symbols are legal property keys.
|
|
14
|
+
* Excluding them would arbitrarily narrow what a record can describe. They
|
|
15
|
+
* do not survive `Adapter/TypeBox` — see its `record` case.
|
|
16
|
+
*/
|
|
17
|
+
export type Key = AnySchema & {
|
|
18
|
+
readonly [Produces]?: string | symbol;
|
|
19
|
+
};
|
|
20
|
+
export type Value = AnySchema;
|
|
21
|
+
/**
|
|
22
|
+
* Whether a key type spans a whole primitive key type rather than a finite
|
|
23
|
+
* set of literals — i.e. whether the record's keyspace is open-ended.
|
|
24
|
+
*/
|
|
25
|
+
type IsKeyspaceOpen<$Key> = string extends $Key ? true : symbol extends $Key ? true : false;
|
|
26
|
+
/**
|
|
27
|
+
* Split is *open keyspace vs. finite*, not string vs. symbol.
|
|
28
|
+
*
|
|
29
|
+
* An open key (`string`, `symbol`, or both) is a plain index signature: no
|
|
30
|
+
* `Partial` — an index signature never guarantees a key is present, and
|
|
31
|
+
* wrapping one would only add a spurious `| undefined`. Carrying
|
|
32
|
+
* `ValueOf<$Key>` rather than hardcoding `string` keeps a mixed
|
|
33
|
+
* `string | symbol` key as `Record<string | symbol, ...>` instead of
|
|
34
|
+
* silently dropping the symbol half.
|
|
35
|
+
*
|
|
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
|
+
* so a two-member key schema may produce only one. Every key present wants
|
|
39
|
+
* `T.object({ ... })` — what a record over a finite key set degenerates to.
|
|
40
|
+
*/
|
|
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>>>;
|
|
42
|
+
/**
|
|
43
|
+
* How many entries to attempt, uniformly across `[minTried, max]`.
|
|
44
|
+
*
|
|
45
|
+
* Asymmetric naming is the point. Colliding keys collapse rather than being
|
|
46
|
+
* redrawn, so surviving count is only ever *at most* what was attempted:
|
|
47
|
+
* `max` is a real upper bound; the lower bound is not guaranteed and the
|
|
48
|
+
* field says so. `minTried` is optional, default `0`, matching
|
|
49
|
+
* `string`'s `whereby.length.min`.
|
|
50
|
+
*
|
|
51
|
+
* No bare-number form (unlike `array`'s `length`): "exactly N" is a promise
|
|
52
|
+
* a collapsing key set cannot keep.
|
|
53
|
+
*/
|
|
54
|
+
export type Whereby = {
|
|
55
|
+
size: {
|
|
56
|
+
max: number;
|
|
57
|
+
minTried?: number | undefined;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
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
|
+
* way. `produce` is carried *alongside* `whereby` rather than replacing it,
|
|
64
|
+
* so a prior size spec survives `as` for future validation — same as
|
|
65
|
+
* `array`'s `Meta`.
|
|
66
|
+
*/
|
|
67
|
+
export type Meta<$Key extends Key = Key, $Value extends Value = Value> = {
|
|
68
|
+
key: $Key;
|
|
69
|
+
value: $Value;
|
|
70
|
+
whereby: Whereby;
|
|
71
|
+
produce?: never;
|
|
72
|
+
} | {
|
|
73
|
+
key: $Key;
|
|
74
|
+
value: $Value;
|
|
75
|
+
whereby?: Whereby;
|
|
76
|
+
produce: Produce<Fabricated<$Key, $Value>>;
|
|
77
|
+
};
|
|
78
|
+
export interface Core<$Key extends Key = Key, $Value extends Value = Value, $Adaptations extends Adaptations = {}> {
|
|
79
|
+
[Kind]: "record";
|
|
80
|
+
[Meta]: Meta<$Key, $Value>;
|
|
81
|
+
bindings?: unknown[];
|
|
82
|
+
readonly [Produces]?: Fabricated<$Key, $Value, NonNullable<this["bindings"]>>;
|
|
83
|
+
readonly [Adaptation]?: $Adaptations;
|
|
84
|
+
}
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AdaptationsOf } from "../../Adapter/Types";
|
|
2
|
+
import type { ConstructionContext, FabricatorContext, NaiveFabricator } from "../../Fabricator/Types";
|
|
3
|
+
import type { RandomSource, Trace } from "../../Random/Types";
|
|
4
|
+
import { Kind, Meta, type Adaptation } from "../../Types";
|
|
5
|
+
import { Schema } from "./Schema";
|
|
6
|
+
import type { Fabricated, Meta as ThisMeta } from "./Types";
|
|
7
|
+
export type Fabrication<$Fabricator extends Fabricator> = $Fabricator extends Fabricator<infer $Schema extends {
|
|
8
|
+
[Meta]: ThisMeta;
|
|
9
|
+
}> ? Fabricated<$Schema[typeof Meta]["body"]> : never;
|
|
10
|
+
export type Fabricator<$Schema extends {
|
|
11
|
+
[Meta]: ThisMeta;
|
|
12
|
+
} = {
|
|
13
|
+
[Meta]: ThisMeta;
|
|
14
|
+
}> = NaiveFabricator<Fabricated<$Schema[typeof Meta]["body"]>> & {
|
|
15
|
+
[Kind]: "recursive";
|
|
16
|
+
[Meta]: $Schema[typeof Meta];
|
|
17
|
+
readonly trace: Trace;
|
|
18
|
+
readonly [Adaptation]?: AdaptationsOf<$Schema>;
|
|
19
|
+
schema: Schema<$Schema[typeof Meta]["body"], AdaptationsOf<$Schema>>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Expansion is lazy — one dispatch per `self` at fabricate time, not unrolled
|
|
23
|
+
* to `depth.max` at build. This is the only place dispatch (assigning a node
|
|
24
|
+
* its private stream) happens *inside* `fabricate()`, not at
|
|
25
|
+
* `new Fabricator(...)`. Safe because of isolation, not memoization: every
|
|
26
|
+
* other kind's dispatch count is a function of schema shape, so structural
|
|
27
|
+
* path keying already identifies it. A recursive node's count is
|
|
28
|
+
* data-dependent — how deep this `fabricate()` goes — so no structural path
|
|
29
|
+
* distinguishes sibling expansions at the same depth (an `array` of three
|
|
30
|
+
* `self` children calls `fabricateAt` three times on one shared element
|
|
31
|
+
* Fabricator; the schema does not tell them apart). Each expansion gets its
|
|
32
|
+
* own *root*: `forkSource` mints an isolated `RandomSource` seeded from this
|
|
33
|
+
* node's draw, and each `fabricateAt` opens a `"counted"` scope on it
|
|
34
|
+
* (`Random/Types.ts`'s `RootKind` — recorded on each expansion's
|
|
35
|
+
* `trace`, not chosen at `ConstructorOptions`). The
|
|
36
|
+
* private source's construction counter orders expansions; nothing to
|
|
37
|
+
* increment here. Isolation also keeps this node's data-dependent draws from
|
|
38
|
+
* perturbing (or being perturbed by) an unrelated Fabricator from the same
|
|
39
|
+
* `initialize()` instance.
|
|
40
|
+
*
|
|
41
|
+
* Each `self` gets its own independently-dispatched expansion — calling
|
|
42
|
+
* `context.self` twice (two array slots) is two `fabricateAt` calls, each
|
|
43
|
+
* with its own scope and stream space — `tuple`'s per-slot convention, not
|
|
44
|
+
* `array`'s shared-element one. Sibling tree branches therefore draw
|
|
45
|
+
* independently, not a correlated shared sequence.
|
|
46
|
+
*/
|
|
47
|
+
export declare function Fabricator<$Body>(context: FabricatorContext<Schema<$Body>>, forkSource: (seed: string) => RandomSource, make: (schema: unknown, path: ReadonlyArray<string>, context: ConstructionContext) => NaiveFabricator<unknown>): Fabricator<Schema<$Body>>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AnySchema } from "../../Schema/Types";
|
|
2
|
+
import { type Schema as SelfSchema } from "./self";
|
|
3
|
+
import { Schema } from "./Schema";
|
|
4
|
+
import type { Whereby } from "./Types";
|
|
5
|
+
/**
|
|
6
|
+
* `T.recursive(body)` — a builder, not a Schema, matching `array`/`record`:
|
|
7
|
+
* `.whereby({ depth })` is what produces one; no bare form. `terminal` is
|
|
8
|
+
* optional: omitted, it is derived from `body` (`Terminate.ts`).
|
|
9
|
+
*
|
|
10
|
+
* `body` is called exactly once, here, with a single freshly-minted `self`
|
|
11
|
+
* placeholder — eagerly, the same timing `array`/`record` normalize their
|
|
12
|
+
* nested definitions at call time, not deferred to `.whereby()`. Every
|
|
13
|
+
* `self` in the returned schema is this same placeholder;
|
|
14
|
+
* `Constructor.ts`'s `make` matches it only by `[Kind]`, never by identity,
|
|
15
|
+
* so a `self` captured out of its callback and reused elsewhere silently
|
|
16
|
+
* resolves against whichever recursion is currently active rather than
|
|
17
|
+
* erroring — a misuse this library doesn't guard, the same way passing the
|
|
18
|
+
* wrong schema object elsewhere isn't.
|
|
19
|
+
*/
|
|
20
|
+
export default function <const $Body extends AnySchema>(body: (self: SelfSchema) => $Body): {
|
|
21
|
+
whereby(config: Whereby<$Body>): Schema<$Body>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type AdaptationEntry } from "../../Adapter/Core";
|
|
2
|
+
import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
|
|
3
|
+
import type { Core } from "./Types";
|
|
4
|
+
/**
|
|
5
|
+
* A recursive schema, produced by `.whereby({ depth })` — see
|
|
6
|
+
* `Registry.ts` for the builder `T.recursive(body)` itself returns.
|
|
7
|
+
* `terminal` is optional there; omitted, it is derived from `body`.
|
|
8
|
+
*
|
|
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
|
+
* exactly the problem `depth`/`terminal` already solve — deferred rather
|
|
12
|
+
* than ruled out, since adding it later is non-breaking.
|
|
13
|
+
*/
|
|
14
|
+
export interface Schema<$Body = unknown, $Adaptations extends Adaptations = {}> extends Core<$Body, $Adaptations> {
|
|
15
|
+
/**
|
|
16
|
+
* Override what this schema maps to in one or more external schema
|
|
17
|
+
* libraries — see `string/Schema.ts`'s `adapt` for the full contract.
|
|
18
|
+
*/
|
|
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
|
+
}
|
|
21
|
+
export declare function Schema<$Body, $Adaptations extends Adaptations = {}>(schema: Core<$Body, $Adaptations>): Schema<$Body, $Adaptations>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AnySchema } from "../../Schema/Types";
|
|
2
|
+
/**
|
|
3
|
+
* Derive the schema that `fabricateAt` swaps in at `depth.max` when the
|
|
4
|
+
* caller omits `terminal`. Walks `body` and rewrites every `self` site
|
|
5
|
+
* into a declining state so the result contains *no* `recursive.self`
|
|
6
|
+
* nodes — `Constructor.ts`'s `make` still dispatches nested schemas
|
|
7
|
+
* eagerly, and `recursive.self` throws when `context.self` is missing
|
|
8
|
+
* (which it is, at the ceiling).
|
|
9
|
+
*
|
|
10
|
+
* Empty collections are `opaque(() => [])` / `opaque(() => ({}))`,
|
|
11
|
+
* never `always([])`: each leaf must get its own reference (see
|
|
12
|
+
* `Recursive.test.ts`). Presence wrappers become a self-free schema
|
|
13
|
+
* that always declines (`null` / `undefined` / `Omitted`), rather than
|
|
14
|
+
* keeping the inner `self` behind a produce short-circuit — `make`
|
|
15
|
+
* would still construct that inner node.
|
|
16
|
+
*
|
|
17
|
+
* Nested `T.recursive` is its own fixed point and is treated as a
|
|
18
|
+
* leaf; its inner `self` is not this walk's `self`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function terminate(body: AnySchema): AnySchema;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Adaptations } from "../../Adapter/Types";
|
|
2
|
+
import type { AnySchema, ValueOf } from "../../Schema/Types";
|
|
3
|
+
import { Produces, type Adaptation, type Kind, type Meta } from "../../Types";
|
|
4
|
+
/**
|
|
5
|
+
* Fixed point of a recursive schema. A self-referential alias, normally
|
|
6
|
+
* `TS2456` ("`RecursiveValue` circularly references itself") — legal *only*
|
|
7
|
+
* because `ValueOf`'s second argument is read through an interface member
|
|
8
|
+
* (`this["bindings"]` on every composite `Core`), which TypeScript defers.
|
|
9
|
+
* Do not rewrite as a conditional; that reintroduces the error. See
|
|
10
|
+
* `CLAUDE.md`'s "`ValueOf`'s `$Bindings`".
|
|
11
|
+
*
|
|
12
|
+
* Wherever `self` sits in `$Body` (nested through `array`/`object`/`tuple`/
|
|
13
|
+
* etc., each forwarding `this["bindings"]`), it reads `bindings[0]` —
|
|
14
|
+
* `RecursiveValue<$Body>` itself, closing the loop.
|
|
15
|
+
*/
|
|
16
|
+
export type RecursiveValue<$Body> = ValueOf<$Body, [RecursiveValue<$Body>]>;
|
|
17
|
+
export type Fabricated<$Body> = RecursiveValue<$Body>;
|
|
18
|
+
/**
|
|
19
|
+
* `terminal` is what `self` expands into at `depth.max`, in place of `body`.
|
|
20
|
+
* Expansion is lazy (per `self`, at fabricate time) — see `Fabricator.ts`.
|
|
21
|
+
*
|
|
22
|
+
* Constraining `terminal` against `RecursiveValue<$Body>` as a plain field
|
|
23
|
+
* type (not `terminal`'s own type parameter) is enough: structural
|
|
24
|
+
* assignability already rejects a wrong terminal (e.g. missing a required
|
|
25
|
+
* field `body` has), and nothing downstream needs `terminal`'s precise type
|
|
26
|
+
* (`Core`'s `[Produces]` depends only on `$Body`). A bare-vs-generic
|
|
27
|
+
* comparison rejects the same wrong terminal either way.
|
|
28
|
+
*
|
|
29
|
+
* Omitted, `terminal` is derived from `body` (`Terminate.ts`): every `self`
|
|
30
|
+
* behind a declining kind is rewritten into a stop (empty array/record,
|
|
31
|
+
* remaining non-`self` choice arms, `null`/`undefined`/`Omitted`). A
|
|
32
|
+
* required `self` cannot be derived — `.whereby()` throws
|
|
33
|
+
* `UnterminableRecursiveError`, and an explicit `terminal` is the way out.
|
|
34
|
+
* A provided `terminal` is a wholesale override of that derivation (custom
|
|
35
|
+
* leaf values, a narrower JSON leaf), not a patch of `self` sites.
|
|
36
|
+
*
|
|
37
|
+
* `depth.max` is a ceiling, not a target: `fabricateAt` (`Fabricator.ts`)
|
|
38
|
+
* only *compares* a counter against it, never draws one — unlike
|
|
39
|
+
* `array`/`record`/`string`'s `{min, max}`, there is no drawn count for a
|
|
40
|
+
* `min` to constrain. Realized depth is emergent: intervening kinds decline
|
|
41
|
+
* to recurse (an `array`/`record` rolling 0, a `choice` picking a non-`self`
|
|
42
|
+
* option, an `omittable`/`optional`/`undefinable` resolving absent). The
|
|
43
|
+
* recursive node has no say. "Force `body` while `depth` is below some
|
|
44
|
+
* `min`" is a no-op: that already happens below `depth.max`. A genuine floor
|
|
45
|
+
* would coerce those intervening kinds' draws — a different feature than a
|
|
46
|
+
* second number here. The derived terminal may empty a collection whose
|
|
47
|
+
* `body` said `length.min > 0`: the ceiling has to stop somehow, and an
|
|
48
|
+
* explicit `terminal` already did the same with `T.opaque(() => [])`.
|
|
49
|
+
*/
|
|
50
|
+
export type Whereby<$Body> = {
|
|
51
|
+
depth: {
|
|
52
|
+
max: number;
|
|
53
|
+
};
|
|
54
|
+
terminal?: (AnySchema & {
|
|
55
|
+
readonly [Produces]?: RecursiveValue<$Body>;
|
|
56
|
+
}) | undefined;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* `terminal` is stored as `AnySchema` — once `.whereby(...)` has checked it
|
|
60
|
+
* against `RecursiveValue<$Body>`, nothing downstream needs its precise type
|
|
61
|
+
* (unlike `object.compute`'s `source`, which feeds `Resolved<$Source>`).
|
|
62
|
+
*/
|
|
63
|
+
export type Meta<$Body = unknown> = {
|
|
64
|
+
body: $Body;
|
|
65
|
+
depth: {
|
|
66
|
+
max: number;
|
|
67
|
+
};
|
|
68
|
+
terminal: AnySchema;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* A `type` alias, not an `interface` — unlike every composite that *contains*
|
|
72
|
+
* a `self`, `recursive` is where the fixed point *closes*, so `[Produces]`
|
|
73
|
+
* never needs `this["bindings"]`: `RecursiveValue` is already concrete once
|
|
74
|
+
* `$Body` is, regardless of bindings this schema sits inside (a nested
|
|
75
|
+
* `T.recursive` is its own independent fixed point).
|
|
76
|
+
*/
|
|
77
|
+
export type Core<$Body = unknown, $Adaptations extends Adaptations = {}> = {
|
|
78
|
+
[Kind]: "recursive";
|
|
79
|
+
[Meta]: Meta<$Body>;
|
|
80
|
+
readonly [Produces]?: Fabricated<$Body>;
|
|
81
|
+
readonly [Adaptation]?: $Adaptations;
|
|
82
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { FabricatorContext, NaiveFabricator } from "../../../Fabricator/Types";
|
|
2
|
+
import type { Trace } from "../../../Random/Types";
|
|
3
|
+
import { Kind, Meta } from "../../../Types";
|
|
4
|
+
import type { Schema } from "./Schema";
|
|
5
|
+
import type { Fabricated, Meta as ThisMeta } from "./Types";
|
|
6
|
+
export type Fabrication<$Fabricator extends Fabricator> = $Fabricator extends Fabricator<infer $Bindings> ? $Bindings[0] : never;
|
|
7
|
+
/**
|
|
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
|
+
* (`[Meta]` is always `{}`), only whatever `$Bindings` its position resolves
|
|
11
|
+
* against.
|
|
12
|
+
*/
|
|
13
|
+
export type Fabricator<$Bindings extends unknown[] = []> = NaiveFabricator<Fabricated<$Bindings>> & {
|
|
14
|
+
[Kind]: "recursive.self";
|
|
15
|
+
[Meta]: ThisMeta;
|
|
16
|
+
readonly trace: Trace;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* A transient passthrough, unlike every other kind's Fabricator — it draws
|
|
20
|
+
* no randomness of its own: a `self` node stands for wherever
|
|
21
|
+
* `T.recursive`'s current expansion is, and `resolve` *is* that expansion,
|
|
22
|
+
* one level deeper — the same closure `recursive/Fabricator.ts` hands to
|
|
23
|
+
* every `self` in its body via `Constructor.ts`'s `make` context (`case
|
|
24
|
+
* "recursive.self"`). Calling `resolve` is what actually recurses; this
|
|
25
|
+
* function only wraps it in the shape `make` expects back. Absent
|
|
26
|
+
* `resolve` (a `self` rebuilt from its schema plus trace, without the
|
|
27
|
+
* enclosing recursive parent), `.fabricate()` throws `DetachedSelfError`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function Fabricator<$Bindings extends unknown[]>(context: FabricatorContext<Schema>, resolve?: (() => Fabricated<$Bindings>) | undefined): Fabricator<$Bindings>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Schema } from "./Schema";
|
|
2
|
+
/**
|
|
3
|
+
* Mints a fresh `self` placeholder — called only from `recursive/Registry.ts`
|
|
4
|
+
* to hand one to `T.recursive`'s own body callback. Not exposed as `T.self`,
|
|
5
|
+
* the same standing as `object.compute`'s own internal-only factory.
|
|
6
|
+
*/
|
|
7
|
+
export default function (): Schema;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AdaptationEntry } from "../../../Adapter/Core";
|
|
2
|
+
import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../../Adapter/Types";
|
|
3
|
+
import type { Core } from "./Types";
|
|
4
|
+
/**
|
|
5
|
+
* The placeholder `T.recursive`'s body callback receives in place of the
|
|
6
|
+
* schema being defined — everywhere `self` appears, it stands for "recurse
|
|
7
|
+
* one level deeper here." Never constructed directly: `T.recursive` is the
|
|
8
|
+
* only thing that mints one, and only ever hands it to its own callback, so
|
|
9
|
+
* there is no bare `T.self`.
|
|
10
|
+
*
|
|
11
|
+
* No `.as()` — unlike `always`, not because there's nothing left to
|
|
12
|
+
* override, but because there is nothing here *to* produce: a `self` node
|
|
13
|
+
* carries no value of its own, only a reference to whatever the enclosing
|
|
14
|
+
* recursion currently binds it to. `adapt` still applies, on the same
|
|
15
|
+
* footing as every other kind.
|
|
16
|
+
*/
|
|
17
|
+
export interface Schema<$Adaptations extends Adaptations = {}> extends Core<$Adaptations> {
|
|
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>>>;
|
|
19
|
+
}
|
|
20
|
+
export declare function Schema<$Adaptations extends Adaptations = {}>(schema: Core<$Adaptations>): Schema<$Adaptations>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Adaptations } from "../../../Adapter/Types";
|
|
2
|
+
import { Produces, type Adaptation, type Kind, type Meta } from "../../../Types";
|
|
3
|
+
/**
|
|
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
|
+
* `bindings[0]`, the analogue of TypeBox's `TThis` reading
|
|
7
|
+
* `this['params'][0]`; see `Schema/Types.ts`'s `ValueOf` for what
|
|
8
|
+
* `bindings` is and why it's a tuple.
|
|
9
|
+
*
|
|
10
|
+
* Unlike every other kind, `self` has no type parameter of its own — its
|
|
11
|
+
* whole value comes from outside, threaded in structurally by whatever
|
|
12
|
+
* composite kinds wrap it (`recursive/Types.ts`'s `RecursiveValue` is what
|
|
13
|
+
* ultimately supplies `bindings[0]`).
|
|
14
|
+
*/
|
|
15
|
+
export type Fabricated<$Bindings extends unknown[] = []> = $Bindings[0];
|
|
16
|
+
export type Meta = Record<string, never>;
|
|
17
|
+
/**
|
|
18
|
+
* An `interface`, not a `type` alias, so `this["bindings"]` resolves — the
|
|
19
|
+
* entire mechanism this kind exists for. See `CLAUDE.md`'s "`ValueOf`'s
|
|
20
|
+
* `$Bindings`" section for why threading requires this.
|
|
21
|
+
*/
|
|
22
|
+
export interface Core<$Adaptations extends Adaptations = {}> {
|
|
23
|
+
[Kind]: "recursive.self";
|
|
24
|
+
[Meta]: Meta;
|
|
25
|
+
bindings?: unknown[];
|
|
26
|
+
readonly [Produces]?: Fabricated<NonNullable<this["bindings"]>>;
|
|
27
|
+
readonly [Adaptation]?: $Adaptations;
|
|
28
|
+
}
|