gemi 0.140.1 → 0.142.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.
Files changed (42) hide show
  1. package/dist/auth/AuthController.d.ts.map +1 -1
  2. package/dist/auth/config.d.ts +24 -5
  3. package/dist/auth/config.d.ts.map +1 -1
  4. package/dist/{chunk-679ndcdq.js → chunk-25gg2nve.js} +2 -2
  5. package/dist/{chunk-679ndcdq.js.map → chunk-25gg2nve.js.map} +1 -1
  6. package/dist/{chunk-1vfnehjr.js → chunk-2yr1ad3c.js} +1 -1
  7. package/dist/chunk-3mnn4nb0.js +24 -0
  8. package/dist/{chunk-2vfdahm9.js.map → chunk-3mnn4nb0.js.map} +3 -3
  9. package/dist/{chunk-bmam8bsm.js → chunk-mg9dgkha.js} +1 -1
  10. package/dist/{chunk-bywhpfyv.js → chunk-n02c478d.js} +16 -16
  11. package/dist/{chunk-bywhpfyv.js.map → chunk-n02c478d.js.map} +6 -6
  12. package/dist/chunks/{RealtimeClient-DFgd6k2O.js → RealtimeClient-D8AB_ksF.js} +2 -2
  13. package/dist/chunks/{RealtimeClient-DFgd6k2O.js.map → RealtimeClient-D8AB_ksF.js.map} +1 -1
  14. package/dist/chunks/{ThemeProvider-D8T12nBG.js → ThemeProvider-BV3tyt_8.js} +4 -4
  15. package/dist/chunks/{ThemeProvider-D8T12nBG.js.map → ThemeProvider-BV3tyt_8.js.map} +1 -1
  16. package/dist/chunks/{fetchFileRequest-Bu8thkJP.js → fetchFileRequest-B2rjj_hy.js} +2 -2
  17. package/dist/chunks/{fetchFileRequest-Bu8thkJP.js.map → fetchFileRequest-B2rjj_hy.js.map} +1 -1
  18. package/dist/chunks/{live-CR8v1KcI.js → live-COU4GpXn.js} +3 -3
  19. package/dist/chunks/{live-CR8v1KcI.js.map → live-COU4GpXn.js.map} +1 -1
  20. package/dist/chunks/{mutationExtras-DuFelh7K.js → mutationExtras-idr-Ane0.js} +2 -2
  21. package/dist/chunks/{mutationExtras-DuFelh7K.js.map → mutationExtras-idr-Ane0.js.map} +1 -1
  22. package/dist/client/ClientRouter.d.ts.map +1 -1
  23. package/dist/client/ClientRouterContext.d.ts.map +1 -1
  24. package/dist/client/index.js +6 -5
  25. package/dist/client/index.js.map +1 -1
  26. package/dist/facades/index.js +1 -1
  27. package/dist/http/index.js +1 -1
  28. package/dist/i18n/index.js +1 -1
  29. package/dist/kernel/index.js +1 -1
  30. package/dist/server/httpProd.d.ts.map +1 -1
  31. package/dist/server/index.js +1 -1
  32. package/dist/services/index.d.ts +1 -1
  33. package/dist/services/index.d.ts.map +1 -1
  34. package/dist/services/index.js +1 -1
  35. package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
  36. package/dist/services/router/config.d.ts +12 -0
  37. package/dist/services/router/config.d.ts.map +1 -1
  38. package/dist/testing/index.js +2 -2
  39. package/package.json +1 -1
  40. package/dist/chunk-2vfdahm9.js +0 -24
  41. /package/dist/{chunk-1vfnehjr.js.map → chunk-2yr1ad3c.js.map} +0 -0
  42. /package/dist/{chunk-bmam8bsm.js.map → chunk-mg9dgkha.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  "version": 3,
3
3
  "sources": ["../server/httpProd.ts", "../server/compression.ts", "../server/staticFile.ts", "../vite/precompressAssets.ts", "../server/generateEtag.ts", "../server/modulePreloads.ts", "../client/chunkLoadRecovery.ts", "../server/staticAssetMiss.ts", "../server/unhandledError.ts", "../server/forwardedFor.ts"],
4
4
  "sourcesContent": [
5
- "import { createHash } from \"node:crypto\";\nimport type { WebSocketHandler } from \"bun\";\nimport { join, resolve, sep } from \"node:path\";\nimport { compressResponse } from \"./compression\";\nimport { listPublicFiles, staticFileResponse } from \"./staticFile\";\nimport { stat } from \"node:fs/promises\";\nimport { createStyles } from \"./styles\";\nimport {\n CLIENT_ENTRY_KEY,\n collectCss,\n collectModulePreloads,\n createClientEntry,\n createIslandResolver,\n} from \"./modulePreloads\";\nimport type { App } from \"../app\";\nimport { Instrumentation } from \"./types\";\nimport { printStartupBanner } from \"./banner\";\nimport { isReservedAssetPath, staticAssetMiss } from \"./staticAssetMiss\";\nimport { assetUrl, readBuiltAssetBase } from \"../config/assetBase\";\nimport { isApiPath } from \"../services/router/apiPath\";\nimport { projectRoot } from \"../support/discover\";\nimport { unhandledErrorResponse } from \"./unhandledError\";\nimport { serverIdleTimeout } from \"./idleTimeout\";\nimport { applyForwardedTrust, parseTrustProxy } from \"./forwardedFor\";\nimport { readStaticAssetsRecord } from \"../vite/precompressAssets\";\nimport type { StaticFileOptions } from \"./staticFile\";\n\n// The rule this file used to spell out itself. It moved to `projectRoot`\n// because discovery needs the same answer during `waitForBoot()`, which is\n// before `ROOT_DIR` below exists — and two spellings of \"where is the project\"\n// is how a job gets looked for in one directory and served from another.\nconst rootDir = projectRoot();\n\nconst appDir = join(rootDir, \"app\");\nconst distDir = join(rootDir, \"dist\");\n\nconst clientDir = join(distDir, \"client\");\n\n// The file in `dist/client` a static-looking pathname names, or `null` when\n// it names nothing there. The pathname is still percent-encoded, and Vite\n// writes files whose names need encoding (a public `my font.woff2`), so it is\n// decoded first. Decoding also turns `%2F` into a separator, which the URL\n// parser's own `..` normalization never saw — so the resolved path is checked\n// to still be inside `dist/client`. A malformed escape is a miss, not a 500.\nfunction clientFilePath(pathname: string): string | null {\n let decoded: string;\n try {\n decoded = decodeURIComponent(pathname);\n } catch {\n return null;\n }\n const path = resolve(clientDir, \".\" + decoded.replace(\"/assets/assets\", \"/assets\"));\n return path.startsWith(clientDir + sep) ? path : null;\n}\n\nasync function isFile(path: string) {\n try {\n return (await stat(path)).isFile();\n } catch {\n return false;\n }\n}\n\n// `app` is built by `Server.start` (from the kernel) and passed in — same as\n// `httpDev` — so prod and dev share one construction path. What differs here is\n// that views/styles are served from the built `dist/` manifests instead of\n// Vite's dev SSR graph.\nexport async function httpProd(app: App, instrumentation: Instrumentation) {\n const manifest = await import(`${distDir}/client/.vite/manifest.json`);\n const serverManifest = await import(`${distDir}/server/.vite/manifest.json`);\n // What the client build was built with, not `GEMI_ASSET_BASE` as it reads\n // now — see `readBuiltAssetBase`. Every URL below that names a chunk goes\n // through it, so the document links exactly what the bundle imports.\n const assetBase = await readBuiltAssetBase(`${distDir}/client`);\n\n process.env.ROOT_DIR = rootDir;\n process.env.APP_DIR = appDir;\n process.env.DIST_DIR = distDir;\n\n const viewImportMap = {};\n const ogMap = {};\n const viewModules = {};\n const cssManifest = {};\n // Which chunks a route's views pull in, so the shell can preload the chain\n // the client would otherwise discover one round trip at a time (#352).\n const modulePreloadManifest: Record<string, string[]> = {};\n const template = (viewName: string, path: string) => `\"${viewName}\": () => import(\"${path}\")`;\n const templates = [];\n\n for (const fileName of [\"404\", ...app.getFlatComponentTree.call(app)]) {\n const serverFile = serverManifest[`app/views/${fileName}.tsx`];\n if (!serverFile?.file) {\n console.log(`Server file not found for ${fileName}`);\n console.log(serverFile);\n const files = Object.keys(serverManifest);\n const path = `app/views/${fileName}.tsx`;\n console.log(`${path} not found in server manifest`);\n console.log(files);\n }\n const mod = await import(`${process.env.DIST_DIR}/server/${serverFile?.file}`);\n viewImportMap[fileName] = mod.default;\n ogMap[fileName] = mod.OpenGraph;\n // The whole module, so a streaming render can put the view's\n // `Loading`/`Error` exports into the shell it sends.\n viewModules[fileName] = mod;\n const clientFile = manifest[`app/views/${fileName}.tsx`];\n\n if (clientFile?.css && clientFile?.css.length > 0) {\n cssManifest[fileName] = clientFile?.css;\n }\n if (clientFile) {\n templates.push(template(fileName, assetUrl(clientFile?.file, assetBase)));\n modulePreloadManifest[fileName] = collectModulePreloads(\n manifest,\n `app/views/${fileName}.tsx`,\n assetBase,\n );\n }\n }\n\n const loaders = `{${templates.join(\",\")}}`;\n\n // Booted from the bootstrap script rather than through React's\n // `bootstrapModules`, which would preload it at `fetchPriority=\"low\"` — see\n // `clientEntry` in `ViewRouteDispatcher`.\n const clientEntry = createClientEntry(manifest, assetBase);\n if (!clientEntry) {\n // Loudly, but without dying: this is boot, and an incomplete `dist/` must\n // not cost the API routes and static assets too.\n console.error(\n `Client manifest has no \"${CLIENT_ENTRY_KEY}\" entry — dist/client is incomplete, so documents will render but never hydrate.`,\n );\n }\n\n // Vite's manifest `css` field is a `string[]` — a client entry can emit more\n // than one CSS chunk. Read and concatenate them all instead of interpolating\n // the array into a single path (which only works for a one-element array).\n const appCssFiles: string[] = manifest[\"app/client.tsx\"]?.css ?? [];\n const appCSSContent = (\n await Promise.all(appCssFiles.map((cssFile) => Bun.file(`${distDir}/client/${cssFile}`).text()))\n ).join(\"\\n\");\n\n // The island entries (`<module>?gemi-island`) a static view's document\n // loads; see `injectIslands`.\n const resolveIsland = createIslandResolver(manifest, assetBase);\n\n // Identifies this client build: a static page with `navigation` swaps in\n // only pages of the same build. The manifest names every content-hashed\n // file, so it changes whenever any of them does.\n const buildId = createHash(\"sha256\")\n .update(await Bun.file(`${distDir}/client/.vite/manifest.json`).text())\n .digest(\"base64url\")\n .slice(0, 12);\n\n // A static view's CSS comes from the whole import closure of its views (and\n // its own layout's, which then replaces the app stylesheet): there is no\n // client to fetch a shared chunk's CSS later, as a hydrated page's chunk\n // loader does. Read once per file: the build does not change under a\n // running server.\n const cssFileCache = new Map<string, Promise<string>>();\n const readCss = (file: string) => {\n let text = cssFileCache.get(file);\n if (!text) {\n text = Bun.file(`${distDir}/client/${file}`).text();\n cssFileCache.set(file, text);\n }\n return text;\n };\n const staticStyles = async (views: string[], layout: string | undefined) => {\n const files = new Set<string>();\n for (const view of layout ? [layout, ...views] : views) {\n for (const file of collectCss(manifest, `app/views/${view}.tsx`)) files.add(file);\n }\n const styles = await Promise.all(\n [...files].map(async (file) => ({ id: file, content: await readCss(file) })),\n );\n return createStyles(layout ? styles : [{ content: appCSSContent }, ...styles]);\n };\n\n // Which requests are answered from `dist/client` rather than the app:\n //\n // - `/assets` and everything under it, whatever the extension. Vite writes\n // fonts, GIFs, video and `?url` JSON there too, and an allowlist of\n // extensions always trailed the build — a `.woff2` went to the router\n // and paid for an SSR attempt. The router refuses routes under `/assets`\n // at boot, so there is no app answer to lose, and `staticAssetMiss`\n // turns a miss into the reload stub or a 404.\n // - `/.well-known/*`.\n // - Any other path that names a file the build copied out of `public/`,\n // whatever its extension (#583). Any other path may be an app route, so\n // it is static only when that exact file exists — read once here, since\n // the build output does not change under a running server. A view at\n // `/manifest` keeps its data URL (`/manifest.json`) unless the app also\n // ships `public/manifest.json`, and then the file wins. View data is\n // never a file in `dist/client`, so a client-side navigation pays for no\n // filesystem lookup.\n const publicFiles = await listPublicFiles(clientDir);\n\n // The build assets `gemi build` emitted or carried over, with the\n // precompressed siblings it wrote for each (#789). Read once: the build\n // output does not change under a running server. Without the record (a\n // build made before it existed) every file is served as identity with the\n // old cache policy.\n const staticAssets = new Map<string, StaticFileOptions>();\n for (const [file, encodings] of Object.entries(\n (await readStaticAssetsRecord(clientDir))?.files ?? {},\n )) {\n const path = resolve(clientDir, file);\n if (path.startsWith(clientDir + sep)) {\n staticAssets.set(path, { immutable: true, encodings });\n }\n }\n\n async function requestHandler(req: Request) {\n const { pathname } = new URL(req.url);\n\n if (isApiPath(pathname)) {\n return await handleWithApp(req, pathname);\n }\n\n const distPath = clientFilePath(pathname);\n const isFileRequest =\n isReservedAssetPath(pathname) ||\n pathname.startsWith(\"/.well-known\") ||\n (distPath !== null && publicFiles.has(distPath));\n\n if (isFileRequest) {\n // Served from here whatever the asset base is: a CDN in front of the\n // app uses this origin as the source it fills from. A file, not merely\n // a path that exists: `/assets` itself is `dist/client/assets`, a\n // directory, and streaming one would answer 200 and then fail mid-body.\n //\n // `Bun.file(path).stream()` is lazy — a missing file only throws ENOENT\n // once the body is streamed, which is *after* this handler has returned,\n // with the response already committed as 200. So existence is checked\n // here, per request, even for a path `publicFiles` lists.\n if (!distPath || !(await isFile(distPath))) {\n return staticAssetMiss(pathname) ?? (await handleWithApp(req, pathname));\n }\n\n try {\n return await staticFileResponse(req, distPath, staticAssets.get(distPath));\n } catch (error) {\n app.onException?.(error);\n return new Response(\"Not found\", { status: 404 });\n }\n }\n\n return await handleWithApp(req, pathname);\n }\n\n async function handleWithApp(req: Request, pathname: string) {\n const handler = app.fetch.bind(app);\n\n try {\n const result = await handler(req);\n if (result instanceof Response) {\n return result;\n } else {\n const styles = [];\n\n styles.push({\n content: appCSSContent,\n });\n\n const getStyles = async (\n currentViews: string[],\n options?: { static?: boolean; layout?: string },\n ) => {\n if (!currentViews) {\n return createStyles([]);\n }\n if (options?.static) {\n return staticStyles(currentViews, options.layout);\n }\n for (const view of currentViews) {\n const clientFile = manifest[`app/views/${view}.tsx`];\n for (const cssFile of clientFile?.css ?? []) {\n const css = Bun.file(`${process.env.DIST_DIR}/client/${cssFile}`);\n styles.push({\n id: cssFile,\n content: await css.text(),\n });\n }\n }\n return createStyles(styles);\n };\n\n return await result({\n getStyles,\n clientEntry,\n modulePreloadManifest,\n loaders,\n viewImportMap,\n viewModules,\n ogMap,\n cssManifest,\n assetBase,\n resolveIsland,\n buildId,\n });\n }\n } catch (err) {\n return unhandledErrorResponse(err, pathname, app.onException);\n }\n }\n\n // Compression is on unless the deployment opts out — set `GEMI_COMPRESSION=off`\n // when a layer in front of the origin already compresses HTML and you would\n // rather not spend origin CPU on it.\n const compressionEnabled = (process.env.GEMI_COMPRESSION ?? \"auto\").toLowerCase() !== \"off\";\n\n // Which `X-Forwarded-For` entries to believe — see `forwardedFor.ts`. Parsed\n // before `Bun.serve` so a bad value fails the boot, not every request.\n const forwardedTrust = parseTrustProxy(process.env.GEMI_TRUST_PROXY);\n\n // The broadcast socket endpoint, when the app declares `route.channels`.\n const sockets = app.sockets();\n if (sockets && forwardedTrust.kind === \"none\") {\n console.warn(\n \"[gemi] Broadcast sockets: GEMI_TRUST_PROXY is not set, so a socket's address is its TCP peer. Behind a proxy or load balancer every client shares the proxy's address, and broadcast.maxConnectionsPerIp caps the whole app per process. Set GEMI_TRUST_PROXY (see forwardedFor) or raise that limit.\",\n );\n }\n\n const server = Bun.serve<any>({\n maxRequestBodySize: 10 * 1024 * 1024 * 1024, // 10 GB\n fetch: async (req, server) => {\n // `requestIP` is null for closed/unix sockets — guard so it never\n // throws before the request is handled.\n applyForwardedTrust(req.headers, server.requestIP(req)?.address ?? null, forwardedTrust);\n // A proxy that proves itself with `route.domains.trustProxy.secret` may\n // name the client in `clientIpHeader`, which then wins.\n app.applyTrustedClientIp(req);\n // Ahead of the instrumentation: an upgrade is not a response to trace,\n // and the hub runs the global middleware itself.\n if (sockets?.matches(req)) {\n return sockets.upgrade(req, server);\n }\n // The app's global middleware goes in front of the static handler as well\n // as the router, so it can refuse `/assets/*` too.\n const res = await instrumentation(req, (req) =>\n app.withGlobalMiddleware(req, requestHandler, (err) =>\n unhandledErrorResponse(err, new URL(req.url).pathname, app.onException),\n ),\n );\n // Applied at the very edge, after instrumentation, so every HTML response\n // goes through the same negotiation — including the ones an app's\n // instrumentation produced itself. Anything that isn't HTML comes back\n // untouched.\n return compressionEnabled ? compressResponse(req, res) : res;\n },\n idleTimeout: serverIdleTimeout(),\n port: process.env.PORT || 5173,\n websocket: sockets?.websocket as WebSocketHandler<any>,\n });\n await sockets?.start(server);\n\n printStartupBanner({ port: server.port, rootDir });\n\n return server;\n}\n",
5
+ "import { createHash } from \"node:crypto\";\nimport type { WebSocketHandler } from \"bun\";\nimport { join, resolve, sep } from \"node:path\";\nimport { compressResponse } from \"./compression\";\nimport { listPublicFiles, staticFileResponse } from \"./staticFile\";\nimport { stat } from \"node:fs/promises\";\nimport { createStyles } from \"./styles\";\nimport {\n CLIENT_ENTRY_KEY,\n collectCss,\n collectModulePreloads,\n createClientEntry,\n createIslandResolver,\n} from \"./modulePreloads\";\nimport type { App } from \"../app\";\nimport { Instrumentation } from \"./types\";\nimport { printStartupBanner } from \"./banner\";\nimport { isReservedAssetPath, staticAssetMiss } from \"./staticAssetMiss\";\nimport { assetUrl, readBuiltAssetBase } from \"../config/assetBase\";\nimport { isApiPath } from \"../services/router/apiPath\";\nimport { projectRoot } from \"../support/discover\";\nimport { unhandledErrorResponse } from \"./unhandledError\";\nimport { serverIdleTimeout } from \"./idleTimeout\";\nimport { applyForwardedTrust, parseTrustProxy } from \"./forwardedFor\";\nimport { readStaticAssetsRecord } from \"../vite/precompressAssets\";\nimport type { StaticFileOptions } from \"./staticFile\";\n\n// The rule this file used to spell out itself. It moved to `projectRoot`\n// because discovery needs the same answer during `waitForBoot()`, which is\n// before `ROOT_DIR` below exists — and two spellings of \"where is the project\"\n// is how a job gets looked for in one directory and served from another.\nconst rootDir = projectRoot();\n\nconst appDir = join(rootDir, \"app\");\nconst distDir = join(rootDir, \"dist\");\n\nconst clientDir = join(distDir, \"client\");\n\n// The file in `dist/client` a static-looking pathname names, or `null` when\n// it names nothing there. The pathname is still percent-encoded, and Vite\n// writes files whose names need encoding (a public `my font.woff2`), so it is\n// decoded first. Decoding also turns `%2F` into a separator, which the URL\n// parser's own `..` normalization never saw — so the resolved path is checked\n// to still be inside `dist/client`. A malformed escape is a miss, not a 500.\nfunction clientFilePath(pathname: string): string | null {\n let decoded: string;\n try {\n decoded = decodeURIComponent(pathname);\n } catch {\n return null;\n }\n const path = resolve(clientDir, \".\" + decoded.replace(\"/assets/assets\", \"/assets\"));\n return path.startsWith(clientDir + sep) ? path : null;\n}\n\nasync function isFile(path: string) {\n try {\n return (await stat(path)).isFile();\n } catch {\n return false;\n }\n}\n\n// `app` is built by `Server.start` (from the kernel) and passed in — same as\n// `httpDev` — so prod and dev share one construction path. What differs here is\n// that views/styles are served from the built `dist/` manifests instead of\n// Vite's dev SSR graph.\nexport async function httpProd(app: App, instrumentation: Instrumentation) {\n const manifest = await import(`${distDir}/client/.vite/manifest.json`);\n const serverManifest = await import(`${distDir}/server/.vite/manifest.json`);\n // What the client build was built with, not `GEMI_ASSET_BASE` as it reads\n // now — see `readBuiltAssetBase`. Every URL below that names a chunk goes\n // through it, so the document links exactly what the bundle imports.\n const assetBase = await readBuiltAssetBase(`${distDir}/client`);\n\n process.env.ROOT_DIR = rootDir;\n process.env.APP_DIR = appDir;\n process.env.DIST_DIR = distDir;\n\n const viewImportMap = {};\n const ogMap = {};\n const viewModules = {};\n const cssManifest = {};\n // Which chunks a route's views pull in, so the shell can preload the chain\n // the client would otherwise discover one round trip at a time (#352).\n const modulePreloadManifest: Record<string, string[]> = {};\n const template = (viewName: string, path: string) => `\"${viewName}\": () => import(\"${path}\")`;\n const templates = [];\n\n for (const fileName of [\"404\", ...app.getFlatComponentTree.call(app)]) {\n const serverFile = serverManifest[`app/views/${fileName}.tsx`];\n if (!serverFile?.file) {\n console.log(`Server file not found for ${fileName}`);\n console.log(serverFile);\n const files = Object.keys(serverManifest);\n const path = `app/views/${fileName}.tsx`;\n console.log(`${path} not found in server manifest`);\n console.log(files);\n }\n const mod = await import(`${process.env.DIST_DIR}/server/${serverFile?.file}`);\n viewImportMap[fileName] = mod.default;\n ogMap[fileName] = mod.OpenGraph;\n // The whole module, so a streaming render can put the view's\n // `Loading`/`Error` exports into the shell it sends.\n viewModules[fileName] = mod;\n const clientFile = manifest[`app/views/${fileName}.tsx`];\n\n if (clientFile?.css && clientFile?.css.length > 0) {\n cssManifest[fileName] = clientFile?.css;\n }\n if (clientFile) {\n templates.push(template(fileName, assetUrl(clientFile?.file, assetBase)));\n modulePreloadManifest[fileName] = collectModulePreloads(\n manifest,\n `app/views/${fileName}.tsx`,\n assetBase,\n );\n }\n }\n\n const loaders = `{${templates.join(\",\")}}`;\n\n // Booted from the bootstrap script rather than through React's\n // `bootstrapModules`, which would preload it at `fetchPriority=\"low\"` — see\n // `clientEntry` in `ViewRouteDispatcher`.\n const clientEntry = createClientEntry(manifest, assetBase);\n if (!clientEntry) {\n // Loudly, but without dying: this is boot, and an incomplete `dist/` must\n // not cost the API routes and static assets too.\n console.error(\n `Client manifest has no \"${CLIENT_ENTRY_KEY}\" entry — dist/client is incomplete, so documents will render but never hydrate.`,\n );\n }\n\n // Vite's manifest `css` field is a `string[]` — a client entry can emit more\n // than one CSS chunk. Read and concatenate them all instead of interpolating\n // the array into a single path (which only works for a one-element array).\n const appCssFiles: string[] = manifest[\"app/client.tsx\"]?.css ?? [];\n const appCSSContent = (\n await Promise.all(appCssFiles.map((cssFile) => Bun.file(`${distDir}/client/${cssFile}`).text()))\n ).join(\"\\n\");\n\n // The island entries (`<module>?gemi-island`) a static view's document\n // loads; see `injectIslands`.\n const resolveIsland = createIslandResolver(manifest, assetBase);\n\n // Identifies this client build: a static page with `navigation` swaps in\n // only pages of the same build. The manifest names every content-hashed\n // file, so it changes whenever any of them does.\n const buildId = createHash(\"sha256\")\n .update(await Bun.file(`${distDir}/client/.vite/manifest.json`).text())\n .digest(\"base64url\")\n .slice(0, 12);\n\n // A static view's CSS comes from the whole import closure of its views (and\n // its own layout's, which then replaces the app stylesheet): there is no\n // client to fetch a shared chunk's CSS later, as a hydrated page's chunk\n // loader does. Read once per file: the build does not change under a\n // running server.\n const cssFileCache = new Map<string, Promise<string>>();\n const readCss = (file: string) => {\n let text = cssFileCache.get(file);\n if (!text) {\n text = Bun.file(`${distDir}/client/${file}`).text();\n cssFileCache.set(file, text);\n }\n return text;\n };\n const staticStyles = async (views: string[], layout: string | undefined) => {\n const files = new Set<string>();\n for (const view of layout ? [layout, ...views] : views) {\n for (const file of collectCss(manifest, `app/views/${view}.tsx`)) files.add(file);\n }\n const styles = await Promise.all(\n [...files].map(async (file) => ({ id: file, content: await readCss(file) })),\n );\n return createStyles(layout ? styles : [{ content: appCSSContent }, ...styles]);\n };\n\n // Which requests are answered from `dist/client` rather than the app:\n //\n // - `/assets` and everything under it, whatever the extension. Vite writes\n // fonts, GIFs, video and `?url` JSON there too, and an allowlist of\n // extensions always trailed the build — a `.woff2` went to the router\n // and paid for an SSR attempt. The router refuses routes under `/assets`\n // at boot, so there is no app answer to lose, and `staticAssetMiss`\n // turns a miss into the reload stub or a 404.\n // - `/.well-known/*`.\n // - Any other path that names a file the build copied out of `public/`,\n // whatever its extension (#583). Any other path may be an app route, so\n // it is static only when that exact file exists — read once here, since\n // the build output does not change under a running server. A view at\n // `/manifest` keeps its data URL (`/manifest.json`) unless the app also\n // ships `public/manifest.json`, and then the file wins. View data is\n // never a file in `dist/client`, so a client-side navigation pays for no\n // filesystem lookup.\n const publicFiles = await listPublicFiles(clientDir);\n\n // The build assets `gemi build` emitted or carried over, with the\n // precompressed siblings it wrote for each (#789). Read once: the build\n // output does not change under a running server. Without the record (a\n // build made before it existed) every file is served as identity with the\n // old cache policy.\n const staticAssets = new Map<string, StaticFileOptions>();\n for (const [file, encodings] of Object.entries(\n (await readStaticAssetsRecord(clientDir))?.files ?? {},\n )) {\n const path = resolve(clientDir, file);\n if (path.startsWith(clientDir + sep)) {\n staticAssets.set(path, { immutable: true, encodings });\n }\n }\n\n async function requestHandler(req: Request) {\n const { pathname } = new URL(req.url);\n\n if (isApiPath(pathname)) {\n return await handleWithApp(req, pathname);\n }\n\n const distPath = clientFilePath(pathname);\n const isFileRequest =\n isReservedAssetPath(pathname) ||\n pathname.startsWith(\"/.well-known\") ||\n (distPath !== null && publicFiles.has(distPath));\n\n if (isFileRequest) {\n // Served from here whatever the asset base is: a CDN in front of the\n // app uses this origin as the source it fills from. A file, not merely\n // a path that exists: `/assets` itself is `dist/client/assets`, a\n // directory, and streaming one would answer 200 and then fail mid-body.\n //\n // `Bun.file(path).stream()` is lazy — a missing file only throws ENOENT\n // once the body is streamed, which is *after* this handler has returned,\n // with the response already committed as 200. So existence is checked\n // here, per request, even for a path `publicFiles` lists.\n if (!distPath || !(await isFile(distPath))) {\n return staticAssetMiss(pathname) ?? (await handleWithApp(req, pathname));\n }\n\n try {\n return await staticFileResponse(req, distPath, staticAssets.get(distPath));\n } catch (error) {\n app.onException?.(error);\n return new Response(\"Not found\", { status: 404 });\n }\n }\n\n return await handleWithApp(req, pathname);\n }\n\n async function handleWithApp(req: Request, pathname: string) {\n const handler = app.fetch.bind(app);\n\n try {\n const result = await handler(req);\n if (result instanceof Response) {\n return result;\n } else {\n const styles = [];\n\n styles.push({\n content: appCSSContent,\n });\n\n const getStyles = async (\n currentViews: string[] | undefined,\n options?: { static?: boolean; layout?: string },\n ) => {\n // No views is the `404` document (an unmatched path, a missing\n // record, a refusal): it is styled like any other, with the app CSS\n // and the `404` view's own (#951).\n const views = currentViews ?? [\"404\"];\n if (options?.static) {\n return staticStyles(views, options.layout);\n }\n for (const view of views) {\n const clientFile = manifest[`app/views/${view}.tsx`];\n for (const cssFile of clientFile?.css ?? []) {\n const css = Bun.file(`${process.env.DIST_DIR}/client/${cssFile}`);\n styles.push({\n id: cssFile,\n content: await css.text(),\n });\n }\n }\n return createStyles(styles);\n };\n\n return await result({\n getStyles,\n clientEntry,\n modulePreloadManifest,\n loaders,\n viewImportMap,\n viewModules,\n ogMap,\n cssManifest,\n assetBase,\n resolveIsland,\n buildId,\n });\n }\n } catch (err) {\n return unhandledErrorResponse(err, pathname, app.onException);\n }\n }\n\n // Compression is on unless the deployment opts out — set `GEMI_COMPRESSION=off`\n // when a layer in front of the origin already compresses HTML and you would\n // rather not spend origin CPU on it.\n const compressionEnabled = (process.env.GEMI_COMPRESSION ?? \"auto\").toLowerCase() !== \"off\";\n\n // Which `X-Forwarded-For` entries to believe — see `forwardedFor.ts`. Parsed\n // before `Bun.serve` so a bad value fails the boot, not every request.\n const forwardedTrust = parseTrustProxy(process.env.GEMI_TRUST_PROXY);\n\n // The broadcast socket endpoint, when the app declares `route.channels`.\n const sockets = app.sockets();\n if (sockets && forwardedTrust.kind === \"none\") {\n console.warn(\n \"[gemi] Broadcast sockets: GEMI_TRUST_PROXY is not set, so a socket's address is its TCP peer. Behind a proxy or load balancer every client shares the proxy's address, and broadcast.maxConnectionsPerIp caps the whole app per process. Set GEMI_TRUST_PROXY (see forwardedFor) or raise that limit.\",\n );\n }\n\n const server = Bun.serve<any>({\n maxRequestBodySize: 10 * 1024 * 1024 * 1024, // 10 GB\n fetch: async (req, server) => {\n // `requestIP` is null for closed/unix sockets — guard so it never\n // throws before the request is handled.\n applyForwardedTrust(req.headers, server.requestIP(req)?.address ?? null, forwardedTrust);\n // A proxy that proves itself with `route.domains.trustProxy.secret` may\n // name the client in `clientIpHeader`, which then wins.\n app.applyTrustedClientIp(req);\n // Ahead of the instrumentation: an upgrade is not a response to trace,\n // and the hub runs the global middleware itself.\n if (sockets?.matches(req)) {\n return sockets.upgrade(req, server);\n }\n // The app's global middleware goes in front of the static handler as well\n // as the router, so it can refuse `/assets/*` too.\n const res = await instrumentation(req, (req) =>\n app.withGlobalMiddleware(req, requestHandler, (err) =>\n unhandledErrorResponse(err, new URL(req.url).pathname, app.onException),\n ),\n );\n // Applied at the very edge, after instrumentation, so every HTML response\n // goes through the same negotiation — including the ones an app's\n // instrumentation produced itself. Anything that isn't HTML comes back\n // untouched.\n return compressionEnabled ? compressResponse(req, res) : res;\n },\n idleTimeout: serverIdleTimeout(),\n port: process.env.PORT || 5173,\n websocket: sockets?.websocket as WebSocketHandler<any>,\n });\n await sockets?.start(server);\n\n printStartupBanner({ port: server.port, rootDir });\n\n return server;\n}\n",
6
6
  "/**\n * Transport-level compression for SSR HTML responses.\n *\n * This lives in the runtime rather than in an app, because every gemi app\n * serves the same shape of response: a streamed `text/html` document whose\n * bulk is critical CSS, markup and the `window.__GEMI_DATA__` hydration\n * payload. Compressing it here means the win is portable across deployments —\n * it does not depend on a CDN being configured to compress on the origin's\n * behalf — and it also cuts origin→edge bandwidth, which edge compression\n * cannot.\n *\n * Compression stays strictly at the transport layer: what the client decodes\n * is byte-for-byte the HTML React rendered, so hydration is unaffected.\n *\n * Deliberately dependency-free apart from `node:zlib`/`node:stream` so it can\n * be unit tested without booting a server.\n */\n\nimport { Duplex } from \"node:stream\";\nimport { constants, createBrotliCompress, createGzip } from \"node:zlib\";\n\n/** The content codings we can produce, in the order we prefer them. */\nexport type ContentEncoding = \"br\" | \"gzip\";\n\n/**\n * Server preference, used to break q-value ties. Brotli comes first: at the\n * quality we use it is both smaller *and* no more expensive than gzip on a\n * representative SSR document (~177 kB → 28.0 kB in ~2.0 ms, versus 31.6 kB in\n * ~2.0 ms for gzip).\n */\nconst SERVER_PREFERENCE: ContentEncoding[] = [\"br\", \"gzip\"];\n\n/**\n * Below this, an encoded body plus its framing overhead is not worth the CPU.\n * Only applied when the response declares a `Content-Length` — a streamed SSR\n * response does not, and buffering one just to measure it would defeat the\n * streaming render.\n */\nconst MIN_COMPRESSIBLE_BYTES = 1024;\n\n/**\n * Brotli quality 5 (of 11). The default, 11, is meant for static assets\n * compressed once at build time — on a streamed document it costs ~175 ms,\n * two orders of magnitude more than quality 5 for ~12% more savings. Quality 5\n * is the usual choice for dynamic content.\n *\n * `LGWIN` 19 caps the window at 512 kB rather than the default 16 MB. An SSR\n * document is far smaller than that, so the ratio is unchanged, and the bound\n * matters under concurrency: the window is allocated per in-flight response.\n */\nconst BROTLI_QUALITY = 5;\nconst BROTLI_WINDOW_BITS = 19;\n\n/** zlib's default level. Level 9 costs measurably more for ~1% on HTML. */\nconst GZIP_LEVEL = 6;\n\nfunction parseQValue(raw: string | undefined): number {\n if (raw === undefined) {\n return 1;\n }\n // `q` is a fixed-point number with at most three decimals (RFC 9110 §12.4.2).\n // Anything else is malformed; treat it as an unqualified \"acceptable\" rather\n // than dropping the encoding, matching what tolerant servers do.\n if (!/^\\d+(\\.\\d{0,3})?$/.test(raw.trim())) {\n return 1;\n }\n const value = Number(raw.trim());\n return Number.isFinite(value) ? Math.min(value, 1) : 1;\n}\n\n/**\n * Parses a request `Accept-Encoding` into `coding -> qvalue`.\n *\n * Returns `null` when the header is *absent*, which is distinct from an empty\n * one. RFC 9110 §12.5.3 says an absent header means any coding is acceptable,\n * but a client that cannot decode and forgets to say so is a broken page, not\n * a slow one — so we treat \"absent\" as \"identity\" and only encode when a\n * client has explicitly opted in. An empty header (`Accept-Encoding:`) is a\n * deliberate \"identity only\" and parses to an empty map.\n */\nexport function parseAcceptEncoding(header: string | null | undefined): Map<string, number> | null {\n if (header === null || header === undefined) {\n return null;\n }\n\n const accepted = new Map<string, number>();\n for (const part of header.split(\",\")) {\n const [rawCoding, ...params] = part.split(\";\");\n const coding = rawCoding.trim().toLowerCase();\n if (coding === \"\") {\n continue;\n }\n\n let q = 1;\n for (const param of params) {\n const separator = param.indexOf(\"=\");\n if (separator === -1) {\n continue;\n }\n if (param.slice(0, separator).trim().toLowerCase() === \"q\") {\n q = parseQValue(param.slice(separator + 1));\n break;\n }\n }\n\n accepted.set(coding, q);\n }\n\n return accepted;\n}\n\n/**\n * Picks the coding to use, or `null` for identity.\n *\n * A `q=0` is a refusal, `*` covers codings the client did not name, and ties\n * fall back to `available`'s order — so a plain `Accept-Encoding: gzip, br`\n * (equal q of 1) resolves to our preference rather than the client's.\n */\nexport function negotiateEncoding(\n header: string | null | undefined,\n available: ContentEncoding[] = SERVER_PREFERENCE,\n): ContentEncoding | null {\n const accepted = parseAcceptEncoding(header);\n if (!accepted) {\n return null;\n }\n\n const wildcard = accepted.get(\"*\");\n let best: ContentEncoding | null = null;\n let bestQ = 0;\n\n for (const coding of available) {\n const q = accepted.get(coding) ?? wildcard ?? 0;\n if (q > bestQ) {\n best = coding;\n bestQ = q;\n }\n }\n\n return best;\n}\n\nfunction hasDirective(headerValue: string | null, directive: string): boolean {\n if (!headerValue) {\n return false;\n }\n // Token match, not substring: `no-transform` must not be found inside\n // something like `x-no-transform`.\n return headerValue\n .split(\",\")\n .some((token) => token.trim().toLowerCase().split(\"=\")[0].trim() === directive);\n}\n\n/**\n * Whether this response's representation is one we may encode — and therefore\n * one that varies by `Accept-Encoding`, even on the requests where we end up\n * sending identity.\n *\n * HTML only, on purpose. JSON view-data and API responses are left alone so\n * that this change cannot alter how they are produced, framed or cached;\n * widening the set is a separate decision.\n */\nexport function isCompressible(method: string, res: Response): boolean {\n // A HEAD response carries no body to encode, and emitting `Content-Encoding`\n // without one would describe a body the client never receives.\n if (method === \"HEAD\") {\n return false;\n }\n\n // 204/304 are bodyless; 206 is a byte range of an already-committed\n // representation and re-encoding it would invalidate its `Content-Range`.\n if (res.status < 200 || res.status === 204 || res.status === 206 || res.status === 304) {\n return false;\n }\n\n if (res.headers.has(\"Content-Range\")) {\n return false;\n }\n\n const contentType = res.headers.get(\"Content-Type\");\n if (!contentType || !/^\\s*text\\/html\\s*(;|$)/i.test(contentType)) {\n return false;\n }\n\n // Only once the status and headers have ruled a range out: on Bun 1.3.14 on\n // Linux, reading `.body` of a Response built on a sliced Blob makes it send\n // past the slice's end (#725), so `.body` is never touched on a non-HTML\n // response this function hands back untouched.\n if (!res.body) {\n return false;\n }\n\n // Already encoded upstream — `identity` is the one value that means \"not\n // encoded\" and is safe to replace.\n const contentEncoding = res.headers.get(\"Content-Encoding\");\n if (contentEncoding && contentEncoding.trim().toLowerCase() !== \"identity\") {\n return false;\n }\n\n // RFC 9110 §5.2.2.6: `no-transform` forbids intermediaries *and* us from\n // changing the representation's encoding.\n if (hasDirective(res.headers.get(\"Cache-Control\"), \"no-transform\")) {\n return false;\n }\n\n const contentLength = res.headers.get(\"Content-Length\");\n if (contentLength !== null && Number(contentLength) < MIN_COMPRESSIBLE_BYTES) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Builds the encoder as a web `TransformStream`-shaped pair.\n *\n * Both codings are driven through `node:zlib` with an explicit per-write flush.\n * Without it the compressor holds output until its internal buffer fills,\n * which would sit on React's shell flush and turn a streamed render into a\n * buffered one — the compression win would be paid for in time to first byte.\n */\nexport function createEncoderStream(encoding: ContentEncoding) {\n const compressor =\n encoding === \"br\"\n ? createBrotliCompress({\n params: {\n [constants.BROTLI_PARAM_QUALITY]: BROTLI_QUALITY,\n [constants.BROTLI_PARAM_LGWIN]: BROTLI_WINDOW_BITS,\n },\n flush: constants.BROTLI_OPERATION_FLUSH,\n })\n : createGzip({ level: GZIP_LEVEL, flush: constants.Z_SYNC_FLUSH });\n\n return Duplex.toWeb(compressor) as unknown as ReadableWritablePair<Uint8Array, Uint8Array>;\n}\n\nfunction withVaryAcceptEncoding(headers: Headers) {\n const vary = headers.get(\"Vary\");\n if (!vary) {\n headers.set(\"Vary\", \"Accept-Encoding\");\n return;\n }\n const tokens = vary.split(\",\").map((token) => token.trim().toLowerCase());\n // `Vary: *` already means \"never reuse for another request\"; narrowing it\n // would be a downgrade.\n if (tokens.includes(\"*\") || tokens.includes(\"accept-encoding\")) {\n return;\n }\n headers.append(\"Vary\", \"Accept-Encoding\");\n}\n\n/**\n * Compresses an SSR HTML response when the client asked for it.\n *\n * Non-HTML responses are returned untouched — same object, same body, so this\n * is safe to apply at the edge of the server for every request.\n *\n * HTML responses always gain `Vary: Accept-Encoding`, whether or not this\n * particular request got an encoded body: without it a shared cache could\n * serve a stored encoded variant to a client that cannot decode it.\n */\nexport function compressResponse(req: Request, res: Response): Response {\n if (!isCompressible(req.method, res)) {\n return res;\n }\n\n const headers = new Headers(res.headers);\n withVaryAcceptEncoding(headers);\n\n const encoding = negotiateEncoding(req.headers.get(\"Accept-Encoding\"));\n if (!encoding) {\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n }\n\n let encoder: ReadableWritablePair<Uint8Array, Uint8Array>;\n try {\n encoder = createEncoderStream(encoding);\n } catch {\n // A compressor we cannot construct is not worth failing a page render\n // over. Serve identity — with the `Vary` we already added.\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n }\n\n headers.set(\"Content-Encoding\", encoding);\n // The length of the identity representation says nothing about the encoded\n // body, and a stale one would truncate the response.\n headers.delete(\"Content-Length\");\n\n return new Response(res.body!.pipeThrough(encoder), {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n}\n",
7
7
  "import { readdir, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { createUnsatisfiableResponse } from \"../http/createStreamResponse\";\nimport { formatContentRange, parseRangeHeader, resolveRange } from \"../http/range\";\nimport { SIBLING_EXTENSION } from \"../vite/precompressAssets\";\nimport { type ContentEncoding, negotiateEncoding } from \"./compression\";\nimport { generateETag } from \"./generateEtag\";\n\n/**\n * Every file in `dist/client` outside `/assets`, as absolute paths — what\n * Vite copied out of `public/` (#583).\n *\n * A root-level path may be an app route, so the static handler may only take\n * one that names a file the app really ships. This used to be guessed from the\n * extension, and every extension the list missed (`.mp4` on 0.58, `.wasm`,\n * `.csv` …) was answered by the router with a rendered 404 page. The build\n * output is fixed for the life of the process, so the exact set is read once\n * at boot instead.\n *\n * `assets/` is left out because the static handler takes everything under it\n * anyway. A name starting with a dot is left out at any depth: `.vite/` is\n * build metadata (both manifests and the asset base record), and a stray\n * `.DS_Store` or `.env` copied in from `public/` is nothing a request should\n * reach. `/.well-known` is served by its own rule.\n */\nexport async function listPublicFiles(clientDir: string): Promise<Set<string>> {\n const files = new Set<string>();\n\n async function walk(dir: string, topLevel: boolean) {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (topLevel && entry.name === \"assets\") continue;\n const path = join(dir, entry.name);\n let isDir = entry.isDirectory();\n let isFile = entry.isFile();\n if (entry.isSymbolicLink()) {\n try {\n const target = await stat(path);\n isDir = target.isDirectory();\n isFile = target.isFile();\n } catch {\n continue;\n }\n }\n if (isFile) files.add(path);\n // A symlinked directory is not followed: a link back up the tree would\n // never end, and `clientFilePath` only names paths inside `dist/client`.\n else if (isDir && !entry.isSymbolicLink()) await walk(path, false);\n }\n }\n\n await walk(clientDir, true);\n return files;\n}\n\nconst LONG_LIVED = \"public, max-age=31536000, must-revalidate\";\n\n/**\n * A content-hashed build asset never changes under its name: a new build\n * writes a new name. So a browser or edge may keep it a year without asking\n * again (#789).\n */\nconst IMMUTABLE = \"public, max-age=31536000, immutable\";\n\nexport interface StaticFileOptions {\n /**\n * The file is a content-hashed build asset (it is in the build's\n * `static-assets.json`), so it is sent as `immutable`.\n */\n immutable?: boolean;\n /**\n * The precompressed siblings the build wrote for it (`file.br`,\n * `file.gz`), in preference order. Offering any makes the response vary by\n * `Accept-Encoding`, so it says so even when it sends identity.\n */\n encodings?: ContentEncoding[];\n}\n\nasync function encodedSibling(\n req: Request,\n path: string,\n encodings: ContentEncoding[],\n): Promise<{ encoding: ContentEncoding; path: string; size: number } | null> {\n // A range is a byte range of the identity representation: an encoded\n // variant has no stable offsets to slice, so a range request gets identity.\n if (encodings.length === 0 || req.headers.has(\"Range\")) {\n return null;\n }\n const encoding = negotiateEncoding(req.headers.get(\"Accept-Encoding\"), encodings);\n if (!encoding) {\n return null;\n }\n const siblingPath = path + SIBLING_EXTENSION[encoding];\n try {\n // Checked per request, like the file itself: a sibling deleted under a\n // running server would otherwise fail mid-body after a committed 200.\n const info = await stat(siblingPath);\n return info.isFile() ? { encoding, path: siblingPath, size: info.size } : null;\n } catch {\n return null;\n }\n}\n\n/**\n * The response for a file in `dist/client` that is known to exist.\n *\n * Honours a single byte `Range`, so a `<video>` pointed at a public `.mp4`\n * can seek — Safari will not play one at all from a server that answers its\n * `bytes=0-1` probe with the whole file. Recent Bun releases slice a\n * file-backed 200 themselves; doing it here keeps that from depending on the\n * Bun version a deployment runs, and answers an unsatisfiable range with the\n * same 416 the `stream()` responses use.\n *\n * A build asset with precompressed siblings is sent as the one\n * `Accept-Encoding` prefers (brotli, then gzip, then identity), with the\n * original's `Content-Type`. Nothing is compressed here: a file without a\n * sibling is sent as is.\n *\n * `Bun.file().type` is the mime lookup, and is `application/octet-stream` for\n * an extension it does not know.\n */\nexport async function staticFileResponse(\n req: Request,\n path: string,\n options: StaticFileOptions = {},\n): Promise<Response> {\n const file = Bun.file(path);\n const encodings = options.encodings ?? [];\n\n const headers: Record<string, string> = {\n \"Content-Type\": file.type || \"application/octet-stream\",\n \"Cache-Control\": options.immutable ? IMMUTABLE : LONG_LIVED,\n \"Accept-Ranges\": \"bytes\",\n };\n if (encodings.length > 0) {\n headers.Vary = \"Accept-Encoding\";\n }\n\n const sibling = await encodedSibling(req, path, encodings);\n if (sibling) {\n const encoded = Bun.file(sibling.path);\n return new Response(encoded.stream(), {\n headers: {\n ...headers,\n \"Content-Encoding\": sibling.encoding,\n \"Content-Length\": String(sibling.size),\n // A different representation, so a different validator.\n ETag: `${generateETag(encoded.lastModified)}-${sibling.encoding}`,\n },\n });\n }\n\n const total = file.size;\n headers.ETag = generateETag(file.lastModified);\n\n const range = parseRangeHeader(req.headers.get(\"Range\"));\n\n if (range) {\n const resolved = resolveRange(range, total);\n if (!resolved) {\n return createUnsatisfiableResponse(total);\n }\n return new Response(file.slice(resolved.start, resolved.end + 1).stream(), {\n status: 206,\n headers: {\n ...headers,\n \"Content-Range\": formatContentRange(resolved.start, resolved.end, total),\n \"Content-Length\": String(resolved.length),\n },\n });\n }\n\n return new Response(file.stream(), {\n headers: { ...headers, \"Content-Length\": String(total) },\n });\n}\n",
8
8
  "import { mkdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { availableParallelism } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { brotliCompress, constants, gzip } from \"node:zlib\";\n\nimport type { ContentEncoding } from \"../server/compression\";\n\n/**\n * Build-time compression of the client bundle (#789).\n *\n * `gemi start` compresses SSR HTML per request, but a hashed chunk is the same\n * bytes for the life of a release, so compressing it per request would spend\n * origin CPU on every visitor for a result that never changes. `gemi build`\n * writes `file.br` (brotli quality 11) and `file.gz` (gzip level 9) next to\n * every compressible build asset instead, once, and the server picks one by\n * `Accept-Encoding`.\n *\n * What the build emitted (and what it carried over from earlier releases, see\n * `previousAssets.ts`) is recorded in `dist/client/.vite/static-assets.json`,\n * with the encodings each file has. The server reads it at boot: a file in the\n * record is a content-hashed build asset, so it is sent as `immutable`, and\n * only the encodings listed for it are offered. A file not in the record (one\n * copied from `public/assets/`, or anything in a build made before this\n * existed) is served as before.\n */\n\n/** Relative to `dist/client`; beside Vite's own manifest, so never served. */\nexport const STATIC_ASSETS_RECORD = \".vite/static-assets.json\";\n\n/**\n * Below this, the encoded body plus its header is not worth a second request\n * representation: a 600-byte chunk saves a few hundred bytes at most, and\n * every file with siblings adds a `stat` per request.\n */\nexport const PRECOMPRESS_MIN_BYTES = 1024;\n\n/**\n * Text-like formats that compress well. Already-compressed formats (images,\n * `woff`/`woff2`, video) are left out: brotli shaves a percent or two off\n * them at best. Source maps are left out because a page never loads one, and\n * only devtools would gain from the extra build time.\n */\nconst COMPRESSIBLE = /\\.(?:m?js|cjs|css|svg|json|webmanifest|wasm|txt|xml|ttf|otf|eot)$/i;\n\nconst TEXT = /\\.(?:m?js|cjs|css|svg|json|webmanifest|txt|xml)$/i;\nconst FONT = /\\.(?:ttf|otf|eot)$/i;\n\nexport const SIBLING_EXTENSION: Record<ContentEncoding, string> = {\n br: \".br\",\n gzip: \".gz\",\n};\n\n/** Server preference: brotli is ~15% smaller than gzip -9 on a JS chunk. */\nconst ENCODINGS: ContentEncoding[] = [\"br\", \"gzip\"];\n\nexport interface StaticAssetsRecord {\n /**\n * Path relative to `dist/client` (`assets/client-DJhrQPW5.js`) → the\n * precompressed siblings it has, in preference order. An empty list is a\n * build asset that is served as identity only (an image, a small file).\n */\n files: Record<string, ContentEncoding[]>;\n}\n\nexport interface PrecompressStats {\n files: number;\n identityBytes: number;\n brBytes: number;\n gzipBytes: number;\n}\n\nconst brotli = promisify(brotliCompress);\nconst gzipAsync = promisify(gzip);\n\nexport function isPrecompressible(file: string): boolean {\n return COMPRESSIBLE.test(file);\n}\n\n/** `true` for `x.js.br` / `x.js.gz`: a sibling, not an asset of its own. */\nexport function isEncodedSibling(file: string): boolean {\n return file.endsWith(\".br\") || file.endsWith(\".gz\");\n}\n\nasync function encode(encoding: ContentEncoding, file: string, input: Buffer): Promise<Buffer> {\n if (encoding === \"gzip\") {\n return gzipAsync(input, { level: 9 });\n }\n return brotli(input, {\n params: {\n [constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MAX_QUALITY,\n [constants.BROTLI_PARAM_MODE]: TEXT.test(file)\n ? constants.BROTLI_MODE_TEXT\n : FONT.test(file)\n ? constants.BROTLI_MODE_FONT\n : constants.BROTLI_MODE_GENERIC,\n [constants.BROTLI_PARAM_SIZE_HINT]: input.length,\n },\n });\n}\n\nasync function fileSize(path: string): Promise<number | null> {\n try {\n const info = await stat(path);\n return info.isFile() ? info.size : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Writes the `.br`/`.gz` siblings of `files` (paths relative to `clientDir`)\n * and returns the encodings each one ended up with.\n *\n * A sibling is only kept when it is smaller than the file itself; one that is\n * not would cost bytes on the wire, so the file is served as identity for\n * that encoding. With `reuseExisting`, a sibling already on disk is trusted\n * rather than rebuilt — for files carried from an earlier release, whose\n * siblings were copied with them and match by content hash.\n */\nexport async function precompressAssets(\n clientDir: string,\n files: Iterable<string>,\n options: {\n reuseExisting?: boolean;\n minBytes?: number;\n concurrency?: number;\n } = {},\n): Promise<{ record: StaticAssetsRecord; stats: PrecompressStats }> {\n const minBytes = options.minBytes ?? PRECOMPRESS_MIN_BYTES;\n const record: StaticAssetsRecord = { files: {} };\n const stats: PrecompressStats = {\n files: 0,\n identityBytes: 0,\n brBytes: 0,\n gzipBytes: 0,\n };\n\n const queue = [...new Set(files)];\n for (const file of queue) {\n record.files[file] = [];\n }\n\n async function work(file: string) {\n if (!isPrecompressible(file)) {\n return;\n }\n const path = join(clientDir, file);\n const size = await fileSize(path);\n if (size === null || size < minBytes) {\n return;\n }\n\n let input: Buffer | null = null;\n const available: ContentEncoding[] = [];\n const sizes: Partial<Record<ContentEncoding, number>> = {};\n for (const encoding of ENCODINGS) {\n const siblingPath = path + SIBLING_EXTENSION[encoding];\n const existing = options.reuseExisting ? await fileSize(siblingPath) : null;\n if (existing !== null) {\n if (existing < size) {\n available.push(encoding);\n sizes[encoding] = existing;\n }\n continue;\n }\n input ??= await readFile(path);\n const output = await encode(encoding, file, input);\n if (output.length < size) {\n await writeFile(siblingPath, output);\n available.push(encoding);\n sizes[encoding] = output.length;\n }\n }\n\n record.files[file] = available;\n if (available.length > 0) {\n stats.files += 1;\n stats.identityBytes += size;\n stats.brBytes += sizes.br ?? size;\n stats.gzipBytes += sizes.gzip ?? size;\n }\n }\n\n // zlib's async calls run on the libuv thread pool; a few files in flight\n // keep it busy without reading the whole bundle into memory at once.\n const concurrency = Math.max(1, options.concurrency ?? Math.min(8, availableParallelism()));\n let next = 0;\n await Promise.all(\n Array.from({ length: Math.min(concurrency, queue.length) }, async () => {\n while (next < queue.length) {\n await work(queue[next++]);\n }\n }),\n );\n\n return { record, stats };\n}\n\nexport async function writeStaticAssetsRecord(clientDir: string, record: StaticAssetsRecord) {\n const path = join(clientDir, STATIC_ASSETS_RECORD);\n await mkdir(dirname(path), { recursive: true });\n // Sorted, so two builds of the same tree write the same file.\n const files = Object.fromEntries(\n Object.entries(record.files).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),\n );\n await writeFile(path, `${JSON.stringify({ files }, null, 2)}\\n`);\n}\n\n/**\n * The record a build wrote, or `null` when there is none (a build made before\n * precompression, or an incomplete `dist/`): the server then serves every file\n * as before. A malformed entry is dropped rather than trusted.\n */\nexport async function readStaticAssetsRecord(\n clientDir: string,\n): Promise<StaticAssetsRecord | null> {\n let raw: string;\n try {\n raw = await readFile(join(clientDir, STATIC_ASSETS_RECORD), \"utf8\");\n } catch {\n return null;\n }\n let files: unknown;\n try {\n files = JSON.parse(raw)?.files;\n } catch {\n return null;\n }\n if (!files || typeof files !== \"object\") {\n return null;\n }\n const record: StaticAssetsRecord = { files: {} };\n for (const [file, encodings] of Object.entries(files)) {\n if (!Array.isArray(encodings)) continue;\n record.files[file] = ENCODINGS.filter((encoding) => encodings.includes(encoding));\n }\n return record;\n}\n",
@@ -13,7 +13,7 @@
13
13
  "import { stringEraRefusal } from \"../http/Error\";\nimport { isApiPath } from \"../services/router/apiPath\";\n\n// The production server's last resort: an error nothing on the way here turned\n// into a response. Request breakers (auth, 404s, 416s) are answered by the\n// dispatchers before this, so what arrives is a genuine failure — and its\n// message and stack are for the developer, not for whoever triggered it. They\n// can carry absolute paths, dependency versions, SQL fragments and column\n// names. The dev server renders them on purpose (`httpDev.ts`); this does not.\n\nconst GENERIC_500_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Internal Server Error</title>\n <style>\n body { font-family: system-ui, sans-serif; margin: 0; min-height: 100vh; display: grid; place-items: center; }\n main { text-align: center; padding: 16px; }\n h1 { font-size: 1.5rem; margin: 0 0 0.5rem; }\n p { margin: 0; opacity: 0.7; }\n </style>\n </head>\n <body>\n <main>\n <h1>Something went wrong</h1>\n <p>Please try again later.</p>\n </main>\n </body>\n</html>`;\n\nexport function unhandledErrorResponse(\n err: unknown,\n pathname: string,\n onException?: (error: Error) => void,\n): Response {\n // `onException` is the report, and the default one `App` installs is a\n // `console.error`, so logging here as well printed every failure twice\n // (three times for `/api`, whose dispatcher logs before rethrowing). Only\n // without a reporter does this log itself.\n //\n // Reported for `/api` too: an app's error tracking should see an API failure\n // that got this far, not only a page one. `onRequestFail` is a different\n // hook (route config, called by the dispatchers), so this is not a second\n // report through the same channel.\n if (!onException) {\n console.error(err);\n } else {\n try {\n // The hook is typed to receive an `Error`; a thrown string or object is\n // wrapped so a reporter reading `.stack` or `.name` gets one.\n onException(err instanceof Error ? err : new Error(String(err), { cause: err }));\n } catch (reportError) {\n // A broken reporter must not turn a 500 into a leaked stack either.\n console.error(err);\n console.error(reportError);\n }\n }\n\n if (isApiPath(pathname)) {\n return new Response(\n JSON.stringify({ error: stringEraRefusal(\"server_error\", \"Internal Server Error\", 500) }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n\n return new Response(GENERIC_500_HTML, {\n status: 500,\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n}\n",
14
14
  "/**\n * Which `X-Forwarded-For` entries the production server believes (#8).\n *\n * `X-Forwarded-For` is written by whoever sends the request. A client talking\n * to the app directly — or through a proxy that appends to the header rather\n * than replacing it — picks any address it likes, and `clientIp` (the rate\n * limiter's default key) used to read the left-most entry, which is exactly\n * the one the client wrote. So the server decides here, once, at the edge,\n * and hands the app a single address it can rely on:\n *\n * - `none` (the default): no proxy is trusted. The header is replaced with the\n * socket's peer address, and `X-Real-IP` is dropped.\n * - `hops` (`GEMI_TRUST_PROXY=<n>`): the `n` proxies nearest the app are\n * trusted. Each appends the address it was reached from, so the client is\n * the `n`-th entry from the right of `X-Forwarded-For`. Anything\n * further left was written by someone the app does not trust and is dropped.\n * - `all` (`GEMI_TRUST_PROXY=true`): the inbound header is passed through\n * unchanged, as before 0.88. Only sound behind a proxy that overwrites\n * `X-Forwarded-For` (and `X-Real-IP`) rather than appending to it.\n */\nexport type ForwardedTrust =\n | { kind: \"none\" }\n | { kind: \"all\" }\n | { kind: \"hops\"; hops: number };\n\nconst NONE: ForwardedTrust = { kind: \"none\" };\n\n/**\n * `GEMI_TRUST_PROXY` as a policy. Unset, empty, `false`, `off` and `0` trust\n * nothing; `true` trusts everything; a positive integer is a hop count.\n * Anything else throws, so a typo fails the boot instead of silently trusting\n * nothing (every client sharing the proxy's address) or everything.\n */\nexport function parseTrustProxy(value: string | undefined): ForwardedTrust {\n const raw = (value ?? \"\").trim().toLowerCase();\n if (raw === \"\" || raw === \"false\" || raw === \"off\" || raw === \"0\") {\n return NONE;\n }\n if (raw === \"true\") {\n return { kind: \"all\" };\n }\n if (/^[1-9]\\d*$/.test(raw)) {\n return { kind: \"hops\", hops: Number(raw) };\n }\n throw new Error(\n `GEMI_TRUST_PROXY must be \"false\", \"true\" or the number of proxies in front of the app (e.g. 1). Got ${JSON.stringify(value)}.`,\n );\n}\n\n/**\n * Rewrites `headers` so `X-Forwarded-For` holds what `trust` says the client\n * address is. `peer` is the socket's remote address — `null` for a unix\n * socket, where the immediate hop is still counted as one proxy.\n */\nexport function applyForwardedTrust(\n headers: Headers,\n peer: string | null,\n trust: ForwardedTrust,\n): void {\n if (trust.kind === \"all\") {\n if (!headers.get(\"x-forwarded-for\") && peer) {\n headers.set(\"x-forwarded-for\", peer);\n }\n return;\n }\n\n // Under any other policy `X-Real-IP` is as client-written as the rest; the\n // address the app should use is the one left in `X-Forwarded-For`.\n headers.delete(\"x-real-ip\");\n\n let client: string | null = peer;\n if (trust.kind === \"hops\") {\n const entries = (headers.get(\"x-forwarded-for\") ?? \"\")\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n // The chain is `entries` + `peer`; the client sits `hops` places left of\n // its end, i.e. `entries[entries.length - hops]`. A shorter chain than\n // expected means the request skipped a proxy, so its left-most hop is the\n // furthest thing seen — never anything further left than that.\n const index = entries.length - trust.hops;\n client = index >= 0 ? entries[index]! : (entries[0] ?? peer);\n }\n\n if (client) {\n headers.set(\"x-forwarded-for\", client);\n } else {\n headers.delete(\"x-forwarded-for\");\n }\n}\n"
15
15
  ],
16
- "mappings": "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",
17
- "debugId": "7D646A3ED7E1FF6A64756E2164756E21",
16
+ "mappings": "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",
17
+ "debugId": "AF73DF72B0CE2E5964756E2164756E21",
18
18
  "names": []
19
19
  }
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{R as S,T as h,U as u}from"./chunk-679ndcdq.js";import{ma as q,na as w}from"./chunk-eydahc2f.js";import"./chunk-a22h5cby.js";import"./chunk-epvpmakp.js";import"./chunk-r3v2cnrj.js";import"./chunk-vp4x2c0k.js";import"./chunk-kk18xqgc.js";import"./chunk-3v4esxbd.js";import{Gi as N}from"./chunk-v2cv3wcw.js";import{Yk as y}from"./chunk-apfk702c.js";import{ll as C}from"./chunk-5aj27bgc.js";import"./chunk-tbhtx2t0.js";import{join as $J}from"path";import{createServer as zJ}from"vite";import{join as l}from"path";import{IncomingMessage as d,ServerResponse as p}from"http";import{Socket as i}from"net";function c(J){return J.replace(/\x1b\[[0-9;]*m/g,"").replace(/\[[0-9;]*m/g,"").replace(/\n\s*\n/g,`
2
+ import{R as S,T as h,U as u}from"./chunk-25gg2nve.js";import{ma as q,na as w}from"./chunk-eydahc2f.js";import"./chunk-a22h5cby.js";import"./chunk-epvpmakp.js";import"./chunk-r3v2cnrj.js";import"./chunk-vp4x2c0k.js";import"./chunk-kk18xqgc.js";import"./chunk-3v4esxbd.js";import{Gi as N}from"./chunk-v2cv3wcw.js";import{Yk as y}from"./chunk-apfk702c.js";import{ll as C}from"./chunk-5aj27bgc.js";import"./chunk-tbhtx2t0.js";import{join as $J}from"path";import{createServer as zJ}from"vite";import{join as l}from"path";import{IncomingMessage as d,ServerResponse as p}from"http";import{Socket as i}from"net";function c(J){return J.replace(/\x1b\[[0-9;]*m/g,"").replace(/\[[0-9;]*m/g,"").replace(/\n\s*\n/g,`
3
3
  `).split(`
4
4
  `).map((W)=>W.trim()).filter((W)=>W.length>0).join(`
5
5
  `).trim()}function _(J){return`