@rshono/core 1.0.0-rc.0
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 +273 -0
- package/bin/rshono.mjs +15 -0
- package/dist/builder/env-shadow-loader.cjs +26 -0
- package/dist/builder/page-entry-loader.cjs +7 -0
- package/dist/builder/page-files.d.ts +2 -0
- package/dist/builder/page-files.d.ts.map +1 -0
- package/dist/builder/page-files.js +45 -0
- package/dist/builder/page-files.js.map +1 -0
- package/dist/builder/public-env.d.ts +2 -0
- package/dist/builder/public-env.d.ts.map +1 -0
- package/dist/builder/public-env.js +5 -0
- package/dist/builder/public-env.js.map +1 -0
- package/dist/builder/rspack-config.d.ts +14 -0
- package/dist/builder/rspack-config.d.ts.map +1 -0
- package/dist/builder/rspack-config.js +235 -0
- package/dist/builder/rspack-config.js.map +1 -0
- package/dist/cli/build.d.ts +11 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +64 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/dev.d.ts +9 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +210 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +77 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/start.d.ts +8 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/cli/start.js +39 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/config.d.ts +121 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -0
- package/dist/deploy/aws-lambda/runtime.d.ts +14 -0
- package/dist/deploy/aws-lambda/runtime.d.ts.map +1 -0
- package/dist/deploy/aws-lambda/runtime.js +24 -0
- package/dist/deploy/aws-lambda/runtime.js.map +1 -0
- package/dist/deploy/build-marker.d.ts +15 -0
- package/dist/deploy/build-marker.d.ts.map +1 -0
- package/dist/deploy/build-marker.js +26 -0
- package/dist/deploy/build-marker.js.map +1 -0
- package/dist/deploy/bun/runtime.d.ts +11 -0
- package/dist/deploy/bun/runtime.d.ts.map +1 -0
- package/dist/deploy/bun/runtime.js +22 -0
- package/dist/deploy/bun/runtime.js.map +1 -0
- package/dist/deploy/cloudflare/build.d.ts +7 -0
- package/dist/deploy/cloudflare/build.d.ts.map +1 -0
- package/dist/deploy/cloudflare/build.js +74 -0
- package/dist/deploy/cloudflare/build.js.map +1 -0
- package/dist/deploy/cloudflare/runtime.d.ts +10 -0
- package/dist/deploy/cloudflare/runtime.d.ts.map +1 -0
- package/dist/deploy/cloudflare/runtime.js +129 -0
- package/dist/deploy/cloudflare/runtime.js.map +1 -0
- package/dist/deploy/contract.d.ts +65 -0
- package/dist/deploy/contract.d.ts.map +1 -0
- package/dist/deploy/contract.js +2 -0
- package/dist/deploy/contract.js.map +1 -0
- package/dist/deploy/deno/runtime.d.ts +11 -0
- package/dist/deploy/deno/runtime.d.ts.map +1 -0
- package/dist/deploy/deno/runtime.js +16 -0
- package/dist/deploy/deno/runtime.js.map +1 -0
- package/dist/deploy/filesystem.d.ts +10 -0
- package/dist/deploy/filesystem.d.ts.map +1 -0
- package/dist/deploy/filesystem.js +47 -0
- package/dist/deploy/filesystem.js.map +1 -0
- package/dist/deploy/listen.d.ts +20 -0
- package/dist/deploy/listen.d.ts.map +1 -0
- package/dist/deploy/listen.js +24 -0
- package/dist/deploy/listen.js.map +1 -0
- package/dist/deploy/netlify/build.d.ts +8 -0
- package/dist/deploy/netlify/build.d.ts.map +1 -0
- package/dist/deploy/netlify/build.js +52 -0
- package/dist/deploy/netlify/build.js.map +1 -0
- package/dist/deploy/netlify/runtime.d.ts +13 -0
- package/dist/deploy/netlify/runtime.d.ts.map +1 -0
- package/dist/deploy/netlify/runtime.js +24 -0
- package/dist/deploy/netlify/runtime.js.map +1 -0
- package/dist/deploy/node/runtime.d.ts +7 -0
- package/dist/deploy/node/runtime.d.ts.map +1 -0
- package/dist/deploy/node/runtime.js +36 -0
- package/dist/deploy/node/runtime.js.map +1 -0
- package/dist/deploy/presets.d.ts +88 -0
- package/dist/deploy/presets.d.ts.map +1 -0
- package/dist/deploy/presets.js +110 -0
- package/dist/deploy/presets.js.map +1 -0
- package/dist/deploy/vercel/build.d.ts +3 -0
- package/dist/deploy/vercel/build.d.ts.map +1 -0
- package/dist/deploy/vercel/build.js +56 -0
- package/dist/deploy/vercel/build.js.map +1 -0
- package/dist/deploy/vercel/runtime.d.ts +14 -0
- package/dist/deploy/vercel/runtime.d.ts.map +1 -0
- package/dist/deploy/vercel/runtime.js +26 -0
- package/dist/deploy/vercel/runtime.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/router.d.ts +337 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +18 -0
- package/dist/router.js.map +1 -0
- package/dist/runtime/boundaries.d.ts +102 -0
- package/dist/runtime/boundaries.d.ts.map +1 -0
- package/dist/runtime/boundaries.js +101 -0
- package/dist/runtime/boundaries.js.map +1 -0
- package/dist/runtime/client.d.ts +16 -0
- package/dist/runtime/client.d.ts.map +1 -0
- package/dist/runtime/client.js +16 -0
- package/dist/runtime/client.js.map +1 -0
- package/dist/runtime/context.d.ts +271 -0
- package/dist/runtime/context.d.ts.map +1 -0
- package/dist/runtime/context.js +360 -0
- package/dist/runtime/context.js.map +1 -0
- package/dist/runtime/control.d.ts +18 -0
- package/dist/runtime/control.d.ts.map +1 -0
- package/dist/runtime/control.js +39 -0
- package/dist/runtime/control.js.map +1 -0
- package/dist/runtime/dev-protocol.d.ts +22 -0
- package/dist/runtime/dev-protocol.d.ts.map +1 -0
- package/dist/runtime/dev-protocol.js +2 -0
- package/dist/runtime/dev-protocol.js.map +1 -0
- package/dist/runtime/empty-server-app.d.ts +3 -0
- package/dist/runtime/empty-server-app.d.ts.map +1 -0
- package/dist/runtime/empty-server-app.js +2 -0
- package/dist/runtime/empty-server-app.js.map +1 -0
- package/dist/runtime/entry.client.d.ts +2 -0
- package/dist/runtime/entry.client.d.ts.map +1 -0
- package/dist/runtime/entry.client.js +453 -0
- package/dist/runtime/entry.client.js.map +1 -0
- package/dist/runtime/entry.rsc.d.ts +32 -0
- package/dist/runtime/entry.rsc.d.ts.map +1 -0
- package/dist/runtime/entry.rsc.js +466 -0
- package/dist/runtime/entry.rsc.js.map +1 -0
- package/dist/runtime/entry.ssr.d.ts +25 -0
- package/dist/runtime/entry.ssr.d.ts.map +1 -0
- package/dist/runtime/entry.ssr.js +86 -0
- package/dist/runtime/entry.ssr.js.map +1 -0
- package/dist/runtime/navigation.d.ts +114 -0
- package/dist/runtime/navigation.d.ts.map +1 -0
- package/dist/runtime/navigation.js +112 -0
- package/dist/runtime/navigation.js.map +1 -0
- package/dist/runtime/request.d.ts +35 -0
- package/dist/runtime/request.d.ts.map +1 -0
- package/dist/runtime/request.js +39 -0
- package/dist/runtime/request.js.map +1 -0
- package/dist/runtime/server.d.ts +24 -0
- package/dist/runtime/server.d.ts.map +1 -0
- package/dist/runtime/server.js +24 -0
- package/dist/runtime/server.js.map +1 -0
- package/dist/server/compress.d.ts +15 -0
- package/dist/server/compress.d.ts.map +1 -0
- package/dist/server/compress.js +76 -0
- package/dist/server/compress.js.map +1 -0
- package/dist/server/headers.d.ts +24 -0
- package/dist/server/headers.d.ts.map +1 -0
- package/dist/server/headers.js +44 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/load-config.d.ts +7 -0
- package/dist/server/load-config.d.ts.map +1 -0
- package/dist/server/load-config.js +41 -0
- package/dist/server/load-config.js.map +1 -0
- package/dist/server/load-env.d.ts +2 -0
- package/dist/server/load-env.d.ts.map +1 -0
- package/dist/server/load-env.js +10 -0
- package/dist/server/load-env.js.map +1 -0
- package/dist/server/prerendered.d.ts +67 -0
- package/dist/server/prerendered.d.ts.map +1 -0
- package/dist/server/prerendered.js +39 -0
- package/dist/server/prerendered.js.map +1 -0
- package/dist/server/server-config.d.ts +72 -0
- package/dist/server/server-config.d.ts.map +1 -0
- package/dist/server/server-config.js +94 -0
- package/dist/server/server-config.js.map +1 -0
- package/dist/server/shutdown.d.ts +7 -0
- package/dist/server/shutdown.d.ts.map +1 -0
- package/dist/server/shutdown.js +11 -0
- package/dist/server/shutdown.js.map +1 -0
- package/dist/server/ssg.d.ts +25 -0
- package/dist/server/ssg.d.ts.map +1 -0
- package/dist/server/ssg.js +160 -0
- package/dist/server/ssg.js.map +1 -0
- package/dist/server/static.d.ts +14 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +30 -0
- package/dist/server/static.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactFormState } from 'react-dom/client';
|
|
2
|
+
export interface RenderHTMLOptions {
|
|
3
|
+
bootstrapScripts?: string[];
|
|
4
|
+
formState?: ReactFormState;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
nonce?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Called when SSR fails before the shell is sent. Reporting is the RSC layer's job — this module
|
|
9
|
+
* is compiled into the SSR layer, which gets its own instance of every module it imports, so a
|
|
10
|
+
* handler registered through `@rshono/core/server` isn't reachable from in here.
|
|
11
|
+
*/
|
|
12
|
+
onShellError?: (error: unknown) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Called for an error that happened during SSR and *originated* in SSR — a client component that
|
|
15
|
+
* threw while rendering on the server, whether a boundary went on to contain it or it took the
|
|
16
|
+
* shell down with it. See {@link renderHTML} for why the ones that didn't originate here are
|
|
17
|
+
* dropped instead.
|
|
18
|
+
*/
|
|
19
|
+
onError?: (error: unknown) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function renderHTML(rscStream: ReadableStream<Uint8Array>, options: RenderHTMLOptions): Promise<{
|
|
22
|
+
stream: ReadableStream<any>;
|
|
23
|
+
status: number | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
//# sourceMappingURL=entry.ssr.d.ts.map
|
|
@@ -0,0 +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;CACpC;AAsDD,wBAAsB,UAAU,CAAC,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,iBAAiB;;;GAiDjG"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { renderToReadableStream } from 'react-dom/server';
|
|
4
|
+
import { createFromReadableStream } from 'react-server-dom-rspack/client';
|
|
5
|
+
import { injectRSCPayload } from 'rsc-html-stream/server';
|
|
6
|
+
import { isControlDigest } from './control.js';
|
|
7
|
+
// From the baked config, not `process.env.NODE_ENV`: this is a property of the build, and a deploy
|
|
8
|
+
// target need not have a `process` at all.
|
|
9
|
+
const isDev = __RSHONO_CONFIG__.isDev;
|
|
10
|
+
/**
|
|
11
|
+
* The last-resort 500 document, for when SSR fails before a single byte of the real shell was sent.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately plain HTML with no client runtime attached: the flight payload comes from the same
|
|
14
|
+
* failed render, so hydrating it would mismatch and React — whose root container is the whole
|
|
15
|
+
* `document` — would tear the page down, blanking the very message being rendered here. Styling is
|
|
16
|
+
* inline because the page's stylesheet links were part of the render that just failed.
|
|
17
|
+
*
|
|
18
|
+
* The detail is dev-only. In production this stays a generic message, matching how the `error` page
|
|
19
|
+
* from routes.ts redacts.
|
|
20
|
+
*/
|
|
21
|
+
function SsrFailureDocument({ error }) {
|
|
22
|
+
const detail = isDev ? (error instanceof Error ? (error.stack ?? `${error.name}: ${error.message}`) : String(error)) : null;
|
|
23
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "500 \u2014 Internal Server Error" })] }), _jsxs("body", { style: { margin: 0, padding: '2rem', font: '16px/1.6 system-ui, -apple-system, sans-serif', color: '#18181b' }, children: [_jsx("h1", { style: { margin: '0 0 0.5rem', fontSize: '1.25rem' }, children: "500 \u2014 Internal Server Error" }), _jsx("p", { style: { margin: '0 0 1.5rem', color: '#52525b' }, children: isDev
|
|
24
|
+
? 'Server-side rendering failed before the page shell could be sent, so the app’s error page could not be reached either.'
|
|
25
|
+
: 'Something went wrong while rendering this page. Please try again.' }), detail && (_jsx("pre", { style: {
|
|
26
|
+
margin: 0,
|
|
27
|
+
padding: '1rem',
|
|
28
|
+
overflow: 'auto',
|
|
29
|
+
background: '#f4f4f5',
|
|
30
|
+
borderLeft: '3px solid #ef4444',
|
|
31
|
+
font: '13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace',
|
|
32
|
+
whiteSpace: 'pre-wrap',
|
|
33
|
+
wordBreak: 'break-word',
|
|
34
|
+
}, children: detail }))] })] }));
|
|
35
|
+
}
|
|
36
|
+
export async function renderHTML(rscStream, options) {
|
|
37
|
+
// One copy is rendered to HTML here; the other rides along in that HTML for the client to hydrate from.
|
|
38
|
+
const [rscForSsr, rscForClient] = rscStream.tee();
|
|
39
|
+
let payload;
|
|
40
|
+
function SsrRoot() {
|
|
41
|
+
payload ??= createFromReadableStream(rscForSsr, options.nonce ? { nonce: options.nonce } : undefined);
|
|
42
|
+
return React.use(payload).root;
|
|
43
|
+
}
|
|
44
|
+
// React hands `onError` every error it meets while streaming, including ones an error boundary
|
|
45
|
+
// contained — and with no handler installed it logs each one itself. Almost all of them are errors
|
|
46
|
+
// it read out of the flight payload, where they arrive as React's redacted stand-in: a `digest`
|
|
47
|
+
// and no message. The RSC layer has already reported the real one in full, so the default handler
|
|
48
|
+
// prints an alarming, detail-free duplicate for a request a boundary handled perfectly well. Only
|
|
49
|
+
// an error carrying no digest started life in this render — a client component that threw during
|
|
50
|
+
// SSR — and that one nothing else will report.
|
|
51
|
+
let reported;
|
|
52
|
+
const onError = (error) => {
|
|
53
|
+
if (typeof error?.digest === 'string')
|
|
54
|
+
return;
|
|
55
|
+
if (options.signal?.aborted)
|
|
56
|
+
return; // an abort is the deadline or the client leaving, not a fault
|
|
57
|
+
reported = error;
|
|
58
|
+
options.onError?.(error);
|
|
59
|
+
};
|
|
60
|
+
let htmlStream;
|
|
61
|
+
let status;
|
|
62
|
+
try {
|
|
63
|
+
htmlStream = await renderToReadableStream(_jsx(SsrRoot, {}), {
|
|
64
|
+
bootstrapScripts: options.bootstrapScripts,
|
|
65
|
+
formState: options.formState,
|
|
66
|
+
signal: options.signal,
|
|
67
|
+
nonce: options.nonce,
|
|
68
|
+
// Deliberately returns nothing, so the digest React gives the client's `onRecoverableError`
|
|
69
|
+
// stays exactly what it was before a handler was installed here.
|
|
70
|
+
onError,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (isControlDigest(error?.digest))
|
|
75
|
+
throw error;
|
|
76
|
+
// `onError` runs first for the failure that aborts the shell, so this reports only what it let
|
|
77
|
+
// through: an error out of the flight payload, whose detail the RSC layer alone has.
|
|
78
|
+
if (!options.signal?.aborted && error !== reported)
|
|
79
|
+
options.onShellError?.(error);
|
|
80
|
+
status = 500;
|
|
81
|
+
htmlStream = await renderToReadableStream(_jsx(SsrFailureDocument, { error: error }), { nonce: options.nonce });
|
|
82
|
+
}
|
|
83
|
+
const responseStream = htmlStream.pipeThrough(injectRSCPayload(rscForClient, options.nonce ? { nonce: options.nonce } : undefined));
|
|
84
|
+
return { stream: responseStream, status };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=entry.ssr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.ssr.js","sourceRoot":"","sources":["../../src/runtime/entry.ssr.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport type { ReactFormState } from 'react-dom/client';\nimport { renderToReadableStream } from 'react-dom/server';\nimport { createFromReadableStream } from 'react-server-dom-rspack/client';\nimport { injectRSCPayload } from 'rsc-html-stream/server';\nimport { isControlDigest } from './control.js';\nimport type { RscPayload } from './entry.rsc.js';\n\nexport interface RenderHTMLOptions {\n bootstrapScripts?: string[];\n formState?: ReactFormState;\n signal?: AbortSignal;\n nonce?: string;\n /**\n * Called when SSR fails before the shell is sent. Reporting is the RSC layer's job — this module\n * is compiled into the SSR layer, which gets its own instance of every module it imports, so a\n * handler registered through `@rshono/core/server` isn't reachable from in here.\n */\n onShellError?: (error: unknown) => void;\n /**\n * Called for an error that happened during SSR and *originated* in SSR — a client component that\n * threw while rendering on the server, whether a boundary went on to contain it or it took the\n * shell down with it. See {@link renderHTML} for why the ones that didn't originate here are\n * dropped instead.\n */\n onError?: (error: unknown) => void;\n}\n\n// From the baked config, not `process.env.NODE_ENV`: this is a property of the build, and a deploy\n// target need not have a `process` at all.\nconst isDev = __RSHONO_CONFIG__.isDev;\n\n/**\n * The last-resort 500 document, for when SSR fails before a single byte of the real shell was sent.\n *\n * Deliberately plain HTML with no client runtime attached: the flight payload comes from the same\n * failed render, so hydrating it would mismatch and React — whose root container is the whole\n * `document` — would tear the page down, blanking the very message being rendered here. Styling is\n * inline because the page's stylesheet links were part of the render that just failed.\n *\n * The detail is dev-only. In production this stays a generic message, matching how the `error` page\n * from routes.ts redacts.\n */\nfunction SsrFailureDocument({ error }: { error: unknown }) {\n const detail = isDev ? (error instanceof Error ? (error.stack ?? `${error.name}: ${error.message}`) : String(error)) : null;\n return (\n <html lang=\"en\">\n <head>\n <meta charSet=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>500 — Internal Server Error</title>\n </head>\n <body style={{ margin: 0, padding: '2rem', font: '16px/1.6 system-ui, -apple-system, sans-serif', color: '#18181b' }}>\n <h1 style={{ margin: '0 0 0.5rem', fontSize: '1.25rem' }}>500 — Internal Server Error</h1>\n <p style={{ margin: '0 0 1.5rem', color: '#52525b' }}>\n {isDev\n ? 'Server-side rendering failed before the page shell could be sent, so the app’s error page could not be reached either.'\n : 'Something went wrong while rendering this page. Please try again.'}\n </p>\n {detail && (\n <pre\n style={{\n margin: 0,\n padding: '1rem',\n overflow: 'auto',\n background: '#f4f4f5',\n borderLeft: '3px solid #ef4444',\n font: '13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n >\n {detail}\n </pre>\n )}\n </body>\n </html>\n );\n}\n\nexport async function renderHTML(rscStream: ReadableStream<Uint8Array>, options: RenderHTMLOptions) {\n // One copy is rendered to HTML here; the other rides along in that HTML for the client to hydrate from.\n const [rscForSsr, rscForClient] = rscStream.tee();\n\n let payload: Promise<RscPayload>;\n function SsrRoot() {\n payload ??= createFromReadableStream<RscPayload>(rscForSsr, options.nonce ? { nonce: options.nonce } : undefined);\n return React.use(payload).root;\n }\n\n // React hands `onError` every error it meets while streaming, including ones an error boundary\n // contained — and with no handler installed it logs each one itself. Almost all of them are errors\n // it read out of the flight payload, where they arrive as React's redacted stand-in: a `digest`\n // and no message. The RSC layer has already reported the real one in full, so the default handler\n // prints an alarming, detail-free duplicate for a request a boundary handled perfectly well. Only\n // an error carrying no digest started life in this render — a client component that threw during\n // SSR — and that one nothing else will report.\n let reported: unknown;\n const onError = (error: unknown): void => {\n if (typeof (error as { digest?: unknown } | null)?.digest === 'string') return;\n if (options.signal?.aborted) return; // an abort is the deadline or the client leaving, not a fault\n reported = error;\n options.onError?.(error);\n };\n\n let htmlStream: ReadableStream<Uint8Array>;\n let status: number | undefined;\n try {\n htmlStream = await renderToReadableStream(<SsrRoot />, {\n bootstrapScripts: options.bootstrapScripts,\n formState: options.formState,\n signal: options.signal,\n nonce: options.nonce,\n // Deliberately returns nothing, so the digest React gives the client's `onRecoverableError`\n // stays exactly what it was before a handler was installed here.\n onError,\n });\n } catch (error) {\n if (isControlDigest((error as { digest?: unknown } | null)?.digest)) throw error;\n // `onError` runs first for the failure that aborts the shell, so this reports only what it let\n // through: an error out of the flight payload, whose detail the RSC layer alone has.\n if (!options.signal?.aborted && error !== reported) options.onShellError?.(error);\n status = 500;\n htmlStream = await renderToReadableStream(<SsrFailureDocument error={error} />, { nonce: options.nonce });\n }\n\n const responseStream = htmlStream.pipeThrough(injectRSCPayload(rscForClient, options.nonce ? { nonce: options.nonce } : undefined));\n\n return { stream: responseStream, status };\n}\n"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Imperative navigation actions, reached as `useNavigation().router`.
|
|
4
|
+
*
|
|
5
|
+
* `push` / `replace` / `refresh` are **soft** navigations: the new page's flight
|
|
6
|
+
* payload is fetched and applied in place, so client component state outside the
|
|
7
|
+
* changed subtree survives. Off-site or non-HTTP hrefs fall back to a full load.
|
|
8
|
+
*/
|
|
9
|
+
export interface Router {
|
|
10
|
+
/** Navigates to `href` and pushes a new history entry. */
|
|
11
|
+
push(href: string): void;
|
|
12
|
+
/** Navigates to `href`, replacing the current history entry instead of adding one. */
|
|
13
|
+
replace(href: string): void;
|
|
14
|
+
/** Goes back one history entry — `history.back()`. */
|
|
15
|
+
back(): void;
|
|
16
|
+
/** Goes forward one history entry — `history.forward()`. */
|
|
17
|
+
forward(): void;
|
|
18
|
+
/** Re-fetches the current route from the server, re-running its server components. */
|
|
19
|
+
refresh(): void;
|
|
20
|
+
/** `true` while a soft navigation is in flight — use it to disable controls or show a spinner. */
|
|
21
|
+
pending: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** The current location plus the {@link Router}, as returned by {@link useNavigation}. */
|
|
24
|
+
export interface Navigation {
|
|
25
|
+
/**
|
|
26
|
+
* The full current {@link URL} — read `url.pathname`, `url.searchParams` and the
|
|
27
|
+
* rest off it. A fresh instance per navigation, so mutating it affects nothing
|
|
28
|
+
* else; it is not written back to the address bar either.
|
|
29
|
+
*/
|
|
30
|
+
url: URL;
|
|
31
|
+
/** Matched route params for the current page, e.g. `{ id: '42' }` for `/profile/:id`. */
|
|
32
|
+
params: Record<string, string>;
|
|
33
|
+
/** Imperative navigation actions and the `pending` flag. */
|
|
34
|
+
router: Router;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Carries the live {@link Router} implementation from the hydration runtime down
|
|
38
|
+
* to {@link RouterProvider}. Framework internal — read the router through
|
|
39
|
+
* {@link useNavigation} instead.
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export declare const RouterContext: import("react").Context<Router>;
|
|
44
|
+
/**
|
|
45
|
+
* Publishes the per-render location and params so {@link useNavigation} can read
|
|
46
|
+
* them. Framework internal — the RSC entry wraps every page in one.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export declare function RouterProvider({ href, params, children }: {
|
|
51
|
+
href: string;
|
|
52
|
+
params: Record<string, string>;
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
}): import("react").JSX.Element;
|
|
55
|
+
/**
|
|
56
|
+
* Reactive access to the current URL and programmatic navigation, in one hook.
|
|
57
|
+
*
|
|
58
|
+
* Call it from a `'use client'` component. The location fields (`url` and
|
|
59
|
+
* `params`) are computed on the server and travel in the flight payload, so they
|
|
60
|
+
* are correct during SSR — no hydration flicker — and update automatically on
|
|
61
|
+
* every navigation. The `router` sub-object holds the imperative actions plus a
|
|
62
|
+
* `pending` flag that is `true` while a client navigation is in flight.
|
|
63
|
+
*
|
|
64
|
+
* Hooks can't run in a server component; read the same URL data there from
|
|
65
|
+
* `getContext()` (`@rshono/core/server`) instead.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* 'use client';
|
|
70
|
+
* import { useNavigation } from '@rshono/core/client';
|
|
71
|
+
*
|
|
72
|
+
* export function NextPage() {
|
|
73
|
+
* const { url, router } = useNavigation();
|
|
74
|
+
* const page = Number(url.searchParams.get('page') ?? '1');
|
|
75
|
+
* return (
|
|
76
|
+
* <button disabled={router.pending} onClick={() => router.push(`${url.pathname}?page=${page + 1}`)}>
|
|
77
|
+
* Next {router.pending ? '…' : ''}
|
|
78
|
+
* </button>
|
|
79
|
+
* );
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @returns The current {@link Navigation}: `url` and `params`, plus `router`
|
|
84
|
+
* ({@link Router}) with `push` / `replace` / `back` / `forward` / `refresh` /
|
|
85
|
+
* `pending`.
|
|
86
|
+
* @throws If called outside a page's React tree, where there is no navigation
|
|
87
|
+
* context to read.
|
|
88
|
+
*/
|
|
89
|
+
export declare function useNavigation(): Navigation;
|
|
90
|
+
export interface NavigationProgressProps {
|
|
91
|
+
/** Bar color. Defaults to a neutral blue. */
|
|
92
|
+
color?: string;
|
|
93
|
+
/** Bar height in pixels. Defaults to `3`. */
|
|
94
|
+
height?: number;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* An opt-in top progress bar that appears while a client navigation is in
|
|
98
|
+
* flight (driven by {@link Router.pending}). Drop one instance in your root
|
|
99
|
+
* layout; it renders nothing on the server and stays invisible until the first
|
|
100
|
+
* soft navigation, so there's no hydration flicker.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```tsx
|
|
104
|
+
* import { NavigationProgress } from '@rshono/core/client';
|
|
105
|
+
*
|
|
106
|
+
* // in your layout, once:
|
|
107
|
+
* <body>
|
|
108
|
+
* <NavigationProgress />
|
|
109
|
+
* {children}
|
|
110
|
+
* </body>
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function NavigationProgress({ color, height }?: NavigationProgressProps): ReactNode;
|
|
114
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/runtime/navigation.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA2D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEhG;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,0DAA0D;IAC1D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,sFAAsF;IACtF,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,sDAAsD;IACtD,IAAI,IAAI,IAAI,CAAC;IACb,4DAA4D;IAC5D,OAAO,IAAI,IAAI,CAAC;IAChB,sFAAsF;IACtF,OAAO,IAAI,IAAI,CAAC;IAChB,kGAAkG;IAClG,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,0FAA0F;AAC1F,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,GAAG,EAAE,GAAG,CAAC;IACT,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,iCAAuC,CAAC;AAIlE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAK/H;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAQ1C;AAED,MAAM,WAAW,uBAAuB;IACtC,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,KAAiB,EAAE,MAAU,EAAE,GAAE,uBAA4B,GAAG,SAAS,CAmC7G"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|
4
|
+
const noop = () => { };
|
|
5
|
+
const defaultRouter = { push: noop, replace: noop, back: noop, forward: noop, refresh: noop, pending: false };
|
|
6
|
+
/**
|
|
7
|
+
* Carries the live {@link Router} implementation from the hydration runtime down
|
|
8
|
+
* to {@link RouterProvider}. Framework internal — read the router through
|
|
9
|
+
* {@link useNavigation} instead.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export const RouterContext = createContext(defaultRouter);
|
|
14
|
+
const NavigationContext = createContext(null);
|
|
15
|
+
/**
|
|
16
|
+
* Publishes the per-render location and params so {@link useNavigation} can read
|
|
17
|
+
* them. Framework internal — the RSC entry wraps every page in one.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export function RouterProvider({ href, params, children }) {
|
|
22
|
+
const router = useContext(RouterContext);
|
|
23
|
+
const value = useMemo(() => ({ url: new URL(href), params, router }), [href, params, router]);
|
|
24
|
+
return _jsx(NavigationContext.Provider, { value: value, children: children });
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Reactive access to the current URL and programmatic navigation, in one hook.
|
|
28
|
+
*
|
|
29
|
+
* Call it from a `'use client'` component. The location fields (`url` and
|
|
30
|
+
* `params`) are computed on the server and travel in the flight payload, so they
|
|
31
|
+
* are correct during SSR — no hydration flicker — and update automatically on
|
|
32
|
+
* every navigation. The `router` sub-object holds the imperative actions plus a
|
|
33
|
+
* `pending` flag that is `true` while a client navigation is in flight.
|
|
34
|
+
*
|
|
35
|
+
* Hooks can't run in a server component; read the same URL data there from
|
|
36
|
+
* `getContext()` (`@rshono/core/server`) instead.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* 'use client';
|
|
41
|
+
* import { useNavigation } from '@rshono/core/client';
|
|
42
|
+
*
|
|
43
|
+
* export function NextPage() {
|
|
44
|
+
* const { url, router } = useNavigation();
|
|
45
|
+
* const page = Number(url.searchParams.get('page') ?? '1');
|
|
46
|
+
* return (
|
|
47
|
+
* <button disabled={router.pending} onClick={() => router.push(`${url.pathname}?page=${page + 1}`)}>
|
|
48
|
+
* Next {router.pending ? '…' : ''}
|
|
49
|
+
* </button>
|
|
50
|
+
* );
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @returns The current {@link Navigation}: `url` and `params`, plus `router`
|
|
55
|
+
* ({@link Router}) with `push` / `replace` / `back` / `forward` / `refresh` /
|
|
56
|
+
* `pending`.
|
|
57
|
+
* @throws If called outside a page's React tree, where there is no navigation
|
|
58
|
+
* context to read.
|
|
59
|
+
*/
|
|
60
|
+
export function useNavigation() {
|
|
61
|
+
const value = useContext(NavigationContext);
|
|
62
|
+
if (!value) {
|
|
63
|
+
throw new Error("[rshono] useNavigation() must be called inside a 'use client' component rendered by a page. In a server component, read the URL from getContext() instead.");
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* An opt-in top progress bar that appears while a client navigation is in
|
|
69
|
+
* flight (driven by {@link Router.pending}). Drop one instance in your root
|
|
70
|
+
* layout; it renders nothing on the server and stays invisible until the first
|
|
71
|
+
* soft navigation, so there's no hydration flicker.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* import { NavigationProgress } from '@rshono/core/client';
|
|
76
|
+
*
|
|
77
|
+
* // in your layout, once:
|
|
78
|
+
* <body>
|
|
79
|
+
* <NavigationProgress />
|
|
80
|
+
* {children}
|
|
81
|
+
* </body>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function NavigationProgress({ color = '#3b82f6', height = 3 } = {}) {
|
|
85
|
+
const { router } = useNavigation();
|
|
86
|
+
const [bar, setBar] = useState({ width: 0, opacity: 0 });
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (router.pending) {
|
|
89
|
+
// Jump in, then creep toward — but never reach — the end while we wait.
|
|
90
|
+
setBar({ width: 15, opacity: 1 });
|
|
91
|
+
const ramp = setTimeout(() => setBar({ width: 85, opacity: 1 }), 80);
|
|
92
|
+
return () => clearTimeout(ramp);
|
|
93
|
+
}
|
|
94
|
+
// Done: snap to full, then fade out. (No-op if it was never shown.)
|
|
95
|
+
setBar((b) => (b.opacity === 0 ? b : { width: 100, opacity: 1 }));
|
|
96
|
+
const hide = setTimeout(() => setBar({ width: 0, opacity: 0 }), 220);
|
|
97
|
+
return () => clearTimeout(hide);
|
|
98
|
+
}, [router.pending]);
|
|
99
|
+
return (_jsx("div", { "data-rshono-progress": "", "aria-hidden": "true", style: {
|
|
100
|
+
position: 'fixed',
|
|
101
|
+
top: 0,
|
|
102
|
+
left: 0,
|
|
103
|
+
height,
|
|
104
|
+
width: `${bar.width}%`,
|
|
105
|
+
opacity: bar.opacity,
|
|
106
|
+
background: color,
|
|
107
|
+
zIndex: 2147483647,
|
|
108
|
+
pointerEvents: 'none',
|
|
109
|
+
transition: 'width 200ms ease-out, opacity 200ms ease-out',
|
|
110
|
+
} }));
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/runtime/navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';\n\n/**\n * Imperative navigation actions, reached as `useNavigation().router`.\n *\n * `push` / `replace` / `refresh` are **soft** navigations: the new page's flight\n * payload is fetched and applied in place, so client component state outside the\n * changed subtree survives. Off-site or non-HTTP hrefs fall back to a full load.\n */\nexport interface Router {\n /** Navigates to `href` and pushes a new history entry. */\n push(href: string): void;\n /** Navigates to `href`, replacing the current history entry instead of adding one. */\n replace(href: string): void;\n /** Goes back one history entry — `history.back()`. */\n back(): void;\n /** Goes forward one history entry — `history.forward()`. */\n forward(): void;\n /** Re-fetches the current route from the server, re-running its server components. */\n refresh(): void;\n /** `true` while a soft navigation is in flight — use it to disable controls or show a spinner. */\n pending: boolean;\n}\n\n/** The current location plus the {@link Router}, as returned by {@link useNavigation}. */\nexport interface Navigation {\n /**\n * The full current {@link URL} — read `url.pathname`, `url.searchParams` and the\n * rest off it. A fresh instance per navigation, so mutating it affects nothing\n * else; it is not written back to the address bar either.\n */\n url: URL;\n /** Matched route params for the current page, e.g. `{ id: '42' }` for `/profile/:id`. */\n params: Record<string, string>;\n /** Imperative navigation actions and the `pending` flag. */\n router: Router;\n}\n\nconst noop = () => {};\n\nconst defaultRouter: Router = { push: noop, replace: noop, back: noop, forward: noop, refresh: noop, pending: false };\n\n/**\n * Carries the live {@link Router} implementation from the hydration runtime down\n * to {@link RouterProvider}. Framework internal — read the router through\n * {@link useNavigation} instead.\n *\n * @internal\n */\nexport const RouterContext = createContext<Router>(defaultRouter);\n\nconst NavigationContext = createContext<Navigation | null>(null);\n\n/**\n * Publishes the per-render location and params so {@link useNavigation} can read\n * them. Framework internal — the RSC entry wraps every page in one.\n *\n * @internal\n */\nexport function RouterProvider({ href, params, children }: { href: string; params: Record<string, string>; children: ReactNode }) {\n const router = useContext(RouterContext);\n const value = useMemo<Navigation>(() => ({ url: new URL(href), params, router }), [href, params, router]);\n\n return <NavigationContext.Provider value={value}>{children}</NavigationContext.Provider>;\n}\n\n/**\n * Reactive access to the current URL and programmatic navigation, in one hook.\n *\n * Call it from a `'use client'` component. The location fields (`url` and\n * `params`) are computed on the server and travel in the flight payload, so they\n * are correct during SSR — no hydration flicker — and update automatically on\n * every navigation. The `router` sub-object holds the imperative actions plus a\n * `pending` flag that is `true` while a client navigation is in flight.\n *\n * Hooks can't run in a server component; read the same URL data there from\n * `getContext()` (`@rshono/core/server`) instead.\n *\n * @example\n * ```tsx\n * 'use client';\n * import { useNavigation } from '@rshono/core/client';\n *\n * export function NextPage() {\n * const { url, router } = useNavigation();\n * const page = Number(url.searchParams.get('page') ?? '1');\n * return (\n * <button disabled={router.pending} onClick={() => router.push(`${url.pathname}?page=${page + 1}`)}>\n * Next {router.pending ? '…' : ''}\n * </button>\n * );\n * }\n * ```\n *\n * @returns The current {@link Navigation}: `url` and `params`, plus `router`\n * ({@link Router}) with `push` / `replace` / `back` / `forward` / `refresh` /\n * `pending`.\n * @throws If called outside a page's React tree, where there is no navigation\n * context to read.\n */\nexport function useNavigation(): Navigation {\n const value = useContext(NavigationContext);\n if (!value) {\n throw new Error(\n \"[rshono] useNavigation() must be called inside a 'use client' component rendered by a page. In a server component, read the URL from getContext() instead.\",\n );\n }\n return value;\n}\n\nexport interface NavigationProgressProps {\n /** Bar color. Defaults to a neutral blue. */\n color?: string;\n /** Bar height in pixels. Defaults to `3`. */\n height?: number;\n}\n\n/**\n * An opt-in top progress bar that appears while a client navigation is in\n * flight (driven by {@link Router.pending}). Drop one instance in your root\n * layout; it renders nothing on the server and stays invisible until the first\n * soft navigation, so there's no hydration flicker.\n *\n * @example\n * ```tsx\n * import { NavigationProgress } from '@rshono/core/client';\n *\n * // in your layout, once:\n * <body>\n * <NavigationProgress />\n * {children}\n * </body>\n * ```\n */\nexport function NavigationProgress({ color = '#3b82f6', height = 3 }: NavigationProgressProps = {}): ReactNode {\n const { router } = useNavigation();\n const [bar, setBar] = useState({ width: 0, opacity: 0 });\n\n useEffect(() => {\n if (router.pending) {\n // Jump in, then creep toward — but never reach — the end while we wait.\n setBar({ width: 15, opacity: 1 });\n const ramp = setTimeout(() => setBar({ width: 85, opacity: 1 }), 80);\n return () => clearTimeout(ramp);\n }\n // Done: snap to full, then fade out. (No-op if it was never shown.)\n setBar((b) => (b.opacity === 0 ? b : { width: 100, opacity: 1 }));\n const hide = setTimeout(() => setBar({ width: 0, opacity: 0 }), 220);\n return () => clearTimeout(hide);\n }, [router.pending]);\n\n return (\n <div\n data-rshono-progress=\"\"\n aria-hidden=\"true\"\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n height,\n width: `${bar.width}%`,\n opacity: bar.opacity,\n background: color,\n zIndex: 2147483647,\n pointerEvents: 'none',\n transition: 'width 200ms ease-out, opacity 200ms ease-out',\n }}\n />\n );\n}\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The four distinct shapes an incoming render request can take, modeled as a
|
|
3
|
+
* discriminated union so illegal combinations (e.g. an action id on a GET) are
|
|
4
|
+
* unrepresentable and every consumer dispatches exhaustively on `kind`.
|
|
5
|
+
*
|
|
6
|
+
* - `document` — a normal navigation; respond with a full SSR HTML document.
|
|
7
|
+
* - `rsc` — a soft-navigation flight fetch (`Accept: text/x-component`).
|
|
8
|
+
* - `form-action` — a progressive-enhancement `<form>` POST (no JavaScript).
|
|
9
|
+
* - `rsc-action` — a client-initiated server-action call carrying an action id.
|
|
10
|
+
*/
|
|
11
|
+
export type RenderRequest = {
|
|
12
|
+
kind: 'document';
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'rsc';
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'form-action';
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'rsc-action';
|
|
19
|
+
actionId: string;
|
|
20
|
+
};
|
|
21
|
+
/** Builds the `Request` the client sends to ask a page for its flight payload, optionally carrying a server action. */
|
|
22
|
+
export declare function createRscRequest(urlString: string, action?: {
|
|
23
|
+
id: string;
|
|
24
|
+
body: BodyInit;
|
|
25
|
+
}): Request;
|
|
26
|
+
export declare function parseRenderRequest(request: Request): RenderRequest;
|
|
27
|
+
/** Whether the client asked for a flight payload. For GET paths that only need the boolean, without parsing. */
|
|
28
|
+
export declare function acceptsRsc(request: Request): boolean;
|
|
29
|
+
/** True when the response should be a flight payload rather than an HTML document. */
|
|
30
|
+
export declare function wantsRsc(renderRequest: RenderRequest): boolean;
|
|
31
|
+
/** True when the request carries a server action to run before rendering. */
|
|
32
|
+
export declare function isActionRequest(renderRequest: RenderRequest): renderRequest is Extract<RenderRequest, {
|
|
33
|
+
kind: 'form-action' | 'rsc-action';
|
|
34
|
+
}>;
|
|
35
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/runtime/request.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAExI,uHAAuH;AACvH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,OAAO,CASpG;AAID,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAQlE;AAED,gHAAgH;AAChH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED,sFAAsF;AACtF,wBAAgB,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAE9D;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,aAAa,EAAE,aAAa,GAAG,aAAa,IAAI,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,aAAa,GAAG,YAAY,CAAA;CAAE,CAAC,CAE7I"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const HEADER_ACTION_ID = 'x-rsc-action';
|
|
2
|
+
const RSC_CONTENT_TYPE = 'text/x-component';
|
|
3
|
+
/** Builds the `Request` the client sends to ask a page for its flight payload, optionally carrying a server action. */
|
|
4
|
+
export function createRscRequest(urlString, action) {
|
|
5
|
+
const url = new URL(urlString, location.origin);
|
|
6
|
+
const headers = new Headers({ Accept: RSC_CONTENT_TYPE });
|
|
7
|
+
if (action)
|
|
8
|
+
headers.set(HEADER_ACTION_ID, action.id);
|
|
9
|
+
return new Request(url, {
|
|
10
|
+
method: action ? 'POST' : 'GET',
|
|
11
|
+
headers,
|
|
12
|
+
body: action?.body,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
const FORM_CONTENT_TYPES = /^(?:multipart\/form-data|application\/x-www-form-urlencoded)/i;
|
|
16
|
+
export function parseRenderRequest(request) {
|
|
17
|
+
if (request.method === 'POST') {
|
|
18
|
+
const actionId = request.headers.get(HEADER_ACTION_ID);
|
|
19
|
+
if (actionId)
|
|
20
|
+
return { kind: 'rsc-action', actionId };
|
|
21
|
+
if (FORM_CONTENT_TYPES.test(request.headers.get('content-type') ?? ''))
|
|
22
|
+
return { kind: 'form-action' };
|
|
23
|
+
return { kind: 'document' };
|
|
24
|
+
}
|
|
25
|
+
return { kind: acceptsRsc(request) ? 'rsc' : 'document' };
|
|
26
|
+
}
|
|
27
|
+
/** Whether the client asked for a flight payload. For GET paths that only need the boolean, without parsing. */
|
|
28
|
+
export function acceptsRsc(request) {
|
|
29
|
+
return request.headers.get('accept')?.includes(RSC_CONTENT_TYPE) ?? false;
|
|
30
|
+
}
|
|
31
|
+
/** True when the response should be a flight payload rather than an HTML document. */
|
|
32
|
+
export function wantsRsc(renderRequest) {
|
|
33
|
+
return renderRequest.kind === 'rsc' || renderRequest.kind === 'rsc-action';
|
|
34
|
+
}
|
|
35
|
+
/** True when the request carries a server action to run before rendering. */
|
|
36
|
+
export function isActionRequest(renderRequest) {
|
|
37
|
+
return renderRequest.kind === 'form-action' || renderRequest.kind === 'rsc-action';
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/runtime/request.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAG,cAAc,CAAC;AACxC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAc5C,uHAAuH;AACvH,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,MAAuC;IACzF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC1D,IAAI,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACrD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE;QACtB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;QAC/B,OAAO;QACP,IAAI,EAAE,MAAM,EAAE,IAAI;KACnB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,kBAAkB,GAAG,+DAA+D,CAAC;AAE3F,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACvD,IAAI,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;QACtD,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QACvG,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;AAC5D,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC;AAC5E,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,QAAQ,CAAC,aAA4B;IACnD,OAAO,aAAa,CAAC,IAAI,KAAK,KAAK,IAAI,aAAa,CAAC,IAAI,KAAK,YAAY,CAAC;AAC7E,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,aAA4B;IAC1D,OAAO,aAAa,CAAC,IAAI,KAAK,aAAa,IAAI,aAAa,CAAC,IAAI,KAAK,YAAY,CAAC;AACrF,CAAC","sourcesContent":["const HEADER_ACTION_ID = 'x-rsc-action';\nconst RSC_CONTENT_TYPE = 'text/x-component';\n\n/**\n * The four distinct shapes an incoming render request can take, modeled as a\n * discriminated union so illegal combinations (e.g. an action id on a GET) are\n * unrepresentable and every consumer dispatches exhaustively on `kind`.\n *\n * - `document` — a normal navigation; respond with a full SSR HTML document.\n * - `rsc` — a soft-navigation flight fetch (`Accept: text/x-component`).\n * - `form-action` — a progressive-enhancement `<form>` POST (no JavaScript).\n * - `rsc-action` — a client-initiated server-action call carrying an action id.\n */\nexport type RenderRequest = { kind: 'document' } | { kind: 'rsc' } | { kind: 'form-action' } | { kind: 'rsc-action'; actionId: string };\n\n/** Builds the `Request` the client sends to ask a page for its flight payload, optionally carrying a server action. */\nexport function createRscRequest(urlString: string, action?: { id: string; body: BodyInit }): Request {\n const url = new URL(urlString, location.origin);\n const headers = new Headers({ Accept: RSC_CONTENT_TYPE });\n if (action) headers.set(HEADER_ACTION_ID, action.id);\n return new Request(url, {\n method: action ? 'POST' : 'GET',\n headers,\n body: action?.body,\n });\n}\n\nconst FORM_CONTENT_TYPES = /^(?:multipart\\/form-data|application\\/x-www-form-urlencoded)/i;\n\nexport function parseRenderRequest(request: Request): RenderRequest {\n if (request.method === 'POST') {\n const actionId = request.headers.get(HEADER_ACTION_ID);\n if (actionId) return { kind: 'rsc-action', actionId };\n if (FORM_CONTENT_TYPES.test(request.headers.get('content-type') ?? '')) return { kind: 'form-action' };\n return { kind: 'document' };\n }\n return { kind: acceptsRsc(request) ? 'rsc' : 'document' };\n}\n\n/** Whether the client asked for a flight payload. For GET paths that only need the boolean, without parsing. */\nexport function acceptsRsc(request: Request): boolean {\n return request.headers.get('accept')?.includes(RSC_CONTENT_TYPE) ?? false;\n}\n\n/** True when the response should be a flight payload rather than an HTML document. */\nexport function wantsRsc(renderRequest: RenderRequest): boolean {\n return renderRequest.kind === 'rsc' || renderRequest.kind === 'rsc-action';\n}\n\n/** True when the request carries a server action to run before rendering. */\nexport function isActionRequest(renderRequest: RenderRequest): renderRequest is Extract<RenderRequest, { kind: 'form-action' | 'rsc-action' }> {\n return renderRequest.kind === 'form-action' || renderRequest.kind === 'rsc-action';\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@rshono/core/server` — the request-scoped surface, for use inside server components
|
|
3
|
+
* and `'use server'` action modules: {@link getContext} for the URL, cookies,
|
|
4
|
+
* params, env and middleware variables, the {@link redirect} and {@link notFound}
|
|
5
|
+
* control-flow helpers, and {@link onServerError} for reporting the errors the
|
|
6
|
+
* framework catches.
|
|
7
|
+
*
|
|
8
|
+
* Server-only. Importing this from a `'use client'` module is a mistake — those
|
|
9
|
+
* run in the browser (and are SSR'd without a bound context). Read what you need
|
|
10
|
+
* on the server and pass it down as props, or use `useNavigation()` from
|
|
11
|
+
* `@rshono/core/client` for URL data.
|
|
12
|
+
*
|
|
13
|
+
* A barrel rather than `./context.js` itself, which is where all of this is
|
|
14
|
+
* implemented: that module also exports the plumbing the framework's own entry
|
|
15
|
+
* points need (`runWithContext`, `readParams`, `publicUrl`, `reportServerError`),
|
|
16
|
+
* and pointing the `./server` subpath straight at it published every one of them —
|
|
17
|
+
* `@internal` in the docs, but present in a consumer's autocomplete and pinned by
|
|
18
|
+
* semver all the same. They stay reachable by relative import, which is the only
|
|
19
|
+
* way the framework itself ever reaches them.
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
export { getContext, notFound, onServerError, redirect, type Ctx, type EnvVars, type RedirectStatus, type ServerErrorContext, type ServerErrorHandler, type ServerErrorSource, } from './context.js';
|
|
24
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/runtime/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EAGR,KAAK,GAAG,EACR,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC"}
|