@atolljs/core 0.1.0 → 0.1.1
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/README.md +159 -59
- package/dist/contract/listSchema.d.ts +47 -0
- package/dist/contract/msgpackCodec.d.ts +7 -0
- package/dist/contract/msgpackrCodec.d.ts +2 -0
- package/dist/contract/mz.d.ts +43 -0
- package/dist/contract/sharedMemory.d.ts +350 -0
- package/dist/contract/types.d.ts +131 -0
- package/dist/contract/zod.d.ts +53 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +18 -18
- package/dist/index10.js +14 -178
- package/dist/index11.js +188 -47
- package/dist/index12.js +45 -59
- package/dist/index13.js +59 -20
- package/dist/index14.js +24 -60
- package/dist/index15.js +56 -43
- package/dist/index16.js +45 -41
- package/dist/index17.js +42 -38
- package/dist/index18.js +36 -55
- package/dist/index19.js +52 -47
- package/dist/index20.js +48 -51
- package/dist/index21.js +59 -0
- package/dist/index3.js +24 -117
- package/dist/index4.js +116 -34
- package/dist/index5.js +32 -473
- package/dist/index6.js +489 -19
- package/dist/index7.js +19 -6
- package/dist/index8.js +6 -33
- package/dist/index9.js +29 -14
- package/dist/log.d.ts +35 -0
- package/dist/observable.d.ts +30 -0
- package/dist/pool/errors.d.ts +16 -0
- package/dist/pool/memory.d.ts +19 -0
- package/dist/pool/workerClient.d.ts +80 -0
- package/dist/pool/workerPool.d.ts +115 -0
- package/dist/reactive.d.ts +46 -0
- package/dist/service.d.ts +181 -0
- package/dist/shared/sharedWorkerClient.d.ts +35 -0
- package/dist/shared/sharedWorkerHost.d.ts +21 -0
- package/dist/task.d.ts +40 -0
- package/dist/worker/defineWorker.d.ts +63 -0
- package/dist/worker/registry.d.ts +8 -0
- package/dist/worker/workerBootstrap.d.ts +1 -0
- package/package.json +14 -2
- package/src/contract/listSchema.ts +13 -8
- package/src/contract/mz.ts +1 -1
- package/src/contract/sharedMemory.ts +28 -1
- package/src/contract/types.ts +21 -0
- package/src/contract/zod.ts +44 -0
- package/src/index.ts +2 -1
- package/src/pool/workerPool.ts +27 -1
package/README.md
CHANGED
|
@@ -4,44 +4,162 @@
|
|
|
4
4
|
[](https://codecov.io/gh/jwhenry3/atolljs)
|
|
5
5
|
|
|
6
6
|
Typed shared-memory worker pools for TypeScript — deterministic `SharedArrayBuffer`
|
|
7
|
-
layouts, first-class task methods, and cross-thread reactive state.
|
|
7
|
+
layouts, first-class task methods, and cross-thread reactive state. A worker
|
|
8
|
+
atoll: pools and shared workers joined to your app through one shared-memory
|
|
9
|
+
fabric, so work is offloaded as typed method calls while large state stays put
|
|
10
|
+
(zero-copy, no postMessage serialization of the values themselves).
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
**[Atoll — package documentation](https://jwhenry3.github.io/atolljs/consumer/#/quickstart)**
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|---|---|
|
|
13
|
-
| `@atolljs/core` | Core SDK — `defineWorker`/`connectWorker` typed worker clients over `WorkerPool`, shared-memory contracts, `watch`/`observe`, codecs |
|
|
14
|
-
| `@atolljs/react` | React hooks — `useObservable`, `useSharedValue`, `useTask` |
|
|
15
|
-
| `@atolljs/vue` | Vue composables — `useObservable`, `useSharedValue`, `useTask` |
|
|
16
|
-
| `@atolljs/solidjs` | Solid primitives — `createObservable`, `createSharedValue`, `createTask` |
|
|
17
|
-
| `@atolljs/svelte` | Svelte 5 rune bindings — `observableValue`, `sharedValue`, `taskState` |
|
|
18
|
-
| `@atolljs/angular` | Angular signals — `observableSignal`, `sharedValue`, `taskState` |
|
|
19
|
-
| `@atolljs/nextjs` | Next.js client-component bindings (React re-export) |
|
|
20
|
-
| `@atolljs/node` | `node:worker_threads` runtime adapter |
|
|
21
|
-
| `@atolljs/nestjs` | NestJS module/decorators for worker pools |
|
|
22
|
-
| `@atolljs/islands` | worker-side React reconciler + proxy DOM islands — opt-in DOM rendering |
|
|
23
|
-
| `@atolljs/react-island` | React shell components for islands — `<Island/>`, `islandComponent`, `lazyIsland` |
|
|
24
|
-
| `@atolljs/vue-island` | Vue shell (`useIsland`, `<AtollIsland>`) + Vue worker renderer |
|
|
25
|
-
| `@atolljs/svelte-island` | Svelte shell (`use:island`, `createIslandState`) + Svelte 5 worker renderer |
|
|
26
|
-
| `@atolljs/solid-island` | Solid shell (`createIsland`, `Island`) + `solid-js/universal` worker renderer |
|
|
27
|
-
| `@atolljs/angular-island` | Angular shell (`<atoll-island>`, `[atollIsland]`) + `Renderer2` worker renderer |
|
|
28
|
-
|
|
29
|
-
Framework bindings are published independently — install only the one you use:
|
|
14
|
+
## Install
|
|
30
15
|
|
|
31
16
|
```bash
|
|
32
|
-
npm install @atolljs/core
|
|
17
|
+
npm install @atolljs/core # the whole SDK
|
|
18
|
+
npm install @atolljs/react # + one framework binding, if you use one
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Framework bindings are published independently — install only the one you use.
|
|
22
|
+
|
|
23
|
+
## Quickstart
|
|
24
|
+
|
|
25
|
+
A minimal counter — one shared field, one worker method, one component.
|
|
26
|
+
Four files, and the method name is written exactly once.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// counter.memory.ts — shared memory, imported by both threads
|
|
30
|
+
import { defineSharedMemory, field } from '@atolljs/core';
|
|
31
|
+
|
|
32
|
+
export const counterMemory = defineSharedMemory({
|
|
33
|
+
count: field.number(),
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// counter.worker.ts — the worker entry; methods live here
|
|
39
|
+
import { defineWorker } from '@atolljs/core';
|
|
40
|
+
import { counterMemory } from './counter.memory';
|
|
41
|
+
|
|
42
|
+
export const counterWorker = defineWorker({
|
|
43
|
+
sharedMemory: counterMemory,
|
|
44
|
+
methods: {
|
|
45
|
+
increment(delta: number) {
|
|
46
|
+
const next = counterMemory.count.read() + delta;
|
|
47
|
+
counterMemory.count.write(next); // write in place — no postMessage
|
|
48
|
+
return next;
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
export type CounterWorker = typeof counterWorker;
|
|
33
53
|
```
|
|
34
54
|
|
|
55
|
+
```ts
|
|
56
|
+
// counter.ts — the typed client; import type only, no worker code in this bundle
|
|
57
|
+
import { connectWorker } from '@atolljs/core';
|
|
58
|
+
import { counterMemory } from './counter.memory';
|
|
59
|
+
import type { CounterWorker } from './counter.worker';
|
|
60
|
+
|
|
61
|
+
export const counter = connectWorker<CounterWorker>({
|
|
62
|
+
sharedMemory: counterMemory,
|
|
63
|
+
// Inline new Worker(new URL(..., import.meta.url)) — every bundler's
|
|
64
|
+
// worker transform can see the entry point this way.
|
|
65
|
+
worker: () => new Worker(new URL('./counter.worker.ts', import.meta.url), { type: 'module' }),
|
|
66
|
+
poolSize: 'auto', // navigator.hardwareConcurrency, or pass a number
|
|
67
|
+
});
|
|
68
|
+
// counter.increment(1) → Promise<number>. The pool spawns on first call
|
|
69
|
+
// (SSR-safe to import); counter.terminate() tears it down.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// App.tsx — bind it in your framework
|
|
74
|
+
import { useSharedValue, useTask } from '@atolljs/react';
|
|
75
|
+
import { counterMemory } from './counter.memory';
|
|
76
|
+
import { counter } from './counter';
|
|
77
|
+
|
|
78
|
+
export function App() {
|
|
79
|
+
const count = useSharedValue(counterMemory, 'count');
|
|
80
|
+
const increment = useTask(counter.increment); // latest-wins task state
|
|
81
|
+
return <button onClick={() => increment.run(1)}>count: {count ?? '…'}</button>;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`increment.run(1)` posts the call to a worker, the worker writes `count` in
|
|
86
|
+
place, and the binding re-renders on the next field write.
|
|
87
|
+
|
|
88
|
+
Shared memory is opt-in: leave `sharedMemory` out of both `defineWorker` and
|
|
89
|
+
`connectWorker` and you get a typed, pooled, cancellable worker RPC that runs
|
|
90
|
+
anywhere Workers do — no isolation headers needed. With shared memory,
|
|
91
|
+
`SharedArrayBuffer` requires
|
|
92
|
+
[cross-origin isolation headers](https://jwhenry3.github.io/atolljs/consumer/#/hosting)
|
|
93
|
+
(COOP/COEP) in the browser; Node needs nothing.
|
|
94
|
+
|
|
95
|
+
## Packages
|
|
96
|
+
|
|
97
|
+
`@atolljs/core` is the SDK; everything else is independently published —
|
|
98
|
+
install only what you use.
|
|
99
|
+
|
|
100
|
+
### Framework bindings
|
|
101
|
+
|
|
102
|
+
| Framework | Package | What it is | Docs |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| React | [`@atolljs/react`](https://www.npmjs.com/package/@atolljs/react) | Hooks — `useObservable`, `useSharedValue`, `useTask` | [React guide](https://jwhenry3.github.io/atolljs/consumer/#/fw-react) |
|
|
105
|
+
| Vue | [`@atolljs/vue`](https://www.npmjs.com/package/@atolljs/vue) | Composables — `useObservable`, `useSharedValue`, `useTask` | [Vue guide](https://jwhenry3.github.io/atolljs/consumer/#/fw-vue) |
|
|
106
|
+
| SolidJS | [`@atolljs/solidjs`](https://www.npmjs.com/package/@atolljs/solidjs) | Primitives — `createObservable`, `createSharedValue`, `createTask` | [SolidJS guide](https://jwhenry3.github.io/atolljs/consumer/#/fw-solid) |
|
|
107
|
+
| Svelte | [`@atolljs/svelte`](https://www.npmjs.com/package/@atolljs/svelte) | Svelte 5 rune bindings — `observableValue`, `sharedValue`, `taskState` | [Svelte guide](https://jwhenry3.github.io/atolljs/consumer/#/fw-svelte) |
|
|
108
|
+
| Angular | [`@atolljs/angular`](https://www.npmjs.com/package/@atolljs/angular) | Signals + DI — `observableSignal`, `sharedValue`, `taskState`, `provideAtoll` | [Angular guide](https://jwhenry3.github.io/atolljs/consumer/#/fw-angular) |
|
|
109
|
+
| Next.js | [`@atolljs/nextjs`](https://www.npmjs.com/package/@atolljs/nextjs) | Client-component bindings (React re-export) | [Next.js guide](https://jwhenry3.github.io/atolljs/consumer/#/fw-nextjs) |
|
|
110
|
+
| NestJS | [`@atolljs/nestjs`](https://www.npmjs.com/package/@atolljs/nestjs) | Server-side module/decorators for worker pools | [NestJS guide](https://jwhenry3.github.io/atolljs/consumer/#/fw-nestjs) |
|
|
111
|
+
|
|
112
|
+
### Worker islands — render framework trees off the main thread
|
|
113
|
+
|
|
114
|
+
| Framework | Package | What it is | Docs |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| *(engine)* | [`@atolljs/islands`](https://www.npmjs.com/package/@atolljs/islands) | `mountIsland`, op protocol, proxy DOM, worker runtimes | [Worker islands](https://jwhenry3.github.io/atolljs/consumer/#/islands) |
|
|
117
|
+
| React | [`@atolljs/react-island`](https://www.npmjs.com/package/@atolljs/react-island) | `<Island/>`, `islandComponent`, `lazyIsland` | [React islands](https://jwhenry3.github.io/atolljs/consumer/#/fw-react/worker-islands) |
|
|
118
|
+
| Vue | [`@atolljs/vue-island`](https://www.npmjs.com/package/@atolljs/vue-island) | `useIsland`, `<AtollIsland>` + Vue worker renderer | [Vue islands](https://jwhenry3.github.io/atolljs/consumer/#/fw-vue/worker-islands) |
|
|
119
|
+
| Svelte | [`@atolljs/svelte-island`](https://www.npmjs.com/package/@atolljs/svelte-island) | `use:island`, `createIslandState` + Svelte 5 worker renderer | [Svelte islands](https://jwhenry3.github.io/atolljs/consumer/#/fw-svelte/worker-islands) |
|
|
120
|
+
| SolidJS | [`@atolljs/solid-island`](https://www.npmjs.com/package/@atolljs/solid-island) | `createIsland`, `Island` + `solid-js/universal` worker renderer | [Solid islands](https://jwhenry3.github.io/atolljs/consumer/#/fw-solid/worker-islands) |
|
|
121
|
+
| Angular | [`@atolljs/angular-island`](https://www.npmjs.com/package/@atolljs/angular-island) | `<atoll-island>`, `[atollIsland]` + `Renderer2` worker renderer | [Angular islands](https://jwhenry3.github.io/atolljs/consumer/#/fw-angular/worker-islands) |
|
|
122
|
+
|
|
123
|
+
### Runtimes
|
|
124
|
+
|
|
125
|
+
| Package | What it is | Docs |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| [`@atolljs/core`](https://www.npmjs.com/package/@atolljs/core) | Core SDK — `defineWorker`/`connectWorker` typed worker clients over `WorkerPool`, shared-memory contracts, `watch`/`observe`, codecs | [Quickstart](https://jwhenry3.github.io/atolljs/consumer/#/quickstart) · [Shared memory](https://jwhenry3.github.io/atolljs/consumer/#/shared-memory) · [Tasks](https://jwhenry3.github.io/atolljs/consumer/#/tasks) |
|
|
128
|
+
| [`@atolljs/node`](https://www.npmjs.com/package/@atolljs/node) | `node:worker_threads` runtime adapter | [Tasks](https://jwhenry3.github.io/atolljs/consumer/#/tasks) |
|
|
129
|
+
|
|
35
130
|
## Documentation
|
|
36
131
|
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
132
|
+
- **[Atoll — package documentation](https://jwhenry3.github.io/atolljs/consumer/#/quickstart)** —
|
|
133
|
+
the consumer-facing site: quickstart, API guides, framework pages, islands,
|
|
134
|
+
hosting & headers.
|
|
135
|
+
- [`docs/`](docs/README.md) — in-repo documentation covering internals,
|
|
136
|
+
contracts, islands, and per-framework bindings (agents: `AGENTS.md` points
|
|
137
|
+
here before extensive work).
|
|
43
138
|
|
|
44
|
-
##
|
|
139
|
+
## Developing this repo
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
src/ core SDK — contract/ (shared protocol), pool/, worker/
|
|
143
|
+
packages/<fw>/ independently publishable framework bindings
|
|
144
|
+
packages/incidents/ demo domain package (contract + worker + pool)
|
|
145
|
+
examples/<fw>/ per-framework demo apps
|
|
146
|
+
docs/ in-repo markdown documentation (internals + bindings)
|
|
147
|
+
docs-consumer/ consumer docs site (deploys to GitHub Pages on master)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm test # vitest — all suites (sdk + packages + example e2e)
|
|
152
|
+
npm run build # typecheck + lib build
|
|
153
|
+
npm run dev:all # launch every example dev server
|
|
154
|
+
npm run build:pages # consumer docs + examples → dist-pages (GitHub Pages artifact)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Worker demos require cross-origin isolation (COOP/COEP) — the dev servers set it;
|
|
158
|
+
GitHub Pages cannot send headers, so the Pages artifact ships `coi-sw.js`, a
|
|
159
|
+
service worker that injects them (first visit reloads once; islands fall back to
|
|
160
|
+
their poll transport where isolation still isn't available).
|
|
161
|
+
|
|
162
|
+
### Releasing
|
|
45
163
|
|
|
46
164
|
Create a GitHub Release tagged `v<semver>` — `.github/workflows/publish.yml`
|
|
47
165
|
runs the full test suite, builds the core `dist`, stamps every publishable
|
|
@@ -50,7 +168,13 @@ and **stages** each to npm with provenance. Staged versions aren't
|
|
|
50
168
|
installable until a maintainer approves them — `npm stage list` /
|
|
51
169
|
`npm stage approve <stage-id>` (2FA at approval, not in CI), or the Staged
|
|
52
170
|
Packages tab on npmjs.com. Requires a granular `NPM_TOKEN` repo secret.
|
|
53
|
-
Preview the plan locally: `node scripts/publish.mjs v0.1.0 --dry-run
|
|
171
|
+
Preview the plan locally: `node scripts/publish.mjs v0.1.0 --dry-run` —
|
|
172
|
+
it lists the exact tarball contents (`npm pack --dry-run`) and the stage
|
|
173
|
+
commands, with nothing written or published. The workflow run ends with a
|
|
174
|
+
step-summary table of every package staged and its result; each publishable
|
|
175
|
+
manifest also pins `publishConfig.registry` to `registry.npmjs.org`, so the
|
|
176
|
+
destination is declared in the repo rather than resolved from the
|
|
177
|
+
publisher's local npmrc.
|
|
54
178
|
|
|
55
179
|
Staging needs each package to already exist on the registry, so the first
|
|
56
180
|
release is a manual bootstrap — from the repo root:
|
|
@@ -61,10 +185,10 @@ npm ci && npx vite build && npx tsc -p tsconfig.build.json
|
|
|
61
185
|
node scripts/publish.mjs 0.1.0 --direct # prompts for 2FA per package
|
|
62
186
|
```
|
|
63
187
|
|
|
64
|
-
Once
|
|
188
|
+
Once every package exists, release-driven `npm stage publish` works for
|
|
65
189
|
every subsequent version.
|
|
66
190
|
|
|
67
|
-
|
|
191
|
+
#### Trusted publishing (OIDC)
|
|
68
192
|
|
|
69
193
|
Prefer OIDC over the `NPM_TOKEN` secret — no long-lived credential, and a
|
|
70
194
|
trust relationship can be **stage-only** so the workflow can't direct-publish
|
|
@@ -72,7 +196,8 @@ even if compromised. Configure per package (needs the package to exist on
|
|
|
72
196
|
npm, and npm CLI ≥ 11.10):
|
|
73
197
|
|
|
74
198
|
```bash
|
|
75
|
-
for p in
|
|
199
|
+
for p in core node react vue solidjs svelte angular nextjs nestjs \
|
|
200
|
+
islands react-island vue-island svelte-island solid-island angular-island; do
|
|
76
201
|
npm trust github "@atolljs/$p" --repo jwhenry3/atolljs --file publish.yml --allow-stage-publish -y
|
|
77
202
|
sleep 2
|
|
78
203
|
done
|
|
@@ -80,31 +205,6 @@ done
|
|
|
80
205
|
|
|
81
206
|
Omit `--allow-publish` — stage-only. First call prompts for 2FA; choose
|
|
82
207
|
"skip for 5 minutes" and the loop finishes hands-free. Verify with
|
|
83
|
-
`npm trust list @atolljs/core`. Once
|
|
208
|
+
`npm trust list @atolljs/core`. Once every package shows the relationship,
|
|
84
209
|
delete the `NODE_AUTH_TOKEN` env line in `publish.yml` (npm only uses OIDC
|
|
85
210
|
when no token is present) — the secret can be revoked after.
|
|
86
|
-
|
|
87
|
-
## Layout
|
|
88
|
-
|
|
89
|
-
```
|
|
90
|
-
src/ core SDK — contract/ (shared protocol), pool/, worker/
|
|
91
|
-
packages/<fw>/ independently publishable framework bindings
|
|
92
|
-
packages/incidents/ demo domain package (contract + worker + pool)
|
|
93
|
-
examples/<fw>/ per-framework demo apps
|
|
94
|
-
docs/ in-repo markdown documentation (internals + bindings)
|
|
95
|
-
docs-consumer/ consumer docs site
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Scripts
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
npm test # vitest — all suites (sdk + packages + example e2e)
|
|
102
|
-
npm run build # typecheck + lib build
|
|
103
|
-
npm run dev:all # launch every example dev server
|
|
104
|
-
npm run build:pages # consumer docs + examples → dist-pages (GitHub Pages artifact)
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Worker demos require cross-origin isolation (COOP/COEP) — the dev servers set it;
|
|
108
|
-
GitHub Pages cannot send headers, so the Pages artifact ships `coi-sw.js`, a
|
|
109
|
-
service worker that injects them (first visit reloads once; islands fall back to
|
|
110
|
-
their poll transport where isolation still isn't available).
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from './zod';
|
|
2
|
+
import type { ListFieldSpec, ListFields, ListMember } from './sharedMemory';
|
|
3
|
+
/** Maps a list member to the zod shape whose inferred output type is
|
|
4
|
+
* identical to `ListRecord<F>[K]` — zod members pass through as
|
|
5
|
+
* themselves so declared bounds (e.g. `.max(3)`) stay in effect. */
|
|
6
|
+
export type ListZodShape<F extends ListFields> = {
|
|
7
|
+
[K in keyof F]: F[K] extends z.ZodTypeAny ? F[K] : F[K] extends {
|
|
8
|
+
string: number;
|
|
9
|
+
} ? z.ZodType<string> : F[K] extends {
|
|
10
|
+
bool: boolean;
|
|
11
|
+
} ? z.ZodType<boolean> : F[K] extends 'i64' | 'u64' ? z.ZodType<bigint> : z.ZodType<number>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Builds a zod object schema from a member map — the shape you would pass
|
|
15
|
+
* to `mz.object(...)` for `field.list({ schema, count })`. Members may be
|
|
16
|
+
* spec tokens or zod schemas; the result's `z.infer` is the record type:
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* const shape = { id: 'u32', site: { string: 10 } } as const;
|
|
20
|
+
* const schema = listSchema(shape); // zod object with storage bounds
|
|
21
|
+
* type Row = z.infer<typeof schema>;
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* `{ string: n }` fields validate UTF-8 byte length, matching the inline
|
|
25
|
+
* capacity the connector enforces; zod `z.string().meta({ bytes: n })`
|
|
26
|
+
* members get the same bound attached to the declared schema.
|
|
27
|
+
*/
|
|
28
|
+
export declare function listSchema<F extends ListFields>(fields: F): z.ZodObject<ListZodShape<F>>;
|
|
29
|
+
/**
|
|
30
|
+
* Compiles one fixed-layout member — a spec token or a zod schema — to its
|
|
31
|
+
* binary layout form. Throws for members that can't express a fixed-width
|
|
32
|
+
* layout.
|
|
33
|
+
*/
|
|
34
|
+
export declare function memberToSpec(member: ListMember, name: string): ListFieldSpec;
|
|
35
|
+
/** The declared member map of a zod object, or null when `schema` isn't one. */
|
|
36
|
+
export declare function zodObjectShape(schema: unknown): ListFields | null;
|
|
37
|
+
/**
|
|
38
|
+
* Element schema + capacity of a bounded zod array — `.max(n)` /
|
|
39
|
+
* `.length(n)` carry the bound in their checks. Returns null for non-array
|
|
40
|
+
* schemas; `capacity` is null for unbounded arrays.
|
|
41
|
+
*/
|
|
42
|
+
export declare function zodArrayInfo(schema: unknown): {
|
|
43
|
+
element: z.ZodTypeAny;
|
|
44
|
+
capacity: number | null;
|
|
45
|
+
} | null;
|
|
46
|
+
/** The byte budget carried by `mz.string(n)` / `z.string().meta({ bytes: n })` — null otherwise. */
|
|
47
|
+
export declare function zodStringBytes(schema: unknown): number | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Codec } from './sharedMemory';
|
|
2
|
+
/**
|
|
3
|
+
* MessagePack transport codec: smaller payloads than JSON and supports types
|
|
4
|
+
* JSON can't express (Uint8Array, BigInt, etc.). Decoded values are still
|
|
5
|
+
* validated by each field's zod schema.
|
|
6
|
+
*/
|
|
7
|
+
export declare const msgpackCodec: Codec;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from './zod';
|
|
2
|
+
/**
|
|
3
|
+
* Atoll zod — the fixed-width schema vocabulary. Every helper produces a
|
|
4
|
+
* plain zod schema the layout compiler can read a byte width from: number
|
|
5
|
+
* formats (`mz.u32()`), int bounds (`mz.int(0, 3)` → u8), byte budgets
|
|
6
|
+
* (`mz.string(10)`), or flags (`mz.boolean()` → u8). There are no unfixed
|
|
7
|
+
* members — `mz.number()`/`z.date()`/`z.enum()` aren't exposed because they
|
|
8
|
+
* can't promise a width.
|
|
9
|
+
*
|
|
10
|
+
* Width coverage: zod 4 provides int32/uint32/float32/float64/int64/uint64
|
|
11
|
+
* formats; mz fills the gaps (i8/u8/i16/u16 via bounded ints, which the
|
|
12
|
+
* compiler narrows identically) so all ten scalar kinds have one spelling.
|
|
13
|
+
*
|
|
14
|
+
* Composition derives byte width upward — `mz.object({...})` members lay out
|
|
15
|
+
* as a fixed record (field.object derives byteLength from it, no maxBytes),
|
|
16
|
+
* `mz.array(el).max(n)` bounds element capacity for field.array, and
|
|
17
|
+
* `mz.string(n)` carries the budget for field.string. The returned values are
|
|
18
|
+
* ordinary zod schemas — `.meta()`, `.refine()`, `.max()` all still work.
|
|
19
|
+
*/
|
|
20
|
+
export declare const mz: {
|
|
21
|
+
i8: () => import("zod").ZodNumber;
|
|
22
|
+
u8: () => import("zod").ZodNumber;
|
|
23
|
+
i16: () => import("zod").ZodNumber;
|
|
24
|
+
u16: () => import("zod").ZodNumber;
|
|
25
|
+
i32: () => import("zod").ZodInt32;
|
|
26
|
+
u32: () => import("zod").ZodUInt32;
|
|
27
|
+
f32: () => import("zod").ZodFloat32;
|
|
28
|
+
f64: () => import("zod").ZodFloat64;
|
|
29
|
+
i64: () => import("zod").ZodInt64;
|
|
30
|
+
u64: () => import("zod").ZodUInt64;
|
|
31
|
+
/** Bounded int — compiles to the narrowest covering kind (0..3 → u8). */
|
|
32
|
+
int: (min: number, max: number) => import("zod").ZodNumber;
|
|
33
|
+
/** A flag byte — reads and writes as boolean. */
|
|
34
|
+
boolean: () => import("zod").ZodBoolean;
|
|
35
|
+
/** Fixed-capacity inline UTF-8 string — `bytes` is the byte budget. The
|
|
36
|
+
* schema itself refuses over-budget values, so `.parse` and connector
|
|
37
|
+
* writes enforce the same limit. */
|
|
38
|
+
string: (bytes: number) => import("zod").ZodString;
|
|
39
|
+
/** A fixed-layout record shape — every member must be a fixed-width schema. */
|
|
40
|
+
object: <S extends z.ZodRawShape>(shape: S) => import("zod").ZodObject<{ -readonly [P in keyof S]: S[P]; }, import("zod/v4/core").$strip>;
|
|
41
|
+
/** A fixed-stride element — bound it with `.max(n)` or `.length(n)` before field.array. */
|
|
42
|
+
array: <E extends z.ZodTypeAny>(element: E) => import("zod").ZodArray<E>;
|
|
43
|
+
};
|