@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
@@ -1,5 +1,5 @@
1
1
  import type { Adaptations } from "../../Adapter/Types";
2
- import type { Bound, InputBound } from "../../Bound";
2
+ import type { InputLength, Length } from "../../Bound";
3
3
  import type { Produce } from "../../Random/Types";
4
4
  import type { Adaptation, Kind, Meta, Produces } from "../../Types";
5
5
  import type { classes } from "./Constants";
@@ -25,17 +25,11 @@ export type CharacterClass = keyof typeof classes;
25
25
  */
26
26
  export type Composition = Partial<Record<CharacterClass, number>> | ReadonlyArray<[number, CharacterSource]>;
27
27
  export type InputWhereby = {
28
- length: {
29
- max: InputBound<number>;
30
- min?: InputBound<number> | undefined;
31
- };
28
+ length: InputLength;
32
29
  composition?: Composition;
33
30
  };
34
31
  export type Whereby = {
35
- length: {
36
- min: Bound<number>;
37
- max: Bound<number>;
38
- };
32
+ length: Length;
39
33
  composition?: Composition;
40
34
  };
41
35
  export type Fabricated = string;
@@ -54,8 +48,10 @@ export type JsonSchema = {
54
48
  pattern?: string;
55
49
  };
56
50
  /**
57
- * A length/composition, drawn via `whereby` no natural bound to fuzz to, so
58
- * unlike `number`/`date` there's no bare form — optionally overridden by an
51
+ * A length and optional composition, drawn via `whereby`. There is no natural
52
+ * bound to fuzz a string to, so unlike `number`/`date` the builder itself has
53
+ * no bare form. `length` does: a bare count, or `{ min?, max, distribution? }`
54
+ * — the same {@link InputLength} `array` uses. Optionally overridden by an
59
55
  * opaque `as` production, carried alongside `whereby` rather than replacing it
60
56
  * (when `whereby` was already set) so a prior length/composition survives `as`
61
57
  * for future validation.
@@ -1,6 +1,7 @@
1
1
  import { type AdaptationEntry } from "../../Adapter/Core";
2
2
  import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
3
3
  import type { Produce } from "../../Random/Types";
4
+ import { type SatisfiesThis } from "../../Schema/Satisfies";
4
5
  import type { Core, Fabricated, Meta as ThisMeta } from "./Types";
5
6
  /**
6
7
  * `$Meta` is generic (defaulting to the full `Meta` union) so builder return
@@ -15,6 +16,12 @@ export interface Schema<$Meta extends ThisMeta = ThisMeta, $Adaptations extends
15
16
  * validation of `produce`) still has it to check against.
16
17
  */
17
18
  as: (produce: Produce<Fabricated>) => Schema<$Meta, $Adaptations>;
19
+ /**
20
+ * Check that this schema's fabricated value type is assignable to `$Target`.
21
+ * Identity at runtime; the target is not carried into later chained calls —
22
+ * see `object/Schema.ts`'s `satisfies`.
23
+ */
24
+ satisfies<$Target>(this: this & SatisfiesThis<Fabricated, $Target>): Schema<$Meta, $Adaptations>;
18
25
  /**
19
26
  * Override what this schema maps to in one or more external schema libraries
20
27
  * — see `string/Schema.ts`'s `adapt` for the full contract.
@@ -1,6 +1,7 @@
1
1
  import { type AdaptationEntry } from "../../Adapter/Core";
2
2
  import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
3
3
  import type { Produce } from "../../Random/Types";
4
+ import { type SatisfiesThis } from "../../Schema/Satisfies";
4
5
  import type { Core, Fabricated, Items } from "./Types";
5
6
  /**
6
7
  * Buildable `tuple` recipe: a fixed-length list of slot schemas, each
@@ -15,6 +16,12 @@ export interface Schema<$Items extends Items = Items, $Adaptations extends Adapt
15
16
  * validation of `produce`) still has it to check against.
16
17
  */
17
18
  as: (produce: Produce<Fabricated<$Items>>) => Schema<$Items, $Adaptations>;
19
+ /**
20
+ * Check that this schema's fabricated value type is assignable to `$Target`.
21
+ * Identity at runtime; the target is not carried into later chained calls —
22
+ * see `object/Schema.ts`'s `satisfies`.
23
+ */
24
+ satisfies<$Target>(this: this & SatisfiesThis<Fabricated<$Items>, $Target>): Schema<$Items, $Adaptations>;
18
25
  /**
19
26
  * Override what this schema maps to in one or more external schema libraries
20
27
  * — see `string/Schema.ts`'s `adapt` for the full contract.
@@ -1,6 +1,7 @@
1
1
  import { type AdaptationEntry } from "../../Adapter/Core";
2
2
  import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
3
3
  import type { Produce } from "../../Random/Types";
4
+ import { type SatisfiesThis } from "../../Schema/Satisfies";
4
5
  import type { AnySchema } from "../../Schema/Types";
5
6
  import type { Core, Definition, Fabricated, Weights } from "./Types";
6
7
  /**
@@ -16,6 +17,12 @@ export interface Schema<$Definition extends Definition = Definition, $Adaptation
16
17
  * does.
17
18
  */
18
19
  as: (produce: Produce<Fabricated<$Definition>>) => Schema<$Definition, $Adaptations>;
20
+ /**
21
+ * Check that this schema's fabricated value type is assignable to `$Target`.
22
+ * Identity at runtime; the target is not carried into later chained calls —
23
+ * see `object/Schema.ts`'s `satisfies`.
24
+ */
25
+ satisfies<$Target>(this: this & SatisfiesThis<Fabricated<$Definition>, $Target>): Schema<$Definition, $Adaptations>;
19
26
  /**
20
27
  * Reweight the built-in 50/50 roll. Keys are optional — an omitted key keeps
21
28
  * baseline weight `1`, the same weight the 50/50 split already uses — but
@@ -1,12 +1,19 @@
1
1
  import { type AdaptationEntry } from "../../Adapter/Core";
2
2
  import type { Adaptations, Adapter, Adapting, WithAdaptations } from "../../Adapter/Types";
3
- import type { Core, Meta as ThisMeta } from "./Types";
3
+ import { type SatisfiesThis } from "../../Schema/Satisfies";
4
+ import type { Core, Fabricated, Meta as ThisMeta } from "./Types";
4
5
  /**
5
6
  * Nothing to configure (see `Types.ts`'s `Meta`), so `adapt` is this kind's
6
- * only builder method — an external library that spells "undefined" differently
7
+ * only mapping method — an external library that spells "undefined" differently
7
8
  * still needs a way to say so.
8
9
  */
9
10
  export interface Schema<$Adaptations extends Adaptations = {}> extends Core<ThisMeta, $Adaptations> {
11
+ /**
12
+ * Check that this schema's fabricated value type is assignable to `$Target`.
13
+ * Identity at runtime; the target is not carried into later chained calls —
14
+ * see `object/Schema.ts`'s `satisfies`.
15
+ */
16
+ satisfies<$Target>(this: this & SatisfiesThis<Fabricated, $Target>): Schema<$Adaptations>;
10
17
  /**
11
18
  * Override what this schema maps to in one or more external schema libraries
12
19
  * — see `string/Schema.ts`'s `adapt` for the full contract.
@@ -0,0 +1,84 @@
1
+ import type { NaiveFabricator } from "../Fabricator/Types";
2
+ import type { Buildable, Produces } from "../Types";
3
+ import type { ValueOf } from "./Types";
4
+ /**
5
+ * The `this`-parameter constraint every kind's `.satisfies<$Target>()`
6
+ * intersects onto the receiver, so a mismatch names both sides on the call that
7
+ * failed — including a nested `T.object({ product: inner.satisfies<P>() })`,
8
+ * where the error lands on `inner` rather than the outer object.
9
+ *
10
+ * `$Produced` is each kind's own `Fabricated<…>` (or `Resolved<…>` for `derive`
11
+ * / `object.compute`, which have no `Fabricated` alias). A shared
12
+ * `ValueOf<this>` form errors in the same place but reports `"schema produces":
13
+ * any`, which is why each kind still names its own produced type. The check is
14
+ * wrapped in a 1-tuple so it does not distribute over unions: a bare `$Produced
15
+ * extends $Target ? unknown : Error` on `"x" | null` becomes `unknown | Error`,
16
+ * which is `unknown`, and `T.nullable(…).satisfies<string>()` would pass. Other
17
+ * signatures that were considered, and why they are not this:
18
+ *
19
+ * - A rest tuple `...check: D extends T ? [] : [error]` errors in the right place
20
+ * but says "Expected 1 arguments, but got 0".
21
+ * - A return type `D extends T ? this : Error` is silent when the result is
22
+ * unused, which is the typical `schema.satisfies<T>()` statement.
23
+ *
24
+ * The target is not carried forward: the method is typed as returning the
25
+ * kind's `Schema`, not a type that remembers `$Target`, so a later `.extend`
26
+ * that changes a field's type is not re-checked. Put `.satisfies` last to check
27
+ * the final shape. Carrying `$Target` on every `Schema` interface would add a
28
+ * type parameter to all 25 kinds, and `.as`'s contravariant parameter check is
29
+ * where a variance shift on those interfaces surfaces — `Types.ts`'s `ValueOf`
30
+ * note records that same check breaking from a constraint on `$Schema`. The
31
+ * return is `Schema`, not polymorphic `this`, because `T.date.past` /
32
+ * `T.number.integer` / `T.symbol` are `Schema & { whereby, … }` and a `this`
33
+ * return is not assignable into those extra members — same as `.as()`.
34
+ */
35
+ export type SatisfiesThis<$Produced, $Target> = [$Produced] extends [$Target] ? unknown : {
36
+ "schema produces": $Produced;
37
+ "but target requires": $Target;
38
+ };
39
+ /**
40
+ * Shared `.satisfies()` body — identity at runtime. A regular function so
41
+ * `this` is the schema it was called on; an arrow would capture the module
42
+ * scope. Distinct from the standalone {@link satisfies} because the two
43
+ * signatures cannot share a name: this one is a method (`this`, return the
44
+ * receiver); that one is a statement (`buildable`, `void`).
45
+ */
46
+ export declare function schemaSatisfies<$Receiver>(this: $Receiver): $Receiver;
47
+ /**
48
+ * Whether `$Buildable` (a Schema or a built Fabricator) fabricates a value
49
+ * assignable to `$Target`. Resolves to `true` or to an object naming both
50
+ * sides, so asserting it (`true satisfies SatisfiedBy<…>`, or a local `type
51
+ * Expect<_ extends true> = true` as the test suites use) fails with a readable
52
+ * message rather than a bare `false`.
53
+ *
54
+ * Target first, so it reads as the sentence it asserts: `SatisfiedBy<Product,
55
+ * typeof schema>` — `Product` is satisfied by the schema. Swapping the
56
+ * parameters would name the opposite relationship.
57
+ *
58
+ * Assignable-to, not exact equality: extra fields pass. `T.optional` does not
59
+ * satisfy `note?: string` under `exactOptionalPropertyTypes` — it produces
60
+ * `note?: string | undefined` (present, present-as-`undefined`, or omitted).
61
+ * `T.omittable` produces `note?: string` and does.
62
+ */
63
+ export type SatisfiedBy<$Target, $Buildable> = ValueOf<$Buildable> extends $Target ? true : {
64
+ produces: ValueOf<$Buildable>;
65
+ required: $Target;
66
+ };
67
+ /**
68
+ * Assert that `buildable` fabricates a value assignable to `$Target`. A
69
+ * statement, and a no-op at runtime — for a built Fabricator (which has no
70
+ * schema methods) and for a Schema the caller does not want to edit.
71
+ *
72
+ * `fabricate?: never` on the Schema arm is required. A built Fabricator has no
73
+ * `[Produces]`, and a type that lacks an optional property still matches `{
74
+ * readonly [Produces]?: $Target }` — the same trap `ValueOf` documents at
75
+ * `Types.ts`. Without the exclusion, a non-conforming Fabricator would pass the
76
+ * Schema arm unchecked. Ordered overloads do not replace this: overload
77
+ * resolution falls through a failing overload onto the next one, so a
78
+ * Fabricator rejected by `NaiveFabricator<$Target>` would still be accepted by
79
+ * the Schema arm.
80
+ */
81
+ export declare function satisfies<$Target>(buildable: NaiveFabricator<$Target> | (Buildable & {
82
+ fabricate?: never;
83
+ readonly [Produces]?: $Target;
84
+ })): void;
@@ -1,4 +1,5 @@
1
1
  import type { Adaptations } from "../Adapter/Types";
2
+ import type { NaiveFabricator } from "../Fabricator/Types";
2
3
  import type { Kind as SchemaKind } from "../Primitive";
3
4
  import type { Adaptation, Kind, Meta, Produces } from "../Types";
4
5
  import type { PlainObject } from "../Utility/Types";
@@ -26,6 +27,21 @@ export type AnySchema = {
26
27
  * (never assigned at runtime — see `DeepMerge`'s handling of optional-only keys
27
28
  * for why that matters).
28
29
  *
30
+ * A built Fabricator carries no `[Produces]` — its value type lives on
31
+ * `fabricate: () => $T` (`Fabricator/Types.ts`) — yet `toSchema` lets one stand
32
+ * anywhere a Schema is expected: an `array` element, an `object` field, a
33
+ * `tuple` slot, a `record` key or value, a wrapper's inner schema. So the
34
+ * `NaiveFabricator` branch comes **first**, reading `$T` straight off
35
+ * `fabricate`, and the `[Produces]` branch handles only what is left. That
36
+ * order is load-bearing: a conditional matching an _optional_ property still
37
+ * succeeds against a type that lacks it entirely (the same behavior
38
+ * `AdaptationsOf` has to work around in `Adapter/Types.ts`), so a Fabricator
39
+ * tested against `[Produces]` first matches, indexes a property it never had,
40
+ * and collapses to `unknown` — `T.array(built)` silently becoming `unknown[]`.
41
+ * `$Bindings` is not threaded into a Fabricator: it is already built, so any
42
+ * `self` inside it was resolved when it was. `Fabrication.types.test.ts`'s
43
+ * `NestedFabricatorAssertions` pin this.
44
+ *
29
45
  * `$Bindings` is threaded down into every composite kind's children (each
30
46
  * `Core` is an `interface` carrying an optional `bindings`, and forwards
31
47
  * `NonNullable<this["bindings"]>` into its own `[Produces]`). It is a
@@ -56,7 +72,7 @@ export type AnySchema = {
56
72
  * deliberately omits it), and that shifts variance enough to break `.as`'s
57
73
  * contravariant parameter check in `Fabrication.types.test.ts`.
58
74
  */
59
- export type ValueOf<$Schema, $Bindings extends unknown[] = []> = $Schema extends {
75
+ export type ValueOf<$Schema, $Bindings extends unknown[] = []> = $Schema extends NaiveFabricator<infer $T> ? $T : $Schema extends {
60
76
  readonly [Produces]?: unknown;
61
77
  } ? Required<$Schema & {
62
78
  bindings: $Bindings;
@@ -149,6 +149,15 @@ export type { Fabrication } from "./Fabricator/Types";
149
149
  * Schema before it's built into a Fabricator.
150
150
  */
151
151
  export type { ValueOf } from "./Schema/Types";
152
+ /**
153
+ * Check that a Schema or built Fabricator produces a value assignable to a
154
+ * supplied type — `.satisfies<T>()` on every kind's Schema is the main form;
155
+ * this function covers a built Fabricator (no schema methods) and a Schema the
156
+ * caller does not want to edit. `SatisfiedBy` is the type-only equivalent. See
157
+ * `Schema/Satisfies.ts`.
158
+ */
159
+ export { satisfies } from "./Schema/Satisfies";
160
+ export type { SatisfiedBy } from "./Schema/Satisfies";
152
161
  /**
153
162
  * `fabricator.trace`'s type — otherwise unnameable by a caller wanting to hold
154
163
  * onto one, the same reason `Stream` is exported above.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghostry/fabricator",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "license": "MIT",
5
5
  "description": "Fabricate typed data from composable schemas.",
6
6
  "keywords": [