@fougere/schema 0.2.0-alpha.1 → 0.3.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EntityDeclarations.d.ts +22 -0
- package/dist/EntityDeclarations.d.ts.map +1 -0
- package/dist/EntityDeclarations.js +19 -0
- package/dist/EntityDeclarations.js.map +1 -0
- package/dist/Field.d.ts +21 -0
- package/dist/Field.d.ts.map +1 -0
- package/dist/Field.js +50 -0
- package/dist/Field.js.map +1 -0
- package/dist/Schema.d.ts +67 -0
- package/dist/Schema.d.ts.map +1 -0
- package/dist/Schema.js +152 -0
- package/dist/Schema.js.map +1 -0
- package/dist/SchemaView.d.ts +18 -0
- package/dist/SchemaView.d.ts.map +1 -0
- package/dist/SchemaView.js +2 -0
- package/dist/SchemaView.js.map +1 -0
- package/dist/axis/Axis.d.ts +10 -0
- package/dist/axis/Axis.d.ts.map +1 -0
- package/dist/axis/Axis.js +9 -0
- package/dist/axis/Axis.js.map +1 -0
- package/dist/axis/Meta.d.ts +4 -0
- package/dist/axis/Meta.d.ts.map +1 -0
- package/dist/axis/Meta.js +2 -0
- package/dist/axis/Meta.js.map +1 -0
- package/dist/axis/boundary/Boundaries.d.ts +20 -0
- package/dist/axis/boundary/Boundaries.d.ts.map +1 -0
- package/dist/axis/boundary/Boundaries.js +31 -0
- package/dist/axis/boundary/Boundaries.js.map +1 -0
- package/dist/axis/boundary/Boundary.d.ts +26 -0
- package/dist/axis/boundary/Boundary.d.ts.map +1 -0
- package/dist/axis/boundary/Boundary.js +53 -0
- package/dist/axis/boundary/Boundary.js.map +1 -0
- package/dist/axis/boundary/axis.d.ts +4 -0
- package/dist/axis/boundary/axis.d.ts.map +1 -0
- package/dist/axis/boundary/axis.js +29 -0
- package/dist/axis/boundary/axis.js.map +1 -0
- package/dist/axis/lifecycle/Generators.d.ts +4 -0
- package/dist/axis/lifecycle/Generators.d.ts.map +1 -0
- package/dist/axis/lifecycle/Generators.js +8 -0
- package/dist/axis/lifecycle/Generators.js.map +1 -0
- package/dist/axis/lifecycle/Lifecycle.d.ts +28 -0
- package/dist/axis/lifecycle/Lifecycle.d.ts.map +1 -0
- package/dist/axis/lifecycle/Lifecycle.js +38 -0
- package/dist/axis/lifecycle/Lifecycle.js.map +1 -0
- package/dist/axis/lifecycle/apply.d.ts +8 -0
- package/dist/axis/lifecycle/apply.d.ts.map +1 -0
- package/dist/axis/lifecycle/apply.js +72 -0
- package/dist/axis/lifecycle/apply.js.map +1 -0
- package/dist/axis/lifecycle/axis.d.ts +4 -0
- package/dist/axis/lifecycle/axis.d.ts.map +1 -0
- package/dist/axis/lifecycle/axis.js +46 -0
- package/dist/axis/lifecycle/axis.js.map +1 -0
- package/dist/axis/role/Relation.d.ts +10 -0
- package/dist/axis/role/Relation.d.ts.map +1 -0
- package/dist/axis/role/Relation.js +6 -0
- package/dist/axis/role/Relation.js.map +1 -0
- package/dist/axis/role/Role.d.ts +38 -0
- package/dist/axis/role/Role.d.ts.map +1 -0
- package/dist/axis/role/Role.js +50 -0
- package/dist/axis/role/Role.js.map +1 -0
- package/dist/axis/role/axis.d.ts +5 -0
- package/dist/axis/role/axis.d.ts.map +1 -0
- package/dist/axis/role/axis.js +101 -0
- package/dist/axis/role/axis.js.map +1 -0
- package/dist/axis/shape/Formats.d.ts +8 -0
- package/dist/axis/shape/Formats.d.ts.map +1 -0
- package/dist/axis/shape/Formats.js +10 -0
- package/dist/axis/shape/Formats.js.map +1 -0
- package/dist/axis/shape/Shape.d.ts +58 -0
- package/dist/axis/shape/Shape.d.ts.map +1 -0
- package/dist/axis/shape/Shape.js +52 -0
- package/dist/axis/shape/Shape.js.map +1 -0
- package/dist/card/Descriptor.d.ts +55 -0
- package/dist/card/Descriptor.d.ts.map +1 -0
- package/dist/card/Descriptor.js +2 -0
- package/dist/card/Descriptor.js.map +1 -0
- package/dist/card/describe.d.ts +12 -0
- package/dist/card/describe.d.ts.map +1 -0
- package/dist/card/describe.js +83 -0
- package/dist/card/describe.js.map +1 -0
- package/dist/card/diff.d.ts +140 -0
- package/dist/card/diff.d.ts.map +1 -0
- package/dist/card/diff.js +123 -0
- package/dist/card/diff.js.map +1 -0
- package/dist/card/reconstruct.d.ts +11 -0
- package/dist/card/reconstruct.d.ts.map +1 -0
- package/dist/card/reconstruct.js +83 -0
- package/dist/card/reconstruct.js.map +1 -0
- package/dist/card/typescript.d.ts +17 -0
- package/dist/card/typescript.d.ts.map +1 -0
- package/dist/card/typescript.js +93 -0
- package/dist/card/typescript.js.map +1 -0
- package/dist/clean.d.ts +2 -0
- package/dist/clean.d.ts.map +1 -0
- package/dist/{projections/card.js → clean.js} +1 -2
- package/dist/clean.js.map +1 -0
- package/dist/constraint/FieldGroup.d.ts +21 -0
- package/dist/constraint/FieldGroup.d.ts.map +1 -0
- package/dist/constraint/FieldGroup.js +65 -0
- package/dist/constraint/FieldGroup.js.map +1 -0
- package/dist/constraint/Unique.d.ts +4 -0
- package/dist/constraint/Unique.d.ts.map +1 -0
- package/dist/constraint/Unique.js +4 -0
- package/dist/constraint/Unique.js.map +1 -0
- package/dist/entity.d.ts +4 -116
- package/dist/entity.d.ts.map +1 -1
- package/dist/entity.js +13 -289
- package/dist/entity.js.map +1 -1
- package/dist/index.d.ts +35 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -26
- package/dist/index.js.map +1 -1
- package/dist/judge/Judge.d.ts +14 -0
- package/dist/judge/Judge.d.ts.map +1 -0
- package/dist/judge/Judge.js +161 -0
- package/dist/judge/Judge.js.map +1 -0
- package/dist/judge/cases.d.ts +50 -0
- package/dist/judge/cases.d.ts.map +1 -0
- package/dist/judge/cases.js +100 -0
- package/dist/judge/cases.js.map +1 -0
- package/dist/judge/form.d.ts +11 -0
- package/dist/judge/form.d.ts.map +1 -0
- package/dist/judge/form.js +18 -0
- package/dist/judge/form.js.map +1 -0
- package/dist/judge/options.d.ts +4 -0
- package/dist/judge/options.d.ts.map +1 -0
- package/dist/judge/options.js +2 -0
- package/dist/judge/options.js.map +1 -0
- package/dist/judge/result.d.ts +17 -0
- package/dist/judge/result.d.ts.map +1 -0
- package/dist/judge/result.js +2 -0
- package/dist/judge/result.js.map +1 -0
- package/dist/name.d.ts +1 -14
- package/dist/name.d.ts.map +1 -1
- package/dist/name.js +3 -14
- package/dist/name.js.map +1 -1
- package/dist/projection/encode.d.ts +3 -0
- package/dist/projection/encode.d.ts.map +1 -0
- package/dist/projection/encode.js +19 -0
- package/dist/projection/encode.js.map +1 -0
- package/dist/projection/io.d.ts +4 -0
- package/dist/projection/io.d.ts.map +1 -0
- package/dist/projection/io.js +29 -0
- package/dist/projection/io.js.map +1 -0
- package/dist/projection/source.d.ts +7 -0
- package/dist/projection/source.d.ts.map +1 -0
- package/dist/projection/source.js +11 -0
- package/dist/projection/source.js.map +1 -0
- package/dist/{projections → projection}/standard.d.ts +0 -8
- package/dist/projection/standard.d.ts.map +1 -0
- package/dist/projection/standard.js +2 -0
- package/dist/projection/standard.js.map +1 -0
- package/dist/same.d.ts +6 -0
- package/dist/same.d.ts.map +1 -0
- package/dist/same.js +35 -0
- package/dist/same.js.map +1 -0
- package/dist/vocabulary/bool.d.ts +1 -1
- package/dist/vocabulary/bool.d.ts.map +1 -1
- package/dist/vocabulary/bool.js +2 -2
- package/dist/vocabulary/bool.js.map +1 -1
- package/dist/vocabulary/created.d.ts +2 -12
- package/dist/vocabulary/created.d.ts.map +1 -1
- package/dist/vocabulary/created.js +3 -14
- package/dist/vocabulary/created.js.map +1 -1
- package/dist/vocabulary/date.d.ts +1 -1
- package/dist/vocabulary/date.d.ts.map +1 -1
- package/dist/vocabulary/date.js +2 -2
- package/dist/vocabulary/date.js.map +1 -1
- package/dist/vocabulary/email.d.ts +1 -2
- package/dist/vocabulary/email.d.ts.map +1 -1
- package/dist/vocabulary/email.js +0 -1
- package/dist/vocabulary/email.js.map +1 -1
- package/dist/vocabulary/immutable.d.ts +2 -8
- package/dist/vocabulary/immutable.d.ts.map +1 -1
- package/dist/vocabulary/immutable.js +4 -10
- package/dist/vocabulary/immutable.js.map +1 -1
- package/dist/vocabulary/indexed.d.ts +2 -18
- package/dist/vocabulary/indexed.d.ts.map +1 -1
- package/dist/vocabulary/indexed.js +2 -20
- package/dist/vocabulary/indexed.js.map +1 -1
- package/dist/vocabulary/json.d.ts +3 -16
- package/dist/vocabulary/json.d.ts.map +1 -1
- package/dist/vocabulary/json.js +12 -9
- package/dist/vocabulary/json.js.map +1 -1
- package/dist/vocabulary/list.d.ts +2 -16
- package/dist/vocabulary/list.d.ts.map +1 -1
- package/dist/vocabulary/list.js +3 -15
- package/dist/vocabulary/list.js.map +1 -1
- package/dist/vocabulary/many.d.ts +2 -6
- package/dist/vocabulary/many.d.ts.map +1 -1
- package/dist/vocabulary/many.js +4 -7
- package/dist/vocabulary/many.js.map +1 -1
- package/dist/vocabulary/nullable.d.ts +2 -8
- package/dist/vocabulary/nullable.d.ts.map +1 -1
- package/dist/vocabulary/nullable.js +5 -12
- package/dist/vocabulary/nullable.js.map +1 -1
- package/dist/vocabulary/number.d.ts +1 -1
- package/dist/vocabulary/number.d.ts.map +1 -1
- package/dist/vocabulary/number.js +2 -2
- package/dist/vocabulary/number.js.map +1 -1
- package/dist/vocabulary/oneOf.d.ts +1 -8
- package/dist/vocabulary/oneOf.d.ts.map +1 -1
- package/dist/vocabulary/oneOf.js +2 -2
- package/dist/vocabulary/oneOf.js.map +1 -1
- package/dist/vocabulary/optional.d.ts +2 -9
- package/dist/vocabulary/optional.d.ts.map +1 -1
- package/dist/vocabulary/optional.js +6 -14
- package/dist/vocabulary/optional.js.map +1 -1
- package/dist/vocabulary/primary.d.ts +4 -17
- package/dist/vocabulary/primary.d.ts.map +1 -1
- package/dist/vocabulary/primary.js +10 -13
- package/dist/vocabulary/primary.js.map +1 -1
- package/dist/vocabulary/readOnly.d.ts +2 -9
- package/dist/vocabulary/readOnly.d.ts.map +1 -1
- package/dist/vocabulary/readOnly.js +5 -11
- package/dist/vocabulary/readOnly.js.map +1 -1
- package/dist/vocabulary/ref.d.ts +2 -7
- package/dist/vocabulary/ref.d.ts.map +1 -1
- package/dist/vocabulary/ref.js +3 -8
- package/dist/vocabulary/ref.js.map +1 -1
- package/dist/vocabulary/text.d.ts +2 -2
- package/dist/vocabulary/text.d.ts.map +1 -1
- package/dist/vocabulary/text.js +2 -2
- package/dist/vocabulary/text.js.map +1 -1
- package/dist/vocabulary/unique.d.ts +2 -22
- package/dist/vocabulary/unique.d.ts.map +1 -1
- package/dist/vocabulary/unique.js +5 -24
- package/dist/vocabulary/unique.js.map +1 -1
- package/dist/vocabulary/updated.d.ts +2 -7
- package/dist/vocabulary/updated.d.ts.map +1 -1
- package/dist/vocabulary/updated.js +1 -7
- package/dist/vocabulary/updated.js.map +1 -1
- package/dist/vocabulary/url.d.ts +1 -2
- package/dist/vocabulary/url.d.ts.map +1 -1
- package/dist/vocabulary/url.js +0 -1
- package/dist/vocabulary/url.js.map +1 -1
- package/dist/vocabulary/vocabulary.d.ts +5 -0
- package/dist/vocabulary/vocabulary.d.ts.map +1 -0
- package/dist/vocabulary/vocabulary.js +31 -0
- package/dist/vocabulary/vocabulary.js.map +1 -0
- package/dist/vocabulary/writeOnly.d.ts +2 -8
- package/dist/vocabulary/writeOnly.d.ts.map +1 -1
- package/dist/vocabulary/writeOnly.js +5 -10
- package/dist/vocabulary/writeOnly.js.map +1 -1
- package/package.json +2 -2
- package/dist/field/boundary.d.ts +0 -86
- package/dist/field/boundary.d.ts.map +0 -1
- package/dist/field/boundary.js +0 -94
- package/dist/field/boundary.js.map +0 -1
- package/dist/field/field.d.ts +0 -64
- package/dist/field/field.d.ts.map +0 -1
- package/dist/field/field.js +0 -28
- package/dist/field/field.js.map +0 -1
- package/dist/field/index.d.ts +0 -7
- package/dist/field/index.d.ts.map +0 -1
- package/dist/field/index.js +0 -9
- package/dist/field/index.js.map +0 -1
- package/dist/field/lifecycle.d.ts +0 -40
- package/dist/field/lifecycle.d.ts.map +0 -1
- package/dist/field/lifecycle.js +0 -27
- package/dist/field/lifecycle.js.map +0 -1
- package/dist/field/meta.d.ts +0 -9
- package/dist/field/meta.d.ts.map +0 -1
- package/dist/field/meta.js +0 -7
- package/dist/field/meta.js.map +0 -1
- package/dist/field/role.d.ts +0 -54
- package/dist/field/role.d.ts.map +0 -1
- package/dist/field/role.js +0 -55
- package/dist/field/role.js.map +0 -1
- package/dist/field/shape.d.ts +0 -77
- package/dist/field/shape.d.ts.map +0 -1
- package/dist/field/shape.js +0 -49
- package/dist/field/shape.js.map +0 -1
- package/dist/hints.d.ts +0 -33
- package/dist/hints.d.ts.map +0 -1
- package/dist/hints.js +0 -2
- package/dist/hints.js.map +0 -1
- package/dist/projections/card.d.ts +0 -117
- package/dist/projections/card.d.ts.map +0 -1
- package/dist/projections/card.js.map +0 -1
- package/dist/projections/describe.d.ts +0 -25
- package/dist/projections/describe.d.ts.map +0 -1
- package/dist/projections/describe.js +0 -136
- package/dist/projections/describe.js.map +0 -1
- package/dist/projections/encode.d.ts +0 -11
- package/dist/projections/encode.d.ts.map +0 -1
- package/dist/projections/encode.js +0 -26
- package/dist/projections/encode.js.map +0 -1
- package/dist/projections/io.d.ts +0 -30
- package/dist/projections/io.d.ts.map +0 -1
- package/dist/projections/io.js +0 -52
- package/dist/projections/io.js.map +0 -1
- package/dist/projections/lifecycle.d.ts +0 -43
- package/dist/projections/lifecycle.d.ts.map +0 -1
- package/dist/projections/lifecycle.js +0 -115
- package/dist/projections/lifecycle.js.map +0 -1
- package/dist/projections/reconstruct.d.ts +0 -36
- package/dist/projections/reconstruct.d.ts.map +0 -1
- package/dist/projections/reconstruct.js +0 -149
- package/dist/projections/reconstruct.js.map +0 -1
- package/dist/projections/source.d.ts +0 -41
- package/dist/projections/source.d.ts.map +0 -1
- package/dist/projections/source.js +0 -37
- package/dist/projections/source.js.map +0 -1
- package/dist/projections/standard.d.ts.map +0 -1
- package/dist/projections/standard.js +0 -10
- package/dist/projections/standard.js.map +0 -1
- package/dist/projections/typescript.d.ts +0 -53
- package/dist/projections/typescript.d.ts.map +0 -1
- package/dist/projections/typescript.js +0 -184
- package/dist/projections/typescript.js.map +0 -1
- package/dist/projections/validation.d.ts +0 -57
- package/dist/projections/validation.d.ts.map +0 -1
- package/dist/projections/validation.js +0 -148
- package/dist/projections/validation.js.map +0 -1
- package/dist/unique.d.ts +0 -65
- package/dist/unique.d.ts.map +0 -1
- package/dist/unique.js +0 -80
- package/dist/unique.js.map +0 -1
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { type Field, type Fields } from '../field/index.js';
|
|
2
|
-
import { type SchemaConstructor, type SchemaViewInfer } from '../entity.js';
|
|
3
|
-
import { type SchemaBundle, type SchemaDescriptor } from './card.js';
|
|
4
|
-
/**
|
|
5
|
-
* The field map a stated row shape implies.
|
|
6
|
-
*
|
|
7
|
-
* Every member is marked auto-at-creation, so `CtorInput` asks for nothing: a card
|
|
8
|
-
* describes rows as they are READ, and "what a caller must supply at creation" is a
|
|
9
|
-
* different question — one `required` answers, and one a synced consumer never asks,
|
|
10
|
-
* since it calls the host rather than constructing.
|
|
11
|
-
*/
|
|
12
|
-
type FieldsOf<T> = {
|
|
13
|
-
[K in keyof T]-?: Field<T[K], true>;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Read a lone card back into a working schema — THE single reconstructor. The result
|
|
17
|
-
* carries its `~standard` (live validation) rebuilt locally: the descriptor crosses
|
|
18
|
-
* the wire as data, the behaviour is reconstituted here. Relations stay name stand-ins
|
|
19
|
-
* (no set to resolve against — use {@link reconstructSet} for live targets).
|
|
20
|
-
*
|
|
21
|
-
* `T` states the shape of a row, and that is what makes a rebuilt schema a CLASS rather
|
|
22
|
-
* than a type and a value declared side by side: `class Post extends reconstruct<{…}>(card) {}`
|
|
23
|
-
* is one declaration carrying both, exactly like `class Post extends entity({…}) {}`.
|
|
24
|
-
* Without it the instance type is an index signature, so a synced entity validated
|
|
25
|
-
* perfectly and taught the compiler nothing — `post.titel` compiled.
|
|
26
|
-
*/
|
|
27
|
-
export declare function reconstruct<T = SchemaViewInfer<Fields>>(descriptor: SchemaDescriptor): SchemaConstructor<FieldsOf<T>>;
|
|
28
|
-
/**
|
|
29
|
-
* Read a whole bundle back into live schemas, keyed by name — THE set reconstructor.
|
|
30
|
-
* Every entity is rebuilt against a shared `$defs` resolver, so a relation's `to()`
|
|
31
|
-
* hands back the real reconstructed target (feeds adapters), not a name stand-in.
|
|
32
|
-
* Targets absent from the set (external/cross-frond `$ref`) keep the stand-in.
|
|
33
|
-
*/
|
|
34
|
-
export declare function reconstructSet(bundle: SchemaBundle): Record<string, SchemaConstructor<Fields>>;
|
|
35
|
-
export {};
|
|
36
|
-
//# sourceMappingURL=reconstruct.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reconstruct.d.ts","sourceRoot":"","sources":["../../src/projections/reconstruct.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,KAAK,EACV,KAAK,MAAM,EAGZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAA2B,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACrG,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAC;AAsHnB;;;;;;;GAOG;AACH,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;CAAE,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,EACrD,UAAU,EAAE,gBAAgB,GAC3B,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAEhC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAc9F"}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { createField, } from '../field/index.js';
|
|
2
|
-
import { createSchemaConstructor } from '../entity.js';
|
|
3
|
-
import { clean, } from './card.js';
|
|
4
|
-
// ─── reconstruct — card → schema (the single reconstructor) ────────
|
|
5
|
-
/**
|
|
6
|
-
* Read a JSON Schema property back into a Fougère shape. The `type` travels
|
|
7
|
-
* VERBATIM — nullability is the `[T,'null']` union on both sides, so there is
|
|
8
|
-
* nothing to split; only the keyword subset of the base type is picked.
|
|
9
|
-
*/
|
|
10
|
-
function reconstructShape(prop) {
|
|
11
|
-
const types = Array.isArray(prop.type) ? prop.type : prop.type ? [prop.type] : [];
|
|
12
|
-
const base = types.find((t) => t !== 'null');
|
|
13
|
-
if (base === undefined)
|
|
14
|
-
return undefined;
|
|
15
|
-
const type = prop.type;
|
|
16
|
-
// `array` is two distinct things: with `items` it is a value list (a real shape);
|
|
17
|
-
// without, it is a bare `many` relation marker — no shape, the role carries it.
|
|
18
|
-
if (base === 'array') {
|
|
19
|
-
if (!prop.items)
|
|
20
|
-
return undefined;
|
|
21
|
-
const items = reconstructShape(prop.items);
|
|
22
|
-
return clean({ type, items, minItems: prop.minItems, maxItems: prop.maxItems });
|
|
23
|
-
}
|
|
24
|
-
switch (base) {
|
|
25
|
-
case 'string':
|
|
26
|
-
return clean({ type, minLength: prop.minLength, maxLength: prop.maxLength, pattern: prop.pattern, enum: prop.enum, format: prop.format });
|
|
27
|
-
case 'number':
|
|
28
|
-
case 'integer':
|
|
29
|
-
return clean({ type, minimum: prop.minimum, maximum: prop.maximum });
|
|
30
|
-
case 'boolean':
|
|
31
|
-
return { type };
|
|
32
|
-
default: // 'object' or anything unrecognised → opaque value (nesting travels verbatim)
|
|
33
|
-
return clean({ type, properties: prop.properties, required: prop.required });
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function reconstructRole(role, resolve) {
|
|
37
|
-
const out = {};
|
|
38
|
-
if (role.primary)
|
|
39
|
-
out.primary = true;
|
|
40
|
-
// Members arrive spelled out and stay that way — a single-member group read back as the
|
|
41
|
-
// empty self-reference would re-describe identically but lose the distinction for no
|
|
42
|
-
// gain. `uniqueMembers` treats a named group as already resolved.
|
|
43
|
-
if (role.unique?.length)
|
|
44
|
-
out.unique = role.unique.map((group) => [...group]);
|
|
45
|
-
if (role.index)
|
|
46
|
-
out.index = true;
|
|
47
|
-
if (role.relation) {
|
|
48
|
-
const name = role.relation.to;
|
|
49
|
-
out.relation = {
|
|
50
|
-
// `to` is the `$ref` (a name). With a resolver (a bundle), it hands back the real
|
|
51
|
-
// reconstructed target — adapters can read its fields. Lazy, so circular relations
|
|
52
|
-
// resolve fine. Without one (a lone card), a name-only stand-in: enough to validate
|
|
53
|
-
// (`kind`) and re-describe identically, but not to feed an adapter.
|
|
54
|
-
to: () => resolve?.(name) ?? { name },
|
|
55
|
-
kind: role.relation.kind,
|
|
56
|
-
...(role.relation.onDelete ? { onDelete: role.relation.onDelete } : {}),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return out;
|
|
60
|
-
}
|
|
61
|
-
function reconstructField(prop, resolve) {
|
|
62
|
-
const ext = prop['x-fougere'];
|
|
63
|
-
return createField({
|
|
64
|
-
shape: reconstructShape(prop),
|
|
65
|
-
role: ext?.role ? reconstructRole(ext.role, resolve) : undefined,
|
|
66
|
-
// The normal forms are pure JSON — they travelled verbatim, they read back verbatim.
|
|
67
|
-
lifecycle: ext?.lifecycle,
|
|
68
|
-
boundary: ext?.boundary,
|
|
69
|
-
meta: prop.description !== undefined ? { description: prop.description } : undefined,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* The entity-level groups implied by the fields — the inverse of
|
|
74
|
-
* `projectUniqueOntoFields`. Only groups of more than one member: a lone `unique(slug)`
|
|
75
|
-
* is fully stated by the field's own role, and listing it here would make `getUnique()`
|
|
76
|
-
* answer a composite the author never declared.
|
|
77
|
-
*/
|
|
78
|
-
function compositeFromFields(fields) {
|
|
79
|
-
const seen = new Map();
|
|
80
|
-
for (const field of Object.values(fields)) {
|
|
81
|
-
for (const group of field.role?.unique ?? []) {
|
|
82
|
-
if (group.length < 2)
|
|
83
|
-
continue;
|
|
84
|
-
// A key that cannot collide with a field name — `JSON.stringify` rather than a
|
|
85
|
-
// separator byte: a NUL in the source made every `grep` read this whole file as
|
|
86
|
-
// binary and skip it silently, a poor price for a de-duplication key.
|
|
87
|
-
seen.set(JSON.stringify(group), [...group]);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return seen.size ? [...seen.values()] : undefined;
|
|
91
|
-
}
|
|
92
|
-
/** Build a live schema from a card; `resolve` wires relation targets when in a bundle. */
|
|
93
|
-
function buildSchema(descriptor, resolve) {
|
|
94
|
-
const fields = {};
|
|
95
|
-
for (const [key, prop] of Object.entries(descriptor.properties)) {
|
|
96
|
-
fields[key] = reconstructField(prop, resolve);
|
|
97
|
-
}
|
|
98
|
-
// Recover the entity-level declaration from what the members carry. The card holds the
|
|
99
|
-
// fact once per member; a group of two arrives twice, so the set is de-duplicated —
|
|
100
|
-
// `getUnique()` then answers what the original author wrote, and the DDL on this side
|
|
101
|
-
// emits the same constraint as the DDL on the other.
|
|
102
|
-
const schema = createSchemaConstructor(fields, undefined, undefined, {}, compositeFromFields(fields));
|
|
103
|
-
// The name is the identity everything downstream keys on — the registration key, the
|
|
104
|
-
// table, the GraphQL type, what a relation's `to` points at. `describe` writes it as
|
|
105
|
-
// `title`; dropping it here left a rebuilt schema called `Schema`, so a card could not
|
|
106
|
-
// round-trip and an adapter standing on one had no entity name to work from.
|
|
107
|
-
// `reconstructSet` still overrides with the bundle key, which is the more specific truth.
|
|
108
|
-
if (descriptor.title) {
|
|
109
|
-
Object.defineProperty(schema, 'name', { value: descriptor.title, configurable: true });
|
|
110
|
-
}
|
|
111
|
-
return schema;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Read a lone card back into a working schema — THE single reconstructor. The result
|
|
115
|
-
* carries its `~standard` (live validation) rebuilt locally: the descriptor crosses
|
|
116
|
-
* the wire as data, the behaviour is reconstituted here. Relations stay name stand-ins
|
|
117
|
-
* (no set to resolve against — use {@link reconstructSet} for live targets).
|
|
118
|
-
*
|
|
119
|
-
* `T` states the shape of a row, and that is what makes a rebuilt schema a CLASS rather
|
|
120
|
-
* than a type and a value declared side by side: `class Post extends reconstruct<{…}>(card) {}`
|
|
121
|
-
* is one declaration carrying both, exactly like `class Post extends entity({…}) {}`.
|
|
122
|
-
* Without it the instance type is an index signature, so a synced entity validated
|
|
123
|
-
* perfectly and taught the compiler nothing — `post.titel` compiled.
|
|
124
|
-
*/
|
|
125
|
-
export function reconstruct(descriptor) {
|
|
126
|
-
return buildSchema(descriptor);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Read a whole bundle back into live schemas, keyed by name — THE set reconstructor.
|
|
130
|
-
* Every entity is rebuilt against a shared `$defs` resolver, so a relation's `to()`
|
|
131
|
-
* hands back the real reconstructed target (feeds adapters), not a name stand-in.
|
|
132
|
-
* Targets absent from the set (external/cross-frond `$ref`) keep the stand-in.
|
|
133
|
-
*/
|
|
134
|
-
export function reconstructSet(bundle) {
|
|
135
|
-
const map = {};
|
|
136
|
-
const resolve = (name) => map[name.toLowerCase()];
|
|
137
|
-
const out = {};
|
|
138
|
-
for (const [name, descriptor] of Object.entries(bundle.$defs)) {
|
|
139
|
-
const schema = buildSchema(descriptor, resolve);
|
|
140
|
-
// Name the rebuilt class after its key so re-describing it yields the same `to` name
|
|
141
|
-
// (describe reads `relation.to().name`). Lazy `to` means the map need only be full
|
|
142
|
-
// before any `.to()` call — true once this loop ends.
|
|
143
|
-
Object.defineProperty(schema, 'name', { value: name, configurable: true });
|
|
144
|
-
map[name.toLowerCase()] = schema;
|
|
145
|
-
out[name] = schema;
|
|
146
|
-
}
|
|
147
|
-
return out;
|
|
148
|
-
}
|
|
149
|
-
//# sourceMappingURL=reconstruct.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reconstruct.js","sourceRoot":"","sources":["../../src/projections/reconstruct.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Fields, SchemaLike } from '../field/index.js';
|
|
2
|
-
import type { SchemaDescriptor } from './card.js';
|
|
3
|
-
/**
|
|
4
|
-
* The two forms a schema reaches an adapter in — and the single reader that takes both.
|
|
5
|
-
*
|
|
6
|
-
* An adapter has never needed the class, only its fields. In-process it gets the class
|
|
7
|
-
* because the class is there; from a remote or foreign frond it gets the card, because a
|
|
8
|
-
* class does not cross a wire. Naming that union here is what lets one projection serve
|
|
9
|
-
* both, instead of each adapter growing its own branch.
|
|
10
|
-
*
|
|
11
|
-
* The card was built for exactly this and had no in-repo reader: every adapter called
|
|
12
|
-
* `getFields()` on the live class, so writing a Fougere adapter meant being inside the
|
|
13
|
-
* repo, in TypeScript, with the class in hand.
|
|
14
|
-
*/
|
|
15
|
-
export type SchemaSource = SchemaLike | SchemaDescriptor;
|
|
16
|
-
/**
|
|
17
|
-
* Normalize a source to a live schema — reconstructing a card, passing a class through.
|
|
18
|
-
*
|
|
19
|
-
* This is what an adapter reaching for the schema MORE THAN ONCE should call, once, at its
|
|
20
|
-
* boundary: `reconstruct` runs per call (6.5 µs for a 17-field entity), so a component that
|
|
21
|
-
* reads fields in two places would otherwise rebuild the schema twice and hold two
|
|
22
|
-
* unrelated field objects. Normalize at the edge, then nothing downstream knows the
|
|
23
|
-
* difference — which is the point.
|
|
24
|
-
*/
|
|
25
|
-
export declare function schemaOf(source: SchemaSource): SchemaLike;
|
|
26
|
-
/**
|
|
27
|
-
* The fields an adapter projects from, whichever form it was handed — {@link schemaOf}
|
|
28
|
-
* for the single-read case.
|
|
29
|
-
*
|
|
30
|
-
* Cost: nothing for a class. For a card, one `reconstruct` — measured at 6.5 µs for a
|
|
31
|
-
* 17-field entity, paid once per entity when the adapter builds, never per request. Read
|
|
32
|
-
* twice and you pay twice: hold the result, or normalize with `schemaOf` instead.
|
|
33
|
-
*/
|
|
34
|
-
export declare function fieldsOf(source: SchemaSource): Fields;
|
|
35
|
-
/**
|
|
36
|
-
* The composite unique groups, whichever form. A bare wrapper (a view mid-derivation)
|
|
37
|
-
* carries no `getUnique` and answers `undefined`; a card's groups are recovered from what
|
|
38
|
-
* its members carry, so `reconstruct` has already restored them by the time this reads.
|
|
39
|
-
*/
|
|
40
|
-
export declare function uniqueOf(source: SchemaSource): ReadonlyArray<ReadonlyArray<string>> | undefined;
|
|
41
|
-
//# sourceMappingURL=source.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/projections/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAOzD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAErD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAE/F"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { reconstruct } from './reconstruct.js';
|
|
2
|
-
/** A card is the plain document — no behaviour, so no `getFields`. */
|
|
3
|
-
function isDescriptor(source) {
|
|
4
|
-
return typeof source.getFields !== 'function';
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Normalize a source to a live schema — reconstructing a card, passing a class through.
|
|
8
|
-
*
|
|
9
|
-
* This is what an adapter reaching for the schema MORE THAN ONCE should call, once, at its
|
|
10
|
-
* boundary: `reconstruct` runs per call (6.5 µs for a 17-field entity), so a component that
|
|
11
|
-
* reads fields in two places would otherwise rebuild the schema twice and hold two
|
|
12
|
-
* unrelated field objects. Normalize at the edge, then nothing downstream knows the
|
|
13
|
-
* difference — which is the point.
|
|
14
|
-
*/
|
|
15
|
-
export function schemaOf(source) {
|
|
16
|
-
return isDescriptor(source) ? reconstruct(source) : source;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* The fields an adapter projects from, whichever form it was handed — {@link schemaOf}
|
|
20
|
-
* for the single-read case.
|
|
21
|
-
*
|
|
22
|
-
* Cost: nothing for a class. For a card, one `reconstruct` — measured at 6.5 µs for a
|
|
23
|
-
* 17-field entity, paid once per entity when the adapter builds, never per request. Read
|
|
24
|
-
* twice and you pay twice: hold the result, or normalize with `schemaOf` instead.
|
|
25
|
-
*/
|
|
26
|
-
export function fieldsOf(source) {
|
|
27
|
-
return schemaOf(source).getFields();
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* The composite unique groups, whichever form. A bare wrapper (a view mid-derivation)
|
|
31
|
-
* carries no `getUnique` and answers `undefined`; a card's groups are recovered from what
|
|
32
|
-
* its members carry, so `reconstruct` has already restored them by the time this reads.
|
|
33
|
-
*/
|
|
34
|
-
export function uniqueOf(source) {
|
|
35
|
-
return schemaOf(source).getUnique?.();
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=source.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/projections/source.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAgB/C,sEAAsE;AACtE,SAAS,YAAY,CAAC,MAAoB;IACxC,OAAO,OAAQ,MAAqB,CAAC,SAAS,KAAK,UAAU,CAAC;AAChE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAoB;IAC3C,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC7D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAoB;IAC3C,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAoB;IAC3C,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"standard.d.ts","sourceRoot":"","sources":["../../src/projections/standard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;IAC/D,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CAC7D;AAED,MAAM,CAAC,OAAO,WAAW,gBAAgB,CAAC;IACxC,UAAU,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;QAC7C,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,QAAQ,EAAE,CACjB,KAAK,EAAE,OAAO,KACX,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;KACnD;IAED,KAAK,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC;IAE5D,UAAU,aAAa,CAAC,MAAM;QAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;KAC7B;IAED,UAAU,aAAa;QACrB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;KACvC;IAED,UAAU,KAAK;QACb,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,SAAS,CAAC;KACtE;IAED,UAAU,WAAW;QACnB,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;KAC3B;IAED,UAAU,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;QAC7C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB;IAED,KAAK,UAAU,CAAC,MAAM,SAAS,gBAAgB,IAAI,WAAW,CAC5D,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAC7B,CAAC,OAAO,CAAC,CAAC;IAEX,KAAK,WAAW,CAAC,MAAM,SAAS,gBAAgB,IAAI,WAAW,CAC7D,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAC7B,CAAC,QAAQ,CAAC,CAAC;CACb"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Standard Schema v1 — types inlined from @standard-schema/spec.
|
|
3
|
-
*
|
|
4
|
-
* We inline instead of depending on the package to keep @fougere/schema zero-dep.
|
|
5
|
-
* The spec is stable (v1) and unlikely to change.
|
|
6
|
-
*
|
|
7
|
-
* @see https://standardschema.dev/
|
|
8
|
-
*/
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=standard.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"standard.js","sourceRoot":"","sources":["../../src/projections/standard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { SchemaDescriptor } from './card.js';
|
|
2
|
-
export interface TypeSourceOptions {
|
|
3
|
-
/** Name of the emitted interface. Defaults to the card's `title`, capitalized. */
|
|
4
|
-
name?: string;
|
|
5
|
-
/** Emit `export` before the declaration. Default: true. */
|
|
6
|
-
exported?: boolean;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* The anonymous object type one card describes — the members, nothing around them.
|
|
10
|
-
*
|
|
11
|
-
* Every property is present: `required` on a Fougère card answers "what must a CALLER
|
|
12
|
-
* supply at creation", not "what is always there when read" — an `id` the system
|
|
13
|
-
* generates is absent from `required` and always present on a row. Typing the read
|
|
14
|
-
* shape from the create rule would make `post.id` possibly-undefined for everyone.
|
|
15
|
-
*/
|
|
16
|
-
export declare function shapeTypeOf(descriptor: SchemaDescriptor, indent?: string): string;
|
|
17
|
-
/**
|
|
18
|
-
* Emit the entity a card describes — ONE class, judge and shape together.
|
|
19
|
-
*
|
|
20
|
-
* An entity is a class here (`class Post extends entity({…}) {}`), and a class is the
|
|
21
|
-
* language's own answer to "a name that is both a value and a type". Emitting an
|
|
22
|
-
* interface next to a const said the same thing twice and relied on declaration
|
|
23
|
-
* merging to look like a class; this IS one.
|
|
24
|
-
*
|
|
25
|
-
* The card travels inline, so the rebuilt judge is exact — the shape written above it
|
|
26
|
-
* is read off that same card, never a second source to keep in step.
|
|
27
|
-
*
|
|
28
|
-
* Requires `reconstruct` in scope: the caller writes the import, since only it knows
|
|
29
|
-
* whether the consumer says `@fougere/schema` or a path.
|
|
30
|
-
*/
|
|
31
|
-
export declare function entitySourceOf(descriptor: SchemaDescriptor, options?: TypeSourceOptions): string;
|
|
32
|
-
/** One operation, as much of it as a card can say. */
|
|
33
|
-
export interface OpDescriptor {
|
|
34
|
-
name: string;
|
|
35
|
-
description?: string;
|
|
36
|
-
output?: SchemaDescriptor;
|
|
37
|
-
/** How much `output` describes. Absent means the card did not say. */
|
|
38
|
-
cardinality?: 'one' | 'maybe' | 'many' | 'page' | 'none';
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Emit the type of a façade — every operation an entity serves, as a caller meets it.
|
|
42
|
-
*
|
|
43
|
-
* This is what `Facade<T>` needs and what no consumer in another repository could have:
|
|
44
|
-
* writing `Facade<ArticleHandler>` used to require importing the handler's class, which
|
|
45
|
-
* `sync` does not carry and should not. The card carries the operations; this reads them.
|
|
46
|
-
*
|
|
47
|
-
* Each op takes an optional invocation and returns a promise — the door's signature, not
|
|
48
|
-
* the handler's. A handler's method takes positional arguments; its door takes the call.
|
|
49
|
-
*/
|
|
50
|
-
export declare function facadeTypeSourceOf(ops: readonly OpDescriptor[], options?: TypeSourceOptions & {
|
|
51
|
-
rowType?: string;
|
|
52
|
-
}): string;
|
|
53
|
-
//# sourceMappingURL=typescript.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/projections/typescript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,gBAAgB,EAAE,MAAM,WAAW,CAAC;AA0FnE,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAK,GAAG,MAAM,CAS7E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CASpG;AAmBD,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,sEAAsE;IACtE,WAAW,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAC1D;AAyBD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,YAAY,EAAE,EAC5B,OAAO,GAAE,iBAAiB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACrD,MAAM,CAYR"}
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* card → TypeScript source — the projection that was missing.
|
|
3
|
-
*
|
|
4
|
-
* `describe` turns a schema into a card and `reconstruct` turns it back into a
|
|
5
|
-
* living judge, so a consumer in another repository validates by the host's rules
|
|
6
|
-
* without holding its code. What it did NOT get is a type: left to infer, a rebuilt
|
|
7
|
-
* schema has an index signature for an instance type, so `post.title` was `any` and
|
|
8
|
-
* `post.titel` compiled. The declaration travelled and the compiler learned nothing.
|
|
9
|
-
*
|
|
10
|
-
* So the card gets a third reader, and it writes the shape where `reconstruct` now
|
|
11
|
-
* accepts it — as the type argument of the class's own base expression, one
|
|
12
|
-
* declaration for the judge and the rows it judges. Same input as the other two
|
|
13
|
-
* readers, same rule: the shape IS JSON Schema, and JSON Schema has a type form.
|
|
14
|
-
*
|
|
15
|
-
* Deliberately NOT a JSON Schema→TS library: the input is not arbitrary JSON Schema,
|
|
16
|
-
* it is a Fougère card, whose vocabulary is closed (`describe` writes it). A general
|
|
17
|
-
* library would carry `$ref`, `allOf`, tuple `items`, `additionalProperties` and the
|
|
18
|
-
* rest of a spec we never emit, and would still need this file to know that
|
|
19
|
-
* `format: date-time` means `Date` here — a fact about our boundary, not about JSON.
|
|
20
|
-
*/
|
|
21
|
-
/** What a field's value looks like once `reconstruct` has decoded it. */
|
|
22
|
-
function typeOf(field) {
|
|
23
|
-
const types = Array.isArray(field.type) ? field.type : field.type ? [field.type] : [];
|
|
24
|
-
const nullable = types.includes('null');
|
|
25
|
-
const base = types.find((t) => t !== 'null');
|
|
26
|
-
const inner = baseTypeOf(base, field);
|
|
27
|
-
return nullable ? `${inner} | null` : inner;
|
|
28
|
-
}
|
|
29
|
-
function baseTypeOf(base, field) {
|
|
30
|
-
// A bounded value set IS a type — the enum travels, so the union does too.
|
|
31
|
-
if (field.enum?.length) {
|
|
32
|
-
return field.enum.map((v) => (v === null ? 'null' : JSON.stringify(v))).join(' | ');
|
|
33
|
-
}
|
|
34
|
-
switch (base) {
|
|
35
|
-
case 'string':
|
|
36
|
-
// `date-time` is the wire form of a value the boundary decodes to a Date, and
|
|
37
|
-
// the façade now hands the decoded value on. The type says what you receive.
|
|
38
|
-
return field.format === 'date-time' ? 'Date' : 'string';
|
|
39
|
-
case 'number':
|
|
40
|
-
case 'integer':
|
|
41
|
-
return 'number';
|
|
42
|
-
case 'boolean':
|
|
43
|
-
return 'boolean';
|
|
44
|
-
case 'array':
|
|
45
|
-
// Two distinct things share `array`: a value list carries `items`, a bare `many`
|
|
46
|
-
// relation carries none — the ids of the other side, which the card names as a
|
|
47
|
-
// relation rather than a shape.
|
|
48
|
-
return field.items ? `${typeOf(field.items)}[]` : 'string[]';
|
|
49
|
-
case 'object':
|
|
50
|
-
return field.properties ? objectTypeOf(field.properties, field.required ?? []) : 'Record<string, unknown>';
|
|
51
|
-
default:
|
|
52
|
-
return 'unknown';
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function objectTypeOf(properties, required) {
|
|
56
|
-
const members = Object.entries(properties).map(([name, field]) => {
|
|
57
|
-
const optional = required.includes(name) ? '' : '?';
|
|
58
|
-
return `${propertyKey(name)}${optional}: ${typeOf(field)}`;
|
|
59
|
-
});
|
|
60
|
-
return `{ ${members.join('; ')} }`;
|
|
61
|
-
}
|
|
62
|
-
/** Quote a key only when it is not a plain identifier — generated source stays readable. */
|
|
63
|
-
function propertyKey(name) {
|
|
64
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* A description lands INSIDE a comment, and a card can come from a stranger.
|
|
68
|
-
*
|
|
69
|
-
* `identifierOf` already refuses a name for this reason — a name stops being data when it
|
|
70
|
-
* lands in a declaration. So does a description: `*\/` ends the comment, and everything
|
|
71
|
-
* after it is source. A card carrying `*\/ } console.log(…); interface X {` produced a file
|
|
72
|
-
* that compiled with zero diagnostics and emitted a top-level statement, which `fougere
|
|
73
|
-
* sync` then wrote into the consumer's repository for its next import to run.
|
|
74
|
-
*
|
|
75
|
-
* Escaped rather than refused, unlike a name: a description is prose, and prose contains
|
|
76
|
-
* `*\/` legitimately (a sentence about a comment, a regex). `*\/` renders the same to a
|
|
77
|
-
* reader and terminates nothing, so the text survives and the exit does not.
|
|
78
|
-
*/
|
|
79
|
-
function docCommentOf(text, indent) {
|
|
80
|
-
if (!text)
|
|
81
|
-
return '';
|
|
82
|
-
return `${indent}/** ${text.replace(/\*\//g, '*\\/')} */\n`;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* The anonymous object type one card describes — the members, nothing around them.
|
|
86
|
-
*
|
|
87
|
-
* Every property is present: `required` on a Fougère card answers "what must a CALLER
|
|
88
|
-
* supply at creation", not "what is always there when read" — an `id` the system
|
|
89
|
-
* generates is absent from `required` and always present on a row. Typing the read
|
|
90
|
-
* shape from the create rule would make `post.id` possibly-undefined for everyone.
|
|
91
|
-
*/
|
|
92
|
-
export function shapeTypeOf(descriptor, indent = '') {
|
|
93
|
-
const entries = Object.entries(descriptor.properties ?? {});
|
|
94
|
-
if (entries.length === 0)
|
|
95
|
-
return '{}';
|
|
96
|
-
const lines = entries.map(([key, field]) => {
|
|
97
|
-
const doc = docCommentOf(field.description, `${indent} `);
|
|
98
|
-
return `${doc}${indent} ${propertyKey(key)}: ${typeOf(field)};`;
|
|
99
|
-
});
|
|
100
|
-
return `{\n${lines.join('\n')}\n${indent}}`;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Emit the entity a card describes — ONE class, judge and shape together.
|
|
104
|
-
*
|
|
105
|
-
* An entity is a class here (`class Post extends entity({…}) {}`), and a class is the
|
|
106
|
-
* language's own answer to "a name that is both a value and a type". Emitting an
|
|
107
|
-
* interface next to a const said the same thing twice and relied on declaration
|
|
108
|
-
* merging to look like a class; this IS one.
|
|
109
|
-
*
|
|
110
|
-
* The card travels inline, so the rebuilt judge is exact — the shape written above it
|
|
111
|
-
* is read off that same card, never a second source to keep in step.
|
|
112
|
-
*
|
|
113
|
-
* Requires `reconstruct` in scope: the caller writes the import, since only it knows
|
|
114
|
-
* whether the consumer says `@fougere/schema` or a path.
|
|
115
|
-
*/
|
|
116
|
-
export function entitySourceOf(descriptor, options = {}) {
|
|
117
|
-
const name = identifierOf(options.name ?? capitalize(descriptor.title ?? 'Schema'));
|
|
118
|
-
const exported = options.exported === false ? '' : 'export ';
|
|
119
|
-
const card = JSON.stringify(descriptor, null, 2)
|
|
120
|
-
.split('\n')
|
|
121
|
-
.map((line, i) => (i === 0 ? line : ` ${line}`))
|
|
122
|
-
.join('\n');
|
|
123
|
-
return `${exported}class ${name} extends reconstruct<${shapeTypeOf(descriptor)}>(${card}) {}`;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* A card names itself, and a card can come from a stranger. Everything else here emits
|
|
127
|
-
* data — a string lands inside `JSON.stringify` — but a name lands in a DECLARATION,
|
|
128
|
-
* so it is the one value that could stop being data. Refuse it here as well as at the
|
|
129
|
-
* caller: the projection should not depend on who calls it to be safe.
|
|
130
|
-
*/
|
|
131
|
-
function identifierOf(name) {
|
|
132
|
-
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) {
|
|
133
|
-
throw new Error(`'${name}' is not a TypeScript identifier — it cannot name a generated declaration`);
|
|
134
|
-
}
|
|
135
|
-
return name;
|
|
136
|
-
}
|
|
137
|
-
function capitalize(s) {
|
|
138
|
-
return s ? s[0].toUpperCase() + s.slice(1) : s;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* What one operation hands back, in TypeScript.
|
|
142
|
-
*
|
|
143
|
-
* `output` is the shape of a ROW; `cardinality` is how many rows. Separating them is
|
|
144
|
-
* what makes this honest — `list` returns a page, not an array, and a generator that
|
|
145
|
-
* assumed otherwise would have written a signature that compiles and lies.
|
|
146
|
-
*
|
|
147
|
-
* A page is spelled as what it IS: `ListResult<T> extends Array<T>`, an array carrying
|
|
148
|
-
* its own totals. So the type is the array intersected with them, not a wrapper.
|
|
149
|
-
*/
|
|
150
|
-
function returnTypeOf(op, rowType) {
|
|
151
|
-
switch (op.cardinality) {
|
|
152
|
-
case 'many': return `${rowType}[]`;
|
|
153
|
-
case 'page': return `${rowType}[] & { total?: number; endCursor?: string; hasMore?: boolean }`;
|
|
154
|
-
case 'maybe': return `${rowType} | undefined`;
|
|
155
|
-
case 'one': return rowType;
|
|
156
|
-
// `none` says there is no shaped output — a boolean, a void. Saying `unknown` is
|
|
157
|
-
// the truth; guessing `void` would forbid reading a value that does come back.
|
|
158
|
-
case 'none': return 'unknown';
|
|
159
|
-
default: return 'unknown';
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Emit the type of a façade — every operation an entity serves, as a caller meets it.
|
|
164
|
-
*
|
|
165
|
-
* This is what `Facade<T>` needs and what no consumer in another repository could have:
|
|
166
|
-
* writing `Facade<ArticleHandler>` used to require importing the handler's class, which
|
|
167
|
-
* `sync` does not carry and should not. The card carries the operations; this reads them.
|
|
168
|
-
*
|
|
169
|
-
* Each op takes an optional invocation and returns a promise — the door's signature, not
|
|
170
|
-
* the handler's. A handler's method takes positional arguments; its door takes the call.
|
|
171
|
-
*/
|
|
172
|
-
export function facadeTypeSourceOf(ops, options = {}) {
|
|
173
|
-
const name = options.name ?? 'Facade';
|
|
174
|
-
const exported = options.exported === false ? '' : 'export ';
|
|
175
|
-
const rowType = options.rowType ?? 'unknown';
|
|
176
|
-
const members = ops.map((op) => {
|
|
177
|
-
const doc = docCommentOf(op.description, ' ');
|
|
178
|
-
return `${doc} ${propertyKey(op.name)}(invocation?: Invocation): Promise<${returnTypeOf(op, rowType)}>;`;
|
|
179
|
-
});
|
|
180
|
-
if (members.length === 0)
|
|
181
|
-
return `${exported}interface ${name} {}`;
|
|
182
|
-
return `${exported}interface ${name} {\n${members.join('\n')}\n}`;
|
|
183
|
-
}
|
|
184
|
-
//# sourceMappingURL=typescript.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../src/projections/typescript.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { AnyField, Fields } from '../field/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Validation — the Field metadata IS the source of truth.
|
|
4
|
-
*
|
|
5
|
-
* Validation is a projection of one axis: `shape` (the value), a PURE predicate —
|
|
6
|
-
* it answers "is this value valid?" and never mutates the value. Null included:
|
|
7
|
-
* the shape's `[T,'null']` union is judged by the engine, there is no hand-rolled
|
|
8
|
-
* null branch. It never looks at `role` (persistence/domain) — a foreign key is
|
|
9
|
-
* just a string here. Converting a valid value (e.g. an ISO string → a `Date`)
|
|
10
|
-
* is a separate step, the `boundary` axis, applied after the predicate passes.
|
|
11
|
-
* Absence is judged by `lifecycle.create` — any create rule makes it legal and
|
|
12
|
-
* the field is OMITTED from the result, never filled: realising the rule
|
|
13
|
-
* (stamp 'now', apply { value }, generate) belongs to the storage adapter at
|
|
14
|
-
* the point of persistence, whose insert returns the complete row.
|
|
15
|
-
*/
|
|
16
|
-
export interface ValidationError {
|
|
17
|
-
path: string;
|
|
18
|
-
message: string;
|
|
19
|
-
}
|
|
20
|
-
export type ValidationResult<T> = {
|
|
21
|
-
success: true;
|
|
22
|
-
data: T;
|
|
23
|
-
} | {
|
|
24
|
-
success: false;
|
|
25
|
-
errors: ValidationError[];
|
|
26
|
-
};
|
|
27
|
-
export type Checked = {
|
|
28
|
-
value: unknown;
|
|
29
|
-
} | {
|
|
30
|
-
error: string;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Validate a present value (null included) against its field — pure, never mutates.
|
|
34
|
-
*
|
|
35
|
-
* Reads `shape` and nothing else, so it answers "is this a legal value?" without ever
|
|
36
|
-
* asking who is speaking. That is what makes it usable on the way OUT of the domain,
|
|
37
|
-
* where the client-only axes (`boundary`, `lifecycle`) do not apply.
|
|
38
|
-
*/
|
|
39
|
-
export declare function checkValue(field: AnyField, value: unknown): Checked;
|
|
40
|
-
export interface ValidateOptions {
|
|
41
|
-
/**
|
|
42
|
-
* Patch mode (update). An absent field is OMITTED from the result — not filled,
|
|
43
|
-
* not required — so `validate({ name })` touches only `name`. Set by `partial()`.
|
|
44
|
-
* Distinguishes "absent → don't touch" (patch) from "absent → null" (create).
|
|
45
|
-
*/
|
|
46
|
-
patch?: boolean;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* A path is a field NAME here, never a dotted trail: `json(Entity)` is judged as one
|
|
50
|
-
* opaque shape by the engine, so a nested failure answers `{ path: 'addr' }` with the
|
|
51
|
-
* inner field in the prose. This used to take a `pathPrefix` that every call site passed
|
|
52
|
-
* as `''` — a parameter for a recursion nobody wrote, which made the code read as if
|
|
53
|
-
* nesting were handled. Writing that recursion changes what `FougereError.details`
|
|
54
|
-
* carries across processes and languages, so it is a contract decision, not a patch.
|
|
55
|
-
*/
|
|
56
|
-
export declare function validateFields(fields: Fields, input: unknown, opts?: ValidateOptions): ValidationResult<Record<string, unknown>>;
|
|
57
|
-
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/projections/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAS,MAAM,mBAAmB,CAAC;AAIjE;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAC1B;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAmB7D;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAgCnE;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,IAAI,GAAE,eAAoB,GACzB,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8E3C"}
|