@atolljs/core 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +27 -22
- package/dist/contract/listSchema.d.ts +4 -4
- package/dist/contract/reef.d.ts +377 -0
- package/dist/contract/sharedMemory.d.ts +13 -13
- package/dist/contract/zod.d.ts +263 -34
- package/dist/index.d.ts +1 -2
- package/dist/index.js +14 -15
- package/dist/index10.js +185 -14
- package/dist/index11.js +47 -188
- package/dist/index12.js +59 -45
- package/dist/index13.js +19 -58
- package/dist/index14.js +60 -24
- package/dist/index15.js +43 -56
- package/dist/index16.js +41 -45
- package/dist/index17.js +38 -42
- package/dist/index18.js +54 -35
- package/dist/index19.js +46 -51
- package/dist/index20.js +50 -47
- package/dist/index3.js +199 -22
- package/dist/index4.js +66 -61
- package/dist/index6.js +84 -84
- package/dist/index7.js +19 -19
- package/dist/index8.js +33 -6
- package/dist/index9.js +14 -29
- package/package.json +12 -8
- package/src/contract/listSchema.ts +51 -29
- package/src/contract/reef.ts +62 -0
- package/src/contract/sharedMemory.ts +25 -25
- package/src/contract/zod.ts +344 -32
- package/src/index.ts +1 -2
- package/dist/contract/msgpackCodec.d.ts +0 -7
- package/dist/contract/mz.d.ts +0 -43
- package/dist/index21.js +0 -59
- package/src/contract/msgpackCodec.ts +0 -9
- package/src/contract/mz.ts +0 -48
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z } from './zod';
|
|
1
|
+
import { z, fluent, type Fluent } from './zod';
|
|
2
2
|
import type {
|
|
3
3
|
ScalarKind,
|
|
4
4
|
ListFieldSpec,
|
|
@@ -8,26 +8,30 @@ import type {
|
|
|
8
8
|
|
|
9
9
|
const utf8 = new TextEncoder();
|
|
10
10
|
|
|
11
|
-
/** Storage-bounded
|
|
11
|
+
/** Storage-bounded schemas per scalar kind — validation catches
|
|
12
12
|
* out-of-range values at the contract boundary instead of silently
|
|
13
13
|
* truncating at write time. */
|
|
14
|
+
const boundedInt = (min: number, max: number) =>
|
|
15
|
+
fluent(z.number().check(z.int(), z.gte(min), z.lte(max)));
|
|
16
|
+
|
|
14
17
|
const SCALAR_SCHEMAS: Record<ScalarKind, z.ZodTypeAny> = {
|
|
15
|
-
i8:
|
|
16
|
-
u8:
|
|
17
|
-
i16:
|
|
18
|
-
u16:
|
|
19
|
-
i32: z.
|
|
20
|
-
u32: z.
|
|
21
|
-
f32: z.number(),
|
|
22
|
-
f64: z.number(),
|
|
23
|
-
i64: z.bigint(),
|
|
24
|
-
u64: z.bigint().nonnegative(),
|
|
18
|
+
i8: boundedInt(-128, 127),
|
|
19
|
+
u8: boundedInt(0, 255),
|
|
20
|
+
i16: boundedInt(-32768, 32767),
|
|
21
|
+
u16: boundedInt(0, 65535),
|
|
22
|
+
i32: fluent(z.int32()),
|
|
23
|
+
u32: fluent(z.uint32()),
|
|
24
|
+
f32: fluent(z.number()),
|
|
25
|
+
f64: fluent(z.number()),
|
|
26
|
+
i64: fluent(z.bigint()),
|
|
27
|
+
u64: fluent(z.bigint().check(z.nonnegative())),
|
|
25
28
|
};
|
|
26
29
|
|
|
27
30
|
const byteBounded = (bytes: number) =>
|
|
28
|
-
|
|
29
|
-
(
|
|
30
|
-
|
|
31
|
+
fluent(
|
|
32
|
+
z.string().check(
|
|
33
|
+
z.refine((s: string) => utf8.encode(s).byteLength <= bytes, `exceeds ${bytes} UTF-8 bytes`)
|
|
34
|
+
)
|
|
31
35
|
);
|
|
32
36
|
|
|
33
37
|
/** Maps a list member to the zod shape whose inferred output type is
|
|
@@ -47,7 +51,7 @@ export type ListZodShape<F extends ListFields> = {
|
|
|
47
51
|
|
|
48
52
|
/**
|
|
49
53
|
* Builds a zod object schema from a member map — the shape you would pass
|
|
50
|
-
* to `
|
|
54
|
+
* to `reef.object(...)` for `field.list({ schema, count })`. Members may be
|
|
51
55
|
* spec tokens or zod schemas; the result's `z.infer` is the record type:
|
|
52
56
|
*
|
|
53
57
|
* ```ts
|
|
@@ -60,21 +64,35 @@ export type ListZodShape<F extends ListFields> = {
|
|
|
60
64
|
* capacity the connector enforces; zod `z.string().meta({ bytes: n })`
|
|
61
65
|
* members get the same bound attached to the declared schema.
|
|
62
66
|
*/
|
|
63
|
-
export function listSchema<F extends ListFields>(fields: F): z.
|
|
67
|
+
export function listSchema<F extends ListFields>(fields: F): Fluent<z.ZodMiniObject<ListZodShape<F>>> {
|
|
64
68
|
const shape: Record<string, z.ZodTypeAny> = {};
|
|
65
69
|
for (const key of Object.keys(fields)) {
|
|
66
70
|
shape[key] = memberToSchema(fields[key]);
|
|
67
71
|
}
|
|
68
|
-
return z.object(shape) as unknown as z.
|
|
72
|
+
return fluent(z.object(shape)) as unknown as Fluent<z.ZodMiniObject<ListZodShape<F>>>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Duck-typed `$Zod*`-style detection — covers atoll-minted, classic zod,
|
|
76
|
+
* and zod/mini schemas: they all carry `_zod.def`. */
|
|
77
|
+
function isZodSchema(value: unknown): value is z.ZodTypeAny {
|
|
78
|
+
return (
|
|
79
|
+
typeof value === 'object' && value !== null &&
|
|
80
|
+
typeof (value as { _zod?: { def?: unknown } })._zod?.def === 'object'
|
|
81
|
+
);
|
|
69
82
|
}
|
|
70
83
|
|
|
71
84
|
function memberToSchema(member: ListMember): z.ZodTypeAny {
|
|
72
|
-
if (member
|
|
85
|
+
if (isZodSchema(member)) {
|
|
73
86
|
const bytes =
|
|
74
87
|
member._zod.def?.type === 'string' ? zodMetaBytes(member) : undefined;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
if (typeof bytes !== 'number') return member;
|
|
89
|
+
const fits = (s: unknown) => utf8.encode(s as string).byteLength <= bytes;
|
|
90
|
+
const message = `exceeds ${bytes} UTF-8 bytes`;
|
|
91
|
+
// classic + fluent-augmented members carry `.refine`; a raw mini schema
|
|
92
|
+
// takes the same check through `.check` — both keep def.type 'string'.
|
|
93
|
+
return typeof (member as { refine?: unknown }).refine === 'function'
|
|
94
|
+
? (member as unknown as { refine: (fn: typeof fits, msg: string) => z.ZodTypeAny }).refine(fits, message)
|
|
95
|
+
: (member as unknown as { check: (c: unknown) => z.ZodTypeAny }).check(z.refine(fits, message));
|
|
78
96
|
}
|
|
79
97
|
return typeof member === 'string'
|
|
80
98
|
? SCALAR_SCHEMAS[member]
|
|
@@ -155,7 +173,7 @@ function numberMemberToSpec(def: ZodMemberDef): ListFieldSpec {
|
|
|
155
173
|
*/
|
|
156
174
|
export function memberToSpec(member: ListMember, name: string): ListFieldSpec {
|
|
157
175
|
if (typeof member === 'string') return member;
|
|
158
|
-
if (!(member
|
|
176
|
+
if (!isZodSchema(member)) {
|
|
159
177
|
if (typeof (member as { string?: unknown }).string === 'number') return member as { string: number };
|
|
160
178
|
if ((member as { bool?: unknown }).bool === true) return member as { bool: true };
|
|
161
179
|
throw new TypeError(`member "${name}": expected a scalar token, { string: n }, { bool: true }, or a zod schema`);
|
|
@@ -182,7 +200,7 @@ export function memberToSpec(member: ListMember, name: string): ListFieldSpec {
|
|
|
182
200
|
|
|
183
201
|
/** The declared member map of a zod object, or null when `schema` isn't one. */
|
|
184
202
|
export function zodObjectShape(schema: unknown): ListFields | null {
|
|
185
|
-
if (!(schema
|
|
203
|
+
if (!isZodSchema(schema) || schema._zod.def.type !== 'object') return null;
|
|
186
204
|
return (schema._zod.def as unknown as { shape: ListFields }).shape;
|
|
187
205
|
}
|
|
188
206
|
|
|
@@ -192,7 +210,7 @@ export function zodObjectShape(schema: unknown): ListFields | null {
|
|
|
192
210
|
* schemas; `capacity` is null for unbounded arrays.
|
|
193
211
|
*/
|
|
194
212
|
export function zodArrayInfo(schema: unknown): { element: z.ZodTypeAny; capacity: number | null } | null {
|
|
195
|
-
if (!(schema
|
|
213
|
+
if (!isZodSchema(schema) || schema._zod.def.type !== 'array') return null;
|
|
196
214
|
const def = schema._zod.def as unknown as ZodMemberDef & { element: z.ZodTypeAny };
|
|
197
215
|
let capacity: number | null = null;
|
|
198
216
|
for (const c of def.checks ?? []) {
|
|
@@ -203,14 +221,18 @@ export function zodArrayInfo(schema: unknown): { element: z.ZodTypeAny; capacity
|
|
|
203
221
|
return { element: def.element, capacity };
|
|
204
222
|
}
|
|
205
223
|
|
|
206
|
-
/**
|
|
224
|
+
/** Byte budget carried in the schema's meta — atoll-minted schemas register
|
|
225
|
+
* into the local `globalRegistry`; classic zod's `.meta()` reads its own
|
|
226
|
+
* registry, so the `.meta?.()` call doubles as the consumer-zod channel. */
|
|
207
227
|
function zodMetaBytes(schema: unknown): number | null {
|
|
208
|
-
const meta =
|
|
228
|
+
const meta =
|
|
229
|
+
(z.globalRegistry.get(schema as z.ZodTypeAny) as { bytes?: unknown } | undefined) ??
|
|
230
|
+
(schema as { meta?: () => { bytes?: unknown } }).meta?.();
|
|
209
231
|
return typeof meta?.bytes === 'number' ? meta.bytes : null;
|
|
210
232
|
}
|
|
211
233
|
|
|
212
|
-
/** The byte budget carried by `
|
|
234
|
+
/** The byte budget carried by `reef.string(n)` / `z.string().meta({ bytes: n })` — null otherwise. */
|
|
213
235
|
export function zodStringBytes(schema: unknown): number | null {
|
|
214
|
-
if (!(schema
|
|
236
|
+
if (!isZodSchema(schema) || schema._zod.def.type !== 'string') return null;
|
|
215
237
|
return zodMetaBytes(schema);
|
|
216
238
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z, fluent } from './zod';
|
|
2
|
+
|
|
3
|
+
const utf8 = new TextEncoder();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reef — the atoll's structural barrier: the fixed-width schema
|
|
7
|
+
* vocabulary standing between your data and the raw buffer. Every helper
|
|
8
|
+
* mints a schema the layout compiler can read a byte width from: number
|
|
9
|
+
* formats (`reef.u32()`), int bounds (`reef.int(0, 3)` → u8), byte budgets
|
|
10
|
+
* (`reef.string(10)`), or flags (`reef.boolean()` → u8). There are no unfixed
|
|
11
|
+
* members — `reef.number()`/`z.date()`/`z.enum()` aren't exposed because they
|
|
12
|
+
* can't promise a width.
|
|
13
|
+
*
|
|
14
|
+
* Schemas are minted by the vendored engine in `./zod.ts` — a zod-shaped
|
|
15
|
+
* `_zod.def` surface (`type`/`format`/`checks`/`shape`/`element`), so no
|
|
16
|
+
* zod dependency ships. Width coverage: int32/uint32/float32/float64/
|
|
17
|
+
* int64/uint64 are format-tagged; reef fills the gaps (i8/u8/i16/u16 via
|
|
18
|
+
* bounded ints, which the compiler narrows identically) so all ten scalar
|
|
19
|
+
* kinds have one spelling.
|
|
20
|
+
*
|
|
21
|
+
* Composition derives byte width upward — `reef.object({...})` members lay out
|
|
22
|
+
* as a fixed record (field.object derives byteLength from it, no maxBytes),
|
|
23
|
+
* `reef.array(el).max(n)` bounds element capacity for field.array, and
|
|
24
|
+
* `reef.string(n)` carries the budget for field.string. Schemas keep the
|
|
25
|
+
* classic chain spellings — `.meta()`, `.refine()`, `.max()`/`.length()` —
|
|
26
|
+
* and consumer-supplied zod schemas introspect identically through their
|
|
27
|
+
* `_zod.def`, so `reef.object({ id: z.uint32() })` mixes freely.
|
|
28
|
+
*/
|
|
29
|
+
export const reef = {
|
|
30
|
+
i8: () => fluent(z.number().check(z.int(), z.gte(-128), z.lte(127))),
|
|
31
|
+
u8: () => fluent(z.number().check(z.int(), z.gte(0), z.lte(255))),
|
|
32
|
+
i16: () => fluent(z.number().check(z.int(), z.gte(-32768), z.lte(32767))),
|
|
33
|
+
u16: () => fluent(z.number().check(z.int(), z.gte(0), z.lte(65535))),
|
|
34
|
+
i32: () => fluent(z.int32()),
|
|
35
|
+
u32: () => fluent(z.uint32()),
|
|
36
|
+
f32: () => fluent(z.float32()),
|
|
37
|
+
f64: () => fluent(z.float64()),
|
|
38
|
+
i64: () => fluent(z.int64()),
|
|
39
|
+
u64: () => fluent(z.uint64()),
|
|
40
|
+
/** Bounded int — compiles to the narrowest covering kind (0..3 → u8). */
|
|
41
|
+
int: (min: number, max: number) => fluent(z.number().check(z.int(), z.gte(min), z.lte(max))),
|
|
42
|
+
/** A flag byte — reads and writes as boolean. */
|
|
43
|
+
boolean: () => fluent(z.boolean()),
|
|
44
|
+
/** Fixed-capacity inline UTF-8 string — `bytes` is the byte budget. The
|
|
45
|
+
* schema itself refuses over-budget values, so `.parse` and connector
|
|
46
|
+
* writes enforce the same limit. */
|
|
47
|
+
string: (bytes: number) =>
|
|
48
|
+
fluent(
|
|
49
|
+
z.string()
|
|
50
|
+
.check(
|
|
51
|
+
z.refine(
|
|
52
|
+
(s: string) => utf8.encode(s).byteLength <= bytes,
|
|
53
|
+
`exceeds ${bytes} UTF-8 bytes`
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
.register(z.globalRegistry, { bytes })
|
|
57
|
+
),
|
|
58
|
+
/** A fixed-layout record shape — every member must be a fixed-width schema. */
|
|
59
|
+
object: <S extends z.ZodRawShape>(shape: S) => fluent(z.object(shape)),
|
|
60
|
+
/** A fixed-stride element — bound it with `.max(n)` or `.length(n)` before field.array. */
|
|
61
|
+
array: <E extends z.ZodTypeAny>(element: E) => fluent(z.array(element)),
|
|
62
|
+
};
|
|
@@ -2,7 +2,7 @@ import type { Prettify, Schema } from './types';
|
|
|
2
2
|
import { msgpackrCodec } from './msgpackrCodec';
|
|
3
3
|
import { memberToSpec, zodArrayInfo, zodObjectShape, zodStringBytes } from './listSchema';
|
|
4
4
|
import { fmtBytes, scoped } from '../log';
|
|
5
|
-
import { z } from './zod';
|
|
5
|
+
import { z, fluent } from './zod';
|
|
6
6
|
|
|
7
7
|
const memLog = scoped('memory');
|
|
8
8
|
|
|
@@ -156,7 +156,7 @@ export type ListSpec = Record<string, ListFieldSpec>;
|
|
|
156
156
|
/**
|
|
157
157
|
* A fixed-width member inside a record or element position — a binary spec
|
|
158
158
|
* token (`'u32'`, `{ string: n }`, `{ bool: true }`) or a zod schema that
|
|
159
|
-
* expresses the same thing (`
|
|
159
|
+
* expresses the same thing (`reef.u32()`, `reef.int(0, 3)`, `reef.string(n)`).
|
|
160
160
|
* Schemas are compiled to tokens for layout and kept as the field's
|
|
161
161
|
* validation schema — one declaration.
|
|
162
162
|
*/
|
|
@@ -170,7 +170,7 @@ export interface ListDescriptor<S extends z.ZodObject<z.ZodRawShape> = z.ZodObje
|
|
|
170
170
|
extends Omit<FieldDescriptor<ListRecord<S>[]>, 'schema'> {
|
|
171
171
|
readonly kind: 'list';
|
|
172
172
|
/**
|
|
173
|
-
* The declared record schema —
|
|
173
|
+
* The declared record schema — a `reef.object` of fixed-width members. It
|
|
174
174
|
* IS the layout source AND the record validator (`schemas.lists.x` is this
|
|
175
175
|
* same object). Note it parses one record, not the whole array.
|
|
176
176
|
*/
|
|
@@ -290,7 +290,7 @@ export interface FixedArrayDescriptor<T = unknown> extends FieldDescriptor<T[]>
|
|
|
290
290
|
interface ObjectFieldFactory {
|
|
291
291
|
/**
|
|
292
292
|
* Inline fixed layout — the schema is a zod object of fixed-width members
|
|
293
|
-
* (`
|
|
293
|
+
* (`reef` helpers, `z.uint32()`, bounded ints, `reef.string(n)`, `z.boolean()`);
|
|
294
294
|
* `byteLength` derives from the member widths. Compile fails loudly for
|
|
295
295
|
* members with no fixed width (unbounded strings, nested objects).
|
|
296
296
|
*/
|
|
@@ -322,9 +322,9 @@ const objectFieldImpl: ObjectFieldFactory = (options: { schema?: Schema<unknown>
|
|
|
322
322
|
interface ArrayFieldFactory {
|
|
323
323
|
/**
|
|
324
324
|
* Inline fixed layout — the schema is a bounded zod array
|
|
325
|
-
* (`
|
|
325
|
+
* (`reef.array(reef.u32()).max(n)`, `.length(n)`); `byteLength` derives from
|
|
326
326
|
* the element width × the bound. Elements must be fixed-width members
|
|
327
|
-
* (scalars, `
|
|
327
|
+
* (scalars, `reef.string(n)`, booleans) — use `field.list` for record arrays.
|
|
328
328
|
*/
|
|
329
329
|
<S extends z.ZodArray>(options: { schema: S }): FixedArrayDescriptor<S extends z.ZodArray<infer E> ? z.output<E> : unknown>;
|
|
330
330
|
/** Codec-encoded blob — explicit byte budget for arbitrary payloads. */
|
|
@@ -363,7 +363,7 @@ const arrayFieldImpl: ArrayFieldFactory = (options: { schema?: Schema<unknown>;
|
|
|
363
363
|
interface StringFieldFactory {
|
|
364
364
|
/** Explicit byte budget — 4-byte length header + up to `maxBytes` of UTF-8. */
|
|
365
365
|
(options: { maxBytes: number; schema?: Schema<string> }): FieldDescriptor<string>;
|
|
366
|
-
/** Budget derived from the schema — `
|
|
366
|
+
/** Budget derived from the schema — `reef.string(n)` / `z.string().meta({ bytes: n })`. */
|
|
367
367
|
(options: { schema: Schema<string> }): FieldDescriptor<string>;
|
|
368
368
|
}
|
|
369
369
|
|
|
@@ -373,7 +373,7 @@ const stringFieldImpl: StringFieldFactory = (options: { schema?: Schema<string>;
|
|
|
373
373
|
const bytes = schema ? zodStringBytes(schema) : null;
|
|
374
374
|
if (bytes !== null) return { kind: 'string', byteLength: 4 + bytes, schema };
|
|
375
375
|
throw new TypeError(
|
|
376
|
-
`field.string: pass { maxBytes } or a schema carrying a byte budget —
|
|
376
|
+
`field.string: pass { maxBytes } or a schema carrying a byte budget — reef.string(n) / z.string().meta({ bytes: n })`
|
|
377
377
|
);
|
|
378
378
|
};
|
|
379
379
|
|
|
@@ -391,16 +391,16 @@ export const field = {
|
|
|
391
391
|
bigInt64Array: ({ length }: { length: number }): FieldDescriptor<BigInt64Array> => ({ kind: 'BigInt64', byteLength: length * 8 }),
|
|
392
392
|
uint8Array: ({ length }: { length: number }): FieldDescriptor<Uint8Array> => ({ kind: 'Uint8', byteLength: length }),
|
|
393
393
|
/**
|
|
394
|
-
* A fixed-layout array of `count` records. `schema` is
|
|
395
|
-
* fixed-width members (`
|
|
396
|
-
* `
|
|
394
|
+
* A fixed-layout array of `count` records. `schema` is a `reef.object` of
|
|
395
|
+
* fixed-width members (`reef.u32()`, `reef.int(0, 3)`, `reef.string(n)`,
|
|
396
|
+
* `reef.boolean()`) — the same schema `field.object` takes, repeated `count`
|
|
397
397
|
* times. Every record occupies `recordSize` bytes at a computable offset:
|
|
398
398
|
* reads and writes are direct memory access, no serialization.
|
|
399
399
|
*/
|
|
400
400
|
list: <S extends z.ZodObject<z.ZodRawShape>>({ schema, count }: { schema: S; count: number }): ListDescriptor<S> => {
|
|
401
401
|
const shape = zodObjectShape(schema);
|
|
402
402
|
if (!shape) {
|
|
403
|
-
throw new TypeError(`field.list: schema must be
|
|
403
|
+
throw new TypeError(`field.list: schema must be a reef.object() of fixed-width members`);
|
|
404
404
|
}
|
|
405
405
|
const { layout, offsets, recordSize } = compileListLayout(shape);
|
|
406
406
|
return {
|
|
@@ -640,7 +640,7 @@ registerConnectorFactory('object', structuredFactory);
|
|
|
640
640
|
registerConnectorFactory('array', structuredFactory);
|
|
641
641
|
|
|
642
642
|
function listFactory(d: FieldDescriptor, ctx: ConnectorContext, byteOffset: number): ListConnector<any> {
|
|
643
|
-
const info = d as ListDescriptor;
|
|
643
|
+
const info = d as unknown as ListDescriptor;
|
|
644
644
|
const { offsets, recordSize, count } = info;
|
|
645
645
|
// `layout` is the compiled token map; `schema` stays the validation schema.
|
|
646
646
|
const record = makeIO(ctx).compile(info.layout, offsets);
|
|
@@ -694,7 +694,7 @@ registerConnectorFactory('list', listFactory);
|
|
|
694
694
|
const definedSharedMemories: SharedMemory<any>[] = [];
|
|
695
695
|
|
|
696
696
|
/**
|
|
697
|
-
* The
|
|
697
|
+
* The schema for a field's logical unit: the declared `schema` for
|
|
698
698
|
* object/array/list fields (for lists, the record schema), and a derived
|
|
699
699
|
* scalar/typed-array schema for everything else.
|
|
700
700
|
*/
|
|
@@ -704,7 +704,7 @@ export type FieldSchema<D> =
|
|
|
704
704
|
: z.ZodType<InferField<D>>;
|
|
705
705
|
|
|
706
706
|
/**
|
|
707
|
-
* A
|
|
707
|
+
* A schema per field — `memory.schemas.<field>` re-exports what the spec
|
|
708
708
|
* declared inline. Intent groups mirror their spec shape:
|
|
709
709
|
* `memory.schemas.lists.incidents` is the record schema.
|
|
710
710
|
*/
|
|
@@ -733,14 +733,14 @@ function buildSchemas<S extends SharedSpec>(spec: S): SpecSchemas<S> {
|
|
|
733
733
|
function fieldSchemaOf(descriptor: FieldDescriptor): Schema<unknown> {
|
|
734
734
|
if (descriptor.schema) return descriptor.schema;
|
|
735
735
|
switch (descriptor.kind) {
|
|
736
|
-
case 'number': return z.number();
|
|
737
|
-
case 'boolean': return z.boolean();
|
|
738
|
-
case 'string': return z.string();
|
|
739
|
-
case 'Int32': return z.instanceof(Int32Array);
|
|
740
|
-
case 'Float64': return z.instanceof(Float64Array);
|
|
741
|
-
case 'BigInt64': return z.instanceof(BigInt64Array);
|
|
742
|
-
case 'Uint8': return z.instanceof(Uint8Array);
|
|
743
|
-
default: return z.unknown();
|
|
736
|
+
case 'number': return fluent(z.number());
|
|
737
|
+
case 'boolean': return fluent(z.boolean());
|
|
738
|
+
case 'string': return fluent(z.string());
|
|
739
|
+
case 'Int32': return fluent(z.instanceof(Int32Array));
|
|
740
|
+
case 'Float64': return fluent(z.instanceof(Float64Array));
|
|
741
|
+
case 'BigInt64': return fluent(z.instanceof(BigInt64Array));
|
|
742
|
+
case 'Uint8': return fluent(z.instanceof(Uint8Array));
|
|
743
|
+
default: return fluent(z.unknown());
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
746
|
|
|
@@ -755,9 +755,9 @@ export class SharedMemory<S extends SharedSpec = SharedSpec> {
|
|
|
755
755
|
/** The field descriptors the contract was defined with — the inline spec. */
|
|
756
756
|
public readonly spec: S;
|
|
757
757
|
/**
|
|
758
|
-
* One
|
|
758
|
+
* One schema per field, derived from the spec: declared schemas on
|
|
759
759
|
* object/array fields, the record schema on list fields, and derived
|
|
760
|
-
* scalar schemas
|
|
760
|
+
* scalar schemas elsewhere.
|
|
761
761
|
*/
|
|
762
762
|
public readonly schemas: SpecSchemas<S>;
|
|
763
763
|
private readonly codec: Codec;
|