@assemora/schema 0.1.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.
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Universal design controls (SPEC.md §61).
3
+ *
4
+ * Every block gets the same seven settings — spacing, width, alignment, background,
5
+ * visibility, responsive visibility and container width — and gets them without its
6
+ * author declaring anything. What a block does with its *own* fields stays the block
7
+ * author's business (SPEC.md §61: "Visual specifics stay in developer-defined
8
+ * blocks").
9
+ *
10
+ * Every value is a token, never CSS. That is the point: a person picks `lg`, an agent
11
+ * writes `lg`, and what `lg` means is decided once by the theme (SPEC.md §62). Nothing
12
+ * here can express a colour, a pixel or a rule, so nothing here can be used to smuggle
13
+ * a stylesheet into a page.
14
+ *
15
+ * The settings live beside `props` on the node rather than inside it, because `props`
16
+ * belongs to the block's own schema and a framework key in there would collide with a
17
+ * field somebody declared.
18
+ */
19
+ import { type ObjectSchema } from './composites-bridge.js';
20
+ import { type OptionalSchema } from './types.js';
21
+ export declare const SPACING_SCALE: readonly ['none', 'xs', 'sm', 'md', 'lg', 'xl', '2xl'];
22
+ export declare const BLOCK_WIDTHS: readonly ['narrow', 'normal', 'wide', 'full'];
23
+ export declare const BLOCK_ALIGNMENTS: readonly ['start', 'center', 'end'];
24
+ export declare const CONTAINER_WIDTHS: readonly ['narrow', 'normal', 'wide', 'full'];
25
+ export declare const VIEWPORTS: readonly ['mobile', 'tablet', 'desktop'];
26
+ /**
27
+ * The corner radii a theme has to define (SPEC.md §62).
28
+ *
29
+ * No control of §61 names one yet, so this scale exists here rather than in
30
+ * `@assemora/theme` for the reason the others do: the scale a theme defines and the
31
+ * scale a block would one day choose from must be one list, or they drift the moment
32
+ * somebody adds a control. `none` and `full` are the two ends that carry meaning on
33
+ * their own — a square corner and a pill — and three steps between them are enough
34
+ * for a token system that is not a CSS editor.
35
+ */
36
+ export declare const RADIUS_SCALE: readonly ['none', 'sm', 'md', 'lg', 'full'];
37
+ export type SpacingScale = (typeof SPACING_SCALE)[number];
38
+ export type RadiusScale = (typeof RADIUS_SCALE)[number];
39
+ export type BlockWidth = (typeof BLOCK_WIDTHS)[number];
40
+ export type BlockAlignment = (typeof BLOCK_ALIGNMENTS)[number];
41
+ export type ContainerWidth = (typeof CONTAINER_WIDTHS)[number];
42
+ export type Viewport = (typeof VIEWPORTS)[number];
43
+ export type BlockDesign = {
44
+ readonly spacingTop?: SpacingScale;
45
+ readonly spacingBottom?: SpacingScale;
46
+ readonly width?: BlockWidth;
47
+ readonly align?: BlockAlignment;
48
+ /** A theme colour token, by name. Never a colour (SPEC.md §62). */
49
+ readonly background?: string;
50
+ /** A media id, for a background image. */
51
+ readonly backgroundImage?: string;
52
+ readonly container?: ContainerWidth;
53
+ /** Where this block is *not* drawn. Responsive visibility (SPEC.md §61). */
54
+ readonly hiddenOn?: readonly Viewport[];
55
+ };
56
+ declare const designShape: {
57
+ spacingTop: OptionalSchema<"2xl" | "lg" | "md" | "none" | "sm" | "xl" | "xs">;
58
+ spacingBottom: OptionalSchema<"2xl" | "lg" | "md" | "none" | "sm" | "xl" | "xs">;
59
+ width: OptionalSchema<"full" | "narrow" | "normal" | "wide">;
60
+ align: OptionalSchema<"center" | "end" | "start">;
61
+ background: OptionalSchema<string>;
62
+ backgroundImage: OptionalSchema<string>;
63
+ container: OptionalSchema<"full" | "narrow" | "normal" | "wide">;
64
+ hiddenOn: OptionalSchema<("desktop" | "mobile" | "tablet")[]>;
65
+ };
66
+ /** The parser behind {@link BlockDesign}. `*.test-d.ts` proves the two agree. */
67
+ export declare const blockDesign: () => ObjectSchema<typeof designShape>;
68
+ declare const patchShape: {
69
+ spacingTop: OptionalSchema<"2xl" | "lg" | "md" | "none" | "sm" | "xl" | "xs" | null>;
70
+ spacingBottom: OptionalSchema<"2xl" | "lg" | "md" | "none" | "sm" | "xl" | "xs" | null>;
71
+ width: OptionalSchema<"full" | "narrow" | "normal" | "wide" | null>;
72
+ align: OptionalSchema<"center" | "end" | "start" | null>;
73
+ background: OptionalSchema<string | null>;
74
+ backgroundImage: OptionalSchema<string | null>;
75
+ container: OptionalSchema<"full" | "narrow" | "normal" | "wide" | null>;
76
+ hiddenOn: OptionalSchema<("desktop" | "mobile" | "tablet")[] | null>;
77
+ };
78
+ /**
79
+ * What `blocks.design` accepts: the controls that changed, and nothing else.
80
+ *
81
+ * Every key is optional, and every one of them accepts `null` — see {@link clearable}.
82
+ */
83
+ export type BlockDesignPatch = {
84
+ readonly [K in keyof BlockDesign]?: BlockDesign[K] | null;
85
+ };
86
+ export declare const blockDesignPatch: () => ObjectSchema<typeof patchShape>;
87
+ /** Nothing set. What a block that has never been touched by the controls carries. */
88
+ export declare const isPlainDesign: (design: BlockDesign | undefined) => boolean;
89
+ /** True when this block should not be drawn on that viewport (SPEC.md §61). */
90
+ export declare const hiddenOnViewport: (design: BlockDesign | undefined, viewport: Viewport) => boolean;
91
+ export {};
92
+ //# sourceMappingURL=design.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../src/design.ts"],"names":[],"mappings":"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"}
package/dist/design.js ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Universal design controls (SPEC.md §61).
3
+ *
4
+ * Every block gets the same seven settings — spacing, width, alignment, background,
5
+ * visibility, responsive visibility and container width — and gets them without its
6
+ * author declaring anything. What a block does with its *own* fields stays the block
7
+ * author's business (SPEC.md §61: "Visual specifics stay in developer-defined
8
+ * blocks").
9
+ *
10
+ * Every value is a token, never CSS. That is the point: a person picks `lg`, an agent
11
+ * writes `lg`, and what `lg` means is decided once by the theme (SPEC.md §62). Nothing
12
+ * here can express a colour, a pixel or a rule, so nothing here can be used to smuggle
13
+ * a stylesheet into a page.
14
+ *
15
+ * The settings live beside `props` on the node rather than inside it, because `props`
16
+ * belongs to the block's own schema and a framework key in there would collide with a
17
+ * field somebody declared.
18
+ */
19
+ import { array, enumOf, object, string } from './composites-bridge.js';
20
+ import { ok } from './types.js';
21
+ export const SPACING_SCALE = ['none', 'xs', 'sm', 'md', 'lg', 'xl', '2xl'];
22
+ export const BLOCK_WIDTHS = ['narrow', 'normal', 'wide', 'full'];
23
+ export const BLOCK_ALIGNMENTS = ['start', 'center', 'end'];
24
+ export const CONTAINER_WIDTHS = ['narrow', 'normal', 'wide', 'full'];
25
+ export const VIEWPORTS = ['mobile', 'tablet', 'desktop'];
26
+ /**
27
+ * The corner radii a theme has to define (SPEC.md §62).
28
+ *
29
+ * No control of §61 names one yet, so this scale exists here rather than in
30
+ * `@assemora/theme` for the reason the others do: the scale a theme defines and the
31
+ * scale a block would one day choose from must be one list, or they drift the moment
32
+ * somebody adds a control. `none` and `full` are the two ends that carry meaning on
33
+ * their own — a square corner and a pill — and three steps between them are enough
34
+ * for a token system that is not a CSS editor.
35
+ */
36
+ export const RADIUS_SCALE = ['none', 'sm', 'md', 'lg', 'full'];
37
+ /**
38
+ * A background token names a theme entry, so it is spelled like one: letters, digits
39
+ * and dashes. `#ff0000` and `red; position: fixed` are both refused.
40
+ */
41
+ const TOKEN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
42
+ const designShape = {
43
+ spacingTop: enumOf(...SPACING_SCALE).optional(),
44
+ spacingBottom: enumOf(...SPACING_SCALE).optional(),
45
+ width: enumOf(...BLOCK_WIDTHS).optional(),
46
+ align: enumOf(...BLOCK_ALIGNMENTS).optional(),
47
+ background: string().pattern(TOKEN, 'Expected a theme token').optional(),
48
+ backgroundImage: string().optional(),
49
+ container: enumOf(...CONTAINER_WIDTHS).optional(),
50
+ hiddenOn: array(enumOf(...VIEWPORTS)).optional(),
51
+ };
52
+ /** The parser behind {@link BlockDesign}. `*.test-d.ts` proves the two agree. */
53
+ export const blockDesign = () => object(designShape);
54
+ /**
55
+ * A control may be absent, or explicitly `null`.
56
+ *
57
+ * They are different answers: absent means "leave this control alone", and `null`
58
+ * means "clear it and let the theme decide again". A properties panel needs both, and
59
+ * only one of them can be expressed by omission.
60
+ */
61
+ const clearable = (inner) => ({
62
+ kind: inner.kind,
63
+ isOptional: true,
64
+ isNullable: true,
65
+ description: inner.description,
66
+ parse: (value) => value === undefined || value === null
67
+ ? ok(value)
68
+ : inner.parse(value),
69
+ toJsonSchema: () => ({ ...inner.toJsonSchema(), nullable: true }),
70
+ });
71
+ const patchShape = {
72
+ spacingTop: clearable(enumOf(...SPACING_SCALE)),
73
+ spacingBottom: clearable(enumOf(...SPACING_SCALE)),
74
+ width: clearable(enumOf(...BLOCK_WIDTHS)),
75
+ align: clearable(enumOf(...BLOCK_ALIGNMENTS)),
76
+ background: clearable(string().pattern(TOKEN, 'Expected a theme token')),
77
+ backgroundImage: clearable(string()),
78
+ container: clearable(enumOf(...CONTAINER_WIDTHS)),
79
+ hiddenOn: clearable(array(enumOf(...VIEWPORTS))),
80
+ };
81
+ export const blockDesignPatch = () => object(patchShape);
82
+ /** Nothing set. What a block that has never been touched by the controls carries. */
83
+ export const isPlainDesign = (design) => design === undefined || Object.values(design).every((value) => value === undefined);
84
+ /** True when this block should not be drawn on that viewport (SPEC.md §61). */
85
+ export const hiddenOnViewport = (design, viewport) => design?.hiddenOn?.includes(viewport) ?? false;
86
+ //# sourceMappingURL=design.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design.js","sourceRoot":"","sources":["../src/design.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `@assemora/schema` — the primitives every other layer is built on.
3
+ *
4
+ * A declaration made here is simultaneously a runtime parser, a compile-time type
5
+ * and a JSON description, so validation, the database, Studio, OpenAPI, the SDK and
6
+ * MCP all read one source (SPEC.md §3.4, §42).
7
+ *
8
+ * This package has no dependencies, external ones included, and never will —
9
+ * `pnpm boundaries` enforces that.
10
+ */
11
+ export { type BlockNode, type BlockTree, blockIds, blockTree, type ChangedBlock, diffTrees, emptyTree, findBlock, type TreeChange, walkBlocks, } from './blocks.js';
12
+ export { type ArraySchema, array, type ObjectSchema, object, } from './composites.js';
13
+ export { BLOCK_ALIGNMENTS, BLOCK_WIDTHS, type BlockAlignment, type BlockDesign, type BlockDesignPatch, type BlockWidth, blockDesign, blockDesignPatch, CONTAINER_WIDTHS, type ContainerWidth, hiddenOnViewport, isPlainDesign, RADIUS_SCALE, type RadiusScale, SPACING_SCALE, type SpacingScale, VIEWPORTS, type Viewport, } from './design.js';
14
+ export { changedFields, diff, type Patch } from './patch.js';
15
+ export { type BigIntSchema, type BinarySchema, type BooleanSchema, bigint, binary, boolean, type EnumSchema, email, enumOf, integer, type JsonValueSchema, json, type NumberSchema, nullable, number, optional, type StringSchema, string, type TimestampSchema, timestamp, type UnknownSchema, unknown, uuid, } from './primitives.js';
16
+ export { fail, failWith, type Infer, type InferShape, type Issue, type JsonSchema, nest, type OptionalSchema, ok, type ParseResult, type Schema, type SchemaKind, type Shape, } from './types.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,QAAQ,EACR,SAAS,EACT,KAAK,YAAY,EACjB,SAAS,EACT,SAAS,EACT,SAAS,EACT,KAAK,UAAU,EACf,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,EACL,KAAK,YAAY,EACjB,MAAM,GACP,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,cAAc,EACnB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,KAAK,WAAW,EAChB,aAAa,EACb,KAAK,YAAY,EACjB,SAAS,EACT,KAAK,QAAQ,GACd,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAA;AAC5D,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,MAAM,EACN,MAAM,EACN,OAAO,EACP,KAAK,UAAU,EACf,KAAK,EACL,MAAM,EACN,OAAO,EACP,KAAK,eAAe,EACpB,IAAI,EACJ,KAAK,YAAY,EACjB,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,KAAK,YAAY,EACjB,MAAM,EACN,KAAK,eAAe,EACpB,SAAS,EACT,KAAK,aAAa,EAClB,OAAO,EACP,IAAI,GACL,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,UAAU,EACf,IAAI,EACJ,KAAK,cAAc,EACnB,EAAE,EACF,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,KAAK,GACX,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `@assemora/schema` — the primitives every other layer is built on.
3
+ *
4
+ * A declaration made here is simultaneously a runtime parser, a compile-time type
5
+ * and a JSON description, so validation, the database, Studio, OpenAPI, the SDK and
6
+ * MCP all read one source (SPEC.md §3.4, §42).
7
+ *
8
+ * This package has no dependencies, external ones included, and never will —
9
+ * `pnpm boundaries` enforces that.
10
+ */
11
+ export { blockIds, blockTree, diffTrees, emptyTree, findBlock, walkBlocks, } from './blocks.js';
12
+ export { array, object, } from './composites.js';
13
+ export { BLOCK_ALIGNMENTS, BLOCK_WIDTHS, blockDesign, blockDesignPatch, CONTAINER_WIDTHS, hiddenOnViewport, isPlainDesign, RADIUS_SCALE, SPACING_SCALE, VIEWPORTS, } from './design.js';
14
+ export { changedFields, diff } from './patch.js';
15
+ export { bigint, binary, boolean, email, enumOf, integer, json, nullable, number, optional, string, timestamp, unknown, uuid, } from './primitives.js';
16
+ export { fail, failWith, nest, ok, } from './types.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAGL,QAAQ,EACR,SAAS,EAET,SAAS,EACT,SAAS,EACT,SAAS,EAET,UAAU,GACX,MAAM,aAAa,CAAA;AACpB,OAAO,EAEL,KAAK,EAEL,MAAM,GACP,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,gBAAgB,EAChB,YAAY,EAKZ,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAEhB,gBAAgB,EAChB,aAAa,EACb,YAAY,EAEZ,aAAa,EAEb,SAAS,GAEV,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,aAAa,EAAE,IAAI,EAAc,MAAM,YAAY,CAAA;AAC5D,OAAO,EAIL,MAAM,EACN,MAAM,EACN,OAAO,EAEP,KAAK,EACL,MAAM,EACN,OAAO,EAEP,IAAI,EAEJ,QAAQ,EACR,MAAM,EACN,QAAQ,EAER,MAAM,EAEN,SAAS,EAET,OAAO,EACP,IAAI,GACL,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,IAAI,EACJ,QAAQ,EAKR,IAAI,EAEJ,EAAE,GAKH,MAAM,YAAY,CAAA"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * What changed between two states (SPEC.md §64, §65, §75).
3
+ *
4
+ * Studio shows this, not the whole document: "spacing: xl → md" is what a person can
5
+ * act on. It lives here because three layers need it and none of them may depend on
6
+ * the others — a revision records one, a dry run builds one, and a change set stores
7
+ * one. Two implementations over the same two snapshots would eventually disagree on
8
+ * a screen that shows both (ADR-0019).
9
+ */
10
+ /** A field-level diff of two snapshots. */
11
+ export type Patch = Readonly<Record<string, {
12
+ readonly from: unknown;
13
+ readonly to: unknown;
14
+ }>>;
15
+ /** A field-level diff of two snapshots. Keys present in either side are considered. */
16
+ export declare const diff: (before: unknown, after: unknown) => Patch;
17
+ export declare const changedFields: (patch: Patch) => readonly string[];
18
+ //# sourceMappingURL=patch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC,CAAA;AAsB9F,uFAAuF;AACvF,eAAO,MAAM,IAAI,WAAY,OAAO,SAAS,OAAO,KAAG,KAgBtD,CAAA;AAED,eAAO,MAAM,aAAa,UAAW,KAAK,KAAG,SAAS,MAAM,EAAwB,CAAA"}
package/dist/patch.js ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * What changed between two states (SPEC.md §64, §65, §75).
3
+ *
4
+ * Studio shows this, not the whole document: "spacing: xl → md" is what a person can
5
+ * act on. It lives here because three layers need it and none of them may depend on
6
+ * the others — a revision records one, a dry run builds one, and a change set stores
7
+ * one. Two implementations over the same two snapshots would eventually disagree on
8
+ * a screen that shows both (ADR-0019).
9
+ */
10
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
11
+ /**
12
+ * One value out of a snapshot, read only where the snapshot has it.
13
+ *
14
+ * A snapshot is keyed by field names somebody chose (SPEC.md §37, §86), and
15
+ * `constructor`, `toString`, `valueOf` and `hasOwnProperty` are all legal ones —
16
+ * answered by `Object.prototype` on any plain object that was never given the key.
17
+ */
18
+ const own = (record, key) => Object.hasOwn(record, key) ? record[key] : undefined;
19
+ const same = (left, right) => {
20
+ if (left === right)
21
+ return true;
22
+ if (left instanceof Date && right instanceof Date)
23
+ return left.getTime() === right.getTime();
24
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
25
+ };
26
+ /** A field-level diff of two snapshots. Keys present in either side are considered. */
27
+ export const diff = (before, after) => {
28
+ const from = isRecord(before) ? before : {};
29
+ const to = isRecord(after) ? after : {};
30
+ const patch = {};
31
+ for (const key of new Set([...Object.keys(from), ...Object.keys(to)])) {
32
+ // Own keys only. A key is an own key of *one* side here, not of both, so the other
33
+ // side answers it from `Object.prototype` — a field called `constructor` that was
34
+ // cleared read as having changed to a function.
35
+ const was = own(from, key);
36
+ const is = own(to, key);
37
+ if (!same(was, is))
38
+ patch[key] = { from: was, to: is };
39
+ }
40
+ return patch;
41
+ };
42
+ export const changedFields = (patch) => Object.keys(patch);
43
+ //# sourceMappingURL=patch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAEtE;;;;;;GAMG;AACH,MAAM,GAAG,GAAG,CAAC,MAAyC,EAAE,GAAW,EAAW,EAAE,CAC9E,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAEtD,MAAM,IAAI,GAAG,CAAC,IAAa,EAAE,KAAc,EAAW,EAAE;IACtD,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAA;IAC/B,IAAI,IAAI,YAAY,IAAI,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,CAAA;IAE5F,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAA;AACvE,CAAC,CAAA;AAED,uFAAuF;AACvF,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,MAAe,EAAE,KAAc,EAAS,EAAE;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3C,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IACvC,MAAM,KAAK,GAAmD,EAAE,CAAA;IAEhE,KAAK,MAAM,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,mFAAmF;QACnF,kFAAkF;QAClF,gDAAgD;QAChD,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC1B,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QAEvB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAA;IACxD,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAY,EAAqB,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA"}
@@ -0,0 +1,85 @@
1
+ import { type Infer, type OptionalSchema, type Schema } from './types.js';
2
+ /**
3
+ * The two modifiers, as combinators, for a schema whose builder is out of reach.
4
+ *
5
+ * `string().optional()` is how a *declaration* says it. These are how a caller holding
6
+ * a `Schema<T>` says the same thing — and by the time a schema crosses a package
7
+ * boundary that is all it is: `@assemora/resources` builds a group's shape out of the
8
+ * schemas its fields carry, and those arrive already erased to the interface. Without
9
+ * these the only way to make one of them absent-able is to rebuild the wrapper object
10
+ * by hand in every package that needs one, which is how the meaning of "optional"
11
+ * comes to differ between two of them.
12
+ */
13
+ export declare const optional: <T>(inner: Schema<T>) => OptionalSchema<T>;
14
+ export declare const nullable: <T>(inner: Schema<T>) => Schema<T | null>;
15
+ export type StringSchema = Schema<string> & {
16
+ min(length: number): StringSchema;
17
+ max(length: number): StringSchema;
18
+ pattern(expression: RegExp, message?: string): StringSchema;
19
+ email(): StringSchema;
20
+ uuid(): StringSchema;
21
+ describe(text: string): StringSchema;
22
+ optional(): OptionalSchema<string>;
23
+ nullable(): Schema<string | null>;
24
+ };
25
+ export declare const string: () => StringSchema;
26
+ /** A UUID string. Shorthand for `string().uuid()`, which reads better in a model. */
27
+ export declare const uuid: () => StringSchema;
28
+ /** An email address. Shorthand for `string().email()`. */
29
+ export declare const email: () => StringSchema;
30
+ export type NumberSchema = Schema<number> & {
31
+ min(value: number): NumberSchema;
32
+ max(value: number): NumberSchema;
33
+ integer(): NumberSchema;
34
+ describe(text: string): NumberSchema;
35
+ optional(): OptionalSchema<number>;
36
+ nullable(): Schema<number | null>;
37
+ };
38
+ export declare const number: () => NumberSchema;
39
+ export declare const integer: () => NumberSchema;
40
+ export type BooleanSchema = Schema<boolean> & {
41
+ describe(text: string): BooleanSchema;
42
+ optional(): OptionalSchema<boolean>;
43
+ nullable(): Schema<boolean | null>;
44
+ };
45
+ export declare const boolean: () => BooleanSchema;
46
+ export type EnumSchema<T extends string> = Schema<T> & {
47
+ readonly values: readonly T[];
48
+ describe(text: string): EnumSchema<T>;
49
+ optional(): OptionalSchema<T>;
50
+ nullable(): Schema<T | null>;
51
+ };
52
+ /** `enumOf('draft', 'published')` infers the literal union, not `string`. */
53
+ export declare const enumOf: <const V extends readonly [string, ...string[]]>(...values: V) => EnumSchema<V[number]>;
54
+ export type TimestampSchema = Schema<Date> & {
55
+ describe(text: string): TimestampSchema;
56
+ optional(): OptionalSchema<Date>;
57
+ nullable(): Schema<Date | null>;
58
+ };
59
+ export declare const timestamp: () => TimestampSchema;
60
+ export type JsonValueSchema<T> = Schema<T> & {
61
+ describe(text: string): JsonValueSchema<T>;
62
+ optional(): OptionalSchema<T>;
63
+ nullable(): Schema<T | null>;
64
+ };
65
+ /** An opaque JSON payload whose shape the caller declares: `json<UserSettings>()`. */
66
+ export declare const json: <T = unknown>() => JsonValueSchema<T>;
67
+ export type UnknownSchema = Schema<unknown> & {
68
+ describe(text: string): UnknownSchema;
69
+ optional(): OptionalSchema<unknown>;
70
+ };
71
+ export declare const unknown: () => UnknownSchema;
72
+ export type BigIntSchema = Schema<bigint> & {
73
+ describe(text: string): BigIntSchema;
74
+ optional(): OptionalSchema<bigint>;
75
+ nullable(): Schema<bigint | null>;
76
+ };
77
+ export declare const bigint: () => BigIntSchema;
78
+ export type BinarySchema = Schema<Uint8Array> & {
79
+ describe(text: string): BinarySchema;
80
+ optional(): OptionalSchema<Uint8Array>;
81
+ nullable(): Schema<Uint8Array | null>;
82
+ };
83
+ export declare const binary: () => BinarySchema;
84
+ export type { Infer };
85
+ //# sourceMappingURL=primitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"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"}