@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.
Files changed (139) hide show
  1. package/README.md +18 -12
  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 +16 -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 +25 -41
  10. package/dist/esm/Instance/Stack/Async.js +10 -0
  11. package/dist/esm/Instance/Stack/Sync.js +16 -0
  12. package/dist/esm/Primitive/bigint/Registry.js +12 -12
  13. package/dist/esm/Primitive/boolean/Registry.js +2 -1
  14. package/dist/esm/Primitive/date/Registry.js +15 -14
  15. package/dist/esm/Primitive/null/Registry.js +2 -1
  16. package/dist/esm/Primitive/number/Registry.js +18 -17
  17. package/dist/esm/Primitive/recursive/Fabricator.js +1 -1
  18. package/dist/esm/Primitive/symbol/Registry.js +2 -1
  19. package/dist/esm/Primitive/undefined/Registry.js +2 -1
  20. package/dist/esm/Random/index.js +24 -79
  21. package/dist/esm/Utility/Core.js +6 -1
  22. package/dist/esm/adapting.js +2 -0
  23. package/dist/esm/harnessing.js +1 -0
  24. package/dist/esm/index.js +5 -4
  25. package/dist/esm/internal.js +2 -2
  26. package/dist/types/Adapter/Core.d.ts +30 -33
  27. package/dist/types/Adapter/Types.d.ts +78 -88
  28. package/dist/types/Bound.d.ts +15 -15
  29. package/dist/types/Distribution/index.d.ts +54 -61
  30. package/dist/types/Enumeration/Enumerate.d.ts +24 -24
  31. package/dist/types/Enumeration/Plan.d.ts +22 -26
  32. package/dist/types/Enumeration/Types.d.ts +38 -43
  33. package/dist/types/Error/index.d.ts +103 -89
  34. package/dist/types/Fabricator/Constructor.d.ts +24 -26
  35. package/dist/types/Fabricator/Types.d.ts +73 -81
  36. package/dist/types/Harnessing/Core.d.ts +43 -0
  37. package/dist/types/Harnessing/Salt.d.ts +31 -0
  38. package/dist/types/Harnessing/Types.d.ts +79 -0
  39. package/dist/types/Instance/Core.d.ts +38 -74
  40. package/dist/types/Instance/Stack/Async.d.ts +14 -0
  41. package/dist/types/Instance/Stack/Sync.d.ts +14 -0
  42. package/dist/types/Instance/Types.d.ts +98 -102
  43. package/dist/types/Primitive/always/Schema.d.ts +8 -8
  44. package/dist/types/Primitive/always/Types.d.ts +7 -7
  45. package/dist/types/Primitive/array/Registry.d.ts +10 -8
  46. package/dist/types/Primitive/array/Schema.d.ts +4 -5
  47. package/dist/types/Primitive/array/Types.d.ts +6 -6
  48. package/dist/types/Primitive/bigint/Registry.d.ts +6 -6
  49. package/dist/types/Primitive/bigint/Schema.d.ts +8 -8
  50. package/dist/types/Primitive/bigint/Types.d.ts +5 -5
  51. package/dist/types/Primitive/boolean/Outcomes.d.ts +8 -8
  52. package/dist/types/Primitive/boolean/Registry.d.ts +2 -12
  53. package/dist/types/Primitive/boolean/Schema.d.ts +8 -8
  54. package/dist/types/Primitive/boolean/Types.d.ts +3 -3
  55. package/dist/types/Primitive/choice/Fabricator.d.ts +6 -7
  56. package/dist/types/Primitive/choice/Registry.d.ts +13 -13
  57. package/dist/types/Primitive/choice/Schema.d.ts +6 -6
  58. package/dist/types/Primitive/choice/Types.d.ts +11 -11
  59. package/dist/types/Primitive/date/Registry.d.ts +25 -48
  60. package/dist/types/Primitive/date/Schema.d.ts +9 -10
  61. package/dist/types/Primitive/date/Types.d.ts +4 -4
  62. package/dist/types/Primitive/enum/Registry.d.ts +13 -13
  63. package/dist/types/Primitive/enum/Schema.d.ts +5 -5
  64. package/dist/types/Primitive/enum/Types.d.ts +17 -19
  65. package/dist/types/Primitive/namespace.d.ts +10 -10
  66. package/dist/types/Primitive/null/Registry.d.ts +2 -2
  67. package/dist/types/Primitive/null/Schema.d.ts +2 -2
  68. package/dist/types/Primitive/null/Types.d.ts +3 -3
  69. package/dist/types/Primitive/nullable/Fabricator.d.ts +7 -7
  70. package/dist/types/Primitive/nullable/Schema.d.ts +13 -13
  71. package/dist/types/Primitive/nullable/Types.d.ts +9 -10
  72. package/dist/types/Primitive/nullish/Fabricator.d.ts +12 -13
  73. package/dist/types/Primitive/nullish/Schema.d.ts +8 -8
  74. package/dist/types/Primitive/nullish/Types.d.ts +12 -13
  75. package/dist/types/Primitive/number/Registry.d.ts +20 -38
  76. package/dist/types/Primitive/number/Schema.d.ts +11 -12
  77. package/dist/types/Primitive/number/Types.d.ts +13 -13
  78. package/dist/types/Primitive/number/defaults.d.ts +3 -3
  79. package/dist/types/Primitive/object/Fabricator.d.ts +15 -15
  80. package/dist/types/Primitive/object/Registry.d.ts +8 -8
  81. package/dist/types/Primitive/object/Schema.d.ts +10 -10
  82. package/dist/types/Primitive/object/Types.d.ts +20 -22
  83. package/dist/types/Primitive/object/compute/Fabricator.d.ts +4 -5
  84. package/dist/types/Primitive/object/compute/Schema.d.ts +4 -4
  85. package/dist/types/Primitive/object/compute/Types.d.ts +19 -20
  86. package/dist/types/Primitive/object/omittable/Fabricator.d.ts +10 -10
  87. package/dist/types/Primitive/object/omittable/Outcomes.d.ts +2 -2
  88. package/dist/types/Primitive/object/omittable/Schema.d.ts +11 -11
  89. package/dist/types/Primitive/object/omittable/Types.d.ts +14 -15
  90. package/dist/types/Primitive/object/optional/Fabricator.d.ts +16 -18
  91. package/dist/types/Primitive/object/optional/Outcomes.d.ts +2 -2
  92. package/dist/types/Primitive/object/optional/Schema.d.ts +4 -4
  93. package/dist/types/Primitive/object/optional/Types.d.ts +17 -17
  94. package/dist/types/Primitive/opaque/Registry.d.ts +3 -3
  95. package/dist/types/Primitive/opaque/Schema.d.ts +8 -9
  96. package/dist/types/Primitive/record/Registry.d.ts +8 -6
  97. package/dist/types/Primitive/record/Schema.d.ts +9 -11
  98. package/dist/types/Primitive/record/Types.d.ts +25 -25
  99. package/dist/types/Primitive/recursive/Fabricator.d.ts +20 -21
  100. package/dist/types/Primitive/recursive/Registry.d.ts +6 -7
  101. package/dist/types/Primitive/recursive/Schema.d.ts +8 -8
  102. package/dist/types/Primitive/recursive/Terminate.d.ts +13 -14
  103. package/dist/types/Primitive/recursive/Types.d.ts +31 -31
  104. package/dist/types/Primitive/recursive/self/Fabricator.d.ts +11 -12
  105. package/dist/types/Primitive/recursive/self/Schema.d.ts +10 -10
  106. package/dist/types/Primitive/recursive/self/Types.d.ts +7 -8
  107. package/dist/types/Primitive/string/Constants.d.ts +12 -13
  108. package/dist/types/Primitive/string/Fabricator.d.ts +2 -2
  109. package/dist/types/Primitive/string/Registry.d.ts +10 -16
  110. package/dist/types/Primitive/string/Schema.d.ts +5 -5
  111. package/dist/types/Primitive/string/Types.d.ts +17 -17
  112. package/dist/types/Primitive/symbol/Fabricator.d.ts +2 -2
  113. package/dist/types/Primitive/symbol/Registry.d.ts +4 -11
  114. package/dist/types/Primitive/symbol/Schema.d.ts +6 -6
  115. package/dist/types/Primitive/symbol/Types.d.ts +2 -2
  116. package/dist/types/Primitive/tuple/Fabricator.d.ts +7 -8
  117. package/dist/types/Primitive/tuple/Schema.d.ts +5 -5
  118. package/dist/types/Primitive/tuple/Types.d.ts +24 -25
  119. package/dist/types/Primitive/undefinable/Fabricator.d.ts +7 -7
  120. package/dist/types/Primitive/undefinable/Schema.d.ts +13 -13
  121. package/dist/types/Primitive/undefinable/Types.d.ts +10 -10
  122. package/dist/types/Primitive/undefined/Registry.d.ts +2 -2
  123. package/dist/types/Primitive/undefined/Schema.d.ts +4 -4
  124. package/dist/types/Primitive/undefined/Types.d.ts +3 -3
  125. package/dist/types/Random/Generator/sfc32.d.ts +4 -4
  126. package/dist/types/Random/Types.d.ts +151 -293
  127. package/dist/types/Random/index.d.ts +56 -81
  128. package/dist/types/Schema/Core.d.ts +19 -21
  129. package/dist/types/Schema/Registry.d.ts +3 -3
  130. package/dist/types/Schema/Types.d.ts +41 -48
  131. package/dist/types/Types.d.ts +39 -45
  132. package/dist/types/Utility/Core.d.ts +18 -9
  133. package/dist/types/adapting.d.ts +32 -0
  134. package/dist/types/harnessing.d.ts +30 -0
  135. package/dist/types/index.d.ts +95 -128
  136. package/dist/types/internal.d.ts +53 -40
  137. package/package.json +39 -7
  138. package/dist/esm/Random/CallSite.js +0 -56
  139. package/dist/types/Random/CallSite.d.ts +0 -59
@@ -1,186 +1,153 @@
1
1
  import type { Limits } from "./Enumeration/Types";
2
- import type { Instance } from "./Instance/Types";
3
- import type { Algorithm, Attribution, Seed } from "./Random/Types";
2
+ import type { Instance, Stack } from "./Instance/Types";
3
+ import type { Algorithm, Salt } from "./Random/Types";
4
4
  import { registry } from "./Schema/Registry";
5
5
  import type { PlainObject } from "./Utility/Types";
6
6
  export declare function initialize<const $Registry extends PlainObject = typeof registry>(config?: Partial<{
7
7
  /** The registry of type definers to use — `registry` itself. */
8
8
  types: $Registry;
9
9
  /**
10
- * Optional mixer composed into every stream beside `clock`. Accepts
11
- * a single string, or several — several lets a seed be composed out
12
- * of independent, meaningful parts (a user id, a scenario label)
13
- * without hand-joining them first. If omitted, the seed is empty
14
- * (unless `FABRICATOR_SEED` / `SEED` / `RANDOM_SEED` supplies one):
15
- * wall-clock `clock` is the default entropy, so an unconfigured
16
- * instance varies by run and replays from `context.clock` alone.
17
- * Pass a seed when two instances should share a clock but draw
18
- * different universes, or when `clock: "seeded"` should make the
19
- * seed itself the reproducibility unit.
10
+ * Optional differentiator composed into every stream beside `clock` — it
11
+ * distinguishes runs, it does not generate them. Accepts a single string,
12
+ * or several — several lets a salt be composed out of independent,
13
+ * meaningful parts (a user id, a scenario label) without hand-joining them
14
+ * first. If omitted, the salt is empty (unless `FABRICATOR_SALT` supplies
15
+ * one): wall-clock `clock` is the default entropy, so an unconfigured
16
+ * instance varies by run and replays from `context.clock` alone. Pass a
17
+ * salt when two instances should share a clock but draw different
18
+ * universes, or when `clock: "derived"` should make the salt itself the
19
+ * reproducibility unit.
20
20
  */
21
- seed?: Seed;
21
+ salt?: Salt;
22
22
  /**
23
- * Bring your own PRNG: a factory that, given a seed, returns a
24
- * source of randomness — a `() => number` in `[0, 1)`, a drop-in
25
- * for `Math.random`. Defaults to the built-in `sfc32` generator.
23
+ * Bring your own PRNG: a factory that, given a seed, returns a source of
24
+ * randomness — a `() => number` in `[0, 1)`, a drop-in for `Math.random`.
25
+ * The seed is a whole encoded trace, of which `salt` is one slot, not the
26
+ * `salt` itself. Defaults to the built-in `sfc32` generator.
26
27
  */
27
28
  algorithm?: Algorithm;
28
29
  /**
29
- * How this instance attributes a construction's randomness to the
30
- * file it was written in:
31
- *
32
- * - `{ kind: "rooted", root }` expresses every file relative to
33
- * `root` (an absolute path or a `file://` URL), so the same seed
34
- * reproduces the same data on a checkout at a different absolute
35
- * path.
36
- * - `{ kind: "call site" }`, the default, is `"rooted"` at the
37
- * directory of whichever file called `initialize()`.
38
- * - `{ kind: "none" }` attributes nothing: every construction of a
39
- * given kind anywhere in the instance shares one stream, keyed
40
- * by kind alone.
41
- *
42
- * See [Reproducibility](https://ghostry-dev.github.io/fabricator/guides/reproducibility)
43
- * for the trade-offs between the three.
44
- */
45
- attribution?: Attribution;
46
- /**
47
- * Instance-wide numeric ceilings. `combinatorial` bounds how many
48
- * instances `combinatorial(...)` may enumerate — the check is
49
- * eager, it throws at call time before any instance is produced.
50
- * Defaults to 1024 if omitted. `coverage(...)` carries no entry
51
- * here: its count is the widest single axis, so there is nothing
52
- * for a limit to protect against.
30
+ * Instance-wide numeric ceilings. `combinatorial` bounds how many instances
31
+ * `combinatorial(...)` may enumerate — the check is eager, it throws at
32
+ * call time before any instance is produced. Defaults to 1024 if omitted.
33
+ * `coverage(...)` carries no entry here: its count is the widest single
34
+ * axis, so there is nothing for a limit to protect against.
53
35
  */
54
36
  limits?: Limits;
55
37
  /**
56
38
  * What `T.date.past`/`T.date.future` (and any producer reading
57
- * `ProduceContext.clock`) resolve "now" against — and, because it
58
- * sits in every leaf's trace, the default entropy for the instance.
59
- * Defaults to the wall-clock instant of this `initialize()` call, so
60
- * an unconfigured run has realistic dates and varies by process, and
61
- * replays from `context.clock` (with the same empty or supplied
62
- * `seed`). Pass a fixed `Date` to freeze "now" (and the rest of the
63
- * run, unless `seed` also differs). Pass `"seeded"` to derive "now"
64
- * from the instance seed instead — an instant drawn across the whole
65
- * representable `Date` span, so an implausible date is the expected
66
- * outcome of that policy, not a bug. `"seeded"` is what makes `seed`
67
- * alone the reproducibility unit.
39
+ * `ProduceContext.clock`) resolve "now" against — and, because it sits in
40
+ * every leaf's trace, the default entropy for the instance. Defaults to the
41
+ * wall-clock instant of this `initialize()` call, so an unconfigured run
42
+ * has realistic dates and varies by process, and replays from
43
+ * `context.clock` (with the same empty or supplied `salt`). Pass a fixed
44
+ * `Date` to freeze "now" (and the rest of the run, unless `salt` also
45
+ * differs). Pass `"derived"` to derive "now" from the instance salt instead
46
+ * — an instant drawn across the whole representable `Date` span, so an
47
+ * implausible date is the expected outcome of that policy, not a bug.
48
+ * `"derived"` is what makes `salt` alone the reproducibility unit.
68
49
  */
69
- clock?: Date | "seeded";
50
+ clock?: Date | "derived";
51
+ /**
52
+ * The ambient carrier backing `wrap` for this lineage — override only to
53
+ * force a specific one.
54
+ *
55
+ * Left unset (the norm), the `#stack` package import picks it: every
56
+ * runtime with `node:async_hooks` — Node, Bun, Deno — gets the
57
+ * `AsyncLocalStorage` carrier, whose frames survive `await` and isolate
58
+ * concurrent `wrap`s; anywhere else falls back to a synchronous LIFO, on
59
+ * which `wrap` rejects an async block rather than silently resolving a
60
+ * later build against this instance. Supplying one is how a test drives the
61
+ * carrier it did not get by condition.
62
+ */
63
+ stack?: Stack;
70
64
  }>): Instance<$Registry>;
71
65
  export { Omitted } from "./Types";
72
66
  /**
73
- * Tags a `Seed` — for `new Fabricator(schema, { seed })`, or `fork`'s
74
- * own `Overlay.seed` — as composing onto whatever base is in effect,
75
- * rather than replacing it outright.
67
+ * Tags a `Salt` — for `new Fabricator(schema, { salt })`, or `fork`'s own
68
+ * `Overlay.salt` — as composing onto whatever base is in effect, rather than
69
+ * replacing it outright.
76
70
  */
77
71
  export { layer } from "./Random";
78
72
  /**
79
- * `layer(...)`'s return type, so a caller building one programmatically
80
- * can name it — the same rationale as the existing `Seed`/`Attribution`
81
- * exports.
73
+ * `layer(...)`'s return type, so a caller building one programmatically can
74
+ * name it — the same rationale as the existing `Salt` export.
82
75
  */
83
76
  export type { Layered } from "./Random/Types";
84
77
  /**
85
78
  * Every failure this library raises is an instance of this class — see
86
- * `src/Error/index.ts` for the full hierarchy. Only the base is
87
- * public; subclasses are distinguished by `.name`.
79
+ * `src/Error/index.ts` for the full hierarchy. Only the base is public;
80
+ * subclasses are distinguished by `.name`.
88
81
  */
89
82
  export { FabricatorError } from "./Error";
90
83
  /**
91
- * The adapter contract, exported because an adapter is a separate
92
- * package rather than something registered here: `Adapter`/`Recurse`
93
- * are what one declares, `drive` is what its conversion entry point
94
- * calls, and `Adaptation`/`AdaptationsOf` are how it reads what a
95
- * Schema declared — `[Adaptation]` at runtime, `AdaptationsOf` at the
96
- * type level, keyed by its own `key` in both cases.
97
- *
98
- * This package names no external schema library and depends on none:
99
- * every mapping, and every dependency it needs, belongs to the
100
- * adapter.
101
- *
102
- * `Adapting` is the odd one out, facing whoever *writes* an adaptation
103
- * rather than whoever implements an adapter: it is the parameter type
104
- * of every kind's `.adapt(adapter, produce)` producer, so a caller
105
- * writing that producer as a named function can name it — the same
106
- * reason `Stream` is exported below.
107
- */
108
- export { drive } from "./Adapter/Core";
109
- export type { Adaptations, AdaptationsOf, Adapter, Adapting, Recurse, } from "./Adapter/Types";
110
- export { Adaptation } from "./Types";
111
- /**
112
- * The default registry of type definers, exported so it can be
113
- * extended via `registry.extend(({ T }) => ({ ... }))` before being
114
- * passed to `initialize({ types })`.
84
+ * The default registry of type definers, exported so it can be extended via
85
+ * `registry.extend(({ T }) => ({ ... }))` before being passed to `initialize({
86
+ * types })`.
115
87
  */
116
88
  export { registry } from "./Schema/Registry";
117
89
  /**
118
- * Canonical `{ value, exclusive }` endpoint stored on `whereby` min/max,
119
- * plus the call-site union that still accepts a scalar (inclusive). Exported
120
- * so a named `.whereby(...)` argument or an `.adapt` producer reading `meta`
121
- * can type it — the same rationale as `Stream`.
90
+ * Canonical `{ value, exclusive }` endpoint stored on `whereby` min/max, plus
91
+ * the call-site union that still accepts a scalar (inclusive). Exported so a
92
+ * named `.whereby(...)` argument or an `.adapt` producer reading `meta` can
93
+ * type it — the same rationale as `Stream`.
122
94
  */
95
+ export { effectiveDiscrete, toBound } from "./Bound";
123
96
  export type { Bound, InputBound } from "./Bound";
124
- export { toBound, effectiveDiscrete } from "./Bound";
125
97
  /**
126
- * Public because it is the type of `ProduceContext`'s `random` member
127
- * — the seeded stream every kind's `.as(produce)` and `T.opaque`'s
128
- * producer are handed — so a caller writing either as a named function
129
- * can name it.
98
+ * Public because it is the type of `ProduceContext`'s `random` member — the
99
+ * seeded stream every kind's `.as(produce)` and `T.opaque`'s producer are
100
+ * handed — so a caller writing either as a named function can name it.
130
101
  */
131
102
  export type { Stream } from "./Random/Types";
132
103
  /**
133
- * What every kind's `.as(produce)` producer is called with — a single
134
- * curated object rather than a positional argument list, so a caller
135
- * writing the producer as a named function can name its parameter.
136
- * `T.opaque`'s producer takes the same shape.
104
+ * What every kind's `.as(produce)` producer is called with — a single curated
105
+ * object rather than a positional argument list, so a caller writing the
106
+ * producer as a named function can name its parameter. `T.opaque`'s producer
107
+ * takes the same shape.
137
108
  */
138
109
  export type { ProduceContext } from "./Random/Types";
139
110
  /**
140
- * The shape `initialize({ seed })` and `new Fabricator(schema, { seed })`
141
- * both accept — a single string, or several — so a caller building one
142
- * programmatically (rather than as an inline literal) can name the
143
- * type.
111
+ * What every kind's `.adapt(adapter, produce)` producer is called with — `{
112
+ * schema, meta }` — the same rationale as `Stream`/`ProduceContext` above: a
113
+ * caller writing the producer as a named function can name its parameter.
114
+ * `meta` is the kind's own config, reachable here without importing the `Meta`
115
+ * well-known symbol from `@ghostry/fabricator/internal` — that symbol stays off
116
+ * the path an ordinary caller writing an `.adapt()` call has to walk. The rest
117
+ * of the adapter contract (`walk`, `Adapter`, `Adaptation`, `Adaptations`,
118
+ * `AdaptationsOf`, `Recurse`) is exported from `@ghostry/fabricator/adapting`
119
+ * instead — surface for implementing an adapter, not for calling `.adapt()`.
144
120
  */
145
- export type { Seed } from "./Random/Types";
121
+ export type { Adapting } from "./Adapter/Types";
146
122
  /**
147
- * The shape `initialize({ attribution })` accepts, so a caller building
148
- * one programmatically — a rooted policy derived from an env var, say
149
- * — can name the type.
123
+ * The shape `initialize({ salt })` and `new Fabricator(schema, { salt })` both
124
+ * accept — a single string, or several — so a caller building one
125
+ * programmatically (rather than as an inline literal) can name the type.
150
126
  */
151
- export type { Attribution } from "./Random/Types";
127
+ export type { Salt } from "./Random/Types";
152
128
  /**
153
- * Reads the value type a built Fabricator produces straight off its
154
- * `fabricate` signature — `Fabrication<typeof Product>` instead of
155
- * `ReturnType<typeof Product.fabricate>`.
129
+ * Reads the value type a built Fabricator produces straight off its `fabricate`
130
+ * signature — `Fabrication<typeof Product>` instead of `ReturnType<typeof
131
+ * Product.fabricate>`.
156
132
  */
157
133
  export type { Fabrication } from "./Fabricator/Types";
158
134
  /**
159
- * Reads the value type a Schema (not yet built) will eventually
160
- * produce, via its phantom `[Produces]` marker. Mostly useful for a
161
- * helper that accepts a Schema before it's built into a Fabricator.
135
+ * Reads the value type a Schema (not yet built) will eventually produce, via
136
+ * its phantom `[Produces]` marker. Mostly useful for a helper that accepts a
137
+ * Schema before it's built into a Fabricator.
162
138
  */
163
139
  export type { ValueOf } from "./Schema/Types";
164
140
  /**
165
- * `fabricator.trace`'s type — otherwise unnameable by a caller
166
- * wanting to hold onto one, the same reason `Stream` is exported
167
- * above.
141
+ * `fabricator.trace`'s type — otherwise unnameable by a caller wanting to hold
142
+ * onto one, the same reason `Stream` is exported above.
168
143
  */
169
144
  export type { Trace } from "./Random/Types";
170
- /**
171
- * How `file` and `ordinal` on a {@link Trace} were resolved — recorded
172
- * so a captured trace is self-describing, including `"counted"`
173
- * (replayed for a node taken from inside a `T.recursive` expansion;
174
- * not a variant you choose when building).
175
- */
176
- export type { RootKind } from "./Random/Types";
177
145
  /**
178
146
  * `fork`/`wrap`'s own config shapes, so a caller building an overlay
179
- * programmatically (rather than as an inline literal) can name them —
180
- * the same rationale as the existing `Seed`/`Attribution` exports.
181
- * `Config` is what `initialize`'s own parameter is a `Partial` of;
182
- * `Overlay` is what `fork`/`wrap` accept; `Context` is
183
- * `instance.context`'s own type, so a caller writing a helper that
147
+ * programmatically (rather than as an inline literal) can name them — the same
148
+ * rationale as the existing `Salt` export. `Config` is what `initialize`'s own
149
+ * parameter is a `Partial` of; `Overlay` is what `fork`/`wrap` accept;
150
+ * `Context` is `instance.context`'s own type, so a caller writing a helper that
184
151
  * reads it can name the parameter.
185
152
  */
186
- export type { Config, Context, Overlay } from "./Instance/Types";
153
+ export type { Config, Context, Overlay, Stack } from "./Instance/Types";
@@ -1,64 +1,77 @@
1
1
  /**
2
2
  * The "adapter-authoring SDK" entry point — published as the
3
- * `@ghostry/fabricator/internal` package export, deliberately *not*
4
- * re-exported from `./index.ts`. An external adapter package (e.g.
5
- * `@ghostry/fabricator-adapter-typebox-v0`) needs to walk a Schema/
6
- * Fabricator structurally and dispatch on each primitive kind's `Core`
7
- * shape — see "Match `Core`, never `Schema`, in a dispatch" — which
8
- * the end-user-facing `.` export has no reason to carry.
3
+ * `@ghostry/fabricator/internal` package export, deliberately _not_ re-exported
4
+ * from `./index.ts`. An external adapter package (e.g.
5
+ * `@ghostry/fabricator-adapter-typebox-v0`) needs to walk a Schema/ Fabricator
6
+ * structurally and dispatch on each primitive kind's `Core` shape — see "Match
7
+ * `Core`, never `Schema`, in a dispatch" — which the end-user-facing `.` export
8
+ * has no reason to carry.
9
9
  *
10
- * Also this package's own white-box test suite's route to source: a
11
- * test file imports through `@ghostry/fabricator`/
12
- * `@ghostry/fabricator/internal` rather than a relative `../src/...`
13
- * path specifically so it resolves through the built `dist/` (see the
14
- * "Random", "Schema", and "Enumeration" groups below) — the same
15
- * reason an adapter needs this entry point, applied to this package's
10
+ * Also this package's own white-box test suite's route to source: a test file
11
+ * imports through `@ghostry/fabricator`/ `@ghostry/fabricator/internal` rather
12
+ * than a relative `../src/...` path specifically so it resolves through the
13
+ * built `dist/` (see the "Random", "Schema", and "Enumeration" groups below) —
14
+ * the same reason an adapter needs this entry point, applied to this package's
16
15
  * own tests instead of an external one.
17
16
  *
18
- * Everything here is curated, not incidental. When wiring a new leaf
19
- * kind into the rest of the system, add its module to
20
- * `Primitive/namespace.ts` (re-exported here as `Primitive`), or no
21
- * adapter can reach that kind's `Core` type.
17
+ * Everything here is curated, not incidental. When wiring a new leaf kind into
18
+ * the rest of the system, add its module to `Primitive/namespace.ts`
19
+ * (re-exported here as `Primitive`), or no adapter can reach that kind's `Core`
20
+ * type.
22
21
  */
23
22
  export type { Fabrication, NaiveFabricator } from "./Fabricator/Types";
23
+ /**
24
+ * Schema -> the Fabricator type `construct()` produces for it, dispatching per
25
+ * kind. `Constructor` already names this as its own construct signature's
26
+ * return, but only _inside_ a generic call: a wrapping library that hands a
27
+ * built Fabricator to its own callers has to name the type without making that
28
+ * call, and cannot infer it back out of `Constructor` because the signature is
29
+ * generic (a `Constructor extends { new (schema: $S, ...): infer $R }` match
30
+ * instantiates at the constraint, not at `$S`).
31
+ *
32
+ * `@ghostry/extern-extension-fabricator-v0` is the case in point: it hands the
33
+ * built Fabricator to a user callback as the shaping handle, so the handle's
34
+ * type is exactly this. Without it, an integration is pushed into hand-writing
35
+ * a per-kind stand-in — a second copy of this mapping, susceptible to drift.
36
+ */
37
+ export type { AsFabricator } from "./Fabricator/Types";
24
38
  export { Children, Kind, Meta, Produces, type Buildable } from "./Types";
25
39
  export { isPlainObject } from "./Utility/Core";
26
40
  export type * as Primitive from "./Primitive/namespace";
27
41
  /**
28
- * `Schema/Types.ts`'s own value-type resolution, needed by tests
29
- * asserting `ValueOf<...>` directly rather than through a built
30
- * Fabricator's `Fabrication<...>`.
42
+ * `Schema/Types.ts`'s own value-type resolution, needed by tests asserting
43
+ * `ValueOf<...>` directly rather than through a built Fabricator's
44
+ * `Fabrication<...>`.
31
45
  */
32
46
  export type { ValueOf } from "./Schema/Types";
33
47
  /**
34
- * `Constructor` is `Instance.Fabricator`'s own type — public in effect
35
- * (every `initialize()` caller receives one), just never named
36
- * directly by the `.` export, which only ever describes it inline.
48
+ * `Constructor` is `Instance.Fabricator`'s own type — public in effect (every
49
+ * `initialize()` caller receives one), just never named directly by the `.`
50
+ * export, which only ever describes it inline.
37
51
  */
38
52
  export type { Constructor } from "./Fabricator/Constructor";
39
53
  /**
40
- * The enumeration planner's own shapes — `combinatorial`/`coverage`
41
- * (the `.` export's public entry points) are built on `plan`/`resolve`,
42
- * which a test asserting `axisFor`'s per-kind width/strategy decisions
43
- * needs directly.
54
+ * The enumeration planner's own shapes — `combinatorial`/`coverage` (the `.`
55
+ * export's public entry points) are built on `plan`/`resolve`, which a test
56
+ * asserting `axisFor`'s per-kind width/strategy decisions needs directly.
44
57
  */
45
58
  export { plan, resolve } from "./Enumeration/Plan";
46
59
  export type { Axis, Enumerable, Pin, Resolvable } from "./Enumeration/Types";
47
60
  /**
48
- * The randomness layer underneath
49
- * `initialize({ seed, algorithm, attribution })` and a Fabricator's
50
- * `.trace` — needed by tests exercising stream attribution and
51
- * construction directly, beneath the level `initialize()` itself
52
- * exposes.
61
+ * The randomness layer underneath `initialize({ clock, salt, algorithm })` and
62
+ * a Fabricator's `.trace` — needed by tests exercising stream construction
63
+ * directly, beneath the level `initialize()` itself exposes.
53
64
  */
54
- export { defaultAlgorithm, encode, randomSeed, toRandomSource, toStream, toStreamFromTrace, } from "./Random";
55
- export type { Algorithm, ConstructionTrace, ConstructorOptions, ResolvedAttribution, RootKind, RootPins, Seed, Trace, } from "./Random/Types";
65
+ export { defaultAlgorithm, encode, randomSalt, toRandomSource, toStream, toStreamFromTrace, } from "./Random";
66
+ export type { Algorithm, ConstructionTrace, ConstructorOptions, RootPins, Salt, Trace, } from "./Random/Types";
56
67
  /**
57
- * `Random/CallSite.ts`'s pure string helpers. Exported for this
58
- * package's own tests: the percent-encoded, `file://`-prefixed, and
59
- * backslashed spellings they exist to fold together cannot be produced
60
- * by running the suite from an ordinary POSIX checkout, so they have
61
- * to be driven with synthetic frame strings instead of real stack
62
- * frames.
68
+ * The synchronous ambient carrier. `#stack` (`package.json`) selects it only
69
+ * where there is no `node:async_hooks` — in practice a browser bundle — so on
70
+ * Bun, Node, and Deno alike the condition always resolves to the
71
+ * `AsyncLocalStorage` one instead. Exported for this package's own tests:
72
+ * without it, neither the synchronous carrier's behavior nor `wrap`'s rejection
73
+ * of an async block under it is reachable from the suite. It is also a
74
+ * serviceable argument for `initialize({ stack })` for anyone who wants the old
75
+ * semantics back deliberately.
63
76
  */
64
- export { directoryOf, normalizeLocation, relativize } from "./Random/CallSite";
77
+ export { toStack as toSynchronousStack } from "./Instance/Stack/Sync";
package/package.json CHANGED
@@ -1,10 +1,16 @@
1
1
  {
2
2
  "name": "@ghostry/fabricator",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "license": "MIT",
5
5
  "description": "Fabricate typed data from composable schemas.",
6
6
  "keywords": [
7
- "factory"
7
+ "factory",
8
+ "reproducible",
9
+ "fixtures",
10
+ "testing",
11
+ "mock",
12
+ "schema",
13
+ "typescript"
8
14
  ],
9
15
  "author": {
10
16
  "name": "Patrick Rebsch"
@@ -14,11 +20,24 @@
14
20
  "url": "git+https://github.com/ghostry-dev/fabricator",
15
21
  "directory": "pkg/fabricator"
16
22
  },
17
- "homepage": "https://github.com/ghostry-dev/fabricator",
23
+ "homepage": "https://docs.ghostry.dev/fabricator/",
18
24
  "bugs": "https://github.com/ghostry-dev/fabricator/issues",
19
25
  "type": "module",
26
+ "sideEffects": false,
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
20
30
  "types": "./dist/types/index.d.ts",
21
31
  "module": "./dist/esm/index.js",
32
+ "imports": {
33
+ "#stack": {
34
+ "types": "./src/Instance/Stack/Async.ts",
35
+ "deno": "./src/Instance/Stack/Async.ts",
36
+ "node": "./dist/esm/Instance/Stack/Async.js",
37
+ "bun": "./dist/esm/Instance/Stack/Async.js",
38
+ "default": "./dist/esm/Instance/Stack/Sync.js"
39
+ }
40
+ },
22
41
  "exports": {
23
42
  ".": {
24
43
  "types": "./dist/types/index.d.ts",
@@ -29,6 +48,16 @@
29
48
  "types": "./dist/types/internal.d.ts",
30
49
  "import": "./dist/esm/internal.js",
31
50
  "default": "./dist/esm/internal.js"
51
+ },
52
+ "./adapting": {
53
+ "types": "./dist/types/adapting.d.ts",
54
+ "import": "./dist/esm/adapting.js",
55
+ "default": "./dist/esm/adapting.js"
56
+ },
57
+ "./harnessing": {
58
+ "types": "./dist/types/harnessing.d.ts",
59
+ "import": "./dist/esm/harnessing.js",
60
+ "default": "./dist/esm/harnessing.js"
32
61
  }
33
62
  },
34
63
  "publishConfig": {
@@ -39,13 +68,16 @@
39
68
  "build:reset": "rm -rf ./dist",
40
69
  "build:compile": "bunx --no-install --bun rslib build --config ./rslib.config.ts",
41
70
  "build:compile:rsdoctor": "RSDOCTOR=true bunx --no-install --bun rslib build --config ./rslib.config.ts",
71
+ "build:types": "bun --bun ../../node_modules/typescript-5/lib/tsc.js -p ./tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --declarationDir ./dist/types",
72
+ "build:verify": "tsc --noEmit -p ./tsconfig.verify.json",
42
73
  "build:clean": "find ./dist -type f -name '*.tsbuildinfo' -delete",
43
- "build": "bun run build:reset && bun run build:compile && bun run build:clean",
44
- "build:rsdoctor": "bun run build:reset && bun run build:compile:rsdoctor && bun run build:clean",
74
+ "build": "bun run build:reset && bun run build:compile && bun run build:types && bun run build:verify && bun run build:clean",
75
+ "build:rsdoctor": "bun run build:reset && bun run build:compile:rsdoctor && bun run build:types && bun run build:verify && bun run build:clean",
45
76
  "check": "tsc --noEmit",
46
77
  "check:ts5": "bun --bun ../../node_modules/typescript-5/lib/tsc.js --noEmit",
47
- "prettier": "bunx --no-install --bun prettier .",
48
- "test": "bun run check && bun run check:ts5 && bun test"
78
+ "check:jsr": "DENO_BIN_PATH=$PWD/../../node_modules/.bin/deno bunx --no-install jsr publish --dry-run --allow-dirty",
79
+ "format": "bunx --no-install oxfmt .",
80
+ "test": "bun run check && bun run check:ts5 && bun run check:jsr && bun test"
49
81
  },
50
82
  "files": [
51
83
  "dist"
@@ -1,56 +0,0 @@
1
- const OWN_ROOT = normalizeLocation(new URL("..", import.meta.url).href);
2
- function stripPosition(text) {
3
- return text.replace(/:\d+:\d+/g, "");
4
- }
5
- function extractLocation(frameLine) {
6
- const trimmed = frameLine.trim().replace(/^at\s+/, "");
7
- const parenthesized = trimmed.match(/\(([^()]*)\)$/);
8
- return parenthesized ? parenthesized[1] : trimmed;
9
- }
10
- function decode(text) {
11
- try {
12
- return decodeURIComponent(text);
13
- } catch {
14
- return text;
15
- }
16
- }
17
- function normalizeLocation(location) {
18
- const isUrl = location.startsWith("file://");
19
- const path = isUrl ? decode(location.slice(7)) : location;
20
- return path.replace(/\\/g, "/").replace(/^\/?([A-Za-z]):\//, (_, letter)=>`/${letter.toUpperCase()}:/`);
21
- }
22
- function directoryOf(location) {
23
- const cut = location.lastIndexOf("/");
24
- return -1 === cut ? location : location.slice(0, cut + 1);
25
- }
26
- function relativize(root, file) {
27
- if (!file.startsWith("/")) return file;
28
- const from = root.split("/").filter(Boolean);
29
- const to = file.split("/").filter(Boolean);
30
- let shared = 0;
31
- while(shared < from.length && shared < to.length && from[shared] === to[shared])shared++;
32
- const traversals = Array(from.length - shared).fill("..");
33
- return [
34
- ...traversals,
35
- ...to.slice(shared)
36
- ].join("/");
37
- }
38
- function isOwnFrame(location) {
39
- return location.startsWith(OWN_ROOT);
40
- }
41
- function firstExternalFrame(stack) {
42
- var _ref, _locations_find;
43
- const locations = stack.split("\n").filter((line)=>line.trim().startsWith("at ")).map(extractLocation).map(normalizeLocation);
44
- return null != (_ref = null != (_locations_find = locations.find((location)=>!isOwnFrame(location))) ? _locations_find : locations[locations.length - 1]) ? _ref : stack;
45
- }
46
- function resolveCallerFile() {
47
- var _stack;
48
- if ("function" == typeof Error.captureStackTrace) {
49
- var _captured_stack;
50
- const captured = {};
51
- Error.captureStackTrace(captured);
52
- return stripPosition(firstExternalFrame(null != (_captured_stack = captured.stack) ? _captured_stack : ""));
53
- }
54
- return stripPosition(null != (_stack = new Error().stack) ? _stack : "");
55
- }
56
- export { directoryOf, normalizeLocation, relativize, resolveCallerFile };
@@ -1,59 +0,0 @@
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;