@solidjs/web 2.0.0-beta.31 → 2.0.0-beta.32

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.
Files changed (64) hide show
  1. package/README.md +1 -6
  2. package/dist/dev.cjs +234 -45
  3. package/dist/dev.js +221 -42
  4. package/dist/server.cjs +456 -123
  5. package/dist/server.js +445 -120
  6. package/dist/web.cjs +234 -45
  7. package/dist/web.js +221 -42
  8. package/frames/dist/client.cjs +217 -112
  9. package/frames/dist/client.dev.cjs +217 -112
  10. package/frames/dist/client.dev.js +218 -113
  11. package/frames/dist/client.js +218 -113
  12. package/frames/dist/server.cjs +488 -177
  13. package/frames/dist/server.js +489 -179
  14. package/package.json +55 -4
  15. package/serialization/dist/serialization.cjs +8 -0
  16. package/serialization/dist/serialization.js +1 -0
  17. package/serialization/types/index.d.ts +173 -6
  18. package/serialization/types-cjs/index.d.cts +173 -6
  19. package/server-functions/dist/client.cjs +46 -9
  20. package/server-functions/dist/client.js +47 -11
  21. package/server-functions/dist/rich-args.cjs +11 -0
  22. package/server-functions/dist/rich-args.js +9 -0
  23. package/server-functions/dist/server.cjs +275 -126
  24. package/server-functions/dist/server.dev.cjs +1053 -0
  25. package/server-functions/dist/server.dev.js +1021 -0
  26. package/server-functions/dist/server.js +273 -127
  27. package/server-functions/package.json +10 -0
  28. package/server-functions/rich-args/package.json +20 -0
  29. package/storage/types/index.d.ts +1 -1
  30. package/storage/types-cjs/index.d.cts +1 -1
  31. package/types/client.d.ts +127 -6
  32. package/types/core.d.ts +3 -1
  33. package/types/frames/client.d.ts +15 -1
  34. package/types/frames/frame-client.d.ts +37 -7
  35. package/types/frames/frame-sink.d.ts +26 -3
  36. package/types/frames/frame-transport.d.ts +39 -7
  37. package/types/frames/serializer.d.ts +173 -6
  38. package/types/frames/server.d.ts +22 -0
  39. package/types/index.d.ts +2 -3
  40. package/types/response.d.ts +45 -0
  41. package/types/serializer.d.ts +173 -6
  42. package/types/server-functions/client.d.ts +1 -0
  43. package/types/server-functions/rich-args.d.ts +10 -0
  44. package/types/server-functions/server.d.ts +98 -0
  45. package/types/server-functions/shared.d.ts +22 -0
  46. package/types/server-mock.d.ts +171 -59
  47. package/types/server.d.ts +188 -36
  48. package/types-cjs/client.d.cts +127 -6
  49. package/types-cjs/core.d.cts +3 -1
  50. package/types-cjs/frames/client.d.cts +15 -1
  51. package/types-cjs/frames/frame-client.d.cts +37 -7
  52. package/types-cjs/frames/frame-sink.d.cts +26 -3
  53. package/types-cjs/frames/frame-transport.d.cts +39 -7
  54. package/types-cjs/frames/serializer.d.cts +173 -6
  55. package/types-cjs/frames/server.d.cts +22 -0
  56. package/types-cjs/index.d.cts +2 -3
  57. package/types-cjs/response.d.cts +45 -0
  58. package/types-cjs/serializer.d.cts +173 -6
  59. package/types-cjs/server-functions/client.d.cts +1 -0
  60. package/types-cjs/server-functions/rich-args.d.cts +10 -0
  61. package/types-cjs/server-functions/server.d.cts +98 -0
  62. package/types-cjs/server-functions/shared.d.cts +22 -0
  63. package/types-cjs/server-mock.d.cts +171 -59
  64. package/types-cjs/server.d.cts +188 -36
@@ -1,7 +1,48 @@
1
+ import type { RequestEvent, RequestEventLocals, ResponseStub } from "./client.cjs";
2
+ /** Static asset manifest produced by a build (e.g. parsed Vite manifest.json). */
3
+ export type AssetManifest = Record<string, {
4
+ file: string;
5
+ css?: string[];
6
+ isEntry?: boolean;
7
+ imports?: string[];
8
+ }> & {
9
+ _base?: string;
10
+ };
11
+ /** Inline style content, e.g. dev CSS collected from a bundler's module graph. */
12
+ export type InlineStyleAsset = {
13
+ id: string;
14
+ content: string;
15
+ attrs?: Record<string, string>;
16
+ };
17
+ export type ResolvedAssets = {
18
+ js: string[];
19
+ css: (string | InlineStyleAsset)[];
20
+ };
21
+ /**
22
+ * Resolver form of the manifest option — the primitive a dev server
23
+ * implements against its live module graph (a static manifest object is
24
+ * normalized into a sync resolver internally). `resolve` may return a
25
+ * promise (async resolvers require streaming rendering); CSS entries may be
26
+ * URL strings (emitted as load-gated `<link>` tags) or inline-style
27
+ * descriptors (emitted as `<style>` tags). A bare `resolve`-shaped function
28
+ * is accepted as shorthand for `{ resolve }`.
29
+ */
30
+ export type AssetResolver = {
31
+ resolve(key: string): ResolvedAssets | null | undefined | Promise<ResolvedAssets | null | undefined>;
32
+ /**
33
+ * Synchronous fast path answering with whatever is knowable without async
34
+ * work (typically js URLs, omitting css). Sync consumers — e.g. a lazy
35
+ * component's `moduleUrl` getter used by islands — use this when `resolve`
36
+ * would return a promise, so adapters should provide it whenever possible.
37
+ */
38
+ resolveSync?(key: string): ResolvedAssets | null | undefined;
39
+ };
40
+ /** Bare-function shorthand for `AssetResolver` (no sync fast path). */
41
+ export type AssetResolverFn = (key: string) => ResolvedAssets | null | undefined | Promise<ResolvedAssets | null | undefined>;
1
42
  /**
2
43
  * Renders a component tree synchronously to an HTML string. Async reads inside
3
44
  * `<Loading>` boundaries emit their `fallback` content; for full-graph
4
- * resolution use `renderToStringAsync` instead.
45
+ * resolution await `renderToStream` instead.
5
46
  *
6
47
  * Pair the returned HTML with `hydrate()` on the client.
7
48
  *
@@ -18,45 +59,20 @@ export declare function renderToString<T>(fn: () => T, options?: {
18
59
  renderId?: string;
19
60
  noScripts?: boolean;
20
61
  plugins?: any[];
21
- manifest?: Record<string, {
22
- file: string;
23
- css?: string[];
24
- isEntry?: boolean;
25
- isDynamicEntry?: boolean;
26
- imports?: string[];
27
- }>;
62
+ manifest?: AssetManifest | AssetResolver | AssetResolverFn;
28
63
  onError?: (err: any) => void;
64
+ /**
65
+ * Embedded-render contract for hosts that own the document. When the
66
+ * render output contains no `</head>`, everything head-bound (resolved
67
+ * `useHead` winners, eager resources, tracked asset links, inline
68
+ * styles) is delivered here as one HTML string — prelude (charset/base)
69
+ * first — for the host to splice into its own `<head>` template, instead
70
+ * of being dropped. Called synchronously before `renderToString`
71
+ * returns; not called when the output has a `</head>` (splicing is
72
+ * automatic then).
73
+ */
74
+ onHead?: (head: string) => void;
29
75
  }): string;
30
- /**
31
- * Renders a component tree to an HTML string and awaits all async reads in the
32
- * subtree before resolving. The returned HTML reflects the fully-settled state
33
- * — no `<Loading>` fallbacks appear in the output.
34
- *
35
- * Use this when you want a complete page in one round-trip. For incremental
36
- * streaming with progressive boundary resolution, use `renderToStream`.
37
- *
38
- * @example
39
- * ```tsx
40
- * import { renderToStringAsync } from "@solidjs/web";
41
- *
42
- * const html = await renderToStringAsync(() => <App />);
43
- * ```
44
- */
45
- export declare function renderToStringAsync<T>(fn: () => T, options?: {
46
- timeoutMs?: number;
47
- nonce?: string;
48
- renderId?: string;
49
- noScripts?: boolean;
50
- plugins?: any[];
51
- manifest?: Record<string, {
52
- file: string;
53
- css?: string[];
54
- isEntry?: boolean;
55
- isDynamicEntry?: boolean;
56
- imports?: string[];
57
- }>;
58
- onError?: (err: any) => void;
59
- }): Promise<string>;
60
76
  /**
61
77
  * Streams an HTML response, flushing the synchronous shell first and then
62
78
  * progressively emitting async-resolved fragments as their `<Loading>`
@@ -64,9 +80,10 @@ export declare function renderToStringAsync<T>(fn: () => T, options?: {
64
80
  *
65
81
  * Returns an object with `pipe`/`pipeTo` for piping to a Node `Writable` or
66
82
  * 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.
83
+ * `new Response(stream.readable)`, plus a thenable for awaiting full
84
+ * completion `await renderToStream(...)` resolves with the settled HTML
85
+ * (the fully-resolved-string form of the render). `pipe`, `pipeTo`, and
86
+ * `readable` each consume the render — use exactly one of the three.
70
87
  *
71
88
  * @example
72
89
  * ```tsx
@@ -77,6 +94,9 @@ export declare function renderToStringAsync<T>(fn: () => T, options?: {
77
94
  *
78
95
  * // Web (Workers / Deno):
79
96
  * return new Response(renderToStream(() => <App />).readable);
97
+ *
98
+ * // Fully settled string:
99
+ * const html = await renderToStream(() => <App />);
80
100
  * ```
81
101
  */
82
102
  export declare function renderToStream<T>(fn: () => T, options?: {
@@ -84,13 +104,7 @@ export declare function renderToStream<T>(fn: () => T, options?: {
84
104
  renderId?: string;
85
105
  noScripts?: boolean;
86
106
  plugins?: any[];
87
- manifest?: Record<string, {
88
- file: string;
89
- css?: string[];
90
- isEntry?: boolean;
91
- isDynamicEntry?: boolean;
92
- imports?: string[];
93
- }>;
107
+ manifest?: AssetManifest | AssetResolver | AssetResolverFn;
94
108
  onCompleteShell?: (info: {
95
109
  write: (v: string) => void;
96
110
  }) => void;
@@ -98,8 +112,25 @@ export declare function renderToStream<T>(fn: () => T, options?: {
98
112
  write: (v: string) => void;
99
113
  }) => void;
100
114
  onError?: (err: any) => void;
115
+ /**
116
+ * Embedded-render contract for hosts that own the document. When the
117
+ * shell contains no `</head>`, everything head-bound at first flush
118
+ * (resolved `useHead` winners, eager resources, tracked asset links,
119
+ * inline styles) is delivered here as one HTML string — prelude first —
120
+ * before the shell chunk is emitted, so the host can write its own
121
+ * `<head>` ahead of piping the stream. Post-shell head updates flow
122
+ * through the stream itself and apply in the browser. Not called when
123
+ * the shell has a `</head>` (splicing is automatic then).
124
+ */
125
+ onHead?: (head: string) => void;
101
126
  }): {
102
- then: (fn: (html: string) => void) => void;
127
+ /**
128
+ * Awaiting the stream resolves with the complete HTML once every boundary
129
+ * settles — the fully-settled-string form of the render. Render errors
130
+ * route through `onError` and the promise resolves with whatever HTML the
131
+ * render produced; it never rejects.
132
+ */
133
+ then<TResult1 = string, TResult2 = never>(onfulfilled?: ((html: string) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
103
134
  pipe: (writable: {
104
135
  write: (v: string) => void;
105
136
  end: () => void;
@@ -107,6 +138,75 @@ export declare function renderToStream<T>(fn: () => T, options?: {
107
138
  pipeTo: (writable: WritableStream) => Promise<void>;
108
139
  readonly readable: ReadableStream<Uint8Array>;
109
140
  };
141
+ /**
142
+ * Fetch-style middleware: receives the `Request` and a `next` continuation
143
+ * (pass a `Request` to substitute it downstream) and returns the `Response`.
144
+ * Composed with `composeMiddleware`; runs inside the request-event scope, so
145
+ * `getRequestEvent()` works exactly as in application code.
146
+ */
147
+ export type FetchMiddleware = (request: Request, next: (request?: Request) => Promise<Response>) => Response | Promise<Response>;
148
+ /**
149
+ * Creates a fresh, uncommitted {@link ResponseStub}. Server-only.
150
+ */
151
+ export declare function createResponseStub(): ResponseStub;
152
+ /**
153
+ * Builds the canonical request event — a web-standard `Request`, a `locals`
154
+ * bag, and a stub-backed `response` head — for `provideRequestEvent`.
155
+ * Server-only: on the client the request event belongs to the server that
156
+ * rendered the page.
157
+ */
158
+ export declare function createRequestEvent<T extends object = {}>(request: Request, init?: T): {
159
+ request: Request;
160
+ locals: RequestEventLocals;
161
+ response: ResponseStub;
162
+ } & T;
163
+ /**
164
+ * The HTTP status a redirect should use: the stub's own status when it is a
165
+ * redirect status (301/302/303/307/308), 302 otherwise. Server-only.
166
+ */
167
+ export declare function getExpectedRedirectStatus(response: ResponseStub): number;
168
+ /**
169
+ * Derives the outgoing `Response` for an SSR render result, running the
170
+ * response-head lifecycle against `event.response`: the stub commits at
171
+ * shell flush, a pre-flush `Location` becomes a real redirect
172
+ * (`getExpectedRedirectStatus`), and a post-flush one appends the
173
+ * nonce-aware `<script>window.location=...</script>` fallback. String
174
+ * results return a `Response` synchronously; stream results resolve at
175
+ * shell flush. Server-only.
176
+ */
177
+ export declare function createSSRResponse(result: string, event: RequestEvent | undefined, options?: {
178
+ responseInit?: ResponseInit;
179
+ nonce?: string;
180
+ transformChunk?: (chunk: string) => string;
181
+ }): Response;
182
+ export declare function createSSRResponse(result: {
183
+ pipe(writable: {
184
+ write: (v: string) => void;
185
+ end: () => void;
186
+ }): void;
187
+ }, event: RequestEvent | undefined, options?: {
188
+ responseInit?: ResponseInit;
189
+ nonce?: string;
190
+ transformChunk?: (chunk: string) => string;
191
+ }): Promise<Response>;
192
+ /**
193
+ * Handler-lifecycle plumbing — the exit for a `Response` that did not go
194
+ * through `createSSRResponse` (a middleware early return, an API result):
195
+ * folds the request event's response stub onto it (cookies append
196
+ * entry-by-entry, other headers gap-fill, status never) and commits the
197
+ * stub. Already-committed stubs pass the response through untouched, so
198
+ * handlers apply it unconditionally after their middleware chain unwinds.
199
+ * `event` defaults to the ambient `getRequestEvent()`. Application
200
+ * middleware never calls this. Server-only.
201
+ */
202
+ export declare function commitEventResponse(response: Response, event?: RequestEvent): Response;
203
+ /**
204
+ * Composes fetch-style middleware — `(request, next) => Response` — into a
205
+ * single function of the same shape. Nothing reaches the wire until the
206
+ * outermost middleware returns, so headers on the returned `Response` stay
207
+ * mutable through the whole unwind, streamed bodies included. Server-only.
208
+ */
209
+ export declare function composeMiddleware(middlewares: FetchMiddleware[]): (request: Request, next: (request?: Request) => Response | Promise<Response>) => Promise<Response>;
110
210
  /**
111
211
  * Compiler primitive — emitted by JSX-DOM-Expressions for tagged-template
112
212
  * SSR output. Not meant for hand-written code.
@@ -124,27 +224,39 @@ export declare function ssrElement(name: string, props: any, children: any, need
124
224
  t: string;
125
225
  };
126
226
  /**
127
- * Compiler primitive — serializes a classList object for SSR output. Not
128
- * meant for hand-written code.
227
+ * Compiler primitive — serializes a class value (string, object map, or
228
+ * array) for SSR output. Not meant for hand-written code.
129
229
  * @internal
130
230
  */
131
- export declare function ssrClassList(value: {
231
+ export declare function ssrClassName(value: string | {
132
232
  [k: string]: boolean;
133
- }): string;
233
+ } | Array<any>): string;
134
234
  /**
135
- * Compiler primitive — serializes a style object for SSR output. Not meant
235
+ * Compiler primitive — serializes a style value for SSR output. Not meant
136
236
  * for hand-written code.
137
237
  * @internal
138
238
  */
139
- export declare function ssrStyle(value: {
239
+ export declare function ssrStyle(value: string | {
140
240
  [k: string]: string;
141
241
  }): string;
142
242
  /**
143
- * Compiler primitive — serializes a boolean attribute for SSR output. Not
243
+ * Compiler primitive — serializes one style property for SSR output. Not
244
+ * meant for hand-written code.
245
+ * @internal
246
+ */
247
+ export declare function ssrStyleProperty(name: string, value: any): string;
248
+ /**
249
+ * Compiler primitive — serializes an attribute for SSR output. Not meant
250
+ * for hand-written code.
251
+ * @internal
252
+ */
253
+ export declare function ssrAttribute(key: string, value: any): string;
254
+ /**
255
+ * Compiler primitive — wraps a template-group closure for SSR output. Not
144
256
  * meant for hand-written code.
145
257
  * @internal
146
258
  */
147
- export declare function ssrAttribute(key: string, value: boolean): string;
259
+ export declare function ssrGroup<T extends () => any[]>(fn: T, n: number): T;
148
260
  /**
149
261
  * Compiler primitive — generates the hydration-key attribute for SSR
150
262
  * output. Not meant for hand-written code.
@@ -156,10 +268,10 @@ export declare function ssrHydrationKey(): string;
156
268
  * Not meant for hand-written code.
157
269
  * @internal
158
270
  */
159
- export declare function resolveSSRNode(node: any): string;
271
+ export declare function resolveSSRNode(node: any, result?: any, top?: boolean): any;
160
272
  /**
161
273
  * Escapes a string for safe inclusion in HTML output. Used by the SSR
162
274
  * runtime; not generally part of user code.
163
275
  * @internal
164
276
  */
165
- export declare function escape(html: string): string;
277
+ export declare function escape(s: any, attr?: boolean): any;
@@ -79,19 +79,6 @@ export function renderToString<T>(
79
79
  onHead?: (head: string) => void;
80
80
  }
81
81
  ): string;
82
- /** @deprecated use renderToStream which also returns a promise */
83
- export function renderToStringAsync<T>(
84
- fn: () => T,
85
- options?: {
86
- timeoutMs?: number;
87
- nonce?: string;
88
- renderId?: string;
89
- noScripts?: boolean;
90
- plugins?: SerializerPlugin[];
91
- manifest?: AssetManifest | AssetResolver | AssetResolverFn;
92
- onError?: (err: any) => void;
93
- }
94
- ): Promise<string>;
95
82
  export function renderToStream<T>(
96
83
  fn: () => T,
97
84
  options?: {
@@ -116,7 +103,17 @@ export function renderToStream<T>(
116
103
  onHead?: (head: string) => void;
117
104
  }
118
105
  ): {
119
- then: (fn: (html: string) => void) => void;
106
+ /**
107
+ * Awaiting the stream resolves with the complete HTML once every boundary
108
+ * settles — the fully-settled-string form of the render (`const html =
109
+ * await renderToStream(...)`). Render errors route through `onError` and
110
+ * the promise resolves with whatever HTML the render produced; it never
111
+ * rejects.
112
+ */
113
+ then<TResult1 = string, TResult2 = never>(
114
+ onfulfilled?: ((html: string) => TResult1 | PromiseLike<TResult1>) | null,
115
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
116
+ ): Promise<TResult1 | TResult2>;
120
117
  pipe: (writable: { write: (v: string) => void; end: () => void }) => void;
121
118
  pipeTo: (writable: WritableStream) => Promise<void>;
122
119
  /**
@@ -153,21 +150,20 @@ export function applyRef(
153
150
  r: ((element: any) => void) | ((element: any) => void)[],
154
151
  element: any
155
152
  ): void;
156
- /** @deprecated Use `useHead` — removed before `0.50.0` stable. */
157
- export function useAssets(fn: () => JSX.Element): void;
158
- /**
159
- * @deprecated Use the `onHead` render option — removed before `0.50.0`
160
- * stable. Reads ambient render state, so it is unsafe across concurrent
161
- * renders; `onHead` is closure-bound to its render and also carries
162
- * `useHead` output, which this does not.
163
- */
164
- export function getAssets(): string;
165
153
  /**
166
154
  * A head tag descriptor. Props values may be getters (evaluated lazily on
167
155
  * the server — at the owning flush boundary — and reactively on the client);
168
156
  * `children` is the text body (title text, inline style/script content).
169
157
  * `key` overrides the built-in dedupe identity (`title` is a hard singleton
170
158
  * that `key` cannot fork).
159
+ *
160
+ * Getters must be plain reads: they evaluate at flush time here (under no
161
+ * component owner) and inside registry-owned computations on the client, so
162
+ * a getter that allocates a reactive owner (`createMemo`, a `children()`
163
+ * helper) consumes a hydration id slot on one side only and desyncs every
164
+ * id allocated after the `useHead` call. Create such helpers eagerly at
165
+ * component position and read them from the getter. See
166
+ * docs/head-management-rfc.md.
171
167
  */
172
168
  export type HeadTag = {
173
169
  tag: "title" | "meta" | "link" | "style" | "script" | "base";
@@ -212,32 +208,62 @@ export declare const RequestContext: unique symbol;
212
208
  * `response` property on `RequestEvent` itself: integrations that provide
213
209
  * one declare it through module augmentation (as `@solidjs/router` does),
214
210
  * and this type names the shape they agree on. Core's server-function
215
- * handler reads its `Set-Cookie` headers when folding single-flight
216
- * cookies but never requires it.
211
+ * handler folds it onto the outgoing response when present — its
212
+ * `Set-Cookie` values (cookies appended during the call via
213
+ * `serializeCookie`) append cookie-by-cookie, other headers fill gaps —
214
+ * and reads it when folding single-flight cookies, but never requires it.
217
215
  */
218
216
  export interface ResponseStub {
219
217
  status?: number;
220
218
  statusText?: string;
221
219
  headers: Headers;
222
220
  /**
223
- * Set by the integration once the response head has been derived/sent
224
- * from this stub — status and headers can no longer change. Consumers
225
- * that write response metadata during render (e.g. JSX response
226
- * components) must treat later status/header writes and cleanup-time
227
- * retractions as no-ops.
221
+ * Set once the response head has been derived/sent from this stub —
222
+ * status and headers can no longer change. Flip it through
223
+ * `commitResponseStub`, which also instruments the stub's `headers` so
224
+ * a post-commit write fails loudly (dev build throws, production
225
+ * reports + no-ops) instead of silently missing the wire. `status`/
226
+ * `statusText` stay plain fields: consumers that write response
227
+ * metadata during render (e.g. JSX response components) must still
228
+ * treat later status writes and cleanup-time retractions as no-ops.
228
229
  */
229
230
  committed?: boolean;
230
231
  }
231
232
 
233
+ /**
234
+ * The type of `RequestEvent.locals` — a module-augmentable interface so
235
+ * applications can type the state their middleware hangs on the event.
236
+ * Augment it through the package that re-exports the event (interface
237
+ * identity flows through the re-export chain):
238
+ *
239
+ * ```ts
240
+ * declare module "@solidjs/web" {
241
+ * interface RequestEventLocals {
242
+ * user: User;
243
+ * }
244
+ * }
245
+ * ```
246
+ *
247
+ * The index signature keeps un-augmented usage permissive — `locals` is a
248
+ * free-form bag by default — so augmentation adds precision for the keys
249
+ * it names without gating existing code. The flip side: unaugmented keys
250
+ * read as `any` rather than erroring, a deliberate trade (a strict-only
251
+ * `locals` would break every untyped write that works today).
252
+ */
253
+ export interface RequestEventLocals {
254
+ [key: string | number | symbol]: any;
255
+ }
256
+
232
257
  /**
233
258
  * The per-request context available on the server: the incoming `Request`
234
- * and a `locals` bag integrations and middleware can hang state on.
235
- * Frameworks typically extend this shape with richer fields (e.g. a
236
- * `response` head — see `ResponseStub`).
259
+ * and a `locals` bag integrations and middleware can hang state on (typed
260
+ * through the augmentable `RequestEventLocals`). Frameworks typically
261
+ * extend this shape with richer fields (e.g. a `response` head — see
262
+ * `ResponseStub`).
237
263
  */
238
264
  export interface RequestEvent {
239
265
  request: Request;
240
- locals: Record<string | number | symbol, any>;
266
+ locals: RequestEventLocals;
241
267
  }
242
268
  /**
243
269
  * The current request event, when called on the server inside a request
@@ -247,7 +273,129 @@ export interface RequestEvent {
247
273
  */
248
274
  export function getRequestEvent(): RequestEvent | undefined;
249
275
 
250
- export function Assets(props: { children?: JSX.Element }): JSX.Element;
276
+ /** A fresh, uncommitted response head. */
277
+ export function createResponseStub(): ResponseStub;
278
+
279
+ /**
280
+ * The canonical request event for HTTP handlers: the incoming `Request`, a
281
+ * `locals` bag, and a `response` head stub the render writes to. `init`
282
+ * spreads over the defaults so frameworks can extend the shape.
283
+ */
284
+ export function createRequestEvent<T extends object = {}>(
285
+ request: Request,
286
+ init?: T
287
+ ): RequestEvent & { response: ResponseStub } & T;
288
+
289
+ /**
290
+ * The status an outgoing redirect should use for a response head carrying
291
+ * a `Location`: the stub's own status when it is a redirect status, 302
292
+ * otherwise.
293
+ */
294
+ export function getExpectedRedirectStatus(response: ResponseStub): number;
295
+
296
+ /**
297
+ * Flips a response stub to `committed` — the moment its head freezes on
298
+ * the wire — and instruments the stub's `headers` mutating methods
299
+ * (`set`/`append`/`delete`, patched in place; the `Headers` identity and
300
+ * reads are untouched) so a post-commit write fails loudly instead of
301
+ * silently missing the wire: it throws in the dev build and reports +
302
+ * no-ops otherwise. Every head materialization path commits through here
303
+ * (`createSSRResponse`, the server-function handler's commit seam);
304
+ * integrations deriving their own heads should too.
305
+ *
306
+ * `allowLateLocation` is the stream path's documented exception: a
307
+ * `Location` set after the shell flushed is still honored client-side
308
+ * (stream completion appends a `window.location` script), so that one
309
+ * write stays permitted there.
310
+ */
311
+ export function commitResponseStub(
312
+ stub: ResponseStub,
313
+ options?: { allowLateLocation?: boolean }
314
+ ): ResponseStub;
315
+
316
+ /**
317
+ * Handler-lifecycle plumbing — a response's exit through the request
318
+ * event's response-stub lifecycle: page results leave through
319
+ * `createSSRResponse`, any other `Response` (a middleware early return, an
320
+ * API result) leaves through `commitEventResponse`; application middleware
321
+ * never calls this. Folds the event's stub onto the outgoing response —
322
+ * `Set-Cookie` appends entry-by-entry alongside the response's own, other
323
+ * stub headers fill gaps only (never the wire-protocol family the handlers
324
+ * own, never `Content-Type`/`Content-Length` on a bodiless response), the
325
+ * status is never taken from the stub — then commits the stub
326
+ * (`commitResponseStub`: post-commit writes fail loudly). Responses with
327
+ * immutable headers are rebuilt around merged copies.
328
+ *
329
+ * Idempotent at handler edges: an already-committed stub passes the
330
+ * response through untouched, so a handler may apply this unconditionally
331
+ * after its middleware chain unwinds — page responses from
332
+ * `createSSRResponse` come back committed and do not double-fold.
333
+ *
334
+ * `event` defaults to the ambient `getRequestEvent()`.
335
+ */
336
+ export function commitEventResponse(response: Response, event?: RequestEvent): Response;
337
+
338
+ /**
339
+ * The cookie codec (the platform-gap primitives — see cookies.d.ts): ALL
340
+ * of core's cookie surface. The blessed patterns are
341
+ * `parseCookieHeader(event.request.headers.get("cookie"))` for reads and
342
+ * `event.response.headers.append("set-cookie", serializeCookie(name,
343
+ * value, options))` for writes.
344
+ */
345
+ export { parseCookieHeader, serializeCookie } from "./cookies.cjs";
346
+ export type { CookieOptions } from "./cookies.cjs";
347
+
348
+ export interface SSRResponseOptions {
349
+ /** Base head; the stub's status/headers win over it. */
350
+ responseInit?: ResponseInit;
351
+ /** Nonce carried by the post-flush `<script>` redirect fallback. */
352
+ nonce?: string;
353
+ /** Rewrites each outgoing HTML chunk (entry script injection, ...). */
354
+ transformChunk?: (chunk: string) => string;
355
+ }
356
+
357
+ /**
358
+ * Derives the outgoing `Response` for an SSR render result, running the
359
+ * response-head lifecycle against `event.response`: commit at shell flush,
360
+ * pre-flush `Location` becomes a real redirect, post-flush `Location`
361
+ * appends a client-side script redirect before the stream closes.
362
+ * Synchronous for string results; resolves at shell flush for stream
363
+ * results.
364
+ */
365
+ export function createSSRResponse(
366
+ result: string,
367
+ event: RequestEvent | undefined,
368
+ options?: SSRResponseOptions
369
+ ): Response;
370
+ export function createSSRResponse(
371
+ result: { pipe(writable: { write: (v: string) => void; end: () => void }): void },
372
+ event: RequestEvent | undefined,
373
+ options?: SSRResponseOptions
374
+ ): Promise<Response>;
375
+
376
+ /**
377
+ * Fetch-style middleware: return a `Response` to answer the request, or
378
+ * call `next()` (optionally with a substitute `Request`) to advance the
379
+ * chain and observe/replace the eventual response.
380
+ */
381
+ export type FetchMiddleware = (
382
+ request: Request,
383
+ next: (request?: Request) => Promise<Response>
384
+ ) => Response | Promise<Response>;
385
+
386
+ /**
387
+ * Composes fetch-style middleware into one function of the same shape;
388
+ * the terminal `next` dispatches to the actual handler. Runs in whatever
389
+ * scope the caller established (`provideRequestEvent`), so
390
+ * `getRequestEvent()` works exactly as in application code.
391
+ */
392
+ export function composeMiddleware(
393
+ middlewares: FetchMiddleware[]
394
+ ): (
395
+ request: Request,
396
+ next: (request?: Request) => Response | Promise<Response>
397
+ ) => Promise<Response>;
398
+
251
399
  export function untrack<T>(fn: () => T): T;
252
400
 
253
401
  // client-only APIs
@@ -347,5 +495,9 @@ export function ref(
347
495
  ): void;
348
496
  /** @deprecated not supported on the server side */
349
497
  export function setStyleProperty(node: Element, name: string, value: any): void;
350
- /** @deprecated not supported on the server side — register assets through the render context instead */
498
+ /**
499
+ * @internal See client.d.ts — head-management RFC policy: ambient CSS is
500
+ * unmanaged; the head registry owns directly-mounted stylesheet lifecycle.
501
+ * @deprecated not supported on the server side — register assets through the render context instead
502
+ */
351
503
  export function acquireAsset(descriptor: unknown): () => void;