@solidjs/web 2.0.0-rc.2 → 2.0.0-rc.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/dist/dev.cjs +86 -61
- package/dist/dev.js +81 -60
- package/dist/server.cjs +34 -17
- package/dist/server.js +35 -19
- package/dist/web.cjs +83 -59
- package/dist/web.js +78 -58
- package/frames/dist/client.cjs +8 -8
- package/frames/dist/client.dev.cjs +8 -8
- package/frames/dist/client.dev.js +8 -8
- package/frames/dist/client.js +8 -8
- package/frames/dist/server.cjs +28 -18
- package/frames/dist/server.js +29 -19
- package/package.json +20 -22
- package/serialization/dist/decode.cjs +3 -3
- package/serialization/dist/decode.js +3 -3
- package/serialization/dist/serialization.cjs +7 -11
- package/serialization/dist/serialization.js +7 -6
- package/serialization/types/index.d.ts +69 -157
- package/serialization/types/serializer-decode.d.ts +89 -112
- package/serialization/types/serializer.d.ts +94 -0
- package/serialization/types-cjs/index.d.cts +69 -157
- package/serialization/types-cjs/serializer-decode.d.cts +89 -112
- package/serialization/types-cjs/serializer.d.cts +94 -0
- package/types/client.d.ts +150 -290
- package/types/constants.d.ts +18 -0
- package/types/cookies.d.ts +31 -75
- package/types/frames/frame-client.d.ts +287 -277
- package/types/frames/frame-container-plugin.d.ts +71 -0
- package/types/frames/frame-sink.d.ts +58 -160
- package/types/frames/frame-transport.d.ts +161 -194
- package/types/frames/serializer-decode.d.ts +159 -0
- package/types/frames/serializer.d.ts +69 -157
- package/types/head.d.ts +16 -0
- package/types/index.d.ts +0 -65
- package/types/index.server.d.ts +125 -0
- package/types/jsx.d.ts +5 -13
- package/types/reconcile.d.ts +1 -0
- package/types/render.d.ts +4 -0
- package/types/response.d.ts +41 -153
- package/types/serializer-decode.d.ts +89 -112
- package/types/serializer.d.ts +69 -157
- package/types/server-functions/client.d.ts +93 -222
- package/types/server-functions/flash.d.ts +10 -30
- package/types/server-functions/registry.d.ts +63 -0
- package/types/server-functions/rich-args.d.ts +1 -10
- package/types/server-functions/server.d.ts +292 -574
- package/types/server-functions/shared.d.ts +112 -458
- package/types/server-mock.d.ts +2 -2
- package/types/server.d.ts +242 -434
- package/types-cjs/client.d.cts +150 -290
- package/types-cjs/constants.d.cts +18 -0
- package/types-cjs/cookies.d.cts +31 -75
- package/types-cjs/frames/frame-client.d.cts +287 -277
- package/types-cjs/frames/frame-container-plugin.d.cts +71 -0
- package/types-cjs/frames/frame-sink.d.cts +58 -160
- package/types-cjs/frames/frame-transport.d.cts +161 -194
- package/types-cjs/frames/serializer-decode.d.cts +159 -0
- package/types-cjs/frames/serializer.d.cts +69 -157
- package/types-cjs/head.d.cts +16 -0
- package/types-cjs/index.d.cts +0 -65
- package/types-cjs/index.server.d.cts +125 -0
- package/types-cjs/jsx.d.cts +5 -13
- package/types-cjs/reconcile.d.cts +1 -0
- package/types-cjs/render.d.cts +4 -0
- package/types-cjs/response.d.cts +41 -153
- package/types-cjs/serializer-decode.d.cts +89 -112
- package/types-cjs/serializer.d.cts +69 -157
- package/types-cjs/server-functions/client.d.cts +93 -222
- package/types-cjs/server-functions/flash.d.cts +10 -30
- package/types-cjs/server-functions/registry.d.cts +63 -0
- package/types-cjs/server-functions/rich-args.d.cts +1 -10
- package/types-cjs/server-functions/server.d.cts +292 -574
- package/types-cjs/server-functions/shared.d.cts +112 -458
- package/types-cjs/server-mock.d.cts +2 -2
- package/types-cjs/server.d.cts +242 -434
- package/LICENSE +0 -21
- package/types/core.d.ts +0 -9
- package/types-cjs/core.d.cts +0 -9
|
@@ -1,222 +1,189 @@
|
|
|
1
|
-
|
|
2
|
-
// experimental preview, excluded from the 2.0 stability guarantee: API
|
|
3
|
-
// shapes and the wire format may change between prereleases (RFC 11).
|
|
4
|
-
// Every export in this module is @experimental.
|
|
5
|
-
import { FrameChunk, FrameHost } from "./frame-client.js";
|
|
1
|
+
import { FrameHost } from "./frame-client.js";
|
|
6
2
|
import { JSONCodecOptions } from "./serializer-decode.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// copy the frames declaration set (solid-web's types build), and the
|
|
11
|
-
// server-functions declarations are copied to a different root.
|
|
12
|
-
type FlightConsumer = (data: unknown, context: { response: Response }) => void | Promise<void>;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Header tagging a Response as a frame stream; its value is the producing
|
|
16
|
-
* frame's id. Frame-owned wire contract — deliberately not a server-function
|
|
17
|
-
* `BodyFormat` entry, since the body is frame chunks, not a serialized value.
|
|
18
|
-
* @experimental
|
|
19
|
-
*/
|
|
20
|
-
export const FRAME_STREAM_HEADER: "X-Frame-Stream";
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Whether a fetch Response carries a frame stream.
|
|
24
|
-
* @experimental
|
|
25
|
-
*/
|
|
26
|
-
export function isFrameStreamResponse(response: Response): boolean;
|
|
27
|
-
|
|
3
|
+
type FlightConsumer = (data: unknown, context: {
|
|
4
|
+
response: Response;
|
|
5
|
+
}) => void | Promise<void>;
|
|
28
6
|
/**
|
|
29
7
|
* Options for `applyFrameResponse`.
|
|
30
8
|
* @experimental
|
|
31
9
|
*/
|
|
32
10
|
export interface ApplyFrameResponseOptions {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Remap the producer's root frame id onto a local one — the id your
|
|
13
|
+
* insertable/frame registered under — so navigations to the same boundary
|
|
14
|
+
* reuse the same frame regardless of what the server called it. Boundary
|
|
15
|
+
* identity belongs to the client.
|
|
16
|
+
*/
|
|
17
|
+
as?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Restamp every chunk of the response with this version (one response IS
|
|
20
|
+
* one version). Versions belong to the client too: the producer cannot
|
|
21
|
+
* know how many streams a boundary has consumed, so pass the Nth-response
|
|
22
|
+
* counter to make policy A's stale-guard real across navigations. A
|
|
23
|
+
* single-flight response addresses several boundaries, each with its own
|
|
24
|
+
* history — pass a function and it is called once per frame in the
|
|
25
|
+
* response.
|
|
26
|
+
*/
|
|
27
|
+
version?: number | ((frameId: string) => number);
|
|
28
|
+
/**
|
|
29
|
+
* Receives the payload text of each `outcome` chunk — the response-scoped
|
|
30
|
+
* single-flight envelope, the caller's result rather than anything the
|
|
31
|
+
* host renders.
|
|
32
|
+
*/
|
|
33
|
+
onOutcome?(payload: string): void;
|
|
56
34
|
}
|
|
57
|
-
|
|
58
35
|
/**
|
|
59
|
-
*
|
|
60
|
-
* `host`. Chunks are length-prefixed JSON over the server-function wire
|
|
61
|
-
* framing. Resolves with the id the chunks were applied under once the
|
|
62
|
-
* stream ends; rejects on a malformed or errored stream.
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```ts
|
|
66
|
-
* const response = await getStory(id); // frame-tagged server function result
|
|
67
|
-
* if (isFrameStreamResponse(response)) {
|
|
68
|
-
* await applyFrameResponse(response, host, { as: "story-pane" });
|
|
69
|
-
* }
|
|
70
|
-
* ```
|
|
36
|
+
* The value under `COMPONENT_BINDING` on a transport-resolved binding.
|
|
71
37
|
* @experimental
|
|
72
38
|
*/
|
|
73
|
-
export
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
39
|
+
export interface ComponentBinding<C = unknown> {
|
|
40
|
+
/** The per-function mount component (the equals-gate identity). */
|
|
41
|
+
component: C;
|
|
42
|
+
/** The call's intrinsic (function, arguments) address — its store's key. */
|
|
43
|
+
address: string;
|
|
44
|
+
}
|
|
79
45
|
/**
|
|
80
|
-
*
|
|
46
|
+
* Options for `createServerComponentHandler`.
|
|
81
47
|
* @experimental
|
|
82
48
|
*/
|
|
83
|
-
export
|
|
84
|
-
|
|
49
|
+
export interface ServerComponentHandlerOptions<C = unknown> {
|
|
50
|
+
host: FrameHost;
|
|
51
|
+
/**
|
|
52
|
+
* Builds the framework's mount component for a server FUNCTION. Invoked
|
|
53
|
+
* once per function and cached — this is the equals-gate identity every
|
|
54
|
+
* call of the function resolves through. The component is CALLED (by the
|
|
55
|
+
* binding wrapper or a gated reader), receiving its current address as a
|
|
56
|
+
* second argument (`() => string`); it should (re-)bind its frame's pull
|
|
57
|
+
* to that address's store. Multi-mount fans out per site.
|
|
58
|
+
*/
|
|
59
|
+
component(fnId: string): C;
|
|
60
|
+
/**
|
|
61
|
+
* A new response is about to stream into an address: rotate
|
|
62
|
+
* response-scoped state (codec data tables) here. `version` is the
|
|
63
|
+
* client-owned stream counter the chunks will be stamped with.
|
|
64
|
+
*/
|
|
65
|
+
onStream?(address: string, version: number, response: Response): void;
|
|
66
|
+
/**
|
|
67
|
+
* Answer a call SYNCHRONOUSLY before any request is made (t = 0 local
|
|
68
|
+
* answers — e.g. a boundary the document already carries). Returning a
|
|
69
|
+
* non-undefined value resolves the call with it; a hydrating consumer
|
|
70
|
+
* never observes a pending beat.
|
|
71
|
+
*/
|
|
72
|
+
intercept?(info: {
|
|
73
|
+
id: string;
|
|
74
|
+
meta: unknown;
|
|
75
|
+
args: unknown[];
|
|
76
|
+
}): C | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Reads the registered single-flight consumer at delivery time. The
|
|
79
|
+
* consumer is module state in the server-function client's SHARED
|
|
80
|
+
* instance; pass a getter reading that instance when your bundling gives
|
|
81
|
+
* this module a private copy. Defaults to the local copy's reader.
|
|
82
|
+
*/
|
|
83
|
+
consumer?(): FlightConsumer | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Reads the configured codec options at decode time — same instance-
|
|
86
|
+
* identity contract as `consumer`. Defaults to the local copy's reader.
|
|
87
|
+
*/
|
|
88
|
+
codec?(): JSONCodecOptions | undefined;
|
|
89
|
+
}
|
|
85
90
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
91
|
+
* Header tagging a Response as a frame stream; its value is the producing
|
|
92
|
+
* frame's id. Frame-owned contract (hence the namespace) — deliberately not
|
|
93
|
+
* a `BodyFormat` entry, since the body is frame chunks, not a serialized
|
|
94
|
+
* value.
|
|
88
95
|
*/
|
|
89
|
-
export const
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* The call's wire address (`frameAddress`), for regions to be emitted under.
|
|
96
|
+
export declare const FRAME_STREAM_HEADER = "X-Frame-Stream"; /**
|
|
97
|
+
* Whether a fetch Response carries a frame stream.
|
|
93
98
|
* @experimental
|
|
94
99
|
*/
|
|
95
|
-
export
|
|
96
|
-
|
|
100
|
+
export declare function isFrameStreamResponse(response: Response): boolean;
|
|
101
|
+
export declare function applyFrameResponse(response: Response, host: FrameHost, options?: ApplyFrameResponseOptions): Promise<string>;
|
|
102
|
+
/** Brands an inline-rendered server component with its function id. */
|
|
103
|
+
export declare const SERVER_COMPONENT: unique symbol;
|
|
104
|
+
/** The unwrapped server component behind an inline-render wrap. */
|
|
105
|
+
export declare const SERVER_COMPONENT_SOURCE: unique symbol;
|
|
106
|
+
/** The call's wire address (`frameAddress`), for regions to be emitted under. */
|
|
107
|
+
export declare const SERVER_COMPONENT_ADDRESS: unique symbol;
|
|
97
108
|
/**
|
|
98
109
|
* The binding brand on values the transport resolves: `{ component, address }`
|
|
99
|
-
*
|
|
100
|
-
* server
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* The value under `COMPONENT_BINDING` on a transport-resolved binding.
|
|
111
|
-
* @experimental
|
|
110
|
+
* (see `createServerComponentHandler`). The identity split (DR-1,
|
|
111
|
+
* docs/server-components-principles.md): `component` is the MOUNT identity —
|
|
112
|
+
* one per server function, stable across every call — while `address` names
|
|
113
|
+
* the call's content store. An equals-gated reader (a framework's `dynamic`)
|
|
114
|
+
* compares `component` across resolutions: same function means "same
|
|
115
|
+
* instance, new binding" — it keeps its mounted instance and delivers the
|
|
116
|
+
* new address into it (the instance's frame re-binds its pull to that
|
|
117
|
+
* address's resident store) — and a different function swaps normally.
|
|
118
|
+
* `Symbol.for`, so consumers honor it without importing this module.
|
|
112
119
|
*/
|
|
113
|
-
export
|
|
114
|
-
|
|
115
|
-
component: C;
|
|
116
|
-
/** The call's intrinsic (function, arguments) address — its store's key. */
|
|
117
|
-
address: string;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
+
export declare const COMPONENT_BINDING: unique symbol;
|
|
121
|
+
export declare function setServerComponentBootstrap(resolve: (ctx: unknown) => string): void;
|
|
120
122
|
/**
|
|
121
|
-
* Seroval plugin for a server component crossing a serialization boundary
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
123
|
+
* Seroval plugin for a server component crossing a serialization boundary.
|
|
124
|
+
* A branded component (see `frameTransformDirectResult`) serializes as a
|
|
125
|
+
* REFERENCE — its markup never rides as data.
|
|
126
|
+
*
|
|
127
|
+
* Two distinct consumers share the one tag:
|
|
128
|
+
*
|
|
129
|
+
* - `serialize` (eval-style, the document hydration serializer): emits
|
|
130
|
+
* `self._$SC.r("<function id>")`. The document shell's inline bootstrap
|
|
131
|
+
* memoizes a stable placeholder per FUNCTION — a delegating shell whose
|
|
132
|
+
* every mount binds to its own SSR'd element during adoption — so the
|
|
133
|
+
* address adds nothing at t=0 and the reference stays id-keyed.
|
|
134
|
+
* - `deserialize` (the JSON codec): the codec only ever carries a component
|
|
135
|
+
* inside a single-flight envelope, so this is a FLIGHT reference. It must
|
|
136
|
+
* resolve to the exact object the reading call site already holds — an
|
|
137
|
+
* integration seeding its cache with anything else fails the consumer's
|
|
138
|
+
* equals-gate and remounts the boundary — so it resolves through the live
|
|
139
|
+
* transport registry by the call's address.
|
|
138
140
|
*/
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
declare function parseServerComponent(value: any, ctx: any): {
|
|
142
|
+
id: any;
|
|
143
|
+
address: any;
|
|
144
|
+
};
|
|
145
|
+
/** @type {import("seroval").Plugin<Function, { id: any, address: any }>} */
|
|
146
|
+
export declare const ServerComponentPlugin: {
|
|
147
|
+
tag: string;
|
|
148
|
+
test(value: any): boolean;
|
|
149
|
+
parse: {
|
|
150
|
+
sync: typeof parseServerComponent;
|
|
151
|
+
async(value: any, ctx: any): Promise<{
|
|
152
|
+
id: any;
|
|
153
|
+
address: any;
|
|
154
|
+
}>;
|
|
155
|
+
stream: typeof parseServerComponent;
|
|
156
|
+
};
|
|
157
|
+
serialize(node: any, ctx: any): string;
|
|
158
|
+
deserialize(node: any, ctx: any): any;
|
|
159
|
+
}; /**
|
|
142
160
|
* The codec options for a single-flight envelope: `codec` plus
|
|
143
161
|
* `ServerComponentPlugin` (deduped by tag). Injected by the protocol on both
|
|
144
162
|
* legs; exported for integrations composing their own flight carriers.
|
|
145
163
|
* @experimental
|
|
146
164
|
*/
|
|
147
|
-
export function flightCodec(codec?: JSONCodecOptions): JSONCodecOptions;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Answer a call SYNCHRONOUSLY before any request is made (t = 0 local
|
|
172
|
-
* answers — e.g. a boundary the document already carries). Returning a
|
|
173
|
-
* non-undefined value resolves the call with it; a hydrating consumer
|
|
174
|
-
* never observes a pending beat.
|
|
175
|
-
*/
|
|
176
|
-
intercept?(info: { id: string; meta: unknown; args: unknown[] }): C | undefined;
|
|
177
|
-
/**
|
|
178
|
-
* Reads the registered single-flight consumer at delivery time. The
|
|
179
|
-
* consumer is module state in the server-function client's SHARED
|
|
180
|
-
* instance; pass a getter reading that instance when your bundling gives
|
|
181
|
-
* this module a private copy. Defaults to the local copy's reader.
|
|
182
|
-
*/
|
|
183
|
-
consumer?(): FlightConsumer | undefined;
|
|
184
|
-
/**
|
|
185
|
-
* Reads the configured codec options at decode time — same instance-
|
|
186
|
-
* identity contract as `consumer`. Defaults to the local copy's reader.
|
|
187
|
-
*/
|
|
188
|
-
codec?(): JSONCodecOptions | undefined;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* The client mirror of `frameTransformResult`, shaped for the server-function
|
|
193
|
-
* client's `responseHandler` seam: frame-stream responses resolve the call
|
|
194
|
-
* with a **binding** — a callable wrapper branded `COMPONENT_BINDING` — so
|
|
195
|
-
* an equals-gated consumer (Solid's `dynamic`) never remounts across
|
|
196
|
-
* refetches or argument changes; the response streams into the address's
|
|
197
|
-
* resident store as the only observable effect.
|
|
198
|
-
*
|
|
199
|
-
* The identity split (DR-1): stores are keyed per-ADDRESS — the call's
|
|
200
|
-
* intrinsic (function, arguments) name, one-to-one with a query cache's
|
|
201
|
-
* per-args entries — while mounts are per-SITE, rendering the per-function
|
|
202
|
-
* component and following delivered addresses. An address nothing is bound
|
|
203
|
-
* to warms its store (preload isolation is the default, not a rule).
|
|
204
|
-
* @experimental
|
|
205
|
-
*/
|
|
206
|
-
export function createServerComponentHandler<C>(options: ServerComponentHandlerOptions<C>): {
|
|
207
|
-
intercept?(info: { id: string; meta: unknown; args: unknown[] }): unknown;
|
|
208
|
-
handle(
|
|
209
|
-
response: Response,
|
|
210
|
-
ctx: { id: string; meta: unknown; args: unknown[]; context: unknown }
|
|
211
|
-
): unknown;
|
|
212
|
-
/**
|
|
213
|
-
* Declares that the document is showing a call: hydration-data references
|
|
214
|
-
* carry their call's address (`_$SC.r(id, address)`) but never travel
|
|
215
|
-
* through the transport, so the integration forwards those records here.
|
|
216
|
-
* Mints the call's binding (a post-load refetch then resolves a value
|
|
217
|
-
* whose component matches what the document mounted) and brands the
|
|
218
|
-
* per-function component so cache-seeded readers deliver instead of
|
|
219
|
-
* remounting when their site later switches calls.
|
|
220
|
-
*/
|
|
221
|
-
showing(address: string, functionId: string): void;
|
|
165
|
+
export declare function flightCodec(codec?: JSONCodecOptions): JSONCodecOptions;
|
|
166
|
+
export declare function createServerComponentHandler<C>(options: ServerComponentHandlerOptions<C>): {
|
|
167
|
+
intercept?(info: {
|
|
168
|
+
id: string;
|
|
169
|
+
meta: unknown;
|
|
170
|
+
args: unknown[];
|
|
171
|
+
}): unknown;
|
|
172
|
+
handle(response: Response, ctx: {
|
|
173
|
+
id: string;
|
|
174
|
+
meta: unknown;
|
|
175
|
+
args: unknown[];
|
|
176
|
+
context: unknown;
|
|
177
|
+
}): unknown;
|
|
178
|
+
/**
|
|
179
|
+
* Declares that the document is showing a call: hydration-data references
|
|
180
|
+
* carry their call's address (`_$SC.r(id, address)`) but never travel
|
|
181
|
+
* through the transport, so the integration forwards those records here.
|
|
182
|
+
* Mints the call's binding (a post-load refetch then resolves a value
|
|
183
|
+
* whose component matches what the document mounted) and brands the
|
|
184
|
+
* per-function component so cache-seeded readers deliver instead of
|
|
185
|
+
* remounting when their site later switches calls.
|
|
186
|
+
*/
|
|
187
|
+
showing(address: string, functionId: string): void;
|
|
222
188
|
};
|
|
189
|
+
export {};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seroval's node shape — the intermediate representation `serializeJSON`
|
|
3
|
+
* emits and `createJSONDeserializer` consumes. Safe to `JSON.stringify`.
|
|
4
|
+
* Declared by hand like the plugin types below (same rationale): the
|
|
5
|
+
* observable envelope — a numeric type tag, an optional reference id —
|
|
6
|
+
* with the rest owned by the codec. Real seroval nodes satisfy it; treat
|
|
7
|
+
* it as an opaque token.
|
|
8
|
+
*
|
|
9
|
+
* Integration-facing; may change (see the entry banner).
|
|
10
|
+
*/
|
|
11
|
+
export interface SerovalNode {
|
|
12
|
+
/** Node type tag (seroval-internal enum). */
|
|
13
|
+
t: number;
|
|
14
|
+
/** Reference id, when the node participates in cross-referencing. */
|
|
15
|
+
i?: number | undefined;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
/** Per-plugin bookkeeping seroval hands each plugin callback. */
|
|
19
|
+
export interface PluginData {
|
|
20
|
+
id: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The shape of a plugin's parsed payload: a map of `SerovalNode`s produced
|
|
24
|
+
* by the parse contexts, consumed by `serialize`/`deserialize`.
|
|
25
|
+
*/
|
|
26
|
+
export type PluginInfo = {
|
|
27
|
+
[key: string]: SerovalNode;
|
|
28
|
+
};
|
|
29
|
+
/** Parse context for `parse.sync`: turns child values into nodes. */
|
|
30
|
+
export interface SyncParsePluginContext {
|
|
31
|
+
parse<T>(current: T): SerovalNode;
|
|
32
|
+
}
|
|
33
|
+
/** Parse context for `parse.async`: like sync, but child parses await. */
|
|
34
|
+
export interface AsyncParsePluginContext {
|
|
35
|
+
parse<T>(current: T): Promise<SerovalNode>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Parse context for `parse.stream`: sync parsing plus the streaming
|
|
39
|
+
* lifecycle (pending-state tracking, late node emission, cleanup).
|
|
40
|
+
*/
|
|
41
|
+
export interface StreamParsePluginContext {
|
|
42
|
+
parse<T>(current: T): SerovalNode;
|
|
43
|
+
parseWithError<T>(current: T): SerovalNode | undefined;
|
|
44
|
+
isAlive(): boolean;
|
|
45
|
+
pushPendingState(): void;
|
|
46
|
+
popPendingState(): void;
|
|
47
|
+
onParse(node: SerovalNode): void;
|
|
48
|
+
onError(error: unknown): void;
|
|
49
|
+
addCleanup(callback: () => void): void;
|
|
50
|
+
}
|
|
51
|
+
/** Serialize context: renders child nodes to JS source. */
|
|
52
|
+
export interface SerializePluginContext {
|
|
53
|
+
serialize(node: SerovalNode): string;
|
|
54
|
+
}
|
|
55
|
+
/** Deserialize context: revives child nodes to runtime values. */
|
|
56
|
+
export interface DeserializePluginContext {
|
|
57
|
+
deserialize<T>(node: SerovalNode): T;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A Seroval plugin usable with the web serializers — teaches the codec how
|
|
61
|
+
* to encode/decode a custom value type (`Value` is the value it matches,
|
|
62
|
+
* `Info` its parsed payload). Supply matching plugins on both peers of a
|
|
63
|
+
* transport. Bare `SerializerPlugin` (both parameters defaulted to `any`)
|
|
64
|
+
* is the list-element type every `plugins` option accepts.
|
|
65
|
+
*
|
|
66
|
+
* Integration-facing; may change (see the entry banner).
|
|
67
|
+
*/
|
|
68
|
+
export interface SerializerPlugin<Value = any, Info extends PluginInfo = any> {
|
|
69
|
+
/** A unique string identifying the plugin — namespace it (`"app/Thing"`). */
|
|
70
|
+
tag: string;
|
|
71
|
+
/** Dependency plugins, resolved ahead of this one. */
|
|
72
|
+
extends?: SerializerPlugin[];
|
|
73
|
+
/** Whether `value` is this plugin's to encode. */
|
|
74
|
+
test(value: unknown): boolean;
|
|
75
|
+
/** Parsing modes — provide the ones the transports you target use. */
|
|
76
|
+
parse: {
|
|
77
|
+
sync?: (value: Value, ctx: SyncParsePluginContext, data: PluginData) => Info;
|
|
78
|
+
async?: (value: Value, ctx: AsyncParsePluginContext, data: PluginData) => Promise<Info>;
|
|
79
|
+
stream?: (value: Value, ctx: StreamParsePluginContext, data: PluginData) => Info;
|
|
80
|
+
};
|
|
81
|
+
/** Renders the parsed payload as JS source (script-injection form). */
|
|
82
|
+
serialize(node: Info, ctx: SerializePluginContext, data: PluginData): string;
|
|
83
|
+
/** Revives the parsed payload back into the runtime value. */
|
|
84
|
+
deserialize(node: Info, ctx: DeserializePluginContext, data: PluginData): Value;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Options shared by both halves of the JSON codec. All of them must match
|
|
88
|
+
* on the serializing and deserializing peer or payloads will not
|
|
89
|
+
* round-trip — for server functions, set them once through the
|
|
90
|
+
* client/server `codec` config option.
|
|
91
|
+
*
|
|
92
|
+
* Integration-facing; may change (see the entry banner).
|
|
93
|
+
*/
|
|
94
|
+
export interface JSONCodecOptions {
|
|
95
|
+
/** Extra plugins, composed ahead of `DEFAULT_WEB_PLUGINS`. Must match on both peers. */
|
|
96
|
+
plugins?: SerializerPlugin[];
|
|
97
|
+
/**
|
|
98
|
+
* Seroval feature bitflags to exclude. Defaults to disabling `RegExp`
|
|
99
|
+
* (payloads may come from an untrusted peer). Must match on both peers.
|
|
100
|
+
* Outside development, the encoding side additionally strips
|
|
101
|
+
* `Error.prototype.stack` on top of any override — serialized stacks leak
|
|
102
|
+
* server paths to the client. Decoding stays permissive, so payloads from
|
|
103
|
+
* a development peer still round-trip.
|
|
104
|
+
*/
|
|
105
|
+
disabledFeatures?: number;
|
|
106
|
+
/** Maximum parse/deserialize depth. Defaults to 64. Must match on both peers. */
|
|
107
|
+
depthLimit?: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* A resident, response-scoped decode table over the keyed JSON codec: apply
|
|
111
|
+
* each frame `data` chunk with `apply`, resolve `{ $ref }` slot args with
|
|
112
|
+
* `resolve`. The frames client host wires one per response
|
|
113
|
+
* (`applyData: c => table.apply(c)`).
|
|
114
|
+
*
|
|
115
|
+
* Integration-facing; may change (see the entry banner). This serialization
|
|
116
|
+
* entry is the single home of the data table — the frames client consumes
|
|
117
|
+
* it internally rather than re-exporting it.
|
|
118
|
+
*/
|
|
119
|
+
export interface JSONDataTable {
|
|
120
|
+
apply(chunk: {
|
|
121
|
+
key?: string;
|
|
122
|
+
node?: unknown;
|
|
123
|
+
initial?: boolean;
|
|
124
|
+
}): void;
|
|
125
|
+
resolve<T = unknown>(ref: {
|
|
126
|
+
$ref: string;
|
|
127
|
+
}): T;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Baseline plugin set for serializing web-platform values. Shared by the
|
|
131
|
+
* hydration serializer and any consumer building its own serializer (e.g.
|
|
132
|
+
* server function transports). Plugin objects carry both their serialize
|
|
133
|
+
* and deserialize halves, so the set lives on the decode side and the
|
|
134
|
+
* encode module composes over it.
|
|
135
|
+
*/
|
|
136
|
+
export declare const DEFAULT_WEB_PLUGINS: any; /**
|
|
137
|
+
* Composes custom plugins with `DEFAULT_WEB_PLUGINS`. Custom plugins come
|
|
138
|
+
* first so they can shadow a default for values both would match. Returns a
|
|
139
|
+
* fresh array; the defaults are never mutated. Useful when handing a full
|
|
140
|
+
* plugin list to another serialization layer.
|
|
141
|
+
*
|
|
142
|
+
* Integration-facing; may change (see the entry banner).
|
|
143
|
+
*/
|
|
144
|
+
export declare function resolveSerializerPlugins(customPlugins?: SerializerPlugin[]): SerializerPlugin[];
|
|
145
|
+
export declare function resolveCodecOptions({ plugins, disabledFeatures, depthLimit }?: JSONCodecOptions): {
|
|
146
|
+
plugins: SerializerPlugin<any, any>[];
|
|
147
|
+
disabledFeatures: any;
|
|
148
|
+
depthLimit: number;
|
|
149
|
+
}; /**
|
|
150
|
+
* Creates the decoding counterpart of `serializeJSON`. Cross-references
|
|
151
|
+
* between chunks resolve through state shared across calls, so all chunks
|
|
152
|
+
* from one stream must go through the same deserializer instance. The first
|
|
153
|
+
* chunk's return value is the decoded source value; feeding later chunks
|
|
154
|
+
* settles the async values referenced inside it.
|
|
155
|
+
*
|
|
156
|
+
* Integration-facing; may change (see the entry banner).
|
|
157
|
+
*/
|
|
158
|
+
export declare function createJSONDeserializer(options?: JSONCodecOptions): <T>(node: SerovalNode) => T;
|
|
159
|
+
export declare function createJSONDataTable(options?: JSONCodecOptions): JSONDataTable;
|