@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,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<_ extends Fabricator> = Fabricated;
|
|
8
|
+
export type Fabricator<$Schema extends {
|
|
9
|
+
[Meta]: ThisMeta;
|
|
10
|
+
} = {
|
|
11
|
+
[Meta]: ThisMeta;
|
|
12
|
+
}> = NaiveFabricator<Fabricated> & {
|
|
13
|
+
[Kind]: "undefined";
|
|
14
|
+
[Meta]: $Schema[typeof Meta];
|
|
15
|
+
readonly trace: Trace;
|
|
16
|
+
readonly [Adaptation]?: AdaptationsOf<$Schema>;
|
|
17
|
+
schema: Schema<AdaptationsOf<$Schema>>;
|
|
18
|
+
};
|
|
19
|
+
export declare function Fabricator(context: FabricatorContext<Schema>): Fabricator;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type AdaptationEntry } from "../../Adapter/Core";
|
|
2
|
+
import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
|
|
3
|
+
import type { Core, Meta as ThisMeta } from "./Types";
|
|
4
|
+
/**
|
|
5
|
+
* Nothing to configure (see `Types.ts`'s `Meta`), so `adapt` is this kind's
|
|
6
|
+
* only builder method — an external library that spells "undefined"
|
|
7
|
+
* differently still needs a way to say so.
|
|
8
|
+
*/
|
|
9
|
+
export interface Schema<$Adaptations extends Adaptations = {}> extends Core<ThisMeta, $Adaptations> {
|
|
10
|
+
/**
|
|
11
|
+
* Override what this schema maps to in one or more external schema
|
|
12
|
+
* libraries — see `string/Schema.ts`'s `adapt` for the full contract.
|
|
13
|
+
*/
|
|
14
|
+
adapt: <const $Adapter extends Adapter, $Returnable extends ReturnType<$Adapter["convert"]>>(adapter: $Adapter, produce: (adapting: Adapting<Schema<$Adaptations>>) => $Returnable) => Schema<WithAdaptations<$Adaptations, AdaptationEntry<$Adapter, $Returnable>>>;
|
|
15
|
+
}
|
|
16
|
+
export declare function Schema<$Adaptations extends Adaptations = {}>(schema: Core<ThisMeta, $Adaptations>): Schema<$Adaptations>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Adaptations } from "../../Adapter/Types";
|
|
2
|
+
import type { Adaptation, Kind, Meta, Produces } from "../../Types";
|
|
3
|
+
export type Fabricated = undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Nothing to configure: `undefined` has exactly one possible value, so
|
|
6
|
+
* there is no `.as()` (see `always/Types.ts` for the same reasoning) and
|
|
7
|
+
* no other knob to carry.
|
|
8
|
+
*/
|
|
9
|
+
export type Meta = Record<string, never>;
|
|
10
|
+
export type Core<$Meta extends Meta = Meta, $Adaptations extends Adaptations = {}> = {
|
|
11
|
+
[Kind]: "undefined";
|
|
12
|
+
[Meta]: $Meta;
|
|
13
|
+
readonly [Produces]?: Fabricated;
|
|
14
|
+
readonly [Adaptation]?: $Adaptations;
|
|
15
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One canonical form for a location, whatever produced it: Node ESM
|
|
3
|
+
* emits `file:///…` URLs, Bun emits bare absolute paths, and this
|
|
4
|
+
* module's own `import.meta.url` is percent-encoded — three spellings
|
|
5
|
+
* of one file that must compare equal, or `isOwnFrame`/`relativize`
|
|
6
|
+
* silently stop matching. A bare path is trusted as-is and never
|
|
7
|
+
* decoded, since it may contain a literal `%20`; only the `file://`
|
|
8
|
+
* form's escaping is guaranteed well-formed. Forward slashes and an
|
|
9
|
+
* uppercased leading `/X:/` drive fold Windows' `C:\a\b` and
|
|
10
|
+
* `file:///c:/a/b` together — the drive is the one component two
|
|
11
|
+
* sources disagree on, so it's the only thing case-folded: doing more
|
|
12
|
+
* would break case-sensitive filesystems and change what ends up
|
|
13
|
+
* hashed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeLocation(location: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* The directory a location sits in, trailing separator included —
|
|
18
|
+
* without it, a root of `/a/b/` would match the unrelated sibling
|
|
19
|
+
* `/a/bcd/x.ts`, since `startsWith`/prefix-stripping only sees
|
|
20
|
+
* character runs, not path segments.
|
|
21
|
+
*/
|
|
22
|
+
export declare function directoryOf(location: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* `file` expressed relative to `root`, ascending with `..` where `file`
|
|
25
|
+
* sits outside `root` rather than falling back to `file` unchanged. An
|
|
26
|
+
* ascending path stays identical across machines whose checkouts hold
|
|
27
|
+
* both locations at the same relative position, the common case for
|
|
28
|
+
* anything under the same repository — passing an escaping file through
|
|
29
|
+
* as absolute would defeat the default `"call site"` policy for every
|
|
30
|
+
* schema helper that isn't a sibling of wherever `initialize()` was
|
|
31
|
+
* called. A location that isn't an absolute path (`native`,
|
|
32
|
+
* `<anonymous>`, or a value that has already been relativized) doesn't
|
|
33
|
+
* start with `/` and is returned unchanged — applying this twice is a
|
|
34
|
+
* no-op, which lets `T.recursive` thread an already-relativized file
|
|
35
|
+
* back through here uniformly.
|
|
36
|
+
*/
|
|
37
|
+
export declare function relativize(root: string, file: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the file that (transitively) triggered the current call, so
|
|
40
|
+
* construction can be attributed to the source file the user wrote it
|
|
41
|
+
* in.
|
|
42
|
+
*
|
|
43
|
+
* Primary path: `Error.captureStackTrace` (V8, and Bun for Node
|
|
44
|
+
* compatibility) captures the full stack, then `firstExternalFrame`
|
|
45
|
+
* skips this library's own frames by path — no need to hardcode how
|
|
46
|
+
* many frames to exclude, so it stays correct as internal call depth
|
|
47
|
+
* changes.
|
|
48
|
+
*
|
|
49
|
+
* Fallback: engines without `captureStackTrace` get the whole raw
|
|
50
|
+
* stack, position-stripped, hashed as-is rather than guessing which
|
|
51
|
+
* frame to isolate. Lower fidelity (sensitive to edits anywhere in the
|
|
52
|
+
* visible call chain, not just the immediate caller), but rarely
|
|
53
|
+
* exercised — Bun, Node, and Chrome all support the primary path. Left
|
|
54
|
+
* unnormalized: a whole multi-line stack has no single location for
|
|
55
|
+
* `normalizeLocation`'s separator/drive rewriting to apply to, so this
|
|
56
|
+
* path never relativizes — it always falls through `relativize`'s
|
|
57
|
+
* non-absolute passthrough instead.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveCallerFile(): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { NumberGenerator } from "../Types";
|
|
2
|
+
/**
|
|
3
|
+
* sfc32 ("Small Fast Counter"): a 128-bit-state PRNG that is fast, compact,
|
|
4
|
+
* and statistically strong (passes both PractRand and TestU01 BigCrush).
|
|
5
|
+
* Each call advances the state and returns the top 32 bits scaled into
|
|
6
|
+
* `[0, 1)`. Non-cryptographic: never use this for secrets or tokens.
|
|
7
|
+
*
|
|
8
|
+
* @see https://stackoverflow.com/a/47593316
|
|
9
|
+
*/
|
|
10
|
+
export declare function sfc32(a: number, b: number, c: number, d: number): NumberGenerator;
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { Layer } from "../Types";
|
|
2
|
+
/**
|
|
3
|
+
* A zero-argument function that produces a float in `[0, 1)`, exactly
|
|
4
|
+
* like `Math.random()` does.
|
|
5
|
+
*/
|
|
6
|
+
export type NumberGenerator = () => number;
|
|
7
|
+
/**
|
|
8
|
+
* A stream of randomness.
|
|
9
|
+
*/
|
|
10
|
+
export type Stream = {
|
|
11
|
+
next: NumberGenerator;
|
|
12
|
+
/**
|
|
13
|
+
* The seed from which this stream was created.
|
|
14
|
+
*/
|
|
15
|
+
readonly seed: string;
|
|
16
|
+
/**
|
|
17
|
+
* The count of times a number has been requested from this stream.
|
|
18
|
+
*/
|
|
19
|
+
readonly iterations: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* A seedable pseudorandom number generator.
|
|
23
|
+
*
|
|
24
|
+
* Given an arbitrary string seed, returns a {@link NumberGenerator}.
|
|
25
|
+
*/
|
|
26
|
+
export type Algorithm = (seed: string) => NumberGenerator;
|
|
27
|
+
/**
|
|
28
|
+
* Everything a single leaf's randomness is derived from. Encoded as a
|
|
29
|
+
* fixed tuple (`Random/index.ts`'s `encode`), this *is* the stream seed:
|
|
30
|
+
* `toStream(algorithm, encode(trace)).seed === stream.seed` for every
|
|
31
|
+
* traced leaf, so the derived seed is not a field of its own.
|
|
32
|
+
*
|
|
33
|
+
* Attached to every built Fabricator as `.trace` — recording is
|
|
34
|
+
* unconditional, even for a node that never draws (a bare `object`,
|
|
35
|
+
* `always`, `object.compute`). Minting a stream from it
|
|
36
|
+
* (`toStreamFromTrace`) is still paid only by nodes that draw.
|
|
37
|
+
*
|
|
38
|
+
* Slots, in encoded order:
|
|
39
|
+
*
|
|
40
|
+
* - `seed` — the *instance's* seed, normalized to its parts
|
|
41
|
+
* ({@link RandomSource.seed}), not anything derived per leaf.
|
|
42
|
+
* - `clock` — this construction's resolved "now," epoch milliseconds
|
|
43
|
+
* (`Instance/Types.ts`'s `Config.clock`). Second, not after the
|
|
44
|
+
* per-leaf slots: blast radius matches `seed` — both are instance-level
|
|
45
|
+
* and perturb every leaf, unlike `file`/`path`/`kind`/`ordinal`, which
|
|
46
|
+
* narrow to one leaf. Never `undefined` (unlike `file`/`ordinal`):
|
|
47
|
+
* clock is always a concrete instant before any leaf dispatches
|
|
48
|
+
* (`RandomSource`'s `Options.clock`).
|
|
49
|
+
* - `root` — how `file` and `ordinal` were resolved ({@link RootKind}).
|
|
50
|
+
* Sits immediately before `file` because that is what it explains.
|
|
51
|
+
* Distinguishes the three situations that all produce `file:
|
|
52
|
+
* undefined` (`{ kind: "none" }` attributed, an unattributed seeded
|
|
53
|
+
* construction, a counted recursive expansion), so a captured trace
|
|
54
|
+
* can be replayed faithfully via `new Fabricator(schema, trace)`.
|
|
55
|
+
* - `file` — the file this node's *construction* (not the node) was
|
|
56
|
+
* attributed to, relative to the instance's {@link Attribution} root
|
|
57
|
+
* (absolute only if outside that root). `undefined` under
|
|
58
|
+
* `"counted"` / `"unattributed"`, or `"attributed"` with
|
|
59
|
+
* `{ kind: "none" }` — {@link RootKind} says which.
|
|
60
|
+
* - `path` — structural position within the construction: field name,
|
|
61
|
+
* tuple slot, choice option, one segment per nesting level
|
|
62
|
+
* (`Constructor.ts`'s `make`). Distinguishes two leaves of the same
|
|
63
|
+
* kind in one construction. Stable under insert/remove/reorder of
|
|
64
|
+
* unrelated siblings — only a leaf's own position identifies it.
|
|
65
|
+
* - `kind` — schema kind the node was constructed as. Redundant given a
|
|
66
|
+
* unique `path`, but changing a field's kind must change its data.
|
|
67
|
+
* - `ordinal` — which construction among those sharing this `file` this
|
|
68
|
+
* node belongs to. `undefined` for `"unattributed"`, already unique
|
|
69
|
+
* by its forked seed.
|
|
70
|
+
*/
|
|
71
|
+
export type Trace = {
|
|
72
|
+
readonly seed: ReadonlyArray<string>;
|
|
73
|
+
readonly clock: number;
|
|
74
|
+
readonly root: RootKind;
|
|
75
|
+
readonly file: string | undefined;
|
|
76
|
+
readonly path: ReadonlyArray<string>;
|
|
77
|
+
readonly kind: string;
|
|
78
|
+
readonly ordinal: number | undefined;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Caller-supplied overrides for the construction-owned {@link Trace}
|
|
82
|
+
* slots {@link RandomSource.toRoot} resolves. `seed` is not among
|
|
83
|
+
* them: it is the {@link RandomSource}'s own identity (forked via
|
|
84
|
+
* {@link ConstructorOptions.seed} when replaying), not something
|
|
85
|
+
* `toRoot` substitutes. `path`/`kind` are per-node and applied in
|
|
86
|
+
* `construct()`, not here.
|
|
87
|
+
*
|
|
88
|
+
* Definedness, not `in`: `root` is present exactly when a trace is
|
|
89
|
+
* being replayed and is never `undefined` on a real {@link Trace}.
|
|
90
|
+
*/
|
|
91
|
+
export type RootPins = {
|
|
92
|
+
clock?: number | undefined;
|
|
93
|
+
root?: RootKind | undefined;
|
|
94
|
+
file?: string | undefined;
|
|
95
|
+
ordinal?: number | undefined;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* A construction's root: every {@link Trace} slot a {@link RootKind}
|
|
99
|
+
* resolution fixes, before a leaf supplies its own `path`/`kind`.
|
|
100
|
+
* `RandomSource.toRoot` resolves this once per construction; callers
|
|
101
|
+
* spread it into a full {@link Trace} per leaf and hand that to
|
|
102
|
+
* `toStreamFromTrace`. One stack walk, one construction-ordinal
|
|
103
|
+
* bump — reused across every leaf that construction dispatches.
|
|
104
|
+
*/
|
|
105
|
+
export type ConstructionTrace = Omit<Trace, "path" | "kind">;
|
|
106
|
+
/**
|
|
107
|
+
* What a producer is told about the fabrication it is running inside.
|
|
108
|
+
* One object, not a positional list: this is the only channel a producer
|
|
109
|
+
* has, and a future addition must not change every kind's `.as(...)`
|
|
110
|
+
* arity. Curated, not the whole instance `Config` — a producer has no
|
|
111
|
+
* business reading `seed` or `attribution`, and `random` already carries
|
|
112
|
+
* this leaf's own derived seed.
|
|
113
|
+
*/
|
|
114
|
+
export type ProduceContext = {
|
|
115
|
+
/** This leaf's own seeded stream, keyed by its structural path. */
|
|
116
|
+
random: Stream;
|
|
117
|
+
/**
|
|
118
|
+
* This construction's resolved "now," epoch milliseconds — the active
|
|
119
|
+
* `wrap` frame's `Config.clock` if one is active, else the instance's
|
|
120
|
+
* (`Instance/Types.ts`'s `Config.clock`). Defaults to an instant derived
|
|
121
|
+
* from the instance's seed, not `Date.now()`, so a producer that reads
|
|
122
|
+
* it replays like one that only reads `random`. A number, not a `Date`:
|
|
123
|
+
* the instant is fixed once resolved, and a `Date` handed to every
|
|
124
|
+
* producer would be a shared mutable — the same footgun `T.always([])`
|
|
125
|
+
* sharing one array reference already warns against.
|
|
126
|
+
*/
|
|
127
|
+
clock: number;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* A kind's opaque custom producer — `.as(produce)` — given a
|
|
131
|
+
* {@link ProduceContext} so its output replays under a seed like every
|
|
132
|
+
* other primitive's draws. A zero-argument function (`() => $T`) is
|
|
133
|
+
* still assignable, so every existing `.as(() => ...)` call compiles.
|
|
134
|
+
*/
|
|
135
|
+
export type Produce<$T> = (context: ProduceContext) => $T;
|
|
136
|
+
/**
|
|
137
|
+
* How one *construction* (a single `new Fabricator(...)` call) is rooted,
|
|
138
|
+
* before any of its leaves are dispatched — resolved once, not per leaf,
|
|
139
|
+
* at `Constructor.ts`'s `construct()`. Every leaf then derives its stream
|
|
140
|
+
* from this root plus its own structural path, so inserting or reordering
|
|
141
|
+
* a sibling field can never shift another field onto a different stream.
|
|
142
|
+
*
|
|
143
|
+
* Each variant is a decision about the two {@link Trace} slots a
|
|
144
|
+
* construction owns — `file` and `ordinal` — and nothing else:
|
|
145
|
+
*
|
|
146
|
+
* | variant | `file` | `ordinal` |
|
|
147
|
+
* | ----------------- | -------------------------- | ---------------------- |
|
|
148
|
+
* | `"attributed"` | resolved from the stack | next ordinal for it |
|
|
149
|
+
* | `"counted"` | `undefined` | next file-less ordinal |
|
|
150
|
+
* | `"unattributed"` | `undefined` | `undefined` |
|
|
151
|
+
*
|
|
152
|
+
* `"attributed"` walks the live call stack once (`resolveCallerFile()`)
|
|
153
|
+
* and relativizes it under the instance's `Attribution` root — or, under
|
|
154
|
+
* `{ kind: "none" }`, resolves no file — then assigns the next ordinal
|
|
155
|
+
* for that file. Two constructions in the same file diverge by default;
|
|
156
|
+
* a lone construction stays reproducible across however many times its
|
|
157
|
+
* file is imported or re-run. `ConstructorOptions.file` without `root`
|
|
158
|
+
* pins that file and draws the next ordinal for it (the wrapping-
|
|
159
|
+
* integration case). A replay (`pins.root` given) takes `file` and
|
|
160
|
+
* `ordinal` verbatim, including `undefined`.
|
|
161
|
+
* `test/fixtures/checkout-a`/`checkout-b` stand in for two checkouts
|
|
162
|
+
* using real frames instead.
|
|
163
|
+
*
|
|
164
|
+
* `"counted"` indexes without attributing. Under `{ kind: "none" }` an
|
|
165
|
+
* `"attributed"` scope resolves to precisely this, and the two share
|
|
166
|
+
* the one file-less bucket — reachable only if both kinds of scope were
|
|
167
|
+
* opened on a single source, which nothing does. `"counted"` is not a
|
|
168
|
+
* variant you choose when building — it is recorded on a node's
|
|
169
|
+
* {@link Trace} (and replayed) for expansions inside `T.recursive`,
|
|
170
|
+
* whose private fork uses it so each lazy expansion gets an ordinal
|
|
171
|
+
* (see `recursive/Fabricator.ts`). An identity that isn't a stack frame
|
|
172
|
+
* but should still vary with the instance's seed is
|
|
173
|
+
* `ConstructorOptions.seed`'s layered form (`{@link Layered}`, via
|
|
174
|
+
* `layer(...)`) — see `ConstructorOptions`.
|
|
175
|
+
*
|
|
176
|
+
* `"unattributed"` fixes neither slot — used only by a source already
|
|
177
|
+
* isolated for one construction (an explicitly seeded
|
|
178
|
+
* `new Fabricator(schema, { seed })`, which forks a new `RandomSource`
|
|
179
|
+
* for that one build). A layered seed (`{@link Layered}`, via
|
|
180
|
+
* `layer(...)`) still opens this same scope: composing onto a base seed
|
|
181
|
+
* is a statement about *what* the fork's seed is, not how the fork
|
|
182
|
+
* itself should be rooted.
|
|
183
|
+
*
|
|
184
|
+
* A plain string union, not a discriminant object: none of the three
|
|
185
|
+
* variants carries data of its own. Caller-supplied overrides go
|
|
186
|
+
* through {@link RootPins} on {@link RandomSource.toRoot}, not through
|
|
187
|
+
* this union. A `{ kind: RootKind }` wrapper would invite a field an
|
|
188
|
+
* object shape can carry and a switch can silently ignore.
|
|
189
|
+
*/
|
|
190
|
+
export type RootKind = "attributed" | "counted" | "unattributed";
|
|
191
|
+
/**
|
|
192
|
+
* A seed as a caller supplies it: one string, or several — several lets
|
|
193
|
+
* a caller compose independent parts (user id, session id, scenario
|
|
194
|
+
* label) without joining them first. Always normalized internally to
|
|
195
|
+
* `ReadonlyArray<string>` (`toRandomSource`'s `normalizeSeed`); a single
|
|
196
|
+
* string is the one-element case.
|
|
197
|
+
*/
|
|
198
|
+
export type Seed = string | ReadonlyArray<string>;
|
|
199
|
+
/**
|
|
200
|
+
* A {@link Seed} tagged as composing onto whatever base is in effect,
|
|
201
|
+
* rather than replacing it — what `layer(seed)` (`Random/index.ts`)
|
|
202
|
+
* produces. Tagged with `[Layer]` exactly as `replace()`
|
|
203
|
+
* (`Utility/Core.ts`) tags a merge operand with `[Replace]`, so a
|
|
204
|
+
* caller never names the symbol and no ordinary `Seed` — string or
|
|
205
|
+
* array — can be mistaken for one.
|
|
206
|
+
*/
|
|
207
|
+
export type Layered = {
|
|
208
|
+
readonly [Layer]: Seed;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* How an instance normalizes a construction's resolved file before it
|
|
212
|
+
* becomes part of that construction's root — set once via
|
|
213
|
+
* `initialize({ attribution })`.
|
|
214
|
+
*
|
|
215
|
+
* `"rooted"` expresses every file relative to `root`, so a checkout at
|
|
216
|
+
* a different absolute path on a different machine derives the same
|
|
217
|
+
* seeds. `root` accepts an absolute path or a `file://` URL (e.g.
|
|
218
|
+
* `new URL("..", import.meta.url).href`, which needs no `node:path`),
|
|
219
|
+
* and is a normalization parameter only — it never enters the hashed
|
|
220
|
+
* material, so moving the root without moving the files under it
|
|
221
|
+
* changes nothing. A file outside `root` is expressed with a leading
|
|
222
|
+
* `..` run rather than left absolute, so it stays stable too, as long
|
|
223
|
+
* as both locations move together under the same checkout (see
|
|
224
|
+
* `relativize`, `Random/CallSite.ts`).
|
|
225
|
+
*
|
|
226
|
+
* `"call site"`, the default, is `"rooted"` at the directory of
|
|
227
|
+
* whichever file called `initialize()` — resolved once, at that call,
|
|
228
|
+
* from the live stack. Two `initialize()` calls in different files that
|
|
229
|
+
* share a seed and happen to produce the same file's-worth of relative
|
|
230
|
+
* paths (a symmetric monorepo layout — this repo's `pkg/fabricator` and
|
|
231
|
+
* `pkg/fabricator-adapter-typebox-v0` test suites) will collide; use
|
|
232
|
+
* `"rooted"` at a shared repository root instead.
|
|
233
|
+
*
|
|
234
|
+
* `"none"` attributes nothing: every construction in the instance draws
|
|
235
|
+
* its root from one shared, file-less counter. Maximally portable — no
|
|
236
|
+
* path can influence a seed — at the cost of every construction sharing
|
|
237
|
+
* one counter, so adding, removing, or reordering a *construction*
|
|
238
|
+
* anywhere in the instance shifts every later one. Individual fields
|
|
239
|
+
* within one construction are unaffected: they're keyed by structural
|
|
240
|
+
* path, not dispatch order.
|
|
241
|
+
*/
|
|
242
|
+
export type Attribution = {
|
|
243
|
+
kind: "rooted";
|
|
244
|
+
root: string;
|
|
245
|
+
} | {
|
|
246
|
+
kind: "call site";
|
|
247
|
+
} | {
|
|
248
|
+
kind: "none";
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* {@link Attribution} after `"call site"` has been resolved against the
|
|
252
|
+
* live stack and `root` normalized — what actually drives
|
|
253
|
+
* construction-root resolution. This, not the caller-facing
|
|
254
|
+
* `Attribution`, is what `RandomSource.fork` threads through:
|
|
255
|
+
* re-resolving `"call site"` inside a fork would read the stack at
|
|
256
|
+
* whatever moment the fork happens to run (an explicitly seeded build,
|
|
257
|
+
* an enumeration's rebuild) and root the child somewhere unrelated to
|
|
258
|
+
* the instance that spawned it.
|
|
259
|
+
*/
|
|
260
|
+
export type ResolvedAttribution = {
|
|
261
|
+
kind: "rooted";
|
|
262
|
+
root: string;
|
|
263
|
+
} | {
|
|
264
|
+
kind: "none";
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* `clock` is required, unlike `seed`/`algorithm`/`attribution` — by the
|
|
268
|
+
* time a `RandomSource` is built, both the wall-clock default and the
|
|
269
|
+
* `"seeded"` policy (`Instance/Types.ts`'s `Config.clock`) have already
|
|
270
|
+
* been resolved to a concrete epoch-millisecond instant
|
|
271
|
+
* (`Instance/Core.ts`'s `resolveClock`), so `toRandomSource` has no
|
|
272
|
+
* default left to supply.
|
|
273
|
+
*/
|
|
274
|
+
export type Options = {
|
|
275
|
+
seed?: Seed | undefined;
|
|
276
|
+
algorithm?: Algorithm | undefined;
|
|
277
|
+
attribution?: Attribution | undefined;
|
|
278
|
+
clock: number;
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* `new Fabricator(schema, options)`'s own option shape — not
|
|
282
|
+
* `Options`. {@link Trace} is assignable to this (every slot optional
|
|
283
|
+
* here, required there, and `file`/`ordinal` are `T | undefined` on
|
|
284
|
+
* both so `{ ...trace }` typechecks under
|
|
285
|
+
* `exactOptionalPropertyTypes`), which is what makes
|
|
286
|
+
* `new Fabricator(schema, trace)` a legal replay.
|
|
287
|
+
*
|
|
288
|
+
* A bare `seed` is a statement about *attribution*: it forks an
|
|
289
|
+
* isolated `RandomSource` from exactly that value, sidestepping both
|
|
290
|
+
* the default call-site logic and the instance's own seed. The same
|
|
291
|
+
* seed reproduces the same result regardless of which file it's
|
|
292
|
+
* constructed from, which instance built it, or how that instance was
|
|
293
|
+
* itself seeded — useful for a fixture that should never change no
|
|
294
|
+
* matter how the surrounding run is reseeded.
|
|
295
|
+
*
|
|
296
|
+
* `seed: layer(...)` (via `layer()`, `Random/index.ts`) is the same
|
|
297
|
+
* fork, but composed onto the instance's own seed
|
|
298
|
+
* (`[...instance.seed, ...seed]`) instead of replacing it — the
|
|
299
|
+
* construction still varies when the instance is reseeded, which the
|
|
300
|
+
* bare form does not (see {@link RootKind}'s `"counted"` paragraph).
|
|
301
|
+
* This is `fork`/`wrap`'s own `Overlay.seed` mechanism one level down:
|
|
302
|
+
* the instance itself is the base, so no separate instance is needed
|
|
303
|
+
* just to pin an identity that should still track the instance's seed.
|
|
304
|
+
*
|
|
305
|
+
* `clock` / `root` / `file` / `ordinal` pin the construction-owned
|
|
306
|
+
* {@link Trace} slots {@link RandomSource.toRoot} would otherwise
|
|
307
|
+
* resolve. Definedness, not `in`: `root` given means this is a replay
|
|
308
|
+
* (`file` and `ordinal` taken verbatim, `undefined` included, no
|
|
309
|
+
* stack walk and no counter bump). `root` absent but `file` given pins
|
|
310
|
+
* that file and draws `ordinal` from *that file's* counter — the
|
|
311
|
+
* wrapping-integration case. Neither given resolves as an ordinary
|
|
312
|
+
* construction. A seeded construction is not, by default, asking for a
|
|
313
|
+
* different "now"; a replayed trace whose `clock` is present explicitly
|
|
314
|
+
* is.
|
|
315
|
+
*
|
|
316
|
+
* `path` is the base structural path `make` extends for descendants,
|
|
317
|
+
* so replaying a nested node's trace reproduces its subtree at the
|
|
318
|
+
* positions it originally occupied. `kind`, when a string, must match
|
|
319
|
+
* `schema`'s own `[Kind]` or `construct()` throws
|
|
320
|
+
* `TraceKindMismatchError`.
|
|
321
|
+
*
|
|
322
|
+
* No per-build algorithm override: it complicates root resolution for
|
|
323
|
+
* a capability nobody asked for, unlike `seed`, which is a real
|
|
324
|
+
* statement about attribution. Only `initialize({ seed, algorithm })`
|
|
325
|
+
* — instance-wide, via `Options` — sets the algorithm.
|
|
326
|
+
*/
|
|
327
|
+
export type ConstructorOptions = {
|
|
328
|
+
seed?: Seed | Layered | undefined;
|
|
329
|
+
clock?: number | undefined;
|
|
330
|
+
root?: RootKind | undefined;
|
|
331
|
+
file?: string | undefined;
|
|
332
|
+
path?: ReadonlyArray<string> | undefined;
|
|
333
|
+
kind?: string | undefined;
|
|
334
|
+
ordinal?: number | undefined;
|
|
335
|
+
};
|
|
336
|
+
/**
|
|
337
|
+
* An isolated source of randomness: everything a single `initialize()`
|
|
338
|
+
* instance needs to derive private, reproducible seeds for the
|
|
339
|
+
* fabricators it builds. Each instance owns its own seed, builder, and
|
|
340
|
+
* per-construction counters — nothing here is shared module-level
|
|
341
|
+
* state, so independently initialized instances (e.g. parallel tests)
|
|
342
|
+
* can never perturb each other.
|
|
343
|
+
*/
|
|
344
|
+
export type RandomSource = {
|
|
345
|
+
/**
|
|
346
|
+
* Resolve one construction's root — see {@link RootKind}. Called once
|
|
347
|
+
* per `new Fabricator(...)` (or per lazy expansion of a `T.recursive`
|
|
348
|
+
* schema, each of which resolves its own root on a private forked
|
|
349
|
+
* source), never per leaf: the returned {@link ConstructionTrace} is
|
|
350
|
+
* what every leaf beneath it completes into a full {@link Trace} and
|
|
351
|
+
* hands to `toStreamFromTrace`. One stack walk and
|
|
352
|
+
* construction-ordinal bump serves the whole construction.
|
|
353
|
+
*/
|
|
354
|
+
toRoot(kind: RootKind, pins?: RootPins): ConstructionTrace;
|
|
355
|
+
/**
|
|
356
|
+
* The algorithm this source (and every fork of it) hashes with.
|
|
357
|
+
* Stream derivation is *not* a member: it depends on no per-source
|
|
358
|
+
* state, so it is the free function `toStreamFromTrace(algorithm,
|
|
359
|
+
* trace)`. `toRoot` is the only stateful member (per-file ordinal
|
|
360
|
+
* counters).
|
|
361
|
+
*/
|
|
362
|
+
readonly algorithm: Algorithm;
|
|
363
|
+
/**
|
|
364
|
+
* The seed this instance currently derives every stream from,
|
|
365
|
+
* normalized to its parts — a single string becomes a one-element
|
|
366
|
+
* array. Always an array so a caller reading it back (e.g.
|
|
367
|
+
* `initialize({ seed: instance.seed })`) round-trips through the same
|
|
368
|
+
* `Seed`-accepting surface it came from.
|
|
369
|
+
*/
|
|
370
|
+
readonly seed: ReadonlyArray<string>;
|
|
371
|
+
/**
|
|
372
|
+
* Create a new, fully isolated `RandomSource` — its own private
|
|
373
|
+
* per-file construction counters, sharing only the algorithm — seeded
|
|
374
|
+
* independently from this one. For a build whose randomness must stay
|
|
375
|
+
* entirely self-contained (an explicitly seeded
|
|
376
|
+
* `new Fabricator(schema, { seed })`, or `T.recursive`, whose expansion
|
|
377
|
+
* count is data-dependent, unlike every other kind's fixed,
|
|
378
|
+
* schema-determined dispatch count): forking means its internal draws
|
|
379
|
+
* can never perturb, or be perturbed by, anything else built from the
|
|
380
|
+
* same `initialize()` instance, no matter how many times or how deeply
|
|
381
|
+
* it expands.
|
|
382
|
+
*/
|
|
383
|
+
fork(seed: Seed): RandomSource;
|
|
384
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Algorithm, Attribution, Layered, NumberGenerator, Options, RandomSource, ResolvedAttribution, Seed, Stream, Trace } from "./Types";
|
|
2
|
+
/**
|
|
3
|
+
* Build the library's built-in PRNG from a seed. The same seed always
|
|
4
|
+
* yields the same stream. Seeds may be numbers or strings; both are
|
|
5
|
+
* stringified and hashed to fully seed sfc32's state.
|
|
6
|
+
*/
|
|
7
|
+
export declare function defaultAlgorithm(seed: string): NumberGenerator;
|
|
8
|
+
/**
|
|
9
|
+
* Mint a fresh seed value — a uint32 label. Not used as
|
|
10
|
+
* `initialize()`'s default (an omitted seed is empty; wall-clock
|
|
11
|
+
* `clock` is the default entropy); kept for callers that want a
|
|
12
|
+
* generated mixer, and for tests that need one.
|
|
13
|
+
*/
|
|
14
|
+
export declare function randomSeed(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Derive the explicit `"seeded"` clock — an epoch-millisecond instant,
|
|
17
|
+
* drawn across the full representable `Date` span — from an instance's
|
|
18
|
+
* own `algorithm`/`seed`. The unconfigured default is wall-clock time
|
|
19
|
+
* (`Instance/Core.ts`'s `overlay`); this is the opt-in that makes
|
|
20
|
+
* `seed` alone the reproducibility unit, at the cost of an implausible
|
|
21
|
+
* "now". A throwaway two-element encoding
|
|
22
|
+
* (`JSON.stringify([seed, "clock"])`), *not* routed through
|
|
23
|
+
* `RandomSource`/`Trace`: after the clock is folded into stream
|
|
24
|
+
* derivation, a forked source's own stream derivation requires a clock,
|
|
25
|
+
* so deriving the clock from a fork would be circular. Kept below that
|
|
26
|
+
* layer, which also keeps this collision-free with every leaf's
|
|
27
|
+
* `encode(trace)` — that encoding is always seven elements, this is
|
|
28
|
+
* always two, and the two can never produce the same JSON array.
|
|
29
|
+
* `Math.trunc`ed because a `Date`'s precision is whole milliseconds.
|
|
30
|
+
*/
|
|
31
|
+
export declare function deriveClock(algorithm: Algorithm, seed: ReadonlyArray<string>): number;
|
|
32
|
+
/**
|
|
33
|
+
* Collapse a {@link Trace} into one string to hash — and, since
|
|
34
|
+
* `toStreamFromTrace` hashes exactly this output, the *definition* of
|
|
35
|
+
* that leaf's stream seed. Concatenating fields with a delimiter would
|
|
36
|
+
* collide when a path/kind/seed part contains that delimiter
|
|
37
|
+
* (`file="a b", kind="c"` vs `file="a", kind="b c"`) — silently: two
|
|
38
|
+
* leaves that should draw independently would share one stream.
|
|
39
|
+
* `JSON.stringify` as an array makes every field's and slot's
|
|
40
|
+
* boundaries unambiguous regardless of content or nesting depth.
|
|
41
|
+
* `undefined` (`file`, `ordinal`) is the right "this slot doesn't
|
|
42
|
+
* apply" rather than a sentinel string: `JSON.stringify` writes it as
|
|
43
|
+
* `null` in an array position, one unambiguous value, with no chance
|
|
44
|
+
* of colliding with a real file path or index.
|
|
45
|
+
*/
|
|
46
|
+
export declare function encode(trace: Trace): string;
|
|
47
|
+
/**
|
|
48
|
+
* Normalize a caller-supplied {@link Seed} to its parts: a single string
|
|
49
|
+
* becomes a one-element array, an array passes through unchanged, and a
|
|
50
|
+
* missing seed is empty — unless {@link envSeed} supplies one. No
|
|
51
|
+
* generated fallback: an omitted seed is not a second source of
|
|
52
|
+
* entropy beside the instance clock.
|
|
53
|
+
*/
|
|
54
|
+
export declare function normalizeSeed(seed: Seed | undefined): ReadonlyArray<string>;
|
|
55
|
+
/**
|
|
56
|
+
* Tag a seed as composing onto whatever base is in effect, rather than
|
|
57
|
+
* replacing it — the reading a bare `seed` has everywhere else in this
|
|
58
|
+
* library. Mirrors `replace()`'s `[Replace]` tagging: the `[Layer]`
|
|
59
|
+
* directive is read (and, at every level that accepts one, consumed) by
|
|
60
|
+
* whoever resolves the seed against its base, so a caller never names
|
|
61
|
+
* the symbol.
|
|
62
|
+
*/
|
|
63
|
+
export declare function layer(seed: Seed): Layered;
|
|
64
|
+
export declare function isLayered(value: unknown): value is Layered;
|
|
65
|
+
/**
|
|
66
|
+
* Collapse a caller-facing {@link Attribution} to the
|
|
67
|
+
* {@link ResolvedAttribution} the stream machinery uses. `"call site"`
|
|
68
|
+
* must resolve *here*, and only here: `resolveCallerFile()` reads the
|
|
69
|
+
* live stack, and `toRandomSource` runs synchronously inside
|
|
70
|
+
* `initialize()`, so this is the one moment the first external frame
|
|
71
|
+
* genuinely is the file that called `initialize()`. Resolving lazily —
|
|
72
|
+
* on first construction, or again inside `fork` — would capture
|
|
73
|
+
* whichever file happened to call `new Fabricator(...)`, or whichever
|
|
74
|
+
* internal mechanism happened to trigger a fork.
|
|
75
|
+
*
|
|
76
|
+
* A directory, not the file itself, becomes the root: rooting at the
|
|
77
|
+
* file would relativize that one file to `""` while every sibling still
|
|
78
|
+
* carried a full relative path from a directory one level up, an
|
|
79
|
+
* arbitrary asymmetry with no reason to prefer it.
|
|
80
|
+
*/
|
|
81
|
+
export declare function resolveAttribution(attribution: Attribution | undefined): ResolvedAttribution;
|
|
82
|
+
export declare function toStream(algorithm: Algorithm, seed: string): Stream;
|
|
83
|
+
/**
|
|
84
|
+
* A leaf's stream: `toStream(algorithm, encode(trace))`. This is the
|
|
85
|
+
* composition that *defines* a leaf's stream seed — the invariant
|
|
86
|
+
* `toStream(algorithm, encode(trace)).seed === stream.seed`. Not a
|
|
87
|
+
* {@link RandomSource} member: derivation depends on no per-source
|
|
88
|
+
* state (a fork shares only the algorithm), so it is a free function
|
|
89
|
+
* of `(algorithm, trace)`. `toRoot` is the only stateful member.
|
|
90
|
+
*
|
|
91
|
+
* {@link deriveClock} cannot route through this: a {@link Trace}
|
|
92
|
+
* carries `clock`, and `deriveClock` is what produces it. That
|
|
93
|
+
* circularity is why `deriveClock` stays below the
|
|
94
|
+
* `RandomSource`/`Trace` layer, with a two-element encoding that can
|
|
95
|
+
* never collide with `encode`'s seven.
|
|
96
|
+
*/
|
|
97
|
+
export declare function toStreamFromTrace(algorithm: Algorithm, trace: Trace): Stream;
|
|
98
|
+
/**
|
|
99
|
+
* Create a fresh, self-contained {@link RandomSource} — the randomness
|
|
100
|
+
* state a single `initialize()` instance owns for its lifetime.
|
|
101
|
+
* `options.clock` is baked in here, once, as a plain number — the
|
|
102
|
+
* `"seeded"` policy is already resolved by the caller
|
|
103
|
+
* (`Instance/Core.ts`'s `resolveClock`) before a source is ever built,
|
|
104
|
+
* so every root this source resolves carries the identical instant, and
|
|
105
|
+
* `fork` threads it forward unchanged.
|
|
106
|
+
*/
|
|
107
|
+
export declare function toRandomSource(options: Options): RandomSource;
|