@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
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { Stream } from "../Random/Types";
|
|
2
2
|
/**
|
|
3
|
-
* How randomly generated values cluster within a `{ min, max }` range.
|
|
4
|
-
*
|
|
5
|
-
* equally likely.
|
|
3
|
+
* How randomly generated values cluster within a `{ min, max }` range. Without
|
|
4
|
+
* one, generation is uniform — every value in the range is equally likely.
|
|
6
5
|
*
|
|
7
|
-
* Each variant is a tagged object so distributions stay
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* Each variant is a tagged object so distributions stay introspectable and
|
|
7
|
+
* serializable. The `custom` variant is the escape hatch: a shaping function
|
|
8
|
+
* `(u) => p` mapping a uniform draw in `[0, 1)` to a position in `[0, 1)`
|
|
9
|
+
* within the range.
|
|
11
10
|
*/
|
|
12
11
|
export type Distribution = Distribution.Uniform | Distribution.Normal | Distribution.Skew | Distribution.Triangular | Distribution.Logarithmic | Distribution.Multi | Distribution.Custom;
|
|
13
12
|
export type Range = {
|
|
@@ -25,9 +24,9 @@ export declare namespace Distribution {
|
|
|
25
24
|
spread?: number | undefined;
|
|
26
25
|
};
|
|
27
26
|
/**
|
|
28
|
-
* Bell curve truncated to the range. `mean` defaults to the range's
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* Bell curve truncated to the range. `mean` defaults to the range's center;
|
|
28
|
+
* `spread` (standard deviation) defaults to a sixth of the span, placing the
|
|
29
|
+
* bounds at roughly ±3σ before truncation.
|
|
31
30
|
*/
|
|
32
31
|
const normal: (params?: {
|
|
33
32
|
mean?: number;
|
|
@@ -38,8 +37,8 @@ export declare namespace Distribution {
|
|
|
38
37
|
exponent: number;
|
|
39
38
|
};
|
|
40
39
|
/**
|
|
41
|
-
* Power curve. `exponent > 1` biases toward `min`, `exponent < 1`
|
|
42
|
-
*
|
|
40
|
+
* Power curve. `exponent > 1` biases toward `min`, `exponent < 1` biases
|
|
41
|
+
* toward `max`, and `exponent === 1` is uniform.
|
|
43
42
|
*/
|
|
44
43
|
const skew: (exponent: number) => Distribution;
|
|
45
44
|
type Triangular = {
|
|
@@ -56,10 +55,9 @@ export declare namespace Distribution {
|
|
|
56
55
|
kind: "logarithmic";
|
|
57
56
|
};
|
|
58
57
|
/**
|
|
59
|
-
* Log-uniform (reciprocal): density proportional to `1/x`, so values
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* or below zero.
|
|
58
|
+
* Log-uniform (reciprocal): density proportional to `1/x`, so values spread
|
|
59
|
+
* evenly across orders of magnitude and cluster toward `min`. Requires a
|
|
60
|
+
* strictly positive range — the logarithm is undefined at or below zero.
|
|
63
61
|
*/
|
|
64
62
|
const logarithmic: () => Distribution;
|
|
65
63
|
type Multi = {
|
|
@@ -70,11 +68,10 @@ export declare namespace Distribution {
|
|
|
70
68
|
}>;
|
|
71
69
|
};
|
|
72
70
|
/**
|
|
73
|
-
* A weighted blend of component distributions, each drawn over the
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* to 1.
|
|
71
|
+
* A weighted blend of component distributions, each drawn over the same
|
|
72
|
+
* range. Localized components with distinct centers (e.g. two `normal`s at
|
|
73
|
+
* different means) produce the separate peaks of a multimodal distribution.
|
|
74
|
+
* Weights are relative — they need not sum to 1.
|
|
78
75
|
*/
|
|
79
76
|
const multi: (components: ReadonlyArray<{
|
|
80
77
|
weight: number;
|
|
@@ -85,73 +82,69 @@ export declare namespace Distribution {
|
|
|
85
82
|
shape: (u: number) => number;
|
|
86
83
|
};
|
|
87
84
|
/**
|
|
88
|
-
* Escape hatch: `shape` maps a uniform draw in `[0, 1)` to a
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* bounds.
|
|
85
|
+
* Escape hatch: `shape` maps a uniform draw in `[0, 1)` to a position in `[0,
|
|
86
|
+
* 1)` within the range (an inverse CDF). The output is clamped to `[0, 1]` so
|
|
87
|
+
* the result always lands within the bounds.
|
|
92
88
|
*/
|
|
93
89
|
const custom: (shape: (u: number) => number) => Distribution;
|
|
94
90
|
}
|
|
95
91
|
/**
|
|
96
|
-
* Build a sampler that draws values within `range` following
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
92
|
+
* Build a sampler that draws values within `range` following `distribution`.
|
|
93
|
+
* Each call consumes one fresh uniform draw and, by construction, returns a
|
|
94
|
+
* value within `[min, max]` — distributions with mass outside the range (e.g. a
|
|
95
|
+
* normal's tails) are truncated via their inverse CDF rather than rejected or
|
|
96
|
+
* clamped.
|
|
101
97
|
*/
|
|
102
98
|
export declare function sampler(distribution: Distribution, range: Range, stream: Stream): () => number;
|
|
103
99
|
export declare function sample<$T>(list: ReadonlyArray<$T>, stream: Stream): $T;
|
|
104
100
|
/**
|
|
105
101
|
* Fisher–Yates (Durstenfeld) shuffle: a new array holding `items` in a
|
|
106
|
-
* uniformly random order — every permutation is equally likely. Does
|
|
107
|
-
*
|
|
108
|
-
* convention.
|
|
102
|
+
* uniformly random order — every permutation is equally likely. Does not mutate
|
|
103
|
+
* `items`, matching `sample`/`weighted`'s read-only convention.
|
|
109
104
|
*/
|
|
110
105
|
export declare function shuffle<$T>(items: ReadonlyArray<$T>, stream: Stream): $T[];
|
|
111
106
|
/**
|
|
112
|
-
* `weighted()`'s own inclusion rule: whether this entry stays in the
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* `weight > 0`.
|
|
107
|
+
* `weighted()`'s own inclusion rule: whether this entry stays in the draw
|
|
108
|
+
* table. `0` is valid and disables the outcome; negative/`NaN` are rejected
|
|
109
|
+
* earlier by {@link isValidWeight}. Exposed so `Enumeration/Plan.ts` and the
|
|
110
|
+
* construction guards share one definition of "will this be drawn" rather than
|
|
111
|
+
* each writing `weight > 0`.
|
|
118
112
|
*/
|
|
119
113
|
export declare function isDrawable(weight: number): boolean;
|
|
120
114
|
/**
|
|
121
|
-
* Whether a weight is
|
|
122
|
-
* drawable. `0` is valid and disables the outcome; a negative weight or
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
115
|
+
* Whether a weight is _expressible_ at all, as opposed to whether it is
|
|
116
|
+
* drawable. `0` is valid and disables the outcome; a negative weight or `NaN`
|
|
117
|
+
* is a mistake. `Infinity` is rejected because it cannot be summed into a
|
|
118
|
+
* usable draw table — every cumulative bound becomes `Infinity`, so
|
|
119
|
+
* `weighted()`'s `x < weight` scan matches nothing.
|
|
126
120
|
*/
|
|
127
121
|
export declare function isValidWeight(weight: number): boolean;
|
|
128
122
|
/**
|
|
129
|
-
* Outcomes that still have a positive weight after applying the
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* `
|
|
123
|
+
* Outcomes that still have a positive weight after applying the baseline of `1`
|
|
124
|
+
* for any unspecified (missing or explicitly `undefined`) key. The one home of
|
|
125
|
+
* that `?? 1` default, so `assertDrawableKeyedWeights` and
|
|
126
|
+
* `Enumeration/Plan.ts` cannot drift.
|
|
133
127
|
*/
|
|
134
128
|
export declare function drawableOutcomes<$Outcome extends string>(outcomes: ReadonlyArray<$Outcome>, weights: Readonly<Record<string, number | undefined>> | undefined): ReadonlyArray<$Outcome>;
|
|
135
129
|
/**
|
|
136
|
-
* Two-stage guard for a `[weight, item]` list (`enum`/`choice`'s
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* (`"T.enum.weighted"`/`"T.choice.weighted"`), `noun` the kind of
|
|
130
|
+
* Two-stage guard for a `[weight, item]` list (`enum`/`choice`'s `.weighted()`
|
|
131
|
+
* registries). Stage 1 rejects any entry that is not {@link isValidWeight};
|
|
132
|
+
* stage 2 rejects a list with no {@link isDrawable} entry left. `label` names
|
|
133
|
+
* the call site (`"T.enum.weighted"`/`"T.choice.weighted"`), `noun` the kind of
|
|
141
134
|
* entry (`"member"`/`"option"`).
|
|
142
135
|
*/
|
|
143
136
|
export declare function assertDrawableWeights(label: string, noun: string, items: ReadonlyArray<readonly [number, unknown]>): void;
|
|
144
137
|
/**
|
|
145
|
-
* The same two-stage guard as {@link assertDrawableWeights}, for the
|
|
146
|
-
*
|
|
147
|
-
*
|
|
138
|
+
* The same two-stage guard as {@link assertDrawableWeights}, for the kinds
|
|
139
|
+
* whose `.weighted(...)` weighs a _fixed, named_ outcome set (`boolean`'s
|
|
140
|
+
* `true`/`false`; `nullable`/`nullish`/`undefinable`/
|
|
148
141
|
* `object.omittable`/`object.optional`'s presence outcomes) rather than a
|
|
149
|
-
* caller-supplied list. Stage 2 must see the kind's **full** outcome list
|
|
150
|
-
*
|
|
142
|
+
* caller-supplied list. Stage 2 must see the kind's **full** outcome list — an
|
|
143
|
+
* omitted key still defaults to `1` — hence `outcomes`.
|
|
151
144
|
*
|
|
152
|
-
* An explicitly-`undefined` value means "unspecified" — `Weights`'
|
|
153
|
-
*
|
|
154
|
-
*
|
|
145
|
+
* An explicitly-`undefined` value means "unspecified" — `Weights`' keys are all
|
|
146
|
+
* optional and fall back to a baseline of `1` — so it is skipped in stage 1 and
|
|
147
|
+
* defaulted in stage 2.
|
|
155
148
|
*/
|
|
156
149
|
export declare function assertDrawableKeyedWeights<$Outcome extends string>(label: string, outcomes: ReadonlyArray<$Outcome>, weights: Readonly<Record<string, number | undefined>>): void;
|
|
157
150
|
export declare function weighted<const $Item>(weights: ReadonlyArray<readonly [number, $Item]>, stream: Stream, label: string): () => $Item;
|
|
@@ -2,32 +2,32 @@ import type { Stack } from "../Instance/Types";
|
|
|
2
2
|
import type { RandomSource } from "../Random/Types";
|
|
3
3
|
import type { Enumerable, Limits } from "./Types";
|
|
4
4
|
/**
|
|
5
|
-
* Typed `combinatorial`/`coverage` boundary, closing over one
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* one precisely-typed layer, mirroring `Constructor.ts`'s `make`/
|
|
5
|
+
* Typed `combinatorial`/`coverage` boundary, closing over one instance's
|
|
6
|
+
* `source` and its already-validated `limits` — same shape as
|
|
7
|
+
* `Constructor(source, stack)`. No separate `clock`: `source` already carries
|
|
8
|
+
* its resolved clock (`Random/Types.ts`'s `Options.clock`), so `Constructor`'s
|
|
9
|
+
* `toConstructionContext` reads it off whichever root a construction resolves
|
|
10
|
+
* against. `plan`/ `resolve` (`./Plan.ts`) do the untyped recursive work; this
|
|
11
|
+
* is the one precisely-typed layer, mirroring `Constructor.ts`'s `make`/
|
|
13
12
|
* `construct` split.
|
|
14
13
|
*
|
|
15
|
-
* Two derived
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
14
|
+
* Two derived salts — one per API — each composed from the _effective_ source's
|
|
15
|
+
* salt (`effectiveSource()` below — the active `wrap` frame's, or this
|
|
16
|
+
* instance's `source`; read fresh on every `combinatorial(...)`/`coverage(...)`
|
|
17
|
+
* call, not once when `enumerables()` was built, so the same `combinatorial`
|
|
18
|
+
* reference behaves differently inside an active `wrap`). Each build pins that
|
|
19
|
+
* salt via `new Fabricator(schema, { salt })` (see `Constructor.ts`'s
|
|
20
|
+
* `construct()`) — a pin, not a fork — so every rebuild of one schema draws
|
|
21
|
+
* from the same universe, distinct from anything built under the instance's own
|
|
22
|
+
* salt.
|
|
23
|
+
*
|
|
24
|
+
* `ordinal: null` is pinned alongside it, and is not incidental: a salt says
|
|
25
|
+
* nothing about ordering, so without this pin each lazy rebuild would take the
|
|
26
|
+
* next ordinal from the effective source's counter — advancing it for every
|
|
27
|
+
* later construction, and giving each pass over the `Iterable` a different
|
|
28
|
+
* ordinal. A pinned ordinal is taken verbatim, so the counter is untouched,
|
|
29
|
+
* every iteration rebuilds from the same explicit identity, and the `null` can
|
|
30
|
+
* never coincide with a counted construction.
|
|
31
31
|
*/
|
|
32
32
|
export declare function enumerables(source: RandomSource, limits: Limits, stack: Stack): {
|
|
33
33
|
combinatorial: Enumerable;
|
|
@@ -7,38 +7,34 @@ type Planning = {
|
|
|
7
7
|
orderer: Orderer;
|
|
8
8
|
};
|
|
9
9
|
/**
|
|
10
|
-
* Enumerable shape of a built Fabricator tree: how many distinct
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* widen/narrow rules.
|
|
10
|
+
* Enumerable shape of a built Fabricator tree: how many distinct combinations,
|
|
11
|
+
* and how to reproduce the `index`-th as a `Pin`. Exhaustive kind dispatch
|
|
12
|
+
* lives in `axisFor`; this wrapper applies `"cycle"` permutation uniformly,
|
|
13
|
+
* once, to whatever axis `axisFor` computes — so every recursive call
|
|
14
|
+
* (`axisFor` cases call back into `plan`, never `axisFor` directly) gets its
|
|
15
|
+
* _own_ independent permutation, decorrelating equal-width siblings without any
|
|
16
|
+
* per-kind case needing to know strategy beyond `Strategy`'s own widen/narrow
|
|
17
|
+
* rules.
|
|
19
18
|
*
|
|
20
|
-
* Width is a function of schema shape
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* re-implemented here.
|
|
19
|
+
* Width is a function of schema shape _and_ weights: a zero-weighted outcome is
|
|
20
|
+
* not fabricable, so `axisFor` filters through `isDrawable` /
|
|
21
|
+
* `drawableOutcomes` rather than treating the declared branch set as the axis.
|
|
22
|
+
* Without that, `coverage()` would pin a value `fabricate()` can never produce.
|
|
23
|
+
* Defaulting of unspecified keyed weights goes through `drawableOutcomes` so
|
|
24
|
+
* the `?? 1` baseline is never re-implemented here.
|
|
27
25
|
*
|
|
28
26
|
* Skipped for width-1 axes (nothing to permute) and under `"product"`
|
|
29
|
-
* (mixed-radix decode already visits every combination, so permuting
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* omit otherwise.
|
|
27
|
+
* (mixed-radix decode already visits every combination, so permuting would only
|
|
28
|
+
* reorder identical output — see `Orderer`). `orders` is therefore only ever
|
|
29
|
+
* read when `strategy === "cycle"` and is safe to omit otherwise.
|
|
33
30
|
*/
|
|
34
31
|
export declare function plan(node: Resolvable, planning: Planning): Axis;
|
|
35
32
|
/**
|
|
36
|
-
* Reproduce the value a `Pin` describes against the built Fabricator
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* be exhaustive the way `plan()`'s is.
|
|
33
|
+
* Reproduce the value a `Pin` describes against the built Fabricator it was
|
|
34
|
+
* planned from. `pin === undefined` is universal — `plan()` gave this node a
|
|
35
|
+
* width-1 axis, so there is nothing to pin and it fabricates normally. Every
|
|
36
|
+
* other case only arises for kinds `plan()` treats as enumerable axes, so this
|
|
37
|
+
* switch does not need to be exhaustive the way `plan()`'s is.
|
|
42
38
|
*/
|
|
43
39
|
export declare function resolve(node: Resolvable, pin: Pin): unknown;
|
|
44
40
|
export {};
|
|
@@ -3,38 +3,35 @@ import type { AnySchema, ValueOf } from "../Schema/Types";
|
|
|
3
3
|
import type { Children, Kind, Meta } from "../Types";
|
|
4
4
|
import type { PlainObject } from "../Utility/Types";
|
|
5
5
|
/**
|
|
6
|
-
* How a composite with more than one child combines their widths.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* strategy.
|
|
6
|
+
* How a composite with more than one child combines their widths. `"product"`
|
|
7
|
+
* is the cartesian product — width is the product of every child's width;
|
|
8
|
+
* `at(index)` mixed-radix decodes to a full combination (`combinatorial`).
|
|
9
|
+
* `"cycle"` (`coverage`) takes the widest child as the composite's width,
|
|
10
|
+
* cycling narrower children to fill it — see CLAUDE.md's "sum vs product" note
|
|
11
|
+
* for why cycling only ever applies to `object`/`tuple` and never to a sum node
|
|
12
|
+
* (`choice`, the presence wrappers), which always total their children's widths
|
|
13
|
+
* regardless of strategy.
|
|
15
14
|
*/
|
|
16
15
|
export type Strategy = "product" | "cycle";
|
|
17
16
|
/**
|
|
18
|
-
* A fresh, reproducible permutation of `0..width-1` each call — one
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* `
|
|
26
|
-
*
|
|
27
|
-
* imports randomness.
|
|
17
|
+
* A fresh, reproducible permutation of `0..width-1` each call — one per
|
|
18
|
+
* width-`>1` node `plan()` visits, in walk order, so two nodes of the same
|
|
19
|
+
* width never receive the same permutation (which would otherwise iterate them
|
|
20
|
+
* in lockstep — see CLAUDE.md's note on why a constant phase offset isn't
|
|
21
|
+
* enough). Only consulted under `"cycle"`; `"product"`'s mixed-radix decode
|
|
22
|
+
* already visits every combination, so permuting there would only reorder
|
|
23
|
+
* identical output. Built in `Enumerate.ts` (which can reach `Random/`), then
|
|
24
|
+
* threaded through `plan()` as data — `Plan.ts` stays a total function and
|
|
25
|
+
* never imports randomness.
|
|
28
26
|
*/
|
|
29
27
|
export type Orderer = (width: bigint) => ReadonlyArray<bigint>;
|
|
30
28
|
/**
|
|
31
|
-
* Recipe for one enumerated combination against a built Fabricator
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* recursing into whichever child was picked.
|
|
29
|
+
* Recipe for one enumerated combination against a built Fabricator tree:
|
|
30
|
+
* `undefined` for a drawn (not chosen) node — fabricate normally; `{ value }`
|
|
31
|
+
* for a literal (enum member, boolean, `null`, `undefined`, `Omitted`); `{
|
|
32
|
+
* slots }`/`{ fields }` for a tuple/object, recursing per position/key; `{
|
|
33
|
+
* branch, inner }` for a choice's chosen option, or a presence wrapper's
|
|
34
|
+
* "present" arm, recursing into whichever child was picked.
|
|
38
35
|
*/
|
|
39
36
|
export type Pin = undefined | {
|
|
40
37
|
value: unknown;
|
|
@@ -47,35 +44,33 @@ export type Pin = undefined | {
|
|
|
47
44
|
inner: Pin;
|
|
48
45
|
};
|
|
49
46
|
/**
|
|
50
|
-
* One enumerable dimension: how many distinct outcomes, and the `Pin`
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
47
|
+
* One enumerable dimension: how many distinct outcomes, and the `Pin` for the
|
|
48
|
+
* `index`-th (`0 <= index < width`). Widths are `bigint` so a schema with many
|
|
49
|
+
* combined axes can be counted exactly — a `number` would silently lose
|
|
50
|
+
* precision past `Number.MAX_SAFE_INTEGER` and eventually overflow to
|
|
51
|
+
* `Infinity`, which would make a combinatorial limit's error message state a
|
|
52
|
+
* false count.
|
|
56
53
|
*/
|
|
57
54
|
export type Axis = {
|
|
58
55
|
readonly width: bigint;
|
|
59
56
|
readonly at: (index: bigint) => Pin;
|
|
60
57
|
};
|
|
61
58
|
/**
|
|
62
|
-
* Resolved, already-validated enumeration limits — `initialize()` is
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* axis, linear in the schema as written rather than a product, so
|
|
59
|
+
* Resolved, already-validated enumeration limits — `initialize()` is where
|
|
60
|
+
* `limits.combinatorial` is defaulted and checked (`Number.isSafeInteger(limit)
|
|
61
|
+
* && limit >= 1`), so `Enumerate()` always receives a value it can trust
|
|
62
|
+
* without re-validating. `coverage` carries no limit here: its count is the
|
|
63
|
+
* widest single axis, linear in the schema as written rather than a product, so
|
|
68
64
|
* there is nothing for a limit to protect against.
|
|
69
65
|
*/
|
|
70
66
|
export type Limits = {
|
|
71
67
|
combinatorial: number;
|
|
72
68
|
};
|
|
73
69
|
/**
|
|
74
|
-
* The shape both `combinatorial` and `coverage` share — strategy and
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* `unknown`.
|
|
70
|
+
* The shape both `combinatorial` and `coverage` share — strategy and limit
|
|
71
|
+
* differ internally, neither visible here. Takes a Schema, not a built
|
|
72
|
+
* Fabricator: `AnySchema` excludes `Fabricator<any>` (which carries no
|
|
73
|
+
* `[Produces]`), so `ValueOf` can't silently degrade to `unknown`.
|
|
79
74
|
*/
|
|
80
75
|
export type Enumerable = <const $Schema extends AnySchema>(schema: $Schema) => Iterable<ValueOf<$Schema>>;
|
|
81
76
|
export type Resolvable = {
|