@ghostry/fabricator 0.0.8 → 0.0.9

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 (73) hide show
  1. package/dist/esm/Bound.js +6 -1
  2. package/dist/esm/Distribution/index.js +9 -1
  3. package/dist/esm/Instance/Core.js +8 -8
  4. package/dist/esm/Primitive/always/Schema.js +2 -0
  5. package/dist/esm/Primitive/array/Fabricator.js +4 -9
  6. package/dist/esm/Primitive/array/Schema.js +2 -0
  7. package/dist/esm/Primitive/bigint/Schema.js +2 -0
  8. package/dist/esm/Primitive/boolean/Schema.js +2 -0
  9. package/dist/esm/Primitive/choice/Schema.js +2 -0
  10. package/dist/esm/Primitive/date/Schema.js +2 -0
  11. package/dist/esm/Primitive/derive/Schema.js +2 -0
  12. package/dist/esm/Primitive/enum/Schema.js +2 -0
  13. package/dist/esm/Primitive/null/Schema.js +2 -0
  14. package/dist/esm/Primitive/nullable/Schema.js +2 -0
  15. package/dist/esm/Primitive/nullish/Schema.js +2 -0
  16. package/dist/esm/Primitive/number/Fabricator.js +3 -7
  17. package/dist/esm/Primitive/number/Schema.js +2 -0
  18. package/dist/esm/Primitive/object/Schema.js +3 -1
  19. package/dist/esm/Primitive/object/compute/Schema.js +2 -0
  20. package/dist/esm/Primitive/object/omittable/Schema.js +2 -0
  21. package/dist/esm/Primitive/object/optional/Schema.js +2 -0
  22. package/dist/esm/Primitive/opaque/Schema.js +2 -0
  23. package/dist/esm/Primitive/record/Fabricator.js +6 -1
  24. package/dist/esm/Primitive/record/Schema.js +2 -0
  25. package/dist/esm/Primitive/recursive/Schema.js +2 -0
  26. package/dist/esm/Primitive/recursive/self/Schema.js +2 -0
  27. package/dist/esm/Primitive/string/Fabricator.js +6 -2
  28. package/dist/esm/Primitive/string/Schema.js +2 -0
  29. package/dist/esm/Primitive/symbol/Schema.js +2 -0
  30. package/dist/esm/Primitive/tuple/Schema.js +2 -0
  31. package/dist/esm/Primitive/undefinable/Schema.js +2 -0
  32. package/dist/esm/Primitive/undefined/Schema.js +2 -0
  33. package/dist/esm/Schema/Satisfies.js +5 -0
  34. package/dist/esm/index.js +1 -0
  35. package/dist/types/Bound.d.ts +20 -4
  36. package/dist/types/Distribution/index.d.ts +14 -0
  37. package/dist/types/Error/index.d.ts +2 -4
  38. package/dist/types/Harnessing/Core.d.ts +4 -4
  39. package/dist/types/Primitive/always/Schema.d.ts +8 -1
  40. package/dist/types/Primitive/array/Registry.d.ts +7 -5
  41. package/dist/types/Primitive/array/Schema.d.ts +7 -0
  42. package/dist/types/Primitive/array/Types.d.ts +3 -9
  43. package/dist/types/Primitive/bigint/Schema.d.ts +7 -0
  44. package/dist/types/Primitive/boolean/Schema.d.ts +7 -0
  45. package/dist/types/Primitive/choice/Schema.d.ts +7 -0
  46. package/dist/types/Primitive/date/Schema.d.ts +7 -0
  47. package/dist/types/Primitive/derive/Schema.d.ts +8 -0
  48. package/dist/types/Primitive/derive/Types.d.ts +5 -6
  49. package/dist/types/Primitive/enum/Schema.d.ts +7 -0
  50. package/dist/types/Primitive/null/Schema.d.ts +9 -2
  51. package/dist/types/Primitive/nullable/Schema.d.ts +7 -0
  52. package/dist/types/Primitive/nullish/Schema.d.ts +7 -0
  53. package/dist/types/Primitive/number/Schema.d.ts +7 -0
  54. package/dist/types/Primitive/object/Schema.d.ts +12 -2
  55. package/dist/types/Primitive/object/compute/Schema.d.ts +8 -0
  56. package/dist/types/Primitive/object/omittable/Schema.d.ts +10 -1
  57. package/dist/types/Primitive/object/optional/Schema.d.ts +9 -1
  58. package/dist/types/Primitive/opaque/Schema.d.ts +8 -1
  59. package/dist/types/Primitive/record/Schema.d.ts +7 -0
  60. package/dist/types/Primitive/record/Types.d.ts +2 -2
  61. package/dist/types/Primitive/recursive/Schema.d.ts +8 -1
  62. package/dist/types/Primitive/recursive/self/Schema.d.ts +11 -1
  63. package/dist/types/Primitive/string/Registry.d.ts +13 -9
  64. package/dist/types/Primitive/string/Schema.d.ts +7 -0
  65. package/dist/types/Primitive/string/Types.d.ts +7 -11
  66. package/dist/types/Primitive/symbol/Schema.d.ts +7 -0
  67. package/dist/types/Primitive/tuple/Schema.d.ts +7 -0
  68. package/dist/types/Primitive/undefinable/Schema.d.ts +7 -0
  69. package/dist/types/Primitive/undefined/Schema.d.ts +9 -2
  70. package/dist/types/Schema/Satisfies.d.ts +84 -0
  71. package/dist/types/Schema/Types.d.ts +17 -1
  72. package/dist/types/index.d.ts +9 -0
  73. package/package.json +1 -1
package/dist/esm/Bound.js CHANGED
@@ -76,6 +76,11 @@ function toLengthRange(length, label) {
76
76
  max: toBound(length.max)
77
77
  };
78
78
  assertNonemptyDiscrete(label, range.min, range.max);
79
- return range;
79
+ if ("number" == typeof length || void 0 === length.distribution) return range;
80
+ return {
81
+ min: range.min,
82
+ max: range.max,
83
+ distribution: length.distribution
84
+ };
80
85
  }
81
86
  export { assertNonemptyContinuous, assertNonemptyDiscrete, assertNonemptyDiscreteBigint, constrainContinuous, effectiveDiscrete, effectiveDiscreteBigint, epochBound, toBound, toLengthRange, towardInterior };
@@ -42,6 +42,14 @@ function unitPosition(x, min, max) {
42
42
  if (!Number.isFinite(ratio)) return 0;
43
43
  return 1 / (1 + ratio);
44
44
  }
45
+ function discreteSampler(distribution, range, stream) {
46
+ const { min, max } = range;
47
+ const draw = sampler(null != distribution ? distribution : Distribution_Distribution.uniform(), {
48
+ min,
49
+ max: max + 1
50
+ }, stream);
51
+ return ()=>Math.min(max, Math.floor(draw()));
52
+ }
45
53
  function sampler(distribution, range, stream) {
46
54
  const { min, max } = range;
47
55
  const span = max - min;
@@ -198,4 +206,4 @@ function weighted(weights, stream, label) {
198
206
  };
199
207
  }
200
208
  var Distribution_Distribution;
201
- export { Distribution_Distribution as Distribution, assertDrawableKeyedWeights, assertDrawableWeights, drawableOutcomes, isDrawable, isValidWeight, sample, sampler, shuffle, weighted };
209
+ export { Distribution_Distribution as Distribution, assertDrawableKeyedWeights, assertDrawableWeights, discreteSampler, drawableOutcomes, isDrawable, isValidWeight, sample, sampler, shuffle, weighted };
@@ -96,14 +96,14 @@ function instantiate(config, stack, parent) {
96
96
  return normalizeSalt((null != (_ref = null == (_visibleFrame = visibleFrame()) ? void 0 : _visibleFrame.config) ? _ref : config).salt);
97
97
  },
98
98
  get algorithm () {
99
- var _ref1;
100
- var _visibleFrame1;
101
- return (null != (_ref1 = null == (_visibleFrame1 = visibleFrame()) ? void 0 : _visibleFrame1.config) ? _ref1 : config).algorithm;
99
+ var _ref;
100
+ var _visibleFrame;
101
+ return (null != (_ref = null == (_visibleFrame = visibleFrame()) ? void 0 : _visibleFrame.config) ? _ref : config).algorithm;
102
102
  },
103
103
  get clock () {
104
- var _ref2;
105
- var _visibleFrame2;
106
- return resolveClock(null != (_ref2 = null == (_visibleFrame2 = visibleFrame()) ? void 0 : _visibleFrame2.config) ? _ref2 : config);
104
+ var _ref;
105
+ var _visibleFrame;
106
+ return resolveClock(null != (_ref = null == (_visibleFrame = visibleFrame()) ? void 0 : _visibleFrame.config) ? _ref : config);
107
107
  },
108
108
  scope: ()=>{
109
109
  var _ref;
@@ -118,8 +118,8 @@ function instantiate(config, stack, parent) {
118
118
  T: config.types,
119
119
  ancestry,
120
120
  get root () {
121
- var _ref3;
122
- return null != (_ref3 = null == parent ? void 0 : parent.root) ? _ref3 : instance;
121
+ var _ref;
122
+ return null != (_ref = null == parent ? void 0 : parent.root) ? _ref : instance;
123
123
  },
124
124
  Fabricator,
125
125
  combinatorial,
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "always",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -1,7 +1,7 @@
1
1
  import { effectiveDiscrete } from "../../Bound.js";
2
+ import { discreteSampler } from "../../Distribution/index.js";
2
3
  import { toStreamFromTrace } from "../../Random/index.js";
3
4
  import { Children, Kind, Meta } from "../../Types.js";
4
- import { inline } from "../../Utility/Core.js";
5
5
  import { Schema } from "./Schema.js";
6
6
  function Fabricator(context, element) {
7
7
  const { schema, algorithm, trace } = context;
@@ -24,15 +24,10 @@ function Fabricator(context, element) {
24
24
  }
25
25
  const stream = toStreamFromTrace(algorithm, trace);
26
26
  const whereby = meta.whereby;
27
- const fabricate = ()=>{
28
- const length = inline(()=>{
29
- const { min, max } = effectiveDiscrete(whereby.length.min, whereby.length.max);
30
- return min + Math.floor(stream.next() * (max - min + 1));
31
- });
32
- return Array.from({
33
- length
27
+ const drawLength = discreteSampler(whereby.length.distribution, effectiveDiscrete(whereby.length.min, whereby.length.max), stream);
28
+ const fabricate = ()=>Array.from({
29
+ length: drawLength()
34
30
  }, ()=>element.fabricate());
35
- };
36
31
  return {
37
32
  [Kind]: "array",
38
33
  [Meta]: meta,
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,5 +1,6 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
2
  import { assertDrawableKeyedWeights } from "../../Distribution/index.js";
3
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
3
4
  import { Kind, Meta } from "../../Types.js";
4
5
  import { outcomes } from "./Outcomes.js";
5
6
  function Schema(schema) {
@@ -13,6 +14,7 @@ function Schema(schema) {
13
14
  produce
14
15
  }
15
16
  }),
17
+ satisfies: schemaSatisfies,
16
18
  weighted: (weights)=>{
17
19
  const merged = {
18
20
  ...schema[Meta].weights,
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "derive",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "null",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -1,5 +1,6 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
2
  import { assertDrawableKeyedWeights } from "../../Distribution/index.js";
3
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
3
4
  import { Kind, Meta } from "../../Types.js";
4
5
  import { outcomes } from "./Outcomes.js";
5
6
  function Schema(schema) {
@@ -13,6 +14,7 @@ function Schema(schema) {
13
14
  produce
14
15
  }
15
16
  }),
17
+ satisfies: schemaSatisfies,
16
18
  weighted: (weights)=>{
17
19
  const merged = {
18
20
  ...schema[Meta].weights,
@@ -1,5 +1,6 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
2
  import { assertDrawableKeyedWeights } from "../../Distribution/index.js";
3
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
3
4
  import { Kind, Meta } from "../../Types.js";
4
5
  import { outcomes } from "./Outcomes.js";
5
6
  function Schema(schema) {
@@ -13,6 +14,7 @@ function Schema(schema) {
13
14
  produce
14
15
  }
15
16
  }),
17
+ satisfies: schemaSatisfies,
16
18
  weighted: (weights)=>{
17
19
  const merged = {
18
20
  ...schema[Meta].weights,
@@ -1,5 +1,5 @@
1
1
  import { constrainContinuous, effectiveDiscrete } from "../../Bound.js";
2
- import { Distribution, sampler } from "../../Distribution/index.js";
2
+ import { Distribution, discreteSampler, sampler } from "../../Distribution/index.js";
3
3
  import { toStreamFromTrace } from "../../Random/index.js";
4
4
  import { Kind, Meta } from "../../Types.js";
5
5
  import { unboundedContinuous, unboundedDiscrete } from "./defaults.js";
@@ -46,16 +46,12 @@ function Fabricator(context) {
46
46
  };
47
47
  const distribution = null != (_range_distribution = range.distribution) ? _range_distribution : Distribution.uniform();
48
48
  if (meta.integer) {
49
- const { min, max } = effectiveDiscrete(range.min, range.max);
50
- const draw = sampler(distribution, {
51
- min,
52
- max: max + 1
53
- }, stream);
49
+ const draw = discreteSampler(distribution, effectiveDiscrete(range.min, range.max), stream);
54
50
  return {
55
51
  [Kind]: "number",
56
52
  [Meta]: meta,
57
53
  trace,
58
- fabricate: ()=>Math.min(max, Math.floor(draw())),
54
+ fabricate: ()=>draw(),
59
55
  schema: rehydrated
60
56
  };
61
57
  }
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -12,6 +13,7 @@ function Schema(schema) {
12
13
  hints
13
14
  }
14
15
  }),
16
+ satisfies: schemaSatisfies,
15
17
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
16
18
  };
17
19
  }
@@ -1,3 +1,4 @@
1
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
1
2
  import { Kind, Meta } from "../../Types.js";
2
3
  function Schema(schema) {
3
4
  return {
@@ -9,7 +10,8 @@ function Schema(schema) {
9
10
  ...schema[Meta],
10
11
  produce
11
12
  }
12
- })
13
+ }),
14
+ satisfies: schemaSatisfies
13
15
  };
14
16
  }
15
17
  function isObjectSchema(candidate) {
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "object.compute",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -1,5 +1,6 @@
1
1
  import { withAdaptations } from "../../../Adapter/Core.js";
2
2
  import { assertDrawableKeyedWeights } from "../../../Distribution/index.js";
3
+ import { schemaSatisfies } from "../../../Schema/Satisfies.js";
3
4
  import { Kind, Meta } from "../../../Types.js";
4
5
  import { outcomes } from "./Outcomes.js";
5
6
  function Schema(schema) {
@@ -13,6 +14,7 @@ function Schema(schema) {
13
14
  produce
14
15
  }
15
16
  }),
17
+ satisfies: schemaSatisfies,
16
18
  weighted: (weights)=>{
17
19
  const merged = {
18
20
  ...schema[Meta].weights,
@@ -1,5 +1,6 @@
1
1
  import { withAdaptations } from "../../../Adapter/Core.js";
2
2
  import { assertDrawableKeyedWeights } from "../../../Distribution/index.js";
3
+ import { schemaSatisfies } from "../../../Schema/Satisfies.js";
3
4
  import { Kind, Meta } from "../../../Types.js";
4
5
  import { outcomes } from "./Outcomes.js";
5
6
  function Schema(schema) {
@@ -13,6 +14,7 @@ function Schema(schema) {
13
14
  produce
14
15
  }
15
16
  }),
17
+ satisfies: schemaSatisfies,
16
18
  weighted: (weights)=>{
17
19
  const merged = {
18
20
  ...schema[Meta].weights,
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "opaque",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -1,3 +1,4 @@
1
+ import { discreteSampler } from "../../Distribution/index.js";
1
2
  import { toStreamFromTrace } from "../../Random/index.js";
2
3
  import { Children, Kind, Meta } from "../../Types.js";
3
4
  import { Schema } from "./Schema.js";
@@ -25,8 +26,12 @@ function Fabricator(context, key, value) {
25
26
  }
26
27
  const stream = toStreamFromTrace(algorithm, trace);
27
28
  const { max, minTried = 0 } = meta.whereby.size;
29
+ const drawSize = discreteSampler(void 0, {
30
+ min: minTried,
31
+ max
32
+ }, stream);
28
33
  const fabricate = ()=>{
29
- const size = minTried + Math.floor(stream.next() * (max - minTried + 1));
34
+ const size = drawSize();
30
35
  const fabricated = {};
31
36
  for(let i = 0; i < size; i++){
32
37
  const k = key.fabricate();
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "recursive",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "recursive.self",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -1,5 +1,5 @@
1
1
  import { effectiveDiscrete } from "../../Bound.js";
2
- import { weighted } from "../../Distribution/index.js";
2
+ import { discreteSampler, weighted } from "../../Distribution/index.js";
3
3
  import { toStreamFromTrace } from "../../Random/index.js";
4
4
  import { Kind, Meta } from "../../Types.js";
5
5
  import { inline } from "../../Utility/Core.js";
@@ -26,6 +26,10 @@ function Fabricator(context) {
26
26
  const stream = toStreamFromTrace(algorithm, trace);
27
27
  const whereby = meta.whereby;
28
28
  const { min, max } = effectiveDiscrete(whereby.length.min, whereby.length.max);
29
+ const drawLength = discreteSampler(whereby.length.distribution, {
30
+ min,
31
+ max
32
+ }, stream);
29
33
  const sources = inline(()=>{
30
34
  const composition = whereby.composition;
31
35
  if (void 0 === composition) return [
@@ -46,7 +50,7 @@ function Fabricator(context) {
46
50
  ]), stream, "T.string.whereby.composition");
47
51
  const fill = compiler(bmpScalars, stream);
48
52
  const fabricate = ()=>{
49
- const length = min + Math.floor(stream.next() * (max - min + 1));
53
+ const length = drawLength();
50
54
  const pieces = [];
51
55
  let remaining = length;
52
56
  while(remaining > 0){
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -12,6 +13,7 @@ function Schema(schema) {
12
13
  hints
13
14
  }
14
15
  }),
16
+ satisfies: schemaSatisfies,
15
17
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
16
18
  };
17
19
  }
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,4 +1,5 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind, Meta } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
@@ -11,6 +12,7 @@ function Schema(schema) {
11
12
  produce
12
13
  }
13
14
  }),
15
+ satisfies: schemaSatisfies,
14
16
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
15
17
  };
16
18
  }
@@ -1,5 +1,6 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
2
  import { assertDrawableKeyedWeights } from "../../Distribution/index.js";
3
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
3
4
  import { Kind, Meta } from "../../Types.js";
4
5
  import { outcomes } from "./Outcomes.js";
5
6
  function Schema(schema) {
@@ -13,6 +14,7 @@ function Schema(schema) {
13
14
  produce
14
15
  }
15
16
  }),
17
+ satisfies: schemaSatisfies,
16
18
  weighted: (weights)=>{
17
19
  const merged = {
18
20
  ...schema[Meta].weights,
@@ -1,9 +1,11 @@
1
1
  import { withAdaptations } from "../../Adapter/Core.js";
2
+ import { schemaSatisfies } from "../../Schema/Satisfies.js";
2
3
  import { Kind } from "../../Types.js";
3
4
  function Schema(schema) {
4
5
  return {
5
6
  ...schema,
6
7
  [Kind]: "undefined",
8
+ satisfies: schemaSatisfies,
7
9
  adapt: (adapter, produce)=>Schema(withAdaptations(schema, adapter, produce))
8
10
  };
9
11
  }
@@ -0,0 +1,5 @@
1
+ function schemaSatisfies() {
2
+ return this;
3
+ }
4
+ function satisfies(buildable) {}
5
+ export { satisfies, schemaSatisfies };
package/dist/esm/index.js CHANGED
@@ -10,4 +10,5 @@ export { FabricatorError } from "./Error/index.js";
10
10
  export { registry } from "./Schema/Registry.js";
11
11
  export { effectiveDiscrete, toBound } from "./Bound.js";
12
12
  export { sample, shuffle } from "./Distribution/index.js";
13
+ export { satisfies } from "./Schema/Satisfies.js";
13
14
  export { initialize };
@@ -1,3 +1,4 @@
1
+ import type { Distribution } from "./Distribution";
1
2
  /**
2
3
  * Canonical endpoint stored on `[Meta].whereby`. Call sites still accept a
3
4
  * scalar (inclusive) via {@link InputBound}; `.whereby()` runs {@link toBound} so
@@ -56,13 +57,28 @@ export declare function towardInterior(value: number, toward: number): number;
56
57
  export declare function constrainContinuous(next: () => number, min: Bound<number>, max: Bound<number>): () => number;
57
58
  export declare function epochBound(bound: Bound<Date>): Bound<number>;
58
59
  /**
59
- * Array/string `length`: a bare number is an exact count; an omitted `min` is
60
- * inclusive `0`. Always stored as a Bound pair so adapters have one path.
60
+ * Call-site `length` for `string` and `array`: a bare number is an exact count,
61
+ * and `{ max, min?, distribution? }` is a range. A scalar end is inclusive.
61
62
  */
62
- export declare function toLengthRange(length: number | {
63
+ export type InputLength = number | {
63
64
  max: InputBound<number>;
64
65
  min?: InputBound<number> | undefined;
65
- }, label: string): {
66
+ distribution?: Distribution | undefined;
67
+ };
68
+ /**
69
+ * Stored `length`: both ends are canonical {@link Bound}s. `distribution` is
70
+ * present only when the caller set one, so a bare count and an unspecified
71
+ * distribution stay off the stored object.
72
+ */
73
+ export type Length = {
66
74
  min: Bound<number>;
67
75
  max: Bound<number>;
76
+ distribution?: Distribution | undefined;
68
77
  };
78
+ /**
79
+ * Array/string `length`: a bare number is an exact count (no distribution); an
80
+ * omitted `min` is inclusive `0`. Always stored as a Bound pair so adapters
81
+ * have one path. `distribution` is copied only when the caller set one,
82
+ * matching `date/Registry.ts`'s `toWhereby`, so stored meta stays minimal.
83
+ */
84
+ export declare function toLengthRange(length: InputLength, label: string): Length;
@@ -88,6 +88,20 @@ export declare namespace Distribution {
88
88
  */
89
89
  const custom: (shape: (u: number) => number) => Distribution;
90
90
  }
91
+ /**
92
+ * Integer draw over the inclusive `[min, max]` of `range`. Samples `[min, max +
93
+ * 1)` and floors, so each integer owns a full-width bucket — avoiding the
94
+ * half-width endpoint bias that rounding a `[min, max]` draw would produce. An
95
+ * omitted `distribution` is uniform. `range` is already the effective inclusive
96
+ * interval; exclusive ends are the caller's to resolve (`effectiveDiscrete`).
97
+ *
98
+ * The `Math.min(max, …)` clamp is load-bearing, not defensive. `max + 1` is
99
+ * exact even at `Number.MAX_SAFE_INTEGER` (it is 2^53), but near there doubles
100
+ * are spaced 1 apart, so `sampler`'s `(1 - u) * min + u * (max + 1)` can round
101
+ * up to exactly `max + 1` — e.g. `[MAX_SAFE_INTEGER - 10, MAX_SAFE_INTEGER]` —
102
+ * which would floor to one past `max`.
103
+ */
104
+ export declare function discreteSampler(distribution: Distribution | undefined, range: Range, stream: Stream): () => number;
91
105
  /**
92
106
  * Build a sampler that draws values within `range` following `distribution`.
93
107
  * Each call consumes one fresh uniform draw and, by construction, returns a
@@ -128,8 +128,7 @@ export declare namespace FabricatorError {
128
128
  */
129
129
  readonly label: string;
130
130
  /**
131
- * What the caller calls its items, e.g.
132
- * `"member"`/`"option"`/`"item"`.
131
+ * What the caller calls its items, e.g. `"member"`/`"option"`/`"item"`.
133
132
  */
134
133
  readonly noun: string;
135
134
  constructor(
@@ -139,8 +138,7 @@ export declare namespace FabricatorError {
139
138
  */
140
139
  label: string,
141
140
  /**
142
- * What the caller calls its items, e.g.
143
- * `"member"`/`"option"`/`"item"`.
141
+ * What the caller calls its items, e.g. `"member"`/`"option"`/`"item"`.
144
142
  */
145
143
  noun: string);
146
144
  }
@@ -35,10 +35,10 @@ import type { FabricatorTestContext, Integration } from "./Types";
35
35
  * captured result would pin one frame.
36
36
  *
37
37
  * The per-test wrap is entered on `context.scope()`, so it governs that
38
- * instance and its ancestors: the integrated instance when nothing encloses
39
- * it, and that instance as an ancestor of the enclosing scope when something
40
- * does. It does not govern forks of the integrated instance. Per-test data
41
- * therefore comes from the instance handed to `integration(...)`, from
38
+ * instance and its ancestors: the integrated instance when nothing encloses it,
39
+ * and that instance as an ancestor of the enclosing scope when something does.
40
+ * It does not govern forks of the integrated instance. Per-test data therefore
41
+ * comes from the instance handed to `integration(...)`, from
42
42
  * `context.fabricator`, or from a fork of that scope — a module-level fork of
43
43
  * the integrated instance draws the same data in every test, and because its
44
44
  * construction counter runs across tests, which values a test gets depends on