@solidjs/web 2.0.0-beta.27 → 2.0.0-beta.29
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 +40 -2
- package/dist/dev.js +39 -4
- package/dist/server.cjs +113 -37
- package/dist/server.js +112 -39
- package/dist/web.cjs +40 -2
- package/dist/web.js +39 -4
- package/frames/dist/client.cjs +370 -209
- package/frames/dist/client.dev.cjs +370 -210
- package/frames/dist/client.dev.js +371 -211
- package/frames/dist/client.js +371 -210
- package/frames/dist/server.cjs +373 -74
- package/frames/dist/server.js +373 -75
- package/package.json +3 -3
- package/server-functions/dist/client.cjs +100 -3
- package/server-functions/dist/client.js +92 -4
- package/server-functions/dist/server.cjs +85 -17
- package/server-functions/dist/server.js +83 -17
- package/types/client.d.ts +15 -0
- package/types/core.d.ts +1 -1
- package/types/frames/client.d.ts +8 -5
- package/types/frames/frame-client.d.ts +17 -0
- package/types/frames/frame-sink.d.ts +29 -6
- package/types/frames/frame-transport.d.ts +76 -12
- package/types/frames/server.d.ts +29 -1
- package/types/index.d.ts +74 -0
- package/types/server-functions/client.d.ts +25 -0
- package/types/server-functions/server.d.ts +105 -18
- package/types/server-functions/shared.d.ts +22 -0
- package/types/server-mock.d.ts +6 -2
- package/types/server.d.ts +39 -1
- package/types-cjs/client.d.cts +15 -0
- package/types-cjs/core.d.cts +1 -1
- package/types-cjs/frames/client.d.cts +8 -5
- package/types-cjs/frames/frame-client.d.cts +17 -0
- package/types-cjs/frames/frame-sink.d.cts +29 -6
- package/types-cjs/frames/frame-transport.d.cts +76 -12
- package/types-cjs/frames/server.d.cts +29 -1
- package/types-cjs/index.d.cts +74 -0
- package/types-cjs/server-functions/client.d.cts +25 -0
- package/types-cjs/server-functions/server.d.cts +105 -18
- package/types-cjs/server-functions/shared.d.cts +22 -0
- package/types-cjs/server-mock.d.cts +6 -2
- package/types-cjs/server.d.cts +39 -1
|
@@ -11,6 +11,7 @@ export {
|
|
|
11
11
|
clearFlashCookie,
|
|
12
12
|
decodeErrorHeaderValue,
|
|
13
13
|
decodeResponse,
|
|
14
|
+
decodeResponsePayload,
|
|
14
15
|
encodeErrorHeaderValue,
|
|
15
16
|
getServerFunctionMetadata,
|
|
16
17
|
hasFlashCookie,
|
|
@@ -31,8 +32,9 @@ import { ServerFunction } from "./shared.js";
|
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* The request event a server function call runs under: the base
|
|
34
|
-
* `RequestEvent` (request + locals)
|
|
35
|
-
* an in-process SSR invocation whose result never serializes to a
|
|
35
|
+
* `RequestEvent` (request + locals) with `serverOnly` added, set when the
|
|
36
|
+
* call is an in-process SSR invocation whose result never serializes to a
|
|
37
|
+
* client.
|
|
36
38
|
*/
|
|
37
39
|
export interface ServerFunctionEvent extends RequestEvent {
|
|
38
40
|
serverOnly?: boolean;
|
|
@@ -68,6 +70,29 @@ export interface ServerFunctionOutcome {
|
|
|
68
70
|
request: Request;
|
|
69
71
|
/** Whether the result was thrown rather than returned. */
|
|
70
72
|
thrown: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* The URL the client will show after the mutation — the redirect
|
|
75
|
+
* `Location` when the outcome carries one (resolved against the request
|
|
76
|
+
* URL, as a browser would), the referring page otherwise. Undefined
|
|
77
|
+
* without a usable referer (a non-browser caller has no page to produce
|
|
78
|
+
* data for) and for redirects leaving the app's origin: produce no data
|
|
79
|
+
* when this is undefined.
|
|
80
|
+
*/
|
|
81
|
+
targetUrl: string | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* The outcome's `X-Revalidate` keys, split — the invalidation scope the
|
|
84
|
+
* mutation declared. Undefined when the outcome carries none (integrations
|
|
85
|
+
* typically collect everything for the target in that case).
|
|
86
|
+
*/
|
|
87
|
+
revalidateKeys: string[] | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* The request headers with the mutation's cookie effects applied: the
|
|
90
|
+
* event response's `Set-Cookie`s (set during the call), then the
|
|
91
|
+
* outcome's own (e.g. `redirect(to, { headers })`), later winning on
|
|
92
|
+
* conflict, deletions honored. Build the data-collection request from
|
|
93
|
+
* these so re-run reads observe post-mutation cookie state.
|
|
94
|
+
*/
|
|
95
|
+
foldedHeaders: Headers;
|
|
71
96
|
}
|
|
72
97
|
|
|
73
98
|
/**
|
|
@@ -82,8 +107,12 @@ export interface ServerFunctionOutcome {
|
|
|
82
107
|
* Runs after `transformResult`, only for scripted calls that sent
|
|
83
108
|
* `SINGLE_FLIGHT_HEADER` on the request, on returned results and thrown
|
|
84
109
|
* `Response`/`ResponseEnvelope` control-flow signals alike (plain thrown
|
|
85
|
-
* errors never collect
|
|
86
|
-
*
|
|
110
|
+
* errors never collect, and neither do raw body-carrying `Response` values
|
|
111
|
+
* — those are the caller's verbatim payload). The handler owns the
|
|
112
|
+
* enveloping: contributed data ships as `{ value, data }` under the
|
|
113
|
+
* single-flight response header. The generic halves of collection arrive
|
|
114
|
+
* pre-digested on the outcome (`targetUrl`, `revalidateKeys`,
|
|
115
|
+
* `foldedHeaders`); the hook supplies only the data strategy.
|
|
87
116
|
*/
|
|
88
117
|
export type CollectFlightDataHook = (
|
|
89
118
|
event: ServerFunctionEvent,
|
|
@@ -168,13 +197,36 @@ export interface ServerFunctionsServerConfig {
|
|
|
168
197
|
transformResult?(
|
|
169
198
|
event: ServerFunctionEvent,
|
|
170
199
|
result: unknown,
|
|
171
|
-
context: {
|
|
200
|
+
context: {
|
|
201
|
+
id: string;
|
|
202
|
+
args: unknown[];
|
|
203
|
+
instance: string | null;
|
|
204
|
+
request: Request;
|
|
205
|
+
thrown?: boolean;
|
|
206
|
+
}
|
|
172
207
|
): unknown | ResponseEnvelope | Promise<unknown | ResponseEnvelope>;
|
|
208
|
+
/**
|
|
209
|
+
* `transformResult`'s counterpart for the single-flight fold: when a
|
|
210
|
+
* call's flight payload needs a body only a policy knows how to build
|
|
211
|
+
* (frames' `frameTransformFlightResult` — an invalidated entry is
|
|
212
|
+
* markup), this gets first refusal on the `{ value, data }` outcome.
|
|
213
|
+
* Return a `Response` to carry the outcome (call headers and cookies are
|
|
214
|
+
* copied onto it), or `undefined` to decline and keep the plain
|
|
215
|
+
* serialized envelope. A per-request option overrides it.
|
|
216
|
+
*/
|
|
217
|
+
transformFlightResult?(
|
|
218
|
+
event: ServerFunctionEvent,
|
|
219
|
+
outcome: { value: unknown; data: unknown },
|
|
220
|
+
context: { id: string; args: unknown[]; instance: string | null; request: Request }
|
|
221
|
+
): Response | undefined | Promise<Response | undefined>;
|
|
173
222
|
/**
|
|
174
223
|
* The in-process mirror of `transformResult` for direct (same-server)
|
|
175
224
|
* calls during document SSR — e.g. frames' `frameTransformDirectResult`.
|
|
176
225
|
*/
|
|
177
|
-
transformDirectResult?(
|
|
226
|
+
transformDirectResult?(
|
|
227
|
+
value: unknown,
|
|
228
|
+
options: { id: string; args: unknown[]; event: ServerFunctionEvent }
|
|
229
|
+
): unknown;
|
|
178
230
|
/**
|
|
179
231
|
* Server-wide response builder for calls made without the client runtime
|
|
180
232
|
* (see `handleNoJS` in `HandleServerFunctionRequestOptions`); a
|
|
@@ -305,17 +357,33 @@ export function GET<A extends readonly any[], R>(
|
|
|
305
357
|
fn: (...args: A) => R
|
|
306
358
|
): ServerFunction<A, Awaited<R>>;
|
|
307
359
|
|
|
308
|
-
/** Identity of the currently executing server function. */
|
|
309
|
-
export interface
|
|
360
|
+
/** Identity of the currently executing server function call. */
|
|
361
|
+
export interface ServerFunctionInvocation {
|
|
310
362
|
id: string;
|
|
311
363
|
}
|
|
312
364
|
|
|
313
365
|
/**
|
|
314
|
-
* Reads the
|
|
315
|
-
* event — usable inside a server function body, e.g. to key caches
|
|
316
|
-
* by function. Returns undefined outside a server function call.
|
|
366
|
+
* Reads the in-flight server function invocation (its id) for the current
|
|
367
|
+
* request event — usable inside a server function body, e.g. to key caches
|
|
368
|
+
* or logs by function. Returns undefined outside a server function call.
|
|
369
|
+
* The state lives in a module-private WeakMap keyed by the per-call request
|
|
370
|
+
* event (never in `event.locals`, which derived events share with their
|
|
371
|
+
* outer event). Distinct from `getServerFunctionMetadata(fn)`, which reads
|
|
372
|
+
* a reference's static declaration metadata; this describes the call
|
|
373
|
+
* currently executing.
|
|
374
|
+
*/
|
|
375
|
+
export function getServerFunctionInvocation(): ServerFunctionInvocation | undefined;
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* The event-keyed half of `getServerFunctionInvocation`, for callers handed
|
|
379
|
+
* an event outside its provideEvent scope (the handler's result transforms
|
|
380
|
+
* run after the scope has exited). Integration plumbing — application code
|
|
381
|
+
* reads the ambient accessor instead.
|
|
382
|
+
* @internal
|
|
317
383
|
*/
|
|
318
|
-
export function
|
|
384
|
+
export function getEventServerFunctionInvocation(
|
|
385
|
+
event: RequestEvent | undefined
|
|
386
|
+
): ServerFunctionInvocation | undefined;
|
|
319
387
|
|
|
320
388
|
/**
|
|
321
389
|
* Hooks layering framework policy onto `handleServerFunctionRequest`.
|
|
@@ -339,16 +407,26 @@ export interface HandleServerFunctionOptions {
|
|
|
339
407
|
* extension point for response metadata policies (headers, statuses,
|
|
340
408
|
* substituted results). Runs for returned and thrown results alike
|
|
341
409
|
* (`context.thrown` distinguishes); `context.instance` is null for no-JS
|
|
342
|
-
* calls.
|
|
343
|
-
* `
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
410
|
+
* calls. The context carries the call's identity — the function `id` and
|
|
411
|
+
* the parsed `args` the implementation was invoked with — matching the
|
|
412
|
+
* direct-call mirror (`transformDirectResult`), so a policy keying state
|
|
413
|
+
* by the call works over either dispatch path. Return the result
|
|
414
|
+
* unchanged to pass through, or a `ResponseEnvelope` (exposed through
|
|
415
|
+
* the core entry) to send HTTP metadata plus a structured payload. Runs
|
|
416
|
+
* before `collectFlightData`, so the flight hook sees the transformed
|
|
417
|
+
* outcome — use `collectFlightData`, not this, to fold data into the
|
|
418
|
+
* response.
|
|
347
419
|
*/
|
|
348
420
|
transformResult?(
|
|
349
421
|
event: ServerFunctionEvent,
|
|
350
422
|
result: unknown,
|
|
351
|
-
context: {
|
|
423
|
+
context: {
|
|
424
|
+
id: string;
|
|
425
|
+
args: unknown[];
|
|
426
|
+
instance: string | null;
|
|
427
|
+
request: Request;
|
|
428
|
+
thrown?: boolean;
|
|
429
|
+
}
|
|
352
430
|
): unknown | ResponseEnvelope | Promise<unknown | ResponseEnvelope>;
|
|
353
431
|
/**
|
|
354
432
|
* Overrides the configured single-flight hook for this handler — same
|
|
@@ -356,6 +434,15 @@ export interface HandleServerFunctionOptions {
|
|
|
356
434
|
* `CollectFlightDataHook`).
|
|
357
435
|
*/
|
|
358
436
|
collectFlightData?: CollectFlightDataHook;
|
|
437
|
+
/**
|
|
438
|
+
* Overrides the configured single-flight fold policy for this handler —
|
|
439
|
+
* same contract as the `transformFlightResult` config option.
|
|
440
|
+
*/
|
|
441
|
+
transformFlightResult?(
|
|
442
|
+
event: ServerFunctionEvent,
|
|
443
|
+
outcome: { value: unknown; data: unknown },
|
|
444
|
+
context: { id: string; args: unknown[]; instance: string | null; request: Request }
|
|
445
|
+
): Response | undefined | Promise<Response | undefined>;
|
|
359
446
|
/**
|
|
360
447
|
* Builds the response for calls made without the client runtime (no
|
|
361
448
|
* instance header — no-JS form posts, direct HTTP). Receives the
|
|
@@ -405,6 +405,19 @@ export function decodeResponse<T = unknown>(
|
|
|
405
405
|
codecOptions?: JSONCodecOptions
|
|
406
406
|
): Promise<T | undefined>;
|
|
407
407
|
|
|
408
|
+
/**
|
|
409
|
+
* `decodeResponse` plus the single-flight envelope split: when the response
|
|
410
|
+
* carries the single-flight header the decoded `{ value, data }` payload is
|
|
411
|
+
* unwrapped into `{ value, flightData }`; otherwise the decoded body (or
|
|
412
|
+
* undefined for body-less responses) rides as `{ value }`. Integrations
|
|
413
|
+
* that apply response metadata themselves use this so the payload shape
|
|
414
|
+
* stays core's own.
|
|
415
|
+
*/
|
|
416
|
+
export function decodeResponsePayload<T = unknown, D = unknown>(
|
|
417
|
+
response: Response,
|
|
418
|
+
codecOptions?: JSONCodecOptions
|
|
419
|
+
): Promise<{ value: T | undefined; flightData?: D }>;
|
|
420
|
+
|
|
408
421
|
/**
|
|
409
422
|
* Frame one payload for the server-function wire: a `;0x<len32>;` length
|
|
410
423
|
* prefix followed by the utf-8 data. Both transports (server-function
|
|
@@ -421,3 +434,12 @@ export class ChunkReader {
|
|
|
421
434
|
constructor(stream: ReadableStream<Uint8Array>);
|
|
422
435
|
next(): Promise<{ done: boolean; value: string | undefined }>;
|
|
423
436
|
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* The intrinsic wire address of a server-component call: the function id,
|
|
440
|
+
* suffixed with a realm-stable hash of the arguments when there are any.
|
|
441
|
+
* Both peers derive it independently — the server names flight regions with
|
|
442
|
+
* it, the client routes them by it — so it must stay deterministic across
|
|
443
|
+
* realms and releases.
|
|
444
|
+
*/
|
|
445
|
+
export function frameAddress(id: string, args?: readonly unknown[]): string;
|
package/types/server-mock.d.ts
CHANGED
|
@@ -63,7 +63,10 @@ export declare function renderToStringAsync<T>(fn: () => T, options?: {
|
|
|
63
63
|
* boundaries settle. Good for time-to-first-byte sensitive pages.
|
|
64
64
|
*
|
|
65
65
|
* Returns an object with `pipe`/`pipeTo` for piping to a Node `Writable` or
|
|
66
|
-
* a Web `WritableStream`,
|
|
66
|
+
* a Web `WritableStream`, a lazy `readable` byte-stream view for
|
|
67
|
+
* `new Response(stream.readable)`, plus a `then` for awaiting full
|
|
68
|
+
* completion. `pipe`, `pipeTo`, and `readable` each consume the render —
|
|
69
|
+
* use exactly one of the three.
|
|
67
70
|
*
|
|
68
71
|
* @example
|
|
69
72
|
* ```tsx
|
|
@@ -73,7 +76,7 @@ export declare function renderToStringAsync<T>(fn: () => T, options?: {
|
|
|
73
76
|
* renderToStream(() => <App />).pipe(res);
|
|
74
77
|
*
|
|
75
78
|
* // Web (Workers / Deno):
|
|
76
|
-
*
|
|
79
|
+
* return new Response(renderToStream(() => <App />).readable);
|
|
77
80
|
* ```
|
|
78
81
|
*/
|
|
79
82
|
export declare function renderToStream<T>(fn: () => T, options?: {
|
|
@@ -102,6 +105,7 @@ export declare function renderToStream<T>(fn: () => T, options?: {
|
|
|
102
105
|
end: () => void;
|
|
103
106
|
}) => void;
|
|
104
107
|
pipeTo: (writable: WritableStream) => Promise<void>;
|
|
108
|
+
readonly readable: ReadableStream<Uint8Array>;
|
|
105
109
|
};
|
|
106
110
|
/**
|
|
107
111
|
* Compiler primitive — emitted by JSX-DOM-Expressions for tagged-template
|
package/types/server.d.ts
CHANGED
|
@@ -97,6 +97,17 @@ export function renderToStream<T>(
|
|
|
97
97
|
then: (fn: (html: string) => void) => void;
|
|
98
98
|
pipe: (writable: { write: (v: string) => void; end: () => void }) => void;
|
|
99
99
|
pipeTo: (writable: WritableStream) => Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Lazy `ReadableStream<Uint8Array>` view of the render — hand it straight
|
|
102
|
+
* to `new Response(stream.readable)`. First access starts the render
|
|
103
|
+
* piping through an internal `TransformStream` (chunks are UTF-8 encoded
|
|
104
|
+
* bytes, the same as `pipeTo` writes) and the stream is cached, so
|
|
105
|
+
* repeated access returns the same instance. Like `pipe`/`pipeTo`, this
|
|
106
|
+
* consumes the render: use exactly one of the three — mixing distinct
|
|
107
|
+
* consumers (`readable` after `pipe`/`pipeTo`, or vice versa) throws an
|
|
108
|
+
* error naming the conflict.
|
|
109
|
+
*/
|
|
110
|
+
readonly readable: ReadableStream<Uint8Array>;
|
|
100
111
|
};
|
|
101
112
|
|
|
102
113
|
export function HydrationScript(props: { nonce?: string; eventNames?: string[] }): JSX.Element;
|
|
@@ -140,10 +151,37 @@ export function generateHydrationScript(options?: {
|
|
|
140
151
|
* @internal
|
|
141
152
|
*/
|
|
142
153
|
export declare const RequestContext: unique symbol;
|
|
154
|
+
/**
|
|
155
|
+
* The mutable response head an integration's handler exposes on the request
|
|
156
|
+
* event as `event.response`: status/statusText/headers it will apply when
|
|
157
|
+
* sending the response. A scaffold, not a `Response` — application code
|
|
158
|
+
* (e.g. JSX response components) writes to it during render, and the
|
|
159
|
+
* handler reads it when the head goes out. Core does not declare the
|
|
160
|
+
* `response` property on `RequestEvent` itself: integrations that provide
|
|
161
|
+
* one declare it through module augmentation (as `@solidjs/router` does),
|
|
162
|
+
* and this type names the shape they agree on. Core's server-function
|
|
163
|
+
* handler reads its `Set-Cookie` headers when folding single-flight
|
|
164
|
+
* cookies but never requires it.
|
|
165
|
+
*/
|
|
166
|
+
export interface ResponseStub {
|
|
167
|
+
status?: number;
|
|
168
|
+
statusText?: string;
|
|
169
|
+
headers: Headers;
|
|
170
|
+
/**
|
|
171
|
+
* Set by the integration once the response head has been derived/sent
|
|
172
|
+
* from this stub — status and headers can no longer change. Consumers
|
|
173
|
+
* that write response metadata during render (e.g. JSX response
|
|
174
|
+
* components) must treat later status/header writes and cleanup-time
|
|
175
|
+
* retractions as no-ops.
|
|
176
|
+
*/
|
|
177
|
+
committed?: boolean;
|
|
178
|
+
}
|
|
179
|
+
|
|
143
180
|
/**
|
|
144
181
|
* The per-request context available on the server: the incoming `Request`
|
|
145
182
|
* and a `locals` bag integrations and middleware can hang state on.
|
|
146
|
-
* Frameworks typically extend this shape with richer fields.
|
|
183
|
+
* Frameworks typically extend this shape with richer fields (e.g. a
|
|
184
|
+
* `response` head — see `ResponseStub`).
|
|
147
185
|
*/
|
|
148
186
|
export interface RequestEvent {
|
|
149
187
|
request: Request;
|
package/types-cjs/client.d.cts
CHANGED
|
@@ -148,6 +148,21 @@ export function generateHydrationScript(options?: {
|
|
|
148
148
|
eventNames?: string[];
|
|
149
149
|
}): string;
|
|
150
150
|
export function Assets(props: { children?: JSX.Element }): JSX.Element;
|
|
151
|
+
/**
|
|
152
|
+
* See the server entry's `ResponseStub` — the shape of the mutable response
|
|
153
|
+
* head integrations expose as `event.response` via module augmentation.
|
|
154
|
+
*/
|
|
155
|
+
export interface ResponseStub {
|
|
156
|
+
status?: number;
|
|
157
|
+
statusText?: string;
|
|
158
|
+
headers: Headers;
|
|
159
|
+
/**
|
|
160
|
+
* Set by the integration once the response head has been derived/sent
|
|
161
|
+
* from this stub (status/headers can no longer change); consumers must
|
|
162
|
+
* treat later writes and cleanup-time retractions as no-ops.
|
|
163
|
+
*/
|
|
164
|
+
committed?: boolean;
|
|
165
|
+
}
|
|
151
166
|
export interface RequestEvent {
|
|
152
167
|
request: Request;
|
|
153
168
|
locals: Record<string | number | symbol, any>;
|
package/types-cjs/core.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { getOwner, runWithOwner, createComponent, createRoot as root, sharedConfig, untrack, merge as mergeProps, flatten, ssrHandleError, ssrScope, NoHydration, Hydration } from "solid-js";
|
|
1
|
+
export { getOwner, runWithOwner, createComponent, createRoot as root, sharedConfig, untrack, merge as mergeProps, flatten, ssrHandleError, ssrScope, NoHydration, Hydration, runInServerComponentScope } from "solid-js";
|
|
2
2
|
export declare const effect: (fn: any, effectFn: any, options: any) => void;
|
|
3
3
|
export declare const memo: (fn: any) => import("solid-js").SourceAccessor<any>;
|
|
4
4
|
export declare const runWithHydrationScope: (id: any, fn: any) => unknown;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
export { createFrame, createFrameHost, createFrameElement, FRAME_APPLIED_EVENT } from "./frame-client.cjs";
|
|
2
2
|
export { FRAME_STREAM_HEADER, applyFrameResponse, isFrameStreamResponse, createServerComponentHandler } from "./frame-transport.cjs";
|
|
3
3
|
export { createJSONDataTable } from "./serializer.cjs";
|
|
4
|
+
export type { Slot } from "./server.cjs";
|
|
4
5
|
export declare function getFrameHost(): any;
|
|
5
6
|
/**
|
|
6
7
|
* Installs the server-component transport policy on the server-function
|
|
7
|
-
* client: boundary identity
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* client: boundary identity is the call's intrinsic (function, arguments)
|
|
9
|
+
* address — per-args, exactly like the query cache, so a cached component
|
|
10
|
+
* always mounts the boundary showing the call it was cached for. Repeat
|
|
11
|
+
* calls for the same args resolve the identical component (refetches morph
|
|
12
|
+
* in place, cache hits pass `dynamic`'s equals-gate); a source switching
|
|
13
|
+
* args swaps boundaries, re-materialized instantly from the host's
|
|
14
|
+
* retained state.
|
|
12
15
|
*
|
|
13
16
|
* Call once in the client entry (an explicit call — the package is
|
|
14
17
|
* `sideEffects: false`, so a bare import would be tree-shaken away);
|
|
@@ -71,6 +71,14 @@ export interface SlotContext {
|
|
|
71
71
|
* re-call displaced (e.g. `{$frame}` region ranges) is dropped.
|
|
72
72
|
*/
|
|
73
73
|
adopted?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Whether this occurrence is a render-prop CALL (the producer placed it
|
|
76
|
+
* with arguments — possibly empty — via a slot record) as opposed to a
|
|
77
|
+
* direct-insert position. Consumers cannot tell from the resolved props
|
|
78
|
+
* alone: an argless render prop and a direct insert both arrive as `{}`,
|
|
79
|
+
* but one is a function to invoke and the other a value to place.
|
|
80
|
+
*/
|
|
81
|
+
invoked?: boolean;
|
|
74
82
|
/**
|
|
75
83
|
* Register cleanup for when this occurrence's range is removed from the
|
|
76
84
|
* server content, or the owning frame is disposed.
|
|
@@ -83,6 +91,15 @@ export interface SlotContext {
|
|
|
83
91
|
* in place (zero DOM mutation).
|
|
84
92
|
*/
|
|
85
93
|
existing: ChildNode[];
|
|
94
|
+
/**
|
|
95
|
+
* The range's own marker comments, when the occurrence has a placed range.
|
|
96
|
+
* A framework binding whose slot content is reactive at the top level (a
|
|
97
|
+
* boundary accessor, changing route children) owns the interior instead of
|
|
98
|
+
* returning nodes: bind before `end` with the framework's insert primitive
|
|
99
|
+
* and return `undefined` — the frame leaves the range alone (server morphs
|
|
100
|
+
* already protect slot ranges).
|
|
101
|
+
*/
|
|
102
|
+
range?: { start: Comment; end: Comment };
|
|
86
103
|
}
|
|
87
104
|
|
|
88
105
|
/**
|
|
@@ -126,16 +126,39 @@ export function createDocumentSlotProps(
|
|
|
126
126
|
* as `configureServerFunctionsServer({ transformDirectResult })` and a
|
|
127
127
|
* direct (same-process) server-function result that is a function comes back
|
|
128
128
|
* as an inline-renderable server component (frame markers + document
|
|
129
|
-
* slot props)
|
|
129
|
+
* slot props), branded with its function id and the call's wire address.
|
|
130
|
+
* Non-function results pass through.
|
|
130
131
|
*/
|
|
131
|
-
export function frameTransformDirectResult<T>(
|
|
132
|
+
export function frameTransformDirectResult<T>(
|
|
133
|
+
value: T,
|
|
134
|
+
options: { id: string; args?: unknown[] }
|
|
135
|
+
): T;
|
|
132
136
|
|
|
133
137
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* (
|
|
138
|
+
* The frame half of single-flight, as a `transformFlightResult` policy for
|
|
139
|
+
* `handleServerFunctionRequest`: when part of what a mutation invalidated is
|
|
140
|
+
* markup (a component-valued flight-data entry), the frame stream carries
|
|
141
|
+
* the whole payload — each component's content as a region addressed by its
|
|
142
|
+
* call, the `{ value, data }` envelope as `outcome` chunks with the
|
|
143
|
+
* component entries serialized as flight references. Returns `undefined`
|
|
144
|
+
* when nothing invalidated is markup (the response stays the plain
|
|
145
|
+
* single-flight envelope).
|
|
137
146
|
*/
|
|
138
|
-
export
|
|
147
|
+
export function frameTransformFlightResult(
|
|
148
|
+
event: unknown,
|
|
149
|
+
outcome: { value: unknown; data: unknown },
|
|
150
|
+
context?: unknown
|
|
151
|
+
): Promise<Response | undefined>;
|
|
152
|
+
|
|
153
|
+
// The brands and the codec plugin live with the transport (client bundles
|
|
154
|
+
// resolve flight references against the live registry); re-exported here for
|
|
155
|
+
// server integrations importing the document-SSR surface.
|
|
156
|
+
export {
|
|
157
|
+
SERVER_COMPONENT,
|
|
158
|
+
SERVER_COMPONENT_ADDRESS,
|
|
159
|
+
SERVER_COMPONENT_SOURCE,
|
|
160
|
+
ServerComponentPlugin
|
|
161
|
+
} from "./frame-transport.cjs";
|
|
139
162
|
|
|
140
163
|
/**
|
|
141
164
|
* Inline bootstrap for the document shell: installs the `self._$SC`
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { FrameChunk, FrameHost } from "./frame-client.cjs";
|
|
2
|
+
import { JSONCodecOptions } from "./serializer.cjs";
|
|
3
|
+
|
|
4
|
+
// Structural mirror of server-functions/shared.js's FlightDataConsumer:
|
|
5
|
+
// this file may only reference siblings that ship with it when integrations
|
|
6
|
+
// copy the frames declaration set (solid-web's types build), and the
|
|
7
|
+
// server-functions declarations are copied to a different root.
|
|
8
|
+
type FlightConsumer = (data: unknown, context: { response: Response }) => void | Promise<void>;
|
|
2
9
|
|
|
3
10
|
/**
|
|
4
11
|
* Header tagging a Response as a frame stream; its value is the producing
|
|
@@ -23,9 +30,24 @@ export interface ApplyFrameResponseOptions {
|
|
|
23
30
|
* Restamp every chunk of the response with this version (one response IS
|
|
24
31
|
* one version). Versions belong to the client too: the producer cannot
|
|
25
32
|
* know how many streams a boundary has consumed, so pass the Nth-response
|
|
26
|
-
* counter to make policy A's stale-guard real across navigations.
|
|
33
|
+
* counter to make policy A's stale-guard real across navigations. A
|
|
34
|
+
* single-flight response addresses several boundaries, each with its own
|
|
35
|
+
* history — pass a function and it is called once per frame in the
|
|
36
|
+
* response.
|
|
37
|
+
*/
|
|
38
|
+
version?: number | ((frameId: string) => number);
|
|
39
|
+
/**
|
|
40
|
+
* Remap any frame id other than the response's own root onto a local one
|
|
41
|
+
* — how a consumer resolves the addresses a single-flight response uses
|
|
42
|
+
* for the regions it refreshed.
|
|
27
43
|
*/
|
|
28
|
-
|
|
44
|
+
route?(id: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Receives the payload text of each `outcome` chunk — the response-scoped
|
|
47
|
+
* single-flight envelope, the caller's result rather than anything the
|
|
48
|
+
* host renders.
|
|
49
|
+
*/
|
|
50
|
+
onOutcome?(payload: string): void;
|
|
29
51
|
}
|
|
30
52
|
|
|
31
53
|
/**
|
|
@@ -48,6 +70,31 @@ export function applyFrameResponse(
|
|
|
48
70
|
options?: ApplyFrameResponseOptions
|
|
49
71
|
): Promise<string>;
|
|
50
72
|
|
|
73
|
+
/** Brands an inline-rendered server component with its function id. */
|
|
74
|
+
export const SERVER_COMPONENT: unique symbol;
|
|
75
|
+
|
|
76
|
+
/** The unwrapped server component behind an inline-render wrap. */
|
|
77
|
+
export const SERVER_COMPONENT_SOURCE: unique symbol;
|
|
78
|
+
|
|
79
|
+
/** The call's wire address (`frameAddress`), for regions to be emitted under. */
|
|
80
|
+
export const SERVER_COMPONENT_ADDRESS: unique symbol;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Seroval plugin for a server component crossing a serialization boundary:
|
|
84
|
+
* a branded component serializes as a REFERENCE — a per-function document
|
|
85
|
+
* placeholder in the hydration serializer, a live-registry lookup by call
|
|
86
|
+
* address in the JSON codec (single-flight envelopes) — its markup never
|
|
87
|
+
* rides as data.
|
|
88
|
+
*/
|
|
89
|
+
export const ServerComponentPlugin: unknown;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The codec options for a single-flight envelope: `codec` plus
|
|
93
|
+
* `ServerComponentPlugin` (deduped by tag). Injected by the protocol on both
|
|
94
|
+
* legs; exported for integrations composing their own flight carriers.
|
|
95
|
+
*/
|
|
96
|
+
export function flightCodec(codec?: JSONCodecOptions): JSONCodecOptions;
|
|
97
|
+
|
|
51
98
|
/** Options for `createServerComponentHandler`. */
|
|
52
99
|
export interface ServerComponentHandlerOptions<C = unknown> {
|
|
53
100
|
host: FrameHost;
|
|
@@ -57,12 +104,6 @@ export interface ServerComponentHandlerOptions<C = unknown> {
|
|
|
57
104
|
* own frame instance under the boundary id (multi-mount fans out).
|
|
58
105
|
*/
|
|
59
106
|
component(frameId: string): C;
|
|
60
|
-
/**
|
|
61
|
-
* Runs synchronously at each server-function call site (before any
|
|
62
|
-
* await); its return is the call's ambient identity — e.g. Solid's
|
|
63
|
-
* `getOwner`. Calls sharing a captured context share one boundary.
|
|
64
|
-
*/
|
|
65
|
-
capture?(info: { id: string; meta: unknown }): unknown;
|
|
66
107
|
/**
|
|
67
108
|
* A new response is about to stream into a boundary: rotate
|
|
68
109
|
* response-scoped state (codec data tables) here. `version` is the
|
|
@@ -83,6 +124,18 @@ export interface ServerComponentHandlerOptions<C = unknown> {
|
|
|
83
124
|
* never observes a pending beat.
|
|
84
125
|
*/
|
|
85
126
|
intercept?(info: { id: string; meta: unknown; args: unknown[] }): C | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Reads the registered single-flight consumer at delivery time. The
|
|
129
|
+
* consumer is module state in the server-function client's SHARED
|
|
130
|
+
* instance; pass a getter reading that instance when your bundling gives
|
|
131
|
+
* this module a private copy. Defaults to the local copy's reader.
|
|
132
|
+
*/
|
|
133
|
+
consumer?(): FlightConsumer | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* Reads the configured codec options at decode time — same instance-
|
|
136
|
+
* identity contract as `consumer`. Defaults to the local copy's reader.
|
|
137
|
+
*/
|
|
138
|
+
codec?(): JSONCodecOptions | undefined;
|
|
86
139
|
}
|
|
87
140
|
|
|
88
141
|
/**
|
|
@@ -92,15 +145,26 @@ export interface ServerComponentHandlerOptions<C = unknown> {
|
|
|
92
145
|
* (Solid's `dynamic`) never remounts across refetches — the response streams
|
|
93
146
|
* into the boundary underneath as the only observable effect.
|
|
94
147
|
*
|
|
95
|
-
* Boundary identity is derived, never declared:
|
|
96
|
-
*
|
|
97
|
-
*
|
|
148
|
+
* Boundary identity is derived, never declared: every call keys by its
|
|
149
|
+
* intrinsic (function, arguments) address — the query cache's per-args rule,
|
|
150
|
+
* so cached components and boundaries stay one-to-one. Same-args calls
|
|
151
|
+
* resolve the identical component and morph in place; an args switch swaps
|
|
152
|
+
* boundaries, re-materialized from the host's retained state.
|
|
98
153
|
*/
|
|
99
154
|
export function createServerComponentHandler<C>(options: ServerComponentHandlerOptions<C>): {
|
|
100
|
-
capture?(info: { id: string; meta: unknown }): unknown;
|
|
101
155
|
intercept?(info: { id: string; meta: unknown; args: unknown[] }): C | undefined;
|
|
102
156
|
handle(
|
|
103
157
|
response: Response,
|
|
104
158
|
ctx: { id: string; meta: unknown; args: unknown[]; context: unknown }
|
|
105
159
|
): C | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* Declares that the document is showing a call: hydration-data references
|
|
162
|
+
* carry their call's address (`_$SC.r(id, address)`) but never travel
|
|
163
|
+
* through the transport, so the integration forwards those records here —
|
|
164
|
+
* they are how a post-load call for the same (function, arguments) finds
|
|
165
|
+
* its way back to the adopted boundary. `component` must be the exact
|
|
166
|
+
* reference the integration's cache holds for the call (the per-function
|
|
167
|
+
* placeholder), or readers' equals-gates fail into remounts.
|
|
168
|
+
*/
|
|
169
|
+
showing(address: string, functionId: string, component: C): void;
|
|
106
170
|
};
|
|
@@ -1,2 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Element as SolidElement } from "solid-js";
|
|
2
|
+
/**
|
|
3
|
+
* A client position in a server component: a prop the server renders (as JSX
|
|
4
|
+
* or by calling it) where client-owned markup belongs. `P` is the client
|
|
5
|
+
* component's own props, so a server component can reference the client
|
|
6
|
+
* component's type directly instead of restating it.
|
|
7
|
+
*
|
|
8
|
+
* Arguments are classified by VALUE, not by name — any prop may carry any of
|
|
9
|
+
* these:
|
|
10
|
+
*
|
|
11
|
+
* - primitives ride the chunk;
|
|
12
|
+
* - server JSX streams as a nested region (html once, never data);
|
|
13
|
+
* - anything else serializes as a data record.
|
|
14
|
+
*
|
|
15
|
+
* Async server JSX in an argument needs its own boundary: the region is
|
|
16
|
+
* emitted as one finished string, so a bare async read has no fallback to
|
|
17
|
+
* show and no fragment to reveal into.
|
|
18
|
+
*
|
|
19
|
+
* `$key` names the occurrence so client state follows an entity across
|
|
20
|
+
* responses rather than being positional — the slot-level analogue of `For`'s
|
|
21
|
+
* `keyed`, for when references can't carry identity because every response
|
|
22
|
+
* re-creates everything. It is occurrence identity, not client data: it is
|
|
23
|
+
* stripped before the client component sees its props. Positional identity is
|
|
24
|
+
* the right default; `$key` matters when a live list reorders.
|
|
25
|
+
*/
|
|
26
|
+
export type Slot<P = {}> = (props: P & {
|
|
27
|
+
$key?: string | number;
|
|
28
|
+
}) => SolidElement;
|
|
29
|
+
export { renderToFrameStream, renderServerComponent, serverComponentResponse, frameTransformResult, frameTransformFlightResult, createFrameSink, frameTransformDirectResult, ServerComponentPlugin, SERVER_COMPONENT_BOOTSTRAP } from "./frame-sink.cjs";
|
|
2
30
|
export { FRAME_STREAM_HEADER, isFrameStreamResponse } from "./frame-transport.cjs";
|