@rshono/core 1.0.0-rc.2 → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -29
- package/dist/builder/rspack-config.d.ts +3 -3
- package/dist/builder/rspack-config.js +3 -3
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/cli/build.d.ts +2 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts +2 -2
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/index.js +11 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +4 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/deploy/cloudflare/build.js +1 -1
- package/dist/deploy/cloudflare/build.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
- package/dist/deploy/cloudflare/runtime.js +7 -37
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +14 -13
- package/dist/deploy/contract.d.ts.map +1 -1
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts +1 -1
- package/dist/deploy/filesystem.d.ts.map +1 -1
- package/dist/deploy/filesystem.js +1 -3
- package/dist/deploy/filesystem.js.map +1 -1
- package/dist/deploy/node/runtime.d.ts +6 -2
- package/dist/deploy/node/runtime.d.ts.map +1 -1
- package/dist/deploy/node/runtime.js +30 -5
- package/dist/deploy/node/runtime.js.map +1 -1
- package/dist/deploy/presets.d.ts +5 -1
- package/dist/deploy/presets.d.ts.map +1 -1
- package/dist/deploy/presets.js +15 -28
- package/dist/deploy/presets.js.map +1 -1
- package/dist/deploy/vercel/runtime.d.ts.map +1 -1
- package/dist/deploy/vercel/runtime.js +0 -3
- package/dist/deploy/vercel/runtime.js.map +1 -1
- package/dist/index.d.ts +4 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +14 -15
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +5 -6
- package/dist/router.js.map +1 -1
- package/dist/runtime/client.d.ts +5 -6
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +5 -6
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/context.d.ts +36 -40
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +41 -53
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/entry.client.d.ts +4 -0
- package/dist/runtime/entry.client.d.ts.map +1 -1
- package/dist/runtime/entry.client.js +161 -147
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts.map +1 -1
- package/dist/runtime/entry.rsc.js +80 -63
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/entry.ssr.d.ts +9 -1
- package/dist/runtime/entry.ssr.d.ts.map +1 -1
- package/dist/runtime/entry.ssr.js +36 -18
- package/dist/runtime/entry.ssr.js.map +1 -1
- package/dist/runtime/flight-inject.d.ts +31 -0
- package/dist/runtime/flight-inject.d.ts.map +1 -0
- package/dist/runtime/flight-inject.js +221 -0
- package/dist/runtime/flight-inject.js.map +1 -0
- package/dist/runtime/navigation.d.ts +10 -39
- package/dist/runtime/navigation.d.ts.map +1 -1
- package/dist/runtime/navigation.js +7 -53
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts +6 -0
- package/dist/runtime/request.d.ts.map +1 -1
- package/dist/runtime/request.js +8 -0
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/server.d.ts +2 -2
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +2 -2
- package/dist/runtime/server.js.map +1 -1
- package/dist/server/headers.d.ts +9 -9
- package/dist/server/headers.js +9 -9
- package/dist/server/headers.js.map +1 -1
- package/dist/server/load-config.d.ts +2 -2
- package/dist/server/load-config.d.ts.map +1 -1
- package/dist/server/load-config.js +22 -11
- package/dist/server/load-config.js.map +1 -1
- package/dist/server/prerendered.d.ts +52 -9
- package/dist/server/prerendered.d.ts.map +1 -1
- package/dist/server/prerendered.js +57 -0
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +11 -18
- package/dist/server/server-config.d.ts.map +1 -1
- package/dist/server/server-config.js +9 -12
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/ssg.d.ts +2 -2
- package/dist/server/ssg.d.ts.map +1 -1
- package/dist/server/ssg.js +11 -23
- package/dist/server/ssg.js.map +1 -1
- package/package.json +13 -16
- package/dist/deploy/bun/runtime.d.ts +0 -11
- package/dist/deploy/bun/runtime.d.ts.map +0 -1
- package/dist/deploy/bun/runtime.js +0 -22
- package/dist/deploy/bun/runtime.js.map +0 -1
- package/dist/deploy/deno/runtime.d.ts +0 -11
- package/dist/deploy/deno/runtime.d.ts.map +0 -1
- package/dist/deploy/deno/runtime.js +0 -16
- package/dist/deploy/deno/runtime.js.map +0 -1
- package/dist/deploy/listen.d.ts +0 -20
- package/dist/deploy/listen.d.ts.map +0 -1
- package/dist/deploy/listen.js +0 -24
- package/dist/deploy/listen.js.map +0 -1
- package/dist/deploy/netlify/build.d.ts +0 -8
- package/dist/deploy/netlify/build.d.ts.map +0 -1
- package/dist/deploy/netlify/build.js +0 -52
- package/dist/deploy/netlify/build.js.map +0 -1
- package/dist/deploy/netlify/runtime.d.ts +0 -13
- package/dist/deploy/netlify/runtime.d.ts.map +0 -1
- package/dist/deploy/netlify/runtime.js +0 -24
- package/dist/deploy/netlify/runtime.js.map +0 -1
- package/dist/server/compress.d.ts +0 -15
- package/dist/server/compress.d.ts.map +0 -1
- package/dist/server/compress.js +0 -76
- package/dist/server/compress.js.map +0 -1
|
@@ -17,11 +17,11 @@ import { routes as userRoutes } from '@rshono/routes';
|
|
|
17
17
|
import * as serverAppModule from '@rshono/server-app';
|
|
18
18
|
import { isPageRoute } from '../router.js';
|
|
19
19
|
import { appendVary, etagMatches } from '../server/headers.js';
|
|
20
|
-
import {
|
|
20
|
+
import { getRequestContext, publicUrl, readParams, reportServerError, runWithContext } from './context.js';
|
|
21
21
|
import { isControlSignal, RedirectSignal } from './control.js';
|
|
22
22
|
import { renderHTML } from './entry.ssr.js';
|
|
23
23
|
import { RouterProvider } from './navigation.js';
|
|
24
|
-
import { acceptsRsc, isActionRequest, parseRenderRequest, wantsRsc } from './request.js';
|
|
24
|
+
import { acceptsRsc, isActionRequest, parseRenderRequest, requestWantsRsc, wantsRsc } from './request.js';
|
|
25
25
|
const serverApp = (serverAppModule.default ?? null);
|
|
26
26
|
// Framework settings resolved from rshono.config.ts and compiled into the bundle at build time
|
|
27
27
|
// (see builder/rspack-config.ts). These have no runtime env-var interface — env is for secrets.
|
|
@@ -29,7 +29,7 @@ const serverApp = (serverAppModule.default ?? null);
|
|
|
29
29
|
// resolved. `isDev` among them: the build mode is decided by which command produced the bundle, not
|
|
30
30
|
// by `process.env.NODE_ENV`, and not every runtime this deploys to has a `process` to read anyway.
|
|
31
31
|
const CONFIG = __RSHONO_CONFIG__;
|
|
32
|
-
const { isDev,
|
|
32
|
+
const { isDev, cspEnabled, checkOrigin, maxBodyBytes } = CONFIG;
|
|
33
33
|
/** Extra cross-origin hosts permitted to post server actions, beyond the app's own origin. */
|
|
34
34
|
const allowedOrigins = new Set(CONFIG.allowedOrigins);
|
|
35
35
|
/** How long a prerendered page may be reused before revalidating. Also what `public/` files get. */
|
|
@@ -118,51 +118,55 @@ function once(load) {
|
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
|
-
*
|
|
122
|
-
* `using` declaration doesn't fit because the timer must outlive this call to keep
|
|
123
|
-
* guarding the *stream*, not just the function scope). The timer is released on
|
|
124
|
-
* exactly one of: the stream finishing ({@link RenderDeadline.guard}), an explicit
|
|
125
|
-
* {@link RenderDeadline.clear} on an error path, or the signal aborting (client
|
|
126
|
-
* disconnect, or the deadline firing itself). A manually-cleared timer instead of
|
|
127
|
-
* `AbortSignal.timeout()` so a fast response doesn't leave one pending to fire later.
|
|
121
|
+
* Passes `stream` through untouched, calling `done` once it ends — however it ends.
|
|
128
122
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
123
|
+
* Used on the flight-only response path, which has no transform of its own to hang a completion hook
|
|
124
|
+
* off (the document path has {@link injectFlightPayload}). `done` must be idempotent: a cancelled
|
|
125
|
+
* response can reach both `cancel` and the abort forwarder.
|
|
131
126
|
*/
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const signal = AbortSignal.any([requestSignal, controller.signal]);
|
|
137
|
-
const clear = () => clearTimeout(timer);
|
|
138
|
-
signal.addEventListener('abort', clear, { once: true });
|
|
139
|
-
return {
|
|
140
|
-
signal,
|
|
141
|
-
clear,
|
|
142
|
-
guard: (stream) => stream.pipeThrough(new TransformStream({ flush: clear })),
|
|
143
|
-
race(work) {
|
|
144
|
-
if (signal.aborted)
|
|
145
|
-
return Promise.reject(signal.reason);
|
|
146
|
-
const { promise: aborted, reject } = Promise.withResolvers();
|
|
147
|
-
const onAbort = () => reject(signal.reason);
|
|
148
|
-
signal.addEventListener('abort', onAbort, { once: true });
|
|
149
|
-
// `Promise.race` subscribes to `work` either way, so abandoning it can't surface as an
|
|
150
|
-
// unhandled rejection. Detach on settle so a long-lived signal doesn't accumulate listeners.
|
|
151
|
-
return Promise.race([work, aborted]).finally(() => signal.removeEventListener('abort', onAbort));
|
|
127
|
+
function releaseWhenDone(stream, done) {
|
|
128
|
+
return stream.pipeThrough(new TransformStream({
|
|
129
|
+
transform(chunk, controller) {
|
|
130
|
+
controller.enqueue(chunk);
|
|
152
131
|
},
|
|
153
|
-
|
|
132
|
+
flush: done,
|
|
133
|
+
cancel: done,
|
|
134
|
+
}));
|
|
154
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* There is no render deadline here any more.
|
|
138
|
+
*
|
|
139
|
+
* A `renderTimeout` setting used to wrap every request in an `AbortController` with a timer, covering
|
|
140
|
+
* the server action as well as the flight and SSR passes. Every host this deploys to enforces its own
|
|
141
|
+
* request timeout — Workers, Vercel and Lambda all do — so the only shape that needed one was a Node
|
|
142
|
+
* process facing the internet directly, and there a proxy is both the conventional and the more capable
|
|
143
|
+
* place for it. The README shows the middleware for a Node deploy that wants one in-process.
|
|
144
|
+
*
|
|
145
|
+
* What the deadline *also* did was carry the client-disconnect signal into the two React renderers, and
|
|
146
|
+
* that is kept — but not by handing them `c.req.raw.signal`. Both React renderers add an `abort`
|
|
147
|
+
* listener to whatever signal they are given and only remove it if the abort fires, so a listener left on
|
|
148
|
+
* a request-lifetime signal pins the flight request, the Fizz request and the whole rendered tree. That
|
|
149
|
+
* is not theoretical: handing them the request signal directly cost ~169 kB per `/ssr` request, never
|
|
150
|
+
* reclaimed by a major GC, and took GC from 5.8% to 12.9% of wall time under load.
|
|
151
|
+
*
|
|
152
|
+
* The deadline's own `AbortController` was, accidentally, what had kept that collectable — its signal
|
|
153
|
+
* died with the render. So {@link renderComponent} keeps a per-render controller and forwards the request
|
|
154
|
+
* signal into it, releasing the forwarder when the response ends. Never through `AbortSignal.any([...])`,
|
|
155
|
+
* which reads better and leaks worse: a signal it produced is *composite*, and Node holds every composite
|
|
156
|
+
* signal carrying an `abort` listener in a process-lifetime set (`gcPersistentSignals`) until it either
|
|
157
|
+
* aborts or loses its last listener.
|
|
158
|
+
*/
|
|
155
159
|
/**
|
|
156
160
|
* Builds the props a page component is called with.
|
|
157
161
|
*
|
|
158
162
|
* `url` and `params` match `useNavigation()` field for field, so a read can move between a page and
|
|
159
|
-
* a `'use client'` component unchanged. The `URL` is this page's own — `
|
|
163
|
+
* a `'use client'` component unchanged. The `URL` is this page's own — `RequestContext` parses its own — so a
|
|
160
164
|
* page that mutates it cannot disturb anything else on the request.
|
|
161
165
|
*
|
|
162
166
|
* `ctx` is *defined* rather than assigned, and both parts of how carry their weight:
|
|
163
167
|
*
|
|
164
168
|
* - **A getter**, so nothing is built for the pages that never read it, and so a `render: 'static'`
|
|
165
|
-
* page that does read it gets {@link
|
|
169
|
+
* page that does read it gets {@link getRequestContext}'s own "no per-request context while
|
|
166
170
|
* prerendering" error rather than a bare `undefined` — one explanation, in one place.
|
|
167
171
|
* - **Non-enumerable**, so React's *development-only* serialization of a server component's props
|
|
168
172
|
* (the debug channel behind component stacks and the performance track) skips it. That walks own
|
|
@@ -176,12 +180,32 @@ function createRenderDeadline(requestSignal, ms) {
|
|
|
176
180
|
*/
|
|
177
181
|
function pageProps(c, errorInfo) {
|
|
178
182
|
const props = { url: publicUrl(c), params: readParams(c), ...(errorInfo ? { error: errorInfo } : null) };
|
|
179
|
-
Object.defineProperty(props, 'ctx', { get:
|
|
183
|
+
Object.defineProperty(props, 'ctx', { get: getRequestContext, enumerable: false, configurable: true });
|
|
180
184
|
return props;
|
|
181
185
|
}
|
|
182
186
|
async function renderComponent(c, Page, opts) {
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
// The client going away is the one thing that still aborts a render — but React's renderers must not
|
|
188
|
+
// be handed `c.req.raw.signal` to watch for it. Both of them add an `abort` listener and only remove
|
|
189
|
+
// it if the abort fires, so on the happy path the listener stays on a signal that lives as long as the
|
|
190
|
+
// request object, and through it pins the flight request, the Fizz request and the whole rendered
|
|
191
|
+
// tree. Measured at ~169 kB per `/ssr` request, never reclaimed by a major GC.
|
|
192
|
+
//
|
|
193
|
+
// So the render gets a controller of its own and the request signal only forwards into it. The
|
|
194
|
+
// forwarding listener is `once`, so an abort removes it, and {@link release} removes it on the normal
|
|
195
|
+
// path — which is what keeps the request from retaining the render. Deliberately not
|
|
196
|
+
// `AbortSignal.any()`: a signal it produced is *composite*, and Node holds every composite signal
|
|
197
|
+
// carrying an `abort` listener in a process-lifetime set until it aborts or loses its last listener,
|
|
198
|
+
// which is a worse leak than the one being fixed here.
|
|
199
|
+
const requestSignal = c.req.raw.signal;
|
|
200
|
+
const renderAbort = new AbortController();
|
|
201
|
+
const signal = renderAbort.signal;
|
|
202
|
+
const forwardAbort = () => renderAbort.abort(requestSignal.reason);
|
|
203
|
+
if (requestSignal.aborted)
|
|
204
|
+
renderAbort.abort(requestSignal.reason);
|
|
205
|
+
else
|
|
206
|
+
requestSignal.addEventListener('abort', forwardAbort, { once: true });
|
|
207
|
+
/** Detaches the forwarder once the response has been written, so nothing survives the request. */
|
|
208
|
+
const release = () => requestSignal.removeEventListener('abort', forwardAbort);
|
|
185
209
|
const nonce = cspEnabled && !opts.isRsc ? crypto.randomUUID() : undefined;
|
|
186
210
|
const props = pageProps(c, opts.errorInfo);
|
|
187
211
|
const root = (_jsxs(_Fragment, { children: [nonce && _jsx("meta", { property: "csp-nonce", nonce: nonce }), Page.entryCssFiles?.map((href) => (_jsx("link", { rel: "stylesheet", href: href, precedence: "default" }, href))), _jsx(RouterProvider, { href: props.url.href, params: props.params, children: jsx(Page, props) })] }));
|
|
@@ -201,7 +225,7 @@ async function renderComponent(c, Page, opts) {
|
|
|
201
225
|
},
|
|
202
226
|
});
|
|
203
227
|
if (opts.isRsc) {
|
|
204
|
-
return c.body(
|
|
228
|
+
return c.body(releaseWhenDone(rscStream, release), (opts.status ?? 200), {
|
|
205
229
|
'content-type': 'text/x-component;charset=utf-8',
|
|
206
230
|
});
|
|
207
231
|
}
|
|
@@ -212,18 +236,19 @@ async function renderComponent(c, Page, opts) {
|
|
|
212
236
|
formState: opts.formState,
|
|
213
237
|
signal,
|
|
214
238
|
nonce,
|
|
239
|
+
onDone: release,
|
|
215
240
|
onShellError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR shell error:' }),
|
|
216
241
|
onError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR error:' }),
|
|
217
242
|
});
|
|
218
243
|
}
|
|
219
244
|
catch (error) {
|
|
220
|
-
|
|
245
|
+
release();
|
|
221
246
|
if (controlSignal)
|
|
222
247
|
throw controlSignal;
|
|
223
248
|
throw error;
|
|
224
249
|
}
|
|
225
250
|
if (controlSignal) {
|
|
226
|
-
|
|
251
|
+
release();
|
|
227
252
|
throw controlSignal;
|
|
228
253
|
}
|
|
229
254
|
const headers = { 'content-type': 'text/html;charset=utf-8' };
|
|
@@ -234,21 +259,17 @@ async function renderComponent(c, Page, opts) {
|
|
|
234
259
|
const scriptSrc = `script-src ${CSP_SCRIPT_SRC} 'nonce-${nonce}'${isDev ? " 'unsafe-eval'" : ''}`;
|
|
235
260
|
headers['content-security-policy'] = CSP_STATIC ? `${CSP_STATIC}; ${scriptSrc}` : scriptSrc;
|
|
236
261
|
}
|
|
237
|
-
return c.body(
|
|
262
|
+
return c.body(ssrResult.stream, (ssrResult.status ?? opts.status ?? 200), headers);
|
|
238
263
|
}
|
|
239
264
|
async function renderPage(c, loadPage) {
|
|
240
265
|
const request = c.req.raw;
|
|
241
266
|
const renderRequest = parseRenderRequest(request);
|
|
242
|
-
// Created before the action runs so the deadline covers the whole request, then handed to
|
|
243
|
-
// `renderComponent` so the render doesn't get a fresh budget of its own.
|
|
244
|
-
const deadline = createRenderDeadline(request.signal, renderTimeoutMs);
|
|
245
267
|
let returnValue;
|
|
246
268
|
let formState;
|
|
247
269
|
let temporaryReferences;
|
|
248
270
|
let actionStatus;
|
|
249
271
|
if (isActionRequest(renderRequest)) {
|
|
250
272
|
if (!isSameOriginAction(c)) {
|
|
251
|
-
deadline.clear();
|
|
252
273
|
return c.text('Forbidden: cross-origin server action rejected', 403);
|
|
253
274
|
}
|
|
254
275
|
if (renderRequest.kind === 'rsc-action') {
|
|
@@ -256,7 +277,6 @@ async function renderPage(c, loadPage) {
|
|
|
256
277
|
// `loadServerAction` would otherwise fault on the missing manifest entry, turning a bad
|
|
257
278
|
// request into an unhandled 500. `hasOwn` so `__proto__` doesn't resolve to a manifest entry.
|
|
258
279
|
if (!Object.hasOwn(__rspack_rsc_manifest__.serverManifest, renderRequest.actionId)) {
|
|
259
|
-
deadline.clear();
|
|
260
280
|
return c.text('Bad Request: unknown server action', 400);
|
|
261
281
|
}
|
|
262
282
|
const contentType = request.headers.get('content-type');
|
|
@@ -265,7 +285,7 @@ async function renderPage(c, loadPage) {
|
|
|
265
285
|
const args = await decodeReply(body, { temporaryReferences });
|
|
266
286
|
const action = loadServerAction(renderRequest.actionId);
|
|
267
287
|
try {
|
|
268
|
-
returnValue = { ok: true, value: await
|
|
288
|
+
returnValue = { ok: true, value: await action.apply(null, args) };
|
|
269
289
|
}
|
|
270
290
|
catch (error) {
|
|
271
291
|
if (isControlSignal(error))
|
|
@@ -281,7 +301,7 @@ async function renderPage(c, loadPage) {
|
|
|
281
301
|
const formData = await request.formData();
|
|
282
302
|
const decodedAction = await decodeAction(formData, __rspack_rsc_manifest__.serverManifest);
|
|
283
303
|
if (decodedAction) {
|
|
284
|
-
const result = await
|
|
304
|
+
const result = await decodedAction();
|
|
285
305
|
formState = (await decodeFormState(result, formData, __rspack_rsc_manifest__.serverManifest)) ?? undefined;
|
|
286
306
|
}
|
|
287
307
|
}
|
|
@@ -293,15 +313,10 @@ async function renderPage(c, loadPage) {
|
|
|
293
313
|
formState,
|
|
294
314
|
returnValue,
|
|
295
315
|
temporaryReferences,
|
|
296
|
-
deadline,
|
|
297
316
|
});
|
|
298
317
|
}
|
|
299
318
|
function buildApp() {
|
|
300
319
|
const app = new Hono();
|
|
301
|
-
// Outermost, so it wraps the finished response — headers and all — on the way out. A platform that
|
|
302
|
-
// compresses for us (or cannot stream a compressor) offers none, and the setting has nothing to do.
|
|
303
|
-
if (compressEnabled && runtime.compress)
|
|
304
|
-
app.use(runtime.compress);
|
|
305
320
|
// Cheap, unconditional headers that only matter when something else has gone wrong: stop
|
|
306
321
|
// content-type sniffing, keep the full URL (paths, query) out of cross-origin referrers, and
|
|
307
322
|
// refuse to be framed by another origin (clickjacking). `frame-ancestors` in the opt-in CSP is
|
|
@@ -348,7 +363,7 @@ function buildApp() {
|
|
|
348
363
|
const loadNotFoundPage = routeConfig.notFound ? memoizePage(routeConfig.notFound, 'the notFound page') : null;
|
|
349
364
|
/** Turns a thrown `redirect()` / `notFound()` into the response it stands for. */
|
|
350
365
|
const respondToControlSignal = async (c, signal) => {
|
|
351
|
-
const isRsc =
|
|
366
|
+
const isRsc = requestWantsRsc(c.req.raw);
|
|
352
367
|
if (signal instanceof RedirectSignal) {
|
|
353
368
|
if (isRsc) {
|
|
354
369
|
return c.body(renderToReadableStream({ root: null, redirect: signal.location }, { signal: c.req.raw.signal }), 200, {
|
|
@@ -372,18 +387,20 @@ function buildApp() {
|
|
|
372
387
|
try {
|
|
373
388
|
if (servesPrerendered && c.req.method === 'GET') {
|
|
374
389
|
const isRsc = acceptsRsc(c.req.raw);
|
|
375
|
-
//
|
|
376
|
-
//
|
|
377
|
-
//
|
|
378
|
-
|
|
379
|
-
|
|
390
|
+
// A prerendered file is one fixed set of bytes, so it cannot carry a per-request nonce:
|
|
391
|
+
// under `csp` the *document* has to be rendered per request. The flight payload never
|
|
392
|
+
// carries a nonce, so it stays servable from the build either way.
|
|
393
|
+
const mustRenderForNonce = cspEnabled && !isRsc;
|
|
394
|
+
// Otherwise both representations come from the build, so a soft navigation is served from
|
|
395
|
+
// it too rather than re-rendering a page that was already built.
|
|
396
|
+
if (!mustRenderForNonce) {
|
|
380
397
|
const page = await runtime.readPrerendered(c, isRsc ? 'flight' : 'html');
|
|
381
398
|
// A prerendered page is request-independent by construction, so it is safe to cache
|
|
382
399
|
// publicly; the short max-age matches what `public/` files get. The ETag turns the
|
|
383
400
|
// revalidation that follows into a 304 rather than the page all over again.
|
|
384
401
|
//
|
|
385
402
|
// Answered outside `runWithContext`: no app code runs on this path, so there is no
|
|
386
|
-
// `
|
|
403
|
+
// `getRequestContext()` to serve and no reason to pay for the AsyncLocalStorage scope.
|
|
387
404
|
if (page !== null) {
|
|
388
405
|
const headers = {
|
|
389
406
|
'cache-control': SSG_CACHE_CONTROL,
|
|
@@ -422,7 +439,7 @@ function buildApp() {
|
|
|
422
439
|
}
|
|
423
440
|
runtime.mountPublicFallback(app);
|
|
424
441
|
app.notFound(async (c) => {
|
|
425
|
-
const isRsc =
|
|
442
|
+
const isRsc = requestWantsRsc(c.req.raw);
|
|
426
443
|
if (loadNotFoundPage && (isRsc || acceptsHtml(c))) {
|
|
427
444
|
return runWithContext(c, async () => renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc }));
|
|
428
445
|
}
|
|
@@ -433,7 +450,7 @@ function buildApp() {
|
|
|
433
450
|
if (isControlSignal(error))
|
|
434
451
|
return runWithContext(c, () => respondToControlSignal(c, error));
|
|
435
452
|
reportServerError(error, { source: 'request', request: c.req.raw, message: '[rshono] request error:' });
|
|
436
|
-
const isRsc =
|
|
453
|
+
const isRsc = requestWantsRsc(c.req.raw);
|
|
437
454
|
if (loadErrorPage && (isRsc || acceptsHtml(c))) {
|
|
438
455
|
const errorInfo = isDev
|
|
439
456
|
? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.rsc.js","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { Context, Handler } from 'hono';\nimport { Hono } from 'hono';\nimport { bodyLimit } from 'hono/body-limit';\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status';\nimport type React from 'react';\nimport type { ReactFormState } from 'react-dom/client';\n// The JSX factory, by name: the page element is created with this directly rather than as\n// `<Page {...props} />`, because a spread would drop the non-enumerable `ctx` prop. See `pageProps`.\nimport { jsx } from 'react/jsx-runtime';\n// The bare specifier, not `/server.node`: the package ships a build per runtime behind export\n// conditions (`node`, `workerd`, `deno`, `edge-light`), and the RSC layer's `conditionNames` is what\n// picks one — so a non-Node deploy target gets its own build instead of Node's by hard-coded path.\nimport {\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n renderToReadableStream,\n type ServerEntry,\n type TemporaryReferenceSet,\n} from 'react-server-dom-rspack/server';\n// Resolved by the '@rshono/deploy' alias to the selected preset's runtime module — the one place\n// this file knows anything about where it is running. See `deploy/contract.ts`.\nimport { runtime } from '@rshono/deploy';\n// @ts-expect-error — resolved by the '@rshono/routes' alias to the app's routes.ts\nimport { routes as userRoutes } from '@rshono/routes';\n// @ts-expect-error — resolved by the '@rshono/server-app' alias (src/server.ts or the empty fallback)\nimport * as serverAppModule from '@rshono/server-app';\nimport { isPageRoute, type ErrorInfo, type FallbackPage, type PageComponent, type PageProps, type Route, type RouteConfig } from '../router.js';\nimport { appendVary, etagMatches } from '../server/headers.js';\nimport { getContext, publicUrl, readParams, reportServerError, runWithContext } from './context.js';\nimport { isControlSignal, RedirectSignal, type ControlSignal } from './control.js';\nimport { renderHTML } from './entry.ssr.js';\nimport { RouterProvider } from './navigation.js';\nimport { acceptsRsc, isActionRequest, parseRenderRequest, wantsRsc } from './request.js';\n\nconst serverApp = ((serverAppModule as { default?: unknown }).default ?? null) as Hono | null;\n\n// Framework settings resolved from rshono.config.ts and compiled into the bundle at build time\n// (see builder/rspack-config.ts). These have no runtime env-var interface — env is for secrets.\n// Named after their ServerConfig fields, so what a setting does here is one grep from where it is\n// resolved. `isDev` among them: the build mode is decided by which command produced the bundle, not\n// by `process.env.NODE_ENV`, and not every runtime this deploys to has a `process` to read anyway.\nconst CONFIG = __RSHONO_CONFIG__;\nconst { isDev, renderTimeoutMs, cspEnabled, checkOrigin, maxBodyBytes, compress: compressEnabled } = CONFIG;\n/** Extra cross-origin hosts permitted to post server actions, beyond the app's own origin. */\nconst allowedOrigins = new Set(CONFIG.allowedOrigins);\n\n/** How long a prerendered page may be reused before revalidating. Also what `public/` files get. */\nconst SSG_CACHE_CONTROL = 'public, max-age=300';\n\n/**\n * The two content types a page can be served as. Both come back from the *same* URL depending on\n * the `Accept` header, which is what makes `Vary` non-optional here.\n */\nconst PAGE_CONTENT_TYPE = /^(?:text\\/html|text\\/x-component)\\b/;\n\n// The CSP is fixed per build apart from the nonce, so assemble everything but `script-src` once.\nconst CSP_STATIC = Object.entries(CONFIG.cspDirectives)\n .filter(([name]) => name !== 'script-src')\n .map(([name, value]) => `${name} ${value}`)\n .join('; ');\nconst CSP_SCRIPT_SRC = CONFIG.cspDirectives['script-src'] ?? \"'self'\";\n\n// Called here rather than at the top of the deploy runtime's own module so the timing is unchanged:\n// `.env` is loaded once every import above has been evaluated, exactly as before.\nruntime.loadEnv();\n\nconst routeConfig = userRoutes as RouteConfig;\nexport const routes: readonly Route[] = routeConfig.routes;\n\n/** The result of a server action, as a discriminated union (a `Result<T, E>`) rather than an `ok` flag over one field. */\nexport type ActionResult = { ok: true; value: unknown } | { ok: false; error: unknown };\n\nexport type RscPayload = {\n root: React.ReactNode;\n returnValue?: ActionResult;\n formState?: ReactFormState;\n redirect?: string;\n notFound?: boolean;\n};\n\n/**\n * CSRF guard for server-action POSTs, layering the two signals a browser gives us.\n *\n * `Sec-Fetch-Site` is set by the browser and unforgeable by page script, so `same-origin` settles\n * the question on its own — and short-circuiting on it is what keeps the check from misfiring on a\n * legitimate request whose `Host` the proxy rewrote. Everything else falls back to comparing the\n * `Origin` host against our own (see {@link publicUrl} — deliberately *not* against a raw\n * `X-Forwarded-Host`, which the client controls unless `trustProxy` says a proxy owns it).\n *\n * A missing `Origin` is treated as same-origin: no-JS form posts from older browsers omit it, and\n * those same browsers send no `Sec-Fetch-Site` either, so there is nothing left to check. Hosts are\n * compared case-insensitively; the scheme is not compared, so this alone won't stop an\n * `http://` origin posting to the `https://` site (HSTS is the control for that).\n */\nfunction isSameOriginAction(c: Context): boolean {\n if (!checkOrigin) return true;\n\n const secFetchSite = c.req.header('sec-fetch-site');\n if (secFetchSite === 'same-origin') return true;\n\n const origin = c.req.header('origin');\n const originHost = origin ? URL.parse(origin)?.host.toLowerCase() || null : null;\n if (origin !== undefined && originHost === null) return false; // an Origin we can't parse is untrusted.\n\n const trusted = originHost !== null && (originHost === publicUrl(c).host.toLowerCase() || allowedOrigins.has(originHost));\n\n if (secFetchSite && secFetchSite !== 'none') {\n // The browser tells us (unforgeably) this didn't originate from our own site — only a\n // trusted (allowlisted) Origin may proceed.\n return trusted;\n }\n\n if (originHost === null) return true;\n return trusted;\n}\n\nasync function loadPageModule(load: () => Promise<{ default: PageComponent }>, label: string): Promise<ServerEntry<PageComponent>> {\n const mod = await load();\n const Page = mod.default as ServerEntry<PageComponent> | undefined;\n if (typeof Page !== 'function') {\n throw new Error(`[rshono] The page module for ${label} must default-export a server component.`);\n }\n if (!Page.entryJsFiles) {\n throw new Error(\n `[rshono] The page component for ${label} is missing its client-asset info ('use server-entry'). ` +\n \"The directive is added automatically for inline `component: () => import('…')` thunks in routes.ts. \" +\n \"If this page is wired up another way, put 'use server-entry' on the first line of the page module yourself — \" +\n \"and make sure the page is a server component (a 'use client' page must be wrapped by a server component instead).\",\n );\n }\n return Page;\n}\n\n/** A browser navigation or a crawler, as opposed to a fetch that would rather have plain text. */\nfunction acceptsHtml(c: Context): boolean {\n return c.req.header('accept')?.includes('text/html') ?? false;\n}\n\n/** A lazy once-cell: runs `load` at most once and caches the promise, but clears a rejection so a later call can retry. */\nfunction once<T>(load: () => Promise<T>): () => Promise<T> {\n let promise: Promise<T> | undefined;\n return () => {\n if (!promise) {\n const pending = (promise = load());\n pending.catch(() => {\n // Only clear if we're still holding the rejected promise (a later successful load may have already replaced it).\n if (promise === pending) promise = undefined;\n });\n }\n return promise;\n };\n}\n\ninterface ComponentRenderOptions {\n status?: number;\n isRsc: boolean;\n formState?: ReactFormState;\n returnValue?: RscPayload['returnValue'];\n temporaryReferences?: TemporaryReferenceSet;\n /** Passed when the page being rendered is the `error` page, which takes it as an extra prop. */\n errorInfo?: ErrorInfo;\n /** Marks the payload as the not-found page, so a soft navigation can tell it apart from the page it asked for. */\n notFound?: boolean;\n /** An already-running deadline to render under — passed when the request spent time on an action first. */\n deadline?: RenderDeadline;\n}\n\ninterface RenderDeadline {\n /** The request signal combined with the timeout — pass to the RSC/SSR renderers. */\n readonly signal: AbortSignal;\n /** Releases the timer now — call on an error path where nothing will stream. */\n clear(): void;\n /** Wraps a response stream so the timer is released once its last byte flushes. */\n guard(stream: ReadableStream<Uint8Array>): ReadableStream<Uint8Array>;\n /**\n * Settles with `work`, or rejects the moment the deadline (or the client disconnect) fires —\n * for the phases that take a plain promise rather than an {@link AbortSignal}, i.e. running a\n * server action. The abandoned work keeps running to completion; we just stop holding the\n * socket open for it.\n */\n race<T>(work: T | PromiseLike<T>): Promise<T>;\n}\n\n/**\n * Owns the render-deadline lifecycle in one place (the RAII / `defer` pattern — a\n * `using` declaration doesn't fit because the timer must outlive this call to keep\n * guarding the *stream*, not just the function scope). The timer is released on\n * exactly one of: the stream finishing ({@link RenderDeadline.guard}), an explicit\n * {@link RenderDeadline.clear} on an error path, or the signal aborting (client\n * disconnect, or the deadline firing itself). A manually-cleared timer instead of\n * `AbortSignal.timeout()` so a fast response doesn't leave one pending to fire later.\n *\n * One deadline covers the whole request — server action included, not just the render — so a\n * hung action can't pin a socket open indefinitely either.\n */\nfunction createRenderDeadline(requestSignal: AbortSignal, ms: number): RenderDeadline {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(new Error(`[rshono] request exceeded ${ms}ms`)), ms);\n timer.unref?.();\n const signal = AbortSignal.any([requestSignal, controller.signal]);\n const clear = () => clearTimeout(timer);\n signal.addEventListener('abort', clear, { once: true });\n return {\n signal,\n clear,\n guard: (stream) => stream.pipeThrough(new TransformStream<Uint8Array, Uint8Array>({ flush: clear })),\n race<T>(work: T | PromiseLike<T>): Promise<T> {\n if (signal.aborted) return Promise.reject(signal.reason);\n const { promise: aborted, reject } = Promise.withResolvers<never>();\n const onAbort = () => reject(signal.reason);\n signal.addEventListener('abort', onAbort, { once: true });\n // `Promise.race` subscribes to `work` either way, so abandoning it can't surface as an\n // unhandled rejection. Detach on settle so a long-lived signal doesn't accumulate listeners.\n return Promise.race([work, aborted]).finally(() => signal.removeEventListener('abort', onAbort));\n },\n };\n}\n\n/**\n * Builds the props a page component is called with.\n *\n * `url` and `params` match `useNavigation()` field for field, so a read can move between a page and\n * a `'use client'` component unchanged. The `URL` is this page's own — `Ctx` parses its own — so a\n * page that mutates it cannot disturb anything else on the request.\n *\n * `ctx` is *defined* rather than assigned, and both parts of how carry their weight:\n *\n * - **A getter**, so nothing is built for the pages that never read it, and so a `render: 'static'`\n * page that does read it gets {@link getContext}'s own \"no per-request context while\n * prerendering\" error rather than a bare `undefined` — one explanation, in one place.\n * - **Non-enumerable**, so React's *development-only* serialization of a server component's props\n * (the debug channel behind component stacks and the performance track) skips it. That walks own\n * enumerable properties, and `ctx.raw` is the Hono {@link Context} — whose `env` holds the\n * runtime's bindings. An enumerable `ctx` ships every one of them, secrets included, to the\n * browser in dev, and grows a small page's flight payload by well over 10 kB. Production never\n * serializes a server component's props at all, so this is the dev half of the same guarantee.\n *\n * The cost is that the element has to be created by handing this object to `jsx()` *by reference*:\n * a `<Page {...props} />` spread copies enumerable properties only, and would drop `ctx` silently.\n */\nfunction pageProps(c: Context, errorInfo: ErrorInfo | undefined): PageProps & { error?: ErrorInfo } {\n const props = { url: publicUrl(c), params: readParams(c), ...(errorInfo ? { error: errorInfo } : null) };\n Object.defineProperty(props, 'ctx', { get: getContext, enumerable: false, configurable: true });\n return props as PageProps & { error?: ErrorInfo };\n}\n\nasync function renderComponent(c: Context, Page: ServerEntry<PageComponent>, opts: ComponentRenderOptions): Promise<Response> {\n const deadline = opts.deadline ?? createRenderDeadline(c.req.raw.signal, renderTimeoutMs);\n const signal = deadline.signal;\n\n const nonce = cspEnabled && !opts.isRsc ? crypto.randomUUID() : undefined;\n const props = pageProps(c, opts.errorInfo);\n const root = (\n <>\n {nonce && <meta property=\"csp-nonce\" nonce={nonce} />}\n {Page.entryCssFiles?.map((href) => (\n <link key={href} rel=\"stylesheet\" href={href} precedence=\"default\" />\n ))}\n {/* `href`, not the `URL` itself: these props cross into a client component, so they have to be serializable. */}\n <RouterProvider href={props.url.href} params={props.params}>\n {jsx(Page, props)}\n </RouterProvider>\n </>\n );\n\n // `notFound` only when it is true, so the flight payload of an ordinary page doesn't carry the key.\n const rscPayload: RscPayload = { root, formState: opts.formState, returnValue: opts.returnValue, ...(opts.notFound ? { notFound: true } : null) };\n\n let controlSignal: ControlSignal | undefined;\n const rscStream = renderToReadableStream(rscPayload, {\n temporaryReferences: opts.temporaryReferences,\n signal,\n onError(error) {\n if (isControlSignal(error)) {\n controlSignal = error;\n return error.digest;\n }\n if (!signal.aborted) reportServerError(error, { source: 'render', request: c.req.raw, message: '[rshono] render error:' });\n },\n });\n\n if (opts.isRsc) {\n return c.body(deadline.guard(rscStream), (opts.status ?? 200) as ContentfulStatusCode, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n\n let ssrResult: Awaited<ReturnType<typeof renderHTML>>;\n try {\n ssrResult = await renderHTML(rscStream, {\n bootstrapScripts: Page.entryJsFiles,\n formState: opts.formState,\n signal,\n nonce,\n onShellError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR shell error:' }),\n onError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR error:' }),\n });\n } catch (error) {\n deadline.clear();\n if (controlSignal) throw controlSignal;\n throw error;\n }\n if (controlSignal) {\n deadline.clear();\n throw controlSignal;\n }\n const headers: Record<string, string> = { 'content-type': 'text/html;charset=utf-8' };\n if (nonce) {\n // The nonce is always appended to whatever `script-src` resolved to, so overriding the\n // directive in `cspDirectives` can widen the policy but can't accidentally drop the nonce.\n // Dev additionally needs 'unsafe-eval' for react-refresh.\n const scriptSrc = `script-src ${CSP_SCRIPT_SRC} 'nonce-${nonce}'${isDev ? \" 'unsafe-eval'\" : ''}`;\n headers['content-security-policy'] = CSP_STATIC ? `${CSP_STATIC}; ${scriptSrc}` : scriptSrc;\n }\n return c.body(deadline.guard(ssrResult.stream), (ssrResult.status ?? opts.status ?? 200) as ContentfulStatusCode, headers);\n}\n\nasync function renderPage(c: Context, loadPage: () => Promise<ServerEntry<PageComponent>>): Promise<Response> {\n const request = c.req.raw;\n const renderRequest = parseRenderRequest(request);\n // Created before the action runs so the deadline covers the whole request, then handed to\n // `renderComponent` so the render doesn't get a fresh budget of its own.\n const deadline = createRenderDeadline(request.signal, renderTimeoutMs);\n\n let returnValue: ActionResult | undefined;\n let formState: ReactFormState | undefined;\n let temporaryReferences: TemporaryReferenceSet | undefined;\n let actionStatus: number | undefined;\n if (isActionRequest(renderRequest)) {\n if (!isSameOriginAction(c)) {\n deadline.clear();\n return c.text('Forbidden: cross-origin server action rejected', 403);\n }\n if (renderRequest.kind === 'rsc-action') {\n // Checked before the body is decoded, so an unknown id costs nothing to reject — and\n // `loadServerAction` would otherwise fault on the missing manifest entry, turning a bad\n // request into an unhandled 500. `hasOwn` so `__proto__` doesn't resolve to a manifest entry.\n if (!Object.hasOwn(__rspack_rsc_manifest__.serverManifest, renderRequest.actionId)) {\n deadline.clear();\n return c.text('Bad Request: unknown server action', 400);\n }\n const contentType = request.headers.get('content-type');\n const body = contentType?.startsWith('multipart/form-data') ? await request.formData() : await request.text();\n temporaryReferences = createTemporaryReferenceSet();\n const args = await decodeReply<unknown[]>(body, { temporaryReferences });\n const action = loadServerAction(renderRequest.actionId);\n try {\n returnValue = { ok: true, value: await deadline.race(action.apply(null, args)) };\n } catch (error) {\n if (isControlSignal(error)) throw error;\n // React sends a thrown action error to the client as an opaque marker in production — no\n // message, no digest — so without this the failure would be invisible on both ends.\n reportServerError(error, { source: 'action', request, message: '[rshono] server action error:' });\n returnValue = { ok: false, error };\n actionStatus = 500;\n }\n } else {\n const formData = await request.formData();\n const decodedAction = await decodeAction(formData, __rspack_rsc_manifest__.serverManifest);\n if (decodedAction) {\n const result = await deadline.race(decodedAction());\n formState = (await decodeFormState(result, formData, __rspack_rsc_manifest__.serverManifest)) ?? undefined;\n }\n }\n }\n\n const Page = await loadPage();\n return renderComponent(c, Page, {\n status: actionStatus,\n isRsc: wantsRsc(renderRequest),\n formState,\n returnValue,\n temporaryReferences,\n deadline,\n });\n}\n\nfunction buildApp(): Hono {\n const app = new Hono();\n\n // Outermost, so it wraps the finished response — headers and all — on the way out. A platform that\n // compresses for us (or cannot stream a compressor) offers none, and the setting has nothing to do.\n if (compressEnabled && runtime.compress) app.use(runtime.compress);\n\n // Cheap, unconditional headers that only matter when something else has gone wrong: stop\n // content-type sniffing, keep the full URL (paths, query) out of cross-origin referrers, and\n // refuse to be framed by another origin (clickjacking). `frame-ancestors` in the opt-in CSP is\n // stricter and takes precedence where both apply; this is the floor for everyone else.\n // Set after `next()` so a route or middleware that sets its own value wins.\n app.use(async (c, next) => {\n await next();\n const headers = c.res.headers;\n if (!headers.has('x-content-type-options')) headers.set('x-content-type-options', 'nosniff');\n if (!headers.has('referrer-policy')) headers.set('referrer-policy', 'strict-origin-when-cross-origin');\n if (!headers.has('x-frame-options')) headers.set('x-frame-options', 'SAMEORIGIN');\n\n // Page responses only, from here down. Two things are true of them and of nothing else served\n // here: one URL answers with either an HTML document or a flight payload depending on `Accept`,\n // and the default page is request-specific (cookies, session, headers).\n if (!PAGE_CONTENT_TYPE.test(headers.get('content-type') ?? '')) return;\n appendVary(headers, 'Accept');\n // Without this a page carries no cache directives at all, and a shared cache — a CDN, a\n // corporate proxy — is free to store a logged-in user's page and hand it to someone else.\n // `private` forbids exactly that; `no-cache` makes the browser revalidate its own copy rather\n // than re-showing a stale personalised page. Neither blocks bfcache, which `no-store` would.\n // A prerendered page, or anything a route set deliberately, already has its own value.\n if (!headers.has('cache-control')) headers.set('cache-control', 'private, no-cache');\n });\n\n // A memory-exhaustion guard for *every* route — pages and actions, `{ type: 'endpoint' }` routes\n // and the src/server.ts sub-app alike — since anything that buffers a body (`.json()`,\n // `.formData()`) is exposed, not just server actions. Rejects an over-cap `Content-Length` up\n // front and otherwise counts the stream, so a chunked or under-reported body is still cut off.\n if (maxBodyBytes > 0) {\n app.use(bodyLimit({ maxSize: maxBodyBytes, onError: (c) => c.text('Payload Too Large', 413) }));\n }\n\n runtime.mountStaticAssets(app);\n\n // Mounted ahead of the page routes so the sub-app's middleware (auth, logging, trailing-slash)\n // wraps page requests too. The flip side: a *terminal* handler in src/server.ts at the same path\n // as a page route wins over the page.\n if (serverApp) {\n app.route('/', serverApp);\n }\n\n const memoizePage = (page: FallbackPage, label: string) => once(() => loadPageModule(page.component, label));\n const loadNotFoundPage = routeConfig.notFound ? memoizePage(routeConfig.notFound, 'the notFound page') : null;\n\n /** Turns a thrown `redirect()` / `notFound()` into the response it stands for. */\n const respondToControlSignal = async (c: Context, signal: ControlSignal): Promise<Response> => {\n const isRsc = wantsRsc(parseRenderRequest(c.req.raw));\n if (signal instanceof RedirectSignal) {\n if (isRsc) {\n return c.body(renderToReadableStream({ root: null, redirect: signal.location } satisfies RscPayload, { signal: c.req.raw.signal }), 200, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n return c.redirect(signal.location, signal.status as RedirectStatusCode);\n }\n if (loadNotFoundPage) {\n return renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true });\n }\n // Plain text, but still one of the two answers this URL gives depending on `Accept`.\n return c.text('Not Found', 404, { vary: 'Accept' });\n };\n\n for (const route of routes) {\n if (isPageRoute(route)) {\n // Both are fixed for the life of the process, so resolve them once here instead of per request.\n const servesPrerendered = !isDev && route.render === 'static';\n const loadPage = once(() => loadPageModule(route.component, `\"${route.path}\"`));\n\n const handler: Handler = async (c) => {\n try {\n if (servesPrerendered && c.req.method === 'GET') {\n const isRsc = acceptsRsc(c.req.raw);\n // Both representations are prerendered, so a soft navigation is served from the build too\n // rather than re-rendering a page that was already built. The exception is the HTML\n // under `csp`, which has to be rendered per request to carry its nonce — the flight\n // payload never carries one, so it stays servable either way.\n if (!(cspEnabled && !isRsc)) {\n const page = await runtime.readPrerendered(c, isRsc ? 'flight' : 'html');\n // A prerendered page is request-independent by construction, so it is safe to cache\n // publicly; the short max-age matches what `public/` files get. The ETag turns the\n // revalidation that follows into a 304 rather than the page all over again.\n //\n // Answered outside `runWithContext`: no app code runs on this path, so there is no\n // `getContext()` to serve and no reason to pay for the AsyncLocalStorage scope.\n if (page !== null) {\n const headers = {\n 'cache-control': SSG_CACHE_CONTROL,\n etag: page.etag,\n vary: 'Accept',\n 'content-type': isRsc ? 'text/x-component;charset=utf-8' : 'text/html;charset=utf-8',\n };\n if (etagMatches(c.req.header('if-none-match'), page.etag)) return c.body(null, 304, headers);\n return c.body(page.body, 200, { ...headers, 'content-length': page.contentLength });\n }\n }\n }\n return await runWithContext(c, () => renderPage(c, loadPage));\n } catch (error) {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n throw error;\n }\n };\n app.on(['GET', 'POST'], route.path, handler);\n } else {\n const loadEndpoint = once(() => route.server());\n const handler: Handler = async (c, next) => {\n const { handler: endpointHandler } = await loadEndpoint();\n return endpointHandler(c, next);\n };\n const method = route.method ?? 'all';\n if (method === 'all') app.all(route.path, handler);\n else app.on(method.toUpperCase(), route.path, handler);\n }\n }\n\n runtime.mountPublicFallback(app);\n\n app.notFound(async (c) => {\n const isRsc = wantsRsc(parseRenderRequest(c.req.raw));\n if (loadNotFoundPage && (isRsc || acceptsHtml(c))) {\n return runWithContext(c, async () => renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc }));\n }\n return c.text('Not Found', 404, { vary: 'Accept' });\n });\n\n const loadErrorPage = routeConfig.error ? memoizePage(routeConfig.error, 'the error page') : null;\n app.onError(async (error, c) => {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n reportServerError(error, { source: 'request', request: c.req.raw, message: '[rshono] request error:' });\n const isRsc = wantsRsc(parseRenderRequest(c.req.raw));\n if (loadErrorPage && (isRsc || acceptsHtml(c))) {\n const errorInfo: ErrorInfo = isDev\n ? {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n }\n : { message: 'Internal Server Error' };\n try {\n return await runWithContext(c, async () => renderComponent(c, await loadErrorPage(), { status: 500, isRsc, errorInfo }));\n } catch (renderError) {\n reportServerError(renderError, { source: 'request', request: c.req.raw, message: '[rshono] the error page failed to render:' });\n }\n }\n const detail = isDev ? `\\n\\n${error instanceof Error ? (error.stack ?? error.message) : String(error)}` : '';\n return c.text(`Internal Server Error${detail}`, 500, { vary: 'Accept' });\n });\n\n return app;\n}\n\nexport const app = buildApp();\n\n/**\n * The app, handed to whatever is hosting it.\n *\n * On a platform where rshono owns the process this binds a port and the default export is nothing;\n * where the host owns it, this *is* the export the platform looks for — so the same entry serves\n * both without a per-platform entry file. `app` and `routes` stay named exports either way, because\n * `rshono build` imports them to prerender `render: 'static'` routes.\n */\nexport default runtime.serveApp(app);\n"]}
|
|
1
|
+
{"version":3,"file":"entry.rsc.js","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { Context, Handler } from 'hono';\nimport { Hono } from 'hono';\nimport { bodyLimit } from 'hono/body-limit';\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status';\nimport type React from 'react';\nimport type { ReactFormState } from 'react-dom/client';\n// The JSX factory, by name: the page element is created with this directly rather than as\n// `<Page {...props} />`, because a spread would drop the non-enumerable `ctx` prop. See `pageProps`.\nimport { jsx } from 'react/jsx-runtime';\n// The bare specifier, not `/server.node`: the package ships a build per runtime behind export\n// conditions (`node`, `workerd`, `deno`, `edge-light`), and the RSC layer's `conditionNames` is what\n// picks one — so a non-Node deploy target gets its own build instead of Node's by hard-coded path.\nimport {\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n renderToReadableStream,\n type ServerEntry,\n type TemporaryReferenceSet,\n} from 'react-server-dom-rspack/server';\n// Resolved by the '@rshono/deploy' alias to the selected preset's runtime module — the one place\n// this file knows anything about where it is running. See `deploy/contract.ts`.\nimport { runtime } from '@rshono/deploy';\n// @ts-expect-error — resolved by the '@rshono/routes' alias to the app's routes.ts\nimport { routes as userRoutes } from '@rshono/routes';\n// @ts-expect-error — resolved by the '@rshono/server-app' alias (src/server.ts or the empty fallback)\nimport * as serverAppModule from '@rshono/server-app';\nimport { isPageRoute, type ErrorPageInfo, type FallbackPage, type PageComponent, type PageProps, type Route, type RouteConfig } from '../router.js';\nimport { appendVary, etagMatches } from '../server/headers.js';\nimport { getRequestContext, publicUrl, readParams, reportServerError, runWithContext } from './context.js';\nimport { isControlSignal, RedirectSignal, type ControlSignal } from './control.js';\nimport { renderHTML } from './entry.ssr.js';\n// Type-only, so it is erased — the RSC layer does not take its own instance of the SSR layer's module.\nimport type { CancellableTransformer } from './flight-inject.js';\nimport { RouterProvider } from './navigation.js';\nimport { acceptsRsc, isActionRequest, parseRenderRequest, requestWantsRsc, wantsRsc } from './request.js';\n\nconst serverApp = ((serverAppModule as { default?: unknown }).default ?? null) as Hono | null;\n\n// Framework settings resolved from rshono.config.ts and compiled into the bundle at build time\n// (see builder/rspack-config.ts). These have no runtime env-var interface — env is for secrets.\n// Named after their ServerConfig fields, so what a setting does here is one grep from where it is\n// resolved. `isDev` among them: the build mode is decided by which command produced the bundle, not\n// by `process.env.NODE_ENV`, and not every runtime this deploys to has a `process` to read anyway.\nconst CONFIG = __RSHONO_CONFIG__;\nconst { isDev, cspEnabled, checkOrigin, maxBodyBytes } = CONFIG;\n/** Extra cross-origin hosts permitted to post server actions, beyond the app's own origin. */\nconst allowedOrigins = new Set(CONFIG.allowedOrigins);\n\n/** How long a prerendered page may be reused before revalidating. Also what `public/` files get. */\nconst SSG_CACHE_CONTROL = 'public, max-age=300';\n\n/**\n * The two content types a page can be served as. Both come back from the *same* URL depending on\n * the `Accept` header, which is what makes `Vary` non-optional here.\n */\nconst PAGE_CONTENT_TYPE = /^(?:text\\/html|text\\/x-component)\\b/;\n\n// The CSP is fixed per build apart from the nonce, so assemble everything but `script-src` once.\nconst CSP_STATIC = Object.entries(CONFIG.cspDirectives)\n .filter(([name]) => name !== 'script-src')\n .map(([name, value]) => `${name} ${value}`)\n .join('; ');\nconst CSP_SCRIPT_SRC = CONFIG.cspDirectives['script-src'] ?? \"'self'\";\n\n// Called here rather than at the top of the deploy runtime's own module so the timing is unchanged:\n// `.env` is loaded once every import above has been evaluated, exactly as before.\nruntime.loadEnv();\n\nconst routeConfig = userRoutes as RouteConfig;\nexport const routes: readonly Route[] = routeConfig.routes;\n\n/** The result of a server action, as a discriminated union (a `Result<T, E>`) rather than an `ok` flag over one field. */\nexport type ActionResult = { ok: true; value: unknown } | { ok: false; error: unknown };\n\nexport type RscPayload = {\n root: React.ReactNode;\n returnValue?: ActionResult;\n formState?: ReactFormState;\n redirect?: string;\n notFound?: boolean;\n};\n\n/**\n * CSRF guard for server-action POSTs, layering the two signals a browser gives us.\n *\n * `Sec-Fetch-Site` is set by the browser and unforgeable by page script, so `same-origin` settles\n * the question on its own — and short-circuiting on it is what keeps the check from misfiring on a\n * legitimate request whose `Host` the proxy rewrote. Everything else falls back to comparing the\n * `Origin` host against our own (see {@link publicUrl} — deliberately *not* against a raw\n * `X-Forwarded-Host`, which the client controls unless `trustProxy` says a proxy owns it).\n *\n * A missing `Origin` is treated as same-origin: no-JS form posts from older browsers omit it, and\n * those same browsers send no `Sec-Fetch-Site` either, so there is nothing left to check. Hosts are\n * compared case-insensitively; the scheme is not compared, so this alone won't stop an\n * `http://` origin posting to the `https://` site (HSTS is the control for that).\n */\nfunction isSameOriginAction(c: Context): boolean {\n if (!checkOrigin) return true;\n\n const secFetchSite = c.req.header('sec-fetch-site');\n if (secFetchSite === 'same-origin') return true;\n\n const origin = c.req.header('origin');\n const originHost = origin ? URL.parse(origin)?.host.toLowerCase() || null : null;\n if (origin !== undefined && originHost === null) return false; // an Origin we can't parse is untrusted.\n\n const trusted = originHost !== null && (originHost === publicUrl(c).host.toLowerCase() || allowedOrigins.has(originHost));\n\n if (secFetchSite && secFetchSite !== 'none') {\n // The browser tells us (unforgeably) this didn't originate from our own site — only a\n // trusted (allowlisted) Origin may proceed.\n return trusted;\n }\n\n if (originHost === null) return true;\n return trusted;\n}\n\nasync function loadPageModule(load: () => Promise<{ default: PageComponent }>, label: string): Promise<ServerEntry<PageComponent>> {\n const mod = await load();\n const Page = mod.default as ServerEntry<PageComponent> | undefined;\n if (typeof Page !== 'function') {\n throw new Error(`[rshono] The page module for ${label} must default-export a server component.`);\n }\n if (!Page.entryJsFiles) {\n throw new Error(\n `[rshono] The page component for ${label} is missing its client-asset info ('use server-entry'). ` +\n \"The directive is added automatically for inline `component: () => import('…')` thunks in routes.ts. \" +\n \"If this page is wired up another way, put 'use server-entry' on the first line of the page module yourself — \" +\n \"and make sure the page is a server component (a 'use client' page must be wrapped by a server component instead).\",\n );\n }\n return Page;\n}\n\n/** A browser navigation or a crawler, as opposed to a fetch that would rather have plain text. */\nfunction acceptsHtml(c: Context): boolean {\n return c.req.header('accept')?.includes('text/html') ?? false;\n}\n\n/** A lazy once-cell: runs `load` at most once and caches the promise, but clears a rejection so a later call can retry. */\nfunction once<T>(load: () => Promise<T>): () => Promise<T> {\n let promise: Promise<T> | undefined;\n return () => {\n if (!promise) {\n const pending = (promise = load());\n pending.catch(() => {\n // Only clear if we're still holding the rejected promise (a later successful load may have already replaced it).\n if (promise === pending) promise = undefined;\n });\n }\n return promise;\n };\n}\n\n/**\n * Passes `stream` through untouched, calling `done` once it ends — however it ends.\n *\n * Used on the flight-only response path, which has no transform of its own to hang a completion hook\n * off (the document path has {@link injectFlightPayload}). `done` must be idempotent: a cancelled\n * response can reach both `cancel` and the abort forwarder.\n */\nfunction releaseWhenDone(stream: ReadableStream<Uint8Array>, done: () => void): ReadableStream<Uint8Array> {\n return stream.pipeThrough(\n new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n controller.enqueue(chunk);\n },\n flush: done,\n cancel: done,\n } as CancellableTransformer<Uint8Array, Uint8Array>),\n );\n}\n\ninterface ComponentRenderOptions {\n status?: number;\n isRsc: boolean;\n formState?: ReactFormState;\n returnValue?: RscPayload['returnValue'];\n temporaryReferences?: TemporaryReferenceSet;\n /** Passed when the page being rendered is the `error` page, which takes it as an extra prop. */\n errorInfo?: ErrorPageInfo;\n /** Marks the payload as the not-found page, so a soft navigation can tell it apart from the page it asked for. */\n notFound?: boolean;\n}\n\n/**\n * There is no render deadline here any more.\n *\n * A `renderTimeout` setting used to wrap every request in an `AbortController` with a timer, covering\n * the server action as well as the flight and SSR passes. Every host this deploys to enforces its own\n * request timeout — Workers, Vercel and Lambda all do — so the only shape that needed one was a Node\n * process facing the internet directly, and there a proxy is both the conventional and the more capable\n * place for it. The README shows the middleware for a Node deploy that wants one in-process.\n *\n * What the deadline *also* did was carry the client-disconnect signal into the two React renderers, and\n * that is kept — but not by handing them `c.req.raw.signal`. Both React renderers add an `abort`\n * listener to whatever signal they are given and only remove it if the abort fires, so a listener left on\n * a request-lifetime signal pins the flight request, the Fizz request and the whole rendered tree. That\n * is not theoretical: handing them the request signal directly cost ~169 kB per `/ssr` request, never\n * reclaimed by a major GC, and took GC from 5.8% to 12.9% of wall time under load.\n *\n * The deadline's own `AbortController` was, accidentally, what had kept that collectable — its signal\n * died with the render. So {@link renderComponent} keeps a per-render controller and forwards the request\n * signal into it, releasing the forwarder when the response ends. Never through `AbortSignal.any([...])`,\n * which reads better and leaks worse: a signal it produced is *composite*, and Node holds every composite\n * signal carrying an `abort` listener in a process-lifetime set (`gcPersistentSignals`) until it either\n * aborts or loses its last listener.\n */\n\n/**\n * Builds the props a page component is called with.\n *\n * `url` and `params` match `useNavigation()` field for field, so a read can move between a page and\n * a `'use client'` component unchanged. The `URL` is this page's own — `RequestContext` parses its own — so a\n * page that mutates it cannot disturb anything else on the request.\n *\n * `ctx` is *defined* rather than assigned, and both parts of how carry their weight:\n *\n * - **A getter**, so nothing is built for the pages that never read it, and so a `render: 'static'`\n * page that does read it gets {@link getRequestContext}'s own \"no per-request context while\n * prerendering\" error rather than a bare `undefined` — one explanation, in one place.\n * - **Non-enumerable**, so React's *development-only* serialization of a server component's props\n * (the debug channel behind component stacks and the performance track) skips it. That walks own\n * enumerable properties, and `ctx.raw` is the Hono {@link Context} — whose `env` holds the\n * runtime's bindings. An enumerable `ctx` ships every one of them, secrets included, to the\n * browser in dev, and grows a small page's flight payload by well over 10 kB. Production never\n * serializes a server component's props at all, so this is the dev half of the same guarantee.\n *\n * The cost is that the element has to be created by handing this object to `jsx()` *by reference*:\n * a `<Page {...props} />` spread copies enumerable properties only, and would drop `ctx` silently.\n */\nfunction pageProps(c: Context, errorInfo: ErrorPageInfo | undefined): PageProps & { error?: ErrorPageInfo } {\n const props = { url: publicUrl(c), params: readParams(c), ...(errorInfo ? { error: errorInfo } : null) };\n Object.defineProperty(props, 'ctx', { get: getRequestContext, enumerable: false, configurable: true });\n return props as PageProps & { error?: ErrorPageInfo };\n}\n\nasync function renderComponent(c: Context, Page: ServerEntry<PageComponent>, opts: ComponentRenderOptions): Promise<Response> {\n // The client going away is the one thing that still aborts a render — but React's renderers must not\n // be handed `c.req.raw.signal` to watch for it. Both of them add an `abort` listener and only remove\n // it if the abort fires, so on the happy path the listener stays on a signal that lives as long as the\n // request object, and through it pins the flight request, the Fizz request and the whole rendered\n // tree. Measured at ~169 kB per `/ssr` request, never reclaimed by a major GC.\n //\n // So the render gets a controller of its own and the request signal only forwards into it. The\n // forwarding listener is `once`, so an abort removes it, and {@link release} removes it on the normal\n // path — which is what keeps the request from retaining the render. Deliberately not\n // `AbortSignal.any()`: a signal it produced is *composite*, and Node holds every composite signal\n // carrying an `abort` listener in a process-lifetime set until it aborts or loses its last listener,\n // which is a worse leak than the one being fixed here.\n const requestSignal = c.req.raw.signal;\n const renderAbort = new AbortController();\n const signal = renderAbort.signal;\n const forwardAbort = () => renderAbort.abort(requestSignal.reason);\n if (requestSignal.aborted) renderAbort.abort(requestSignal.reason);\n else requestSignal.addEventListener('abort', forwardAbort, { once: true });\n /** Detaches the forwarder once the response has been written, so nothing survives the request. */\n const release = () => requestSignal.removeEventListener('abort', forwardAbort);\n\n const nonce = cspEnabled && !opts.isRsc ? crypto.randomUUID() : undefined;\n const props = pageProps(c, opts.errorInfo);\n const root = (\n <>\n {nonce && <meta property=\"csp-nonce\" nonce={nonce} />}\n {Page.entryCssFiles?.map((href) => (\n <link key={href} rel=\"stylesheet\" href={href} precedence=\"default\" />\n ))}\n {/* `href`, not the `URL` itself: these props cross into a client component, so they have to be serializable. */}\n <RouterProvider href={props.url.href} params={props.params}>\n {jsx(Page, props)}\n </RouterProvider>\n </>\n );\n\n // `notFound` only when it is true, so the flight payload of an ordinary page doesn't carry the key.\n const rscPayload: RscPayload = { root, formState: opts.formState, returnValue: opts.returnValue, ...(opts.notFound ? { notFound: true } : null) };\n\n let controlSignal: ControlSignal | undefined;\n const rscStream = renderToReadableStream(rscPayload, {\n temporaryReferences: opts.temporaryReferences,\n signal,\n onError(error) {\n if (isControlSignal(error)) {\n controlSignal = error;\n return error.digest;\n }\n if (!signal.aborted) reportServerError(error, { source: 'render', request: c.req.raw, message: '[rshono] render error:' });\n },\n });\n\n if (opts.isRsc) {\n return c.body(releaseWhenDone(rscStream, release), (opts.status ?? 200) as ContentfulStatusCode, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n\n let ssrResult: Awaited<ReturnType<typeof renderHTML>>;\n try {\n ssrResult = await renderHTML(rscStream, {\n bootstrapScripts: Page.entryJsFiles,\n formState: opts.formState,\n signal,\n nonce,\n onDone: release,\n onShellError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR shell error:' }),\n onError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR error:' }),\n });\n } catch (error) {\n release();\n if (controlSignal) throw controlSignal;\n throw error;\n }\n if (controlSignal) {\n release();\n throw controlSignal;\n }\n const headers: Record<string, string> = { 'content-type': 'text/html;charset=utf-8' };\n if (nonce) {\n // The nonce is always appended to whatever `script-src` resolved to, so overriding the\n // directive in `cspDirectives` can widen the policy but can't accidentally drop the nonce.\n // Dev additionally needs 'unsafe-eval' for react-refresh.\n const scriptSrc = `script-src ${CSP_SCRIPT_SRC} 'nonce-${nonce}'${isDev ? \" 'unsafe-eval'\" : ''}`;\n headers['content-security-policy'] = CSP_STATIC ? `${CSP_STATIC}; ${scriptSrc}` : scriptSrc;\n }\n return c.body(ssrResult.stream, (ssrResult.status ?? opts.status ?? 200) as ContentfulStatusCode, headers);\n}\n\nasync function renderPage(c: Context, loadPage: () => Promise<ServerEntry<PageComponent>>): Promise<Response> {\n const request = c.req.raw;\n const renderRequest = parseRenderRequest(request);\n\n let returnValue: ActionResult | undefined;\n let formState: ReactFormState | undefined;\n let temporaryReferences: TemporaryReferenceSet | undefined;\n let actionStatus: number | undefined;\n if (isActionRequest(renderRequest)) {\n if (!isSameOriginAction(c)) {\n return c.text('Forbidden: cross-origin server action rejected', 403);\n }\n if (renderRequest.kind === 'rsc-action') {\n // Checked before the body is decoded, so an unknown id costs nothing to reject — and\n // `loadServerAction` would otherwise fault on the missing manifest entry, turning a bad\n // request into an unhandled 500. `hasOwn` so `__proto__` doesn't resolve to a manifest entry.\n if (!Object.hasOwn(__rspack_rsc_manifest__.serverManifest, renderRequest.actionId)) {\n return c.text('Bad Request: unknown server action', 400);\n }\n const contentType = request.headers.get('content-type');\n const body = contentType?.startsWith('multipart/form-data') ? await request.formData() : await request.text();\n temporaryReferences = createTemporaryReferenceSet();\n const args = await decodeReply<unknown[]>(body, { temporaryReferences });\n const action = loadServerAction(renderRequest.actionId);\n try {\n returnValue = { ok: true, value: await action.apply(null, args) };\n } catch (error) {\n if (isControlSignal(error)) throw error;\n // React sends a thrown action error to the client as an opaque marker in production — no\n // message, no digest — so without this the failure would be invisible on both ends.\n reportServerError(error, { source: 'action', request, message: '[rshono] server action error:' });\n returnValue = { ok: false, error };\n actionStatus = 500;\n }\n } else {\n const formData = await request.formData();\n const decodedAction = await decodeAction(formData, __rspack_rsc_manifest__.serverManifest);\n if (decodedAction) {\n const result = await decodedAction();\n formState = (await decodeFormState(result, formData, __rspack_rsc_manifest__.serverManifest)) ?? undefined;\n }\n }\n }\n\n const Page = await loadPage();\n return renderComponent(c, Page, {\n status: actionStatus,\n isRsc: wantsRsc(renderRequest),\n formState,\n returnValue,\n temporaryReferences,\n });\n}\n\nfunction buildApp(): Hono {\n const app = new Hono();\n\n // Cheap, unconditional headers that only matter when something else has gone wrong: stop\n // content-type sniffing, keep the full URL (paths, query) out of cross-origin referrers, and\n // refuse to be framed by another origin (clickjacking). `frame-ancestors` in the opt-in CSP is\n // stricter and takes precedence where both apply; this is the floor for everyone else.\n // Set after `next()` so a route or middleware that sets its own value wins.\n app.use(async (c, next) => {\n await next();\n const headers = c.res.headers;\n if (!headers.has('x-content-type-options')) headers.set('x-content-type-options', 'nosniff');\n if (!headers.has('referrer-policy')) headers.set('referrer-policy', 'strict-origin-when-cross-origin');\n if (!headers.has('x-frame-options')) headers.set('x-frame-options', 'SAMEORIGIN');\n\n // Page responses only, from here down. Two things are true of them and of nothing else served\n // here: one URL answers with either an HTML document or a flight payload depending on `Accept`,\n // and the default page is request-specific (cookies, session, headers).\n if (!PAGE_CONTENT_TYPE.test(headers.get('content-type') ?? '')) return;\n appendVary(headers, 'Accept');\n // Without this a page carries no cache directives at all, and a shared cache — a CDN, a\n // corporate proxy — is free to store a logged-in user's page and hand it to someone else.\n // `private` forbids exactly that; `no-cache` makes the browser revalidate its own copy rather\n // than re-showing a stale personalised page. Neither blocks bfcache, which `no-store` would.\n // A prerendered page, or anything a route set deliberately, already has its own value.\n if (!headers.has('cache-control')) headers.set('cache-control', 'private, no-cache');\n });\n\n // A memory-exhaustion guard for *every* route — pages and actions, `{ type: 'endpoint' }` routes\n // and the src/server.ts sub-app alike — since anything that buffers a body (`.json()`,\n // `.formData()`) is exposed, not just server actions. Rejects an over-cap `Content-Length` up\n // front and otherwise counts the stream, so a chunked or under-reported body is still cut off.\n if (maxBodyBytes > 0) {\n app.use(bodyLimit({ maxSize: maxBodyBytes, onError: (c) => c.text('Payload Too Large', 413) }));\n }\n\n runtime.mountStaticAssets(app);\n\n // Mounted ahead of the page routes so the sub-app's middleware (auth, logging, trailing-slash)\n // wraps page requests too. The flip side: a *terminal* handler in src/server.ts at the same path\n // as a page route wins over the page.\n if (serverApp) {\n app.route('/', serverApp);\n }\n\n const memoizePage = (page: FallbackPage, label: string) => once(() => loadPageModule(page.component, label));\n const loadNotFoundPage = routeConfig.notFound ? memoizePage(routeConfig.notFound, 'the notFound page') : null;\n\n /** Turns a thrown `redirect()` / `notFound()` into the response it stands for. */\n const respondToControlSignal = async (c: Context, signal: ControlSignal): Promise<Response> => {\n const isRsc = requestWantsRsc(c.req.raw);\n if (signal instanceof RedirectSignal) {\n if (isRsc) {\n return c.body(renderToReadableStream({ root: null, redirect: signal.location } satisfies RscPayload, { signal: c.req.raw.signal }), 200, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n return c.redirect(signal.location, signal.status as RedirectStatusCode);\n }\n if (loadNotFoundPage) {\n return renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true });\n }\n // Plain text, but still one of the two answers this URL gives depending on `Accept`.\n return c.text('Not Found', 404, { vary: 'Accept' });\n };\n\n for (const route of routes) {\n if (isPageRoute(route)) {\n // Both are fixed for the life of the process, so resolve them once here instead of per request.\n const servesPrerendered = !isDev && route.render === 'static';\n const loadPage = once(() => loadPageModule(route.component, `\"${route.path}\"`));\n\n const handler: Handler = async (c) => {\n try {\n if (servesPrerendered && c.req.method === 'GET') {\n const isRsc = acceptsRsc(c.req.raw);\n // A prerendered file is one fixed set of bytes, so it cannot carry a per-request nonce:\n // under `csp` the *document* has to be rendered per request. The flight payload never\n // carries a nonce, so it stays servable from the build either way.\n const mustRenderForNonce = cspEnabled && !isRsc;\n // Otherwise both representations come from the build, so a soft navigation is served from\n // it too rather than re-rendering a page that was already built.\n if (!mustRenderForNonce) {\n const page = await runtime.readPrerendered(c, isRsc ? 'flight' : 'html');\n // A prerendered page is request-independent by construction, so it is safe to cache\n // publicly; the short max-age matches what `public/` files get. The ETag turns the\n // revalidation that follows into a 304 rather than the page all over again.\n //\n // Answered outside `runWithContext`: no app code runs on this path, so there is no\n // `getRequestContext()` to serve and no reason to pay for the AsyncLocalStorage scope.\n if (page !== null) {\n const headers = {\n 'cache-control': SSG_CACHE_CONTROL,\n etag: page.etag,\n vary: 'Accept',\n 'content-type': isRsc ? 'text/x-component;charset=utf-8' : 'text/html;charset=utf-8',\n };\n if (etagMatches(c.req.header('if-none-match'), page.etag)) return c.body(null, 304, headers);\n return c.body(page.body, 200, { ...headers, 'content-length': page.contentLength });\n }\n }\n }\n return await runWithContext(c, () => renderPage(c, loadPage));\n } catch (error) {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n throw error;\n }\n };\n app.on(['GET', 'POST'], route.path, handler);\n } else {\n const loadEndpoint = once(() => route.server());\n const handler: Handler = async (c, next) => {\n const { handler: endpointHandler } = await loadEndpoint();\n return endpointHandler(c, next);\n };\n const method = route.method ?? 'all';\n if (method === 'all') app.all(route.path, handler);\n else app.on(method.toUpperCase(), route.path, handler);\n }\n }\n\n runtime.mountPublicFallback(app);\n\n app.notFound(async (c) => {\n const isRsc = requestWantsRsc(c.req.raw);\n if (loadNotFoundPage && (isRsc || acceptsHtml(c))) {\n return runWithContext(c, async () => renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc }));\n }\n return c.text('Not Found', 404, { vary: 'Accept' });\n });\n\n const loadErrorPage = routeConfig.error ? memoizePage(routeConfig.error, 'the error page') : null;\n app.onError(async (error, c) => {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n reportServerError(error, { source: 'request', request: c.req.raw, message: '[rshono] request error:' });\n const isRsc = requestWantsRsc(c.req.raw);\n if (loadErrorPage && (isRsc || acceptsHtml(c))) {\n const errorInfo: ErrorPageInfo = isDev\n ? {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n }\n : { message: 'Internal Server Error' };\n try {\n return await runWithContext(c, async () => renderComponent(c, await loadErrorPage(), { status: 500, isRsc, errorInfo }));\n } catch (renderError) {\n reportServerError(renderError, { source: 'request', request: c.req.raw, message: '[rshono] the error page failed to render:' });\n }\n }\n const detail = isDev ? `\\n\\n${error instanceof Error ? (error.stack ?? error.message) : String(error)}` : '';\n return c.text(`Internal Server Error${detail}`, 500, { vary: 'Accept' });\n });\n\n return app;\n}\n\nexport const app = buildApp();\n\n/**\n * The app, handed to whatever is hosting it.\n *\n * On a platform where rshono owns the process this binds a port and the default export is nothing;\n * where the host owns it, this *is* the export the platform looks for — so the same entry serves\n * both without a per-platform entry file. `app` and `routes` stay named exports either way, because\n * `rshono build` imports them to prerender `render: 'static'` routes.\n */\nexport default runtime.serveApp(app);\n"]}
|
|
@@ -17,9 +17,17 @@ export interface RenderHTMLOptions {
|
|
|
17
17
|
* dropped instead.
|
|
18
18
|
*/
|
|
19
19
|
onError?: (error: unknown) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Called once the response stream has ended, however it ended.
|
|
22
|
+
*
|
|
23
|
+
* The RSC layer uses it to detach the listener forwarding client-disconnect aborts into this render —
|
|
24
|
+
* see `renderComponent`. Without a hook here that listener outlives the request and retains the whole
|
|
25
|
+
* rendered tree, so this is load-bearing rather than a convenience.
|
|
26
|
+
*/
|
|
27
|
+
onDone?: () => void;
|
|
20
28
|
}
|
|
21
29
|
export declare function renderHTML(rscStream: ReadableStream<Uint8Array>, options: RenderHTMLOptions): Promise<{
|
|
22
|
-
stream: ReadableStream<
|
|
30
|
+
stream: ReadableStream<Uint8Array<ArrayBufferLike>>;
|
|
23
31
|
status: number | undefined;
|
|
24
32
|
}>;
|
|
25
33
|
//# sourceMappingURL=entry.ssr.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.ssr.d.ts","sourceRoot":"","sources":["../../src/runtime/entry.ssr.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"entry.ssr.d.ts","sourceRoot":"","sources":["../../src/runtime/entry.ssr.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAqDD,wBAAsB,UAAU,CAAC,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,iBAAiB;;;GAiDjG"}
|