@ghostry/fabricator 0.0.2 → 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.
Files changed (37) hide show
  1. package/README.md +18 -6
  2. package/dist/esm/Adapter/Core.js +3 -3
  3. package/dist/esm/Enumeration/Enumerate.js +16 -13
  4. package/dist/esm/Error/index.js +8 -8
  5. package/dist/esm/Fabricator/Constructor.js +12 -14
  6. package/dist/esm/Harnessing/Core.js +30 -0
  7. package/dist/esm/Harnessing/Salt.js +12 -0
  8. package/dist/esm/Harnessing/Types.js +1 -0
  9. package/dist/esm/Instance/Core.js +17 -24
  10. package/dist/esm/Primitive/recursive/Fabricator.js +1 -1
  11. package/dist/esm/Random/index.js +24 -79
  12. package/dist/esm/adapting.js +2 -0
  13. package/dist/esm/harnessing.js +1 -0
  14. package/dist/esm/index.js +1 -2
  15. package/dist/esm/internal.js +1 -2
  16. package/dist/types/Adapter/Core.d.ts +1 -1
  17. package/dist/types/Adapter/Types.d.ts +1 -1
  18. package/dist/types/Enumeration/Enumerate.d.ts +17 -15
  19. package/dist/types/Error/index.d.ts +15 -19
  20. package/dist/types/Fabricator/Constructor.d.ts +4 -4
  21. package/dist/types/Harnessing/Core.d.ts +43 -0
  22. package/dist/types/Harnessing/Salt.d.ts +31 -0
  23. package/dist/types/Harnessing/Types.d.ts +79 -0
  24. package/dist/types/Instance/Core.d.ts +14 -31
  25. package/dist/types/Instance/Types.d.ts +35 -41
  26. package/dist/types/Primitive/opaque/Registry.d.ts +1 -1
  27. package/dist/types/Primitive/recursive/Fabricator.d.ts +8 -8
  28. package/dist/types/Random/Types.d.ts +97 -217
  29. package/dist/types/Random/index.d.ts +30 -48
  30. package/dist/types/Types.d.ts +3 -3
  31. package/dist/types/adapting.d.ts +32 -0
  32. package/dist/types/harnessing.d.ts +30 -0
  33. package/dist/types/index.d.ts +40 -75
  34. package/dist/types/internal.d.ts +5 -23
  35. package/package.json +23 -3
  36. package/dist/esm/Random/CallSite.js +0 -70
  37. package/dist/types/Random/CallSite.d.ts +0 -78
package/README.md CHANGED
@@ -1,6 +1,20 @@
1
- # fabricator
1
+ <div align="center">
2
2
 
3
- Fabricate typed data from composable schemas.
3
+ <img src="https://docs.ghostry.dev/fabricator/logo.png" alt="fabricator" width="96" height="96">
4
+
5
+ # @ghostry/fabricator
6
+
7
+ **Fabricate typed data from composable schemas.**
8
+
9
+ [![npm](https://img.shields.io/badge/npm-ffffff.svg?style=for-the-badge&color=000000&logo=npm&logoColor=CB3837)](https://www.npmjs.com/package/@ghostry/fabricator)
10
+ [![npmx](https://img.shields.io/badge/npmx-ffffff.svg?style=for-the-badge&color=000000&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNTMiIGhlaWdodD0iMTUzIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxNTMgMTUzIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNi43MDQgOS45ODI3KSI+CiAgICA8cGF0aCBkPSJtMC45MzQ3NiA5Ny4yMDVoMjQuMDgxdjIzLjY5M2gtMjQuMDgxeiIgZmlsbD0iI2ZmZiI+PC9wYXRoPgogICAgPHBhdGggZD0ibTEwMy4xMi05LjIzMDctMy42MjExIDEwLjI0Ni00Ni4zMDkgMTMxLTMuNjIxMSAxMC4yNDZoMTUuNTM3bDMuNjIxMS0xMC4yNDYgMTEuNzE3LTMzLjE0OCAzOC4yMTEtMTA4LjF6IiBmaWxsPSIjNTFjOGZjIj48L3BhdGg+CiAgPC9nPgo8L3N2Zz4K&logoColor=51C8FC)](https://npmx.dev/package/@ghostry/fabricator)
11
+ [![jsr](https://img.shields.io/badge/jsr-ffffff?style=for-the-badge&color=000000&logo=jsr&logoColor=F7DF1E)](https://jsr.io/@ghostry/fabricator)
12
+ [![github](https://img.shields.io/badge/github-ffffff?style=for-the-badge&color=000000&logo=github&logoColor=ffffff)](https://github.com/ghostry-dev/fabricator)
13
+ [![typescript](https://img.shields.io/badge/typescript-ffffff?style=for-the-badge&color=000000&logo=typescript&logoColor=3178C6)](#)
14
+ [![bun](https://img.shields.io/badge/bun-ffffff?style=for-the-badge&color=000000&logo=bun&logoColor=FBF0DF)](#)
15
+ [![node](https://img.shields.io/badge/node-ffffff?style=for-the-badge&color=000000&logo=nodedotjs&logoColor=5FA04E)](#)
16
+
17
+ </div>
4
18
 
5
19
  ## Install
6
20
 
@@ -8,14 +22,12 @@ Fabricate typed data from composable schemas.
8
22
  npm install @ghostry/fabricator
9
23
  ```
10
24
 
11
- Also available via `bun add @ghostry/fabricator` or `bunx jsr add @ghostry/fabricator`.
12
-
13
25
  ## Example
14
26
 
15
27
  ```ts
16
28
  import { initialize } from "@ghostry/fabricator";
17
29
 
18
- const { T, Fabricator } = initialize({ seed: "1234" });
30
+ const { T, Fabricator } = initialize();
19
31
 
20
32
  const ProductSchema = T.object({
21
33
  name: T.string.whereby({ length: { min: 1, max: 25 } }),
@@ -38,4 +50,4 @@ const item = Product.fabricate();
38
50
  const widget = Product.fabricate({ name: "Widget", inStock: true });
39
51
  ```
40
52
 
41
- `seed: "1234"` is an optional mixer; `clock` (the wall-clock instant of this call, by default) is the run's entropy. Pass the same seed and clock to replay. See the [docs site](https://docs.ghostry.dev/fabricator/) for the full guide: the mental model behind Schemas and Fabricators, composing and overriding schemas, custom types, distributions, and the [TypeBox adapter](https://www.npmjs.com/package/@ghostry/fabricator-adapter-typebox-v0).
53
+ `initialize()` takes no required configuration. Its `clock` (by default, the wall-clock instant of the call) is the run's entropy, so every run differs, and passing that one number back as `clock` replays the run exactly. See the [docs site](https://docs.ghostry.dev/fabricator/) for the full guide: the mental model behind Schemas and Fabricators, composing and overriding schemas, custom types, distributions, and the [TypeBox adapter](https://www.npmjs.com/package/@ghostry/fabricator-adapter-typebox-v0).
@@ -38,10 +38,10 @@ function Core_layer(key, adaptation, prior) {
38
38
  [key]: prior
39
39
  }));
40
40
  }
41
- function drive(adapter, schema, context) {
41
+ function walk(adapter, schema, context) {
42
42
  var _schema_Adaptation;
43
43
  const adaptation = null == (_schema_Adaptation = schema[Adaptation]) ? void 0 : _schema_Adaptation[adapter.key];
44
44
  if (adaptation) return adaptation(schema);
45
- return adapter.convert(schema, (child, childContext)=>drive(adapter, child, childContext), context);
45
+ return adapter.convert(schema, (child, childContext)=>walk(adapter, child, childContext), context);
46
46
  }
47
- export { drive, mergeAdaptations, withAdaptations };
47
+ export { mergeAdaptations, walk, withAdaptations };
@@ -34,19 +34,21 @@ function enumerables(source, limits, stack) {
34
34
  };
35
35
  }
36
36
  function combinatorial(schema) {
37
- const combinatorialSeed = [
38
- ...effectiveSource().seed,
37
+ const combinatorialSalt = [
38
+ ...effectiveSource().salt,
39
39
  "combinatorial"
40
40
  ];
41
41
  const probe = plan(new Fabricator(schema, {
42
- seed: combinatorialSeed
42
+ salt: combinatorialSalt,
43
+ ordinal: null
43
44
  }), {
44
45
  strategy: "product"
45
46
  });
46
47
  if (probe.width > BigInt(limits.combinatorial)) throw new FabricatorError.CombinatorialLimitExceededError(probe.width, limits.combinatorial);
47
48
  return iterable(()=>{
48
49
  const built = new Fabricator(schema, {
49
- seed: combinatorialSeed
50
+ salt: combinatorialSalt,
51
+ ordinal: null
50
52
  });
51
53
  return {
52
54
  built,
@@ -58,24 +60,25 @@ function enumerables(source, limits, stack) {
58
60
  }
59
61
  function coverage(schema) {
60
62
  const base = effectiveSource();
61
- const coverageSeed = [
62
- ...base.seed,
63
+ const coverageSalt = [
64
+ ...base.salt,
63
65
  "coverage"
64
66
  ];
65
- const orderSeed = [
66
- ...base.seed,
67
+ const orderSalt = [
68
+ ...base.salt,
67
69
  "coverage",
68
70
  "order"
69
71
  ];
70
72
  return iterable(()=>{
71
73
  const built = new Fabricator(schema, {
72
- seed: coverageSeed
74
+ salt: coverageSalt,
75
+ ordinal: null
73
76
  });
74
77
  return {
75
78
  built,
76
79
  axis: plan(built, {
77
80
  strategy: "cycle",
78
- orderer: orderer(base, orderSeed)
81
+ orderer: orderer(base, orderSalt)
79
82
  })
80
83
  };
81
84
  });
@@ -85,9 +88,9 @@ function enumerables(source, limits, stack) {
85
88
  coverage
86
89
  };
87
90
  }
88
- function orderer(source, seed) {
89
- const forked = source.fork(seed);
90
- const root = forked.toRoot("unattributed");
91
+ function orderer(source, salt) {
92
+ const forked = source.fork(salt);
93
+ const root = forked.toRoot();
91
94
  const stream = toStreamFromTrace(forked.algorithm, {
92
95
  ...root,
93
96
  path: [],
@@ -31,14 +31,6 @@ class Error_FabricatorError extends Error {
31
31
  }
32
32
  }
33
33
  FabricatorError.InvalidCombinatorialLimitError = InvalidCombinatorialLimitError;
34
- class InvalidAttributionRootError extends FabricatorError {
35
- constructor(root){
36
- super(), _define_property(this, "root", void 0), this.root = root;
37
- this.name = "InvalidAttributionRootError";
38
- this.message = `initialize({ attribution: { kind: "rooted", root } }) requires an absolute path or a "file://" URL; received "${root}".`;
39
- }
40
- }
41
- FabricatorError.InvalidAttributionRootError = InvalidAttributionRootError;
42
34
  class DetachedSelfError extends FabricatorError {
43
35
  constructor(during){
44
36
  super(), _define_property(this, "during", void 0), this.during = during;
@@ -205,5 +197,13 @@ class Error_FabricatorError extends Error {
205
197
  }
206
198
  }
207
199
  FabricatorError.SynchronousStackError = SynchronousStackError;
200
+ class HarnessingProviderError extends FabricatorError {
201
+ constructor(){
202
+ super();
203
+ this.name = "HarnessingProviderError";
204
+ this.message = "The `fabricator` provider was called outside its integration's `around`, so there is no per-test scope to provide. A composer must run each integration's providers inside that integration's `around` frame, as `@ghostry/harness` does.";
205
+ }
206
+ }
207
+ FabricatorError.HarnessingProviderError = HarnessingProviderError;
208
208
  })(Error_FabricatorError || (Error_FabricatorError = {}));
209
209
  export { Error_FabricatorError as FabricatorError };
@@ -1,6 +1,6 @@
1
1
  import { FabricatorError } from "../Error/index.js";
2
2
  import { Primitive } from "../Primitive/index.js";
3
- import { isLayered, normalizeSeed } from "../Random/index.js";
3
+ import { isLayered, normalizeSalt } from "../Random/index.js";
4
4
  import { toSchema } from "../Schema/Core.js";
5
5
  import { Adaptation, Fixed, Kind, Layer, Meta } from "../Types.js";
6
6
  import { inline } from "../Utility/Core.js";
@@ -305,24 +305,22 @@ function resolveScope(source, options, stack) {
305
305
  var _ref;
306
306
  const frame = stack.current();
307
307
  const base = null != (_ref = null == frame ? void 0 : frame.source) ? _ref : source;
308
+ const salt = inline(()=>{
309
+ if (!options.salt) return;
310
+ if (isLayered(options.salt)) return [
311
+ ...base.salt,
312
+ ...normalizeSalt(options.salt[Layer])
313
+ ];
314
+ return normalizeSalt(options.salt);
315
+ });
308
316
  const pins = {
317
+ salt,
309
318
  clock: options.clock,
310
- root: options.root,
311
- file: options.file,
312
319
  ordinal: options.ordinal
313
320
  };
314
- if (!options.seed) return {
315
- source: base,
316
- root: base.toRoot("attributed", pins)
317
- };
318
- const seed = isLayered(options.seed) ? [
319
- ...base.seed,
320
- ...normalizeSeed(options.seed[Layer])
321
- ] : options.seed;
322
- const forked = base.fork(seed);
323
321
  return {
324
- source: forked,
325
- root: forked.toRoot("unattributed", pins)
322
+ source: base,
323
+ root: base.toRoot(pins)
326
324
  };
327
325
  }
328
326
  export { Constructor };
@@ -0,0 +1,30 @@
1
+ import { FabricatorError } from "../Error/index.js";
2
+ import { layer as index_js_layer } from "../Random/index.js";
3
+ import { saltFor } from "./Salt.js";
4
+ function integration(instance) {
5
+ let scope;
6
+ return {
7
+ name: "@ghostry/fabricator",
8
+ provides: {
9
+ fabricator: ()=>{
10
+ if (void 0 === scope) throw new FabricatorError.HarnessingProviderError();
11
+ return scope;
12
+ }
13
+ },
14
+ around (identity, body) {
15
+ const salt = index_js_layer(saltFor(identity));
16
+ return instance.wrap({
17
+ salt
18
+ }, (entered)=>{
19
+ const previous = scope;
20
+ scope = entered;
21
+ try {
22
+ return body();
23
+ } finally{
24
+ scope = previous;
25
+ }
26
+ });
27
+ }
28
+ };
29
+ }
30
+ export { integration };
@@ -0,0 +1,12 @@
1
+ function saltFor(identity) {
2
+ const salt = [
3
+ identity.kind,
4
+ ...identity.path,
5
+ identity.name
6
+ ];
7
+ return "number" == typeof identity.row ? [
8
+ ...salt,
9
+ String(identity.row)
10
+ ] : salt;
11
+ }
12
+ export { saltFor };
@@ -0,0 +1 @@
1
+ export { };
@@ -1,7 +1,7 @@
1
1
  import { enumerables } from "../Enumeration/Enumerate.js";
2
2
  import { FabricatorError } from "../Error/index.js";
3
3
  import { Constructor } from "../Fabricator/Constructor.js";
4
- import { defaultAlgorithm, deriveClock, isLayered, normalizeSeed, resolveAttribution, toRandomSource } from "../Random/index.js";
4
+ import { defaultAlgorithm, deriveClock, isLayered, normalizeSalt, toRandomSource } from "../Random/index.js";
5
5
  import { registry } from "../Schema/Registry.js";
6
6
  import { Layer } from "../Types.js";
7
7
  import { inline, isThenable, noop } from "../Utility/Core.js";
@@ -12,30 +12,29 @@ function resolveCombinatorialLimit(limit) {
12
12
  return limit;
13
13
  }
14
14
  function resolveClock(config) {
15
- return "number" == typeof config.clock ? config.clock : deriveClock(config.algorithm, normalizeSeed(config.seed));
15
+ return "number" == typeof config.clock ? config.clock : deriveClock(config.algorithm, normalizeSalt(config.salt));
16
16
  }
17
17
  function overlay(base, over) {
18
- var _ref, _over_algorithm, _base_attribution, _ref1, _over_types, _over_limits;
18
+ var _ref, _over_algorithm, _ref1, _over_types, _over_limits;
19
19
  var _this;
20
- const seed = inline(()=>{
21
- if (void 0 === over.seed) return normalizeSeed(base.seed);
22
- if (isLayered(over.seed)) return [
23
- ...normalizeSeed(base.seed),
24
- ...normalizeSeed(over.seed[Layer])
20
+ const salt = inline(()=>{
21
+ if (void 0 === over.salt) return normalizeSalt(base.salt);
22
+ if (isLayered(over.salt)) return [
23
+ ...normalizeSalt(base.salt),
24
+ ...normalizeSalt(over.salt[Layer])
25
25
  ];
26
- return normalizeSeed(over.seed);
26
+ return normalizeSalt(over.salt);
27
27
  });
28
28
  const clock = inline(()=>{
29
29
  var _base_clock;
30
- if ("seeded" === over.clock) return "seeded";
30
+ if ("derived" === over.clock) return "derived";
31
31
  if (void 0 !== over.clock) return over.clock.valueOf();
32
32
  return null != (_base_clock = base.clock) ? _base_clock : Date.now();
33
33
  });
34
34
  return {
35
- seed,
35
+ salt,
36
36
  clock,
37
37
  algorithm: null != (_ref = null != (_over_algorithm = over.algorithm) ? _over_algorithm : base.algorithm) ? _ref : defaultAlgorithm,
38
- attribution: over.attribution ? resolveAttribution(over.attribution) : null != (_base_attribution = base.attribution) ? _base_attribution : resolveAttribution(void 0),
39
38
  types: null != (_ref1 = null != (_over_types = over.types) ? _over_types : base.types) ? _ref1 : registry,
40
39
  limits: {
41
40
  combinatorial: resolveCombinatorialLimit(null == (_this = null != (_over_limits = over.limits) ? _over_limits : base.limits) ? void 0 : _this.combinatorial)
@@ -44,9 +43,8 @@ function overlay(base, over) {
44
43
  }
45
44
  function instantiate(config, stack) {
46
45
  const source = toRandomSource({
47
- seed: config.seed,
46
+ salt: config.salt,
48
47
  algorithm: config.algorithm,
49
- attribution: config.attribution,
50
48
  clock: resolveClock(config)
51
49
  });
52
50
  const Fabricator = Constructor(source, stack);
@@ -71,25 +69,20 @@ function instantiate(config, stack) {
71
69
  return result;
72
70
  }
73
71
  const context = {
74
- get seed () {
72
+ get salt () {
75
73
  var _ref;
76
74
  var _stack_current;
77
- return normalizeSeed((null != (_ref = null == (_stack_current = stack.current()) ? void 0 : _stack_current.config) ? _ref : config).seed);
75
+ return normalizeSalt((null != (_ref = null == (_stack_current = stack.current()) ? void 0 : _stack_current.config) ? _ref : config).salt);
78
76
  },
79
77
  get algorithm () {
80
78
  var _ref1;
81
79
  var _stack_current1;
82
80
  return (null != (_ref1 = null == (_stack_current1 = stack.current()) ? void 0 : _stack_current1.config) ? _ref1 : config).algorithm;
83
81
  },
84
- get attribution () {
82
+ get clock () {
85
83
  var _ref2;
86
84
  var _stack_current2;
87
- return (null != (_ref2 = null == (_stack_current2 = stack.current()) ? void 0 : _stack_current2.config) ? _ref2 : config).attribution;
88
- },
89
- get clock () {
90
- var _ref3;
91
- var _stack_current3;
92
- return resolveClock(null != (_ref3 = null == (_stack_current3 = stack.current()) ? void 0 : _stack_current3.config) ? _ref3 : config);
85
+ return resolveClock(null != (_ref2 = null == (_stack_current2 = stack.current()) ? void 0 : _stack_current2.config) ? _ref2 : config);
93
86
  }
94
87
  };
95
88
  const instance = {
@@ -97,7 +90,7 @@ function instantiate(config, stack) {
97
90
  Fabricator,
98
91
  combinatorial,
99
92
  coverage,
100
- seed: source.seed,
93
+ salt: source.salt,
101
94
  fork,
102
95
  wrap,
103
96
  context
@@ -10,7 +10,7 @@ function Fabricator(context, forkSource, make) {
10
10
  function fabricateAt(depth) {
11
11
  const atMax = depth >= meta.depth.max;
12
12
  const target = atMax ? meta.terminal : meta.body;
13
- const construction = privateSource.toRoot("counted");
13
+ const construction = privateSource.toRoot();
14
14
  const context = {
15
15
  toTrace: (path, kind)=>({
16
16
  ...construction,
@@ -1,85 +1,53 @@
1
- import { FabricatorError } from "../Error/index.js";
2
1
  import { Layer, MAX_TIME } from "../Types.js";
3
- import { inline } from "../Utility/Core.js";
4
2
  import { cyrb128 } from "../Utility/Digest.js";
5
- import { directoryOf, normalizeLocation, relativize, resolveCallerFile } from "./CallSite.js";
6
3
  import { sfc32 } from "./Generator/sfc32.js";
7
4
  function defaultAlgorithm(seed) {
8
5
  return sfc32(...cyrb128(seed));
9
6
  }
10
- function randomSeed() {
7
+ function randomSalt() {
11
8
  return (0x100000000 * Math.random() >>> 0).toString(10);
12
9
  }
13
- function deriveClock(algorithm, seed) {
10
+ function deriveClock(algorithm, salt) {
14
11
  const stream = toStream(algorithm, JSON.stringify([
15
- seed,
12
+ salt,
16
13
  "clock"
17
14
  ]));
18
15
  return Math.trunc((2 * stream.next() - 1) * MAX_TIME);
19
16
  }
20
- function envSeed() {
21
- var _ref, _ref1;
17
+ function envSalt() {
22
18
  const env = "object" == typeof process ? process.env : void 0;
23
- return null != (_ref = null != (_ref1 = null == env ? void 0 : env["FABRICATOR_SEED"]) ? _ref1 : null == env ? void 0 : env["SEED"]) ? _ref : null == env ? void 0 : env["RANDOM_SEED"];
19
+ return null == env ? void 0 : env["FABRICATOR_SALT"];
24
20
  }
25
21
  function encode(trace) {
26
22
  return JSON.stringify([
27
- trace.seed,
23
+ trace.salt,
28
24
  trace.clock,
29
- trace.root,
30
- trace.file,
31
25
  trace.path,
32
26
  trace.kind,
33
27
  trace.ordinal
34
28
  ]);
35
29
  }
36
- function normalizeSeed(seed) {
37
- if (void 0 === seed) {
38
- const fromEnv = envSeed();
30
+ function normalizeSalt(salt) {
31
+ if (void 0 === salt) {
32
+ const fromEnv = envSalt();
39
33
  return void 0 === fromEnv ? [] : [
40
34
  fromEnv
41
35
  ];
42
36
  }
43
- return "string" == typeof seed ? [
44
- seed
37
+ return "string" == typeof salt ? [
38
+ salt
45
39
  ] : [
46
- ...seed
40
+ ...salt
47
41
  ];
48
42
  }
49
- function Random_layer(seed) {
43
+ function Random_layer(salt) {
50
44
  return {
51
- [Layer]: seed
45
+ [Layer]: salt
52
46
  };
53
47
  }
54
48
  function isLayered(value) {
55
49
  return "object" == typeof value && null !== value && Layer in value;
56
50
  }
57
- function resolveAttribution(attribution) {
58
- const policy = null != attribution ? attribution : {
59
- kind: "call site"
60
- };
61
- switch(policy.kind){
62
- case "none":
63
- return policy;
64
- case "rooted":
65
- {
66
- const root = normalizeLocation(policy.root);
67
- if (!root.startsWith("/")) throw new FabricatorError.InvalidAttributionRootError(policy.root);
68
- return toRooted(root);
69
- }
70
- case "call site":
71
- {
72
- const root = directoryOf(resolveCallerFile());
73
- return toRooted(root);
74
- }
75
- }
76
- }
77
- function toRooted(root) {
78
- return {
79
- kind: "rooted",
80
- root: root.endsWith("/") ? root : `${root}/`
81
- };
82
- }
83
51
  function toStream(algorithm, seed) {
84
52
  const generator = algorithm(seed);
85
53
  let iterations = 0;
@@ -99,53 +67,30 @@ function toStreamFromTrace(algorithm, trace) {
99
67
  }
100
68
  function toRandomSource(options) {
101
69
  var _options_algorithm;
102
- let seed = normalizeSeed(options.seed);
70
+ let salt = normalizeSalt(options.salt);
103
71
  let algorithm = null != (_options_algorithm = options.algorithm) ? _options_algorithm : defaultAlgorithm;
104
- let attribution = resolveAttribution(options.attribution);
105
72
  const clock = options.clock;
106
- let constructionOrdinals = new Map();
107
- function nextConstructionOrdinal(file) {
108
- var _constructionOrdinals_get;
109
- const ordinal = null != (_constructionOrdinals_get = constructionOrdinals.get(file)) ? _constructionOrdinals_get : 0;
110
- constructionOrdinals.set(file, ordinal + 1);
111
- return ordinal;
112
- }
113
- function toRoot(kind, pins = {}) {
114
- var _pins_root, _pins_clock;
115
- const replaying = void 0 !== pins.root;
116
- const root = null != (_pins_root = pins.root) ? _pins_root : kind;
117
- const file = replaying || void 0 !== pins.file ? pins.file : resolveRootFile(kind);
118
- const ordinal = inline(()=>{
119
- if (replaying || void 0 !== pins.ordinal) return pins.ordinal;
120
- if ("unattributed" === root) return;
121
- return nextConstructionOrdinal(file);
122
- });
73
+ let constructionOrdinal = 0;
74
+ function toRoot(pins = {}) {
75
+ var _pins_salt, _pins_clock;
123
76
  return {
124
- seed,
77
+ salt: null != (_pins_salt = pins.salt) ? _pins_salt : salt,
125
78
  clock: null != (_pins_clock = pins.clock) ? _pins_clock : clock,
126
- root,
127
- file,
128
- ordinal
79
+ ordinal: void 0 !== pins.ordinal ? pins.ordinal : constructionOrdinal++
129
80
  };
130
81
  }
131
- function resolveRootFile(kind) {
132
- if ("attributed" !== kind) return;
133
- if ("none" === attribution.kind) return;
134
- return relativize(attribution.root, resolveCallerFile());
135
- }
136
- function fork(childSeed) {
82
+ function fork(childSalt) {
137
83
  return toRandomSource({
138
- seed: childSeed,
84
+ salt: childSalt,
139
85
  algorithm,
140
- attribution,
141
86
  clock
142
87
  });
143
88
  }
144
89
  return {
145
90
  toRoot,
146
91
  algorithm,
147
- seed,
92
+ salt,
148
93
  fork
149
94
  };
150
95
  }
151
- export { Random_layer as layer, defaultAlgorithm, deriveClock, encode, isLayered, normalizeSeed, randomSeed, resolveAttribution, toRandomSource, toStream, toStreamFromTrace };
96
+ export { Random_layer as layer, defaultAlgorithm, deriveClock, encode, isLayered, normalizeSalt, randomSalt, toRandomSource, toStream, toStreamFromTrace };
@@ -0,0 +1,2 @@
1
+ export { walk } from "./Adapter/Core.js";
2
+ export { Adaptation } from "./Types.js";
@@ -0,0 +1 @@
1
+ export { integration } from "./Harnessing/Core.js";
package/dist/esm/index.js CHANGED
@@ -4,10 +4,9 @@ function initialize(config) {
4
4
  var _ref;
5
5
  return instantiate(overlay({}, null != config ? config : {}), null != (_ref = null == config ? void 0 : config.stack) ? _ref : toStack()).instance;
6
6
  }
7
- export { Adaptation, Omitted } from "./Types.js";
7
+ export { Omitted } from "./Types.js";
8
8
  export { layer } from "./Random/index.js";
9
9
  export { FabricatorError } from "./Error/index.js";
10
- export { drive } from "./Adapter/Core.js";
11
10
  export { registry } from "./Schema/Registry.js";
12
11
  export { effectiveDiscrete, toBound } from "./Bound.js";
13
12
  export { initialize };
@@ -1,6 +1,5 @@
1
1
  export { Children, Kind, Meta, Produces } from "./Types.js";
2
2
  export { isPlainObject } from "./Utility/Core.js";
3
3
  export { plan, resolve } from "./Enumeration/Plan.js";
4
- export { defaultAlgorithm, encode, randomSeed, toRandomSource, toStream, toStreamFromTrace } from "./Random/index.js";
5
- export { directoryOf, normalizeLocation, relativize, resolveCallerFile } from "./Random/CallSite.js";
4
+ export { defaultAlgorithm, encode, randomSalt, toRandomSource, toStream, toStreamFromTrace } from "./Random/index.js";
6
5
  export { toStack as toSynchronousStack } from "./Instance/Stack/Sync.js";
@@ -55,7 +55,7 @@ export declare function mergeAdaptations<$Prior extends Adaptations, const $Adap
55
55
  * previous one into the argument. Splitting the two across packages is how they
56
56
  * drift.
57
57
  */
58
- export declare function drive<$Context, $Returnable>(adapter: Adapter<string, $Context, $Returnable>, schema: {
58
+ export declare function walk<$Context, $Returnable>(adapter: Adapter<string, $Context, $Returnable>, schema: {
59
59
  [Adaptation]?: Adaptations;
60
60
  }, context: $Context): $Returnable;
61
61
  export {};
@@ -70,7 +70,7 @@ export type Patch = {
70
70
  };
71
71
  /**
72
72
  * How an adapter recurses into a nested schema — handed to
73
- * {@link Adapter.convert} by `Adapter/Core.ts`'s `drive` rather than being the
73
+ * {@link Adapter.convert} by `Adapter/Core.ts`'s `walk` rather than being the
74
74
  * adapter's own private recursion, so every nested node goes back through the
75
75
  * adaptation lookup, not only the outermost one.
76
76
  *
@@ -11,21 +11,23 @@ import type { Enumerable, Limits } from "./Types";
11
11
  * is the one precisely-typed layer, mirroring `Constructor.ts`'s `make`/
12
12
  * `construct` split.
13
13
  *
14
- * Two derived seeds — one per API — each an independent, deterministic fork off
15
- * the _effective_ source's seed (`effectiveSource()` below — the active `wrap`
16
- * frame's, or this instance's `source`; read fresh on every
17
- * `combinatorial(...)`/`coverage(...)` call, not once when `enumerables()` was
18
- * built, so the same `combinatorial` reference behaves differently inside an
19
- * active `wrap`). `new Fabricator(schema, { seed })` (see `Constructor.ts`'s
20
- * `construct()`) forks a fully isolated `RandomSource` and opens an
21
- * `"unattributed"` scope, so `resolveCallerFile()` is never called the
22
- * lazy-generator attribution hazard a plain `function*` would invite simply
23
- * doesn't arise — the instance's construction counters are never touched, and
24
- * the same seed reproduces regardless of which file
25
- * `combinatorial(...)`/`coverage(...)` is called from. Each `fork()` starts
26
- * from a fresh source, so reusing one seed across many builds (different
27
- * schemas, or the same schema rebuilt per iteration) never lets one build's
28
- * draws leak into another's.
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.
29
31
  */
30
32
  export declare function enumerables(source: RandomSource, limits: Limits, stack: Stack): {
31
33
  combinatorial: Enumerable;