@alxia/react-router 0.26.0 → 0.27.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 CHANGED
@@ -527,6 +527,16 @@ In a build, `build/client` is served before `configure`'s middlewares:
527
527
  A missing asset gets alxia's JSON 404, not a page. In dev, Vite serves
528
528
  these files.
529
529
 
530
+ `react-router build` also writes `.br` and `.gz` copies beside every
531
+ compressible file of the client build (JavaScript, CSS, HTML, SVG, JSON,
532
+ text, XML, web manifests, source maps, WebAssembly, icons, fonts) of at least 1 kB, and the server sends the one a
533
+ browser accepts, with `Content-Encoding` and `Vary: Accept-Encoding`, the
534
+ `Cache-Control` above unchanged. `alxia({ precompress: false })` writes none,
535
+ `alxia({ precompress: { minSize: 4096 } })` moves the threshold, and
536
+ `createServer({ precompressed: false })` (or `reactRouter(app, {
537
+ precompressed: false })`) serves the files as they are, behind a proxy that
538
+ compresses. [More](https://github.com/softistx/alxia/blob/develop/packages/react-router/docs/guide/beside-the-pages.md#compressed)
539
+
530
540
  ## Leaving the pages out of `matchesSpec`
531
541
 
532
542
  An API under `/api`, spec first, is checked against its OpenAPI document
@@ -1132,7 +1142,7 @@ export function loader({ request }: Route.LoaderArgs) {
1132
1142
 
1133
1143
  | export | |
1134
1144
  | --- | --- |
1135
- | `createServer(options?)` | the server of `app/server.ts`. `beforeAll`, `configure`, `getLoadContext`, `proxy` (`alxia({ proxy })`'s, `trustProxy(…)` from `@alxia/core`), `build`, `mode`, `client`, `listen`, `onListen` |
1145
+ | `createServer(options?)` | the server of `app/server.ts`. `beforeAll`, `configure`, `getLoadContext`, `proxy` (`alxia({ proxy })`'s, `trustProxy(…)` from `@alxia/core`), `build`, `mode`, `client`, `precompressed`, `listen`, `onListen` |
1136
1146
  | `ServerOptions<Before, App>` | its options |
1137
1147
  | `ReactRouterServer<App>` | what it returns: `create(wiring)` makes the app, `start(app)` listens |
1138
1148
  | `ServerWiring` | what `create` takes: `build`, `mode`, `client` |
@@ -1150,7 +1160,7 @@ export function loader({ request }: Route.LoaderArgs) {
1150
1160
  | `AppOf<Server>` | the app a server makes |
1151
1161
  | `alxiaContext` | the React Router context key `alxiaOf` and `context.alxia` read, set on every request |
1152
1162
  | `nonceOf(context)` | the request's CSP nonce, for `entry.server.tsx`: the context's `nonce` when a middleware set one, such as `secureHeaders({ nonce: true })`, else `undefined` |
1153
- | `reactRouter(app, options)` | the catch-all and the client's files, for a server of your own. `build`, `mode`, `getLoadContext`, `client` |
1163
+ | `reactRouter(app, options)` | the catch-all and the client's files, for a server of your own. `build`, `mode`, `getLoadContext`, `client`, `precompressed` |
1154
1164
  | `ReactRouterOptions<Ctx>` | its options |
1155
1165
  | `isReactRouterRoute(route)` | whether this package declared a route, for `matchesSpec`'s `exclude` |
1156
1166
 
@@ -1158,8 +1168,8 @@ From `@alxia/react-router/vite`:
1158
1168
 
1159
1169
  | export | |
1160
1170
  | --- | --- |
1161
- | `alxia(options?)` | the Vite plugin, for `react-router dev`, `react-router build` and `vite preview`, building the server for Bun. `entry` is the server file: `app/server.ts` by default, or the default server when there is none. `worker` is the service worker built after `react-router build`: `app/service-worker.ts` by default when it exists, a file, `AlxiaWorkerOptions`, or `false` |
1162
- | `AlxiaOptions`, `AlxiaWorkerOptions` | its options, and the worker's (`buildWorker()`'s but `root`, `client` and `file`, which is optional) |
1171
+ | `alxia(options?)` | the Vite plugin, for `react-router dev`, `react-router build` and `vite preview`, building the server for Bun. `entry` is the server file: `app/server.ts` by default, or the default server when there is none. `worker` is the service worker built after `react-router build`: `app/service-worker.ts` by default when it exists, a file, `AlxiaWorkerOptions`, or `false`. `precompress` writes the `.br` and `.gz` copies of the client build: on by default, `false`, or `PrecompressOptions` (`minSize`) |
1172
+ | `AlxiaOptions`, `AlxiaWorkerOptions`, `PrecompressOptions` | its options, the worker's (`buildWorker()`'s but `root`, `client` and `file`, which is optional) |
1163
1173
 
1164
1174
  From `@alxia/react-router/pwa`:
1165
1175
 
package/dist/assets.d.ts CHANGED
@@ -7,6 +7,8 @@ interface Serving {
7
7
  file(path: string, file: string, options: object): unknown;
8
8
  }
9
9
  /** Declares the client build's routes on `app`. */
10
- export declare function serveClient(app: Serving, client: string): void;
10
+ export declare function serveClient(app: Serving, client: string, options?: {
11
+ readonly precompressed?: boolean;
12
+ }): void;
11
13
  export {};
12
14
  //# sourceMappingURL=assets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAQA,mDAAmD;AACnD,eAAO,MAAM,SAAS,wCAAwC,CAAC;AAC/D,6EAA6E;AAC7E,eAAO,MAAM,OAAO,yBAAyB,CAAC;AAE9C,UAAU,OAAO;IAChB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3D;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsB9D"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAQA,mDAAmD;AACnD,eAAO,MAAM,SAAS,wCAAwC,CAAC;AAC/D,6EAA6E;AAC7E,eAAO,MAAM,OAAO,yBAAyB,CAAC;AAK9C,UAAU,OAAO;IAChB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3D;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CAC1B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAChD,IAAI,CAyBN"}
package/dist/index.js CHANGED
@@ -18,7 +18,9 @@ import { readdirSync, statSync } from "node:fs";
18
18
  import { join } from "node:path";
19
19
  var IMMUTABLE = "public, max-age=31536000, immutable";
20
20
  var AN_HOUR = "public, max-age=3600";
21
- function serveClient(app, client) {
21
+ var CODINGS = ["br", "gzip"];
22
+ function serveClient(app, client, options = {}) {
23
+ const precompressed = options.precompressed === false ? {} : { precompressed: CODINGS };
22
24
  if (!isDirectory(client)) {
23
25
  throw new TypeError(`reactRouter(): client is ${client}, which is not a directory. Pass the client build, build/client by default.`);
24
26
  }
@@ -30,9 +32,9 @@ function serveClient(app, client) {
30
32
  const route = new URL(`/${name}`, "http://localhost").pathname;
31
33
  try {
32
34
  if (isDirectory(path))
33
- app.static(route, path, { cacheControl });
35
+ app.static(route, path, { cacheControl, ...precompressed });
34
36
  else
35
- app.file(route, path, { cacheControl });
37
+ app.file(route, path, { cacheControl, ...precompressed });
36
38
  } catch (error) {
37
39
  throw new TypeError(`reactRouter(): ${path} cannot be served at a path of its own name; rename it. ${error.message}`);
38
40
  }
@@ -66,7 +68,9 @@ function reactRouter(app, options) {
66
68
  const routes = asRoutes(app);
67
69
  declaring(app, () => {
68
70
  if (options.client !== undefined && mode === "production") {
69
- serveClient(routes, pathOf(options.client));
71
+ serveClient(routes, pathOf(options.client), {
72
+ precompressed: options.precompressed ?? true
73
+ });
70
74
  }
71
75
  for (const method of METHODS)
72
76
  routes[method]("/*", handler);
@@ -79,8 +83,8 @@ function routerRequest(ctx) {
79
83
  const request = href === ctx.url.href ? ctx.request : new Request(href, ctx.request);
80
84
  return head ? new Request(request, { method: "GET" }) : request;
81
85
  }
82
- function declareClient(app, client) {
83
- declaring(app, () => serveClient(asRoutes(app), pathOf(client)));
86
+ function declareClient(app, client, precompressed = true) {
87
+ declaring(app, () => serveClient(asRoutes(app), pathOf(client), { precompressed }));
84
88
  }
85
89
  function declaring(app, declare) {
86
90
  const before = new Set(app.routes);
@@ -124,7 +128,7 @@ function createServer(options = {}) {
124
128
  });
125
129
  const before = options.beforeAll?.(fresh) ?? fresh;
126
130
  if (client !== undefined && mode === "production") {
127
- declareClient(before, client);
131
+ declareClient(before, client, options.precompressed ?? true);
128
132
  }
129
133
  const app = options.configure?.(before) ?? before;
130
134
  const getLoadContext = options.getLoadContext;
@@ -172,5 +176,5 @@ export {
172
176
  withAlxia
173
177
  };
174
178
 
175
- //# debugId=121DFAE14BF4BF9464756E2164756E21
179
+ //# debugId=6C7DF5EFFD100B0D64756E2164756E21
176
180
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -2,12 +2,12 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/react-router.ts", "../src/assets.ts", "../src/server.ts", "../src/with-alxia.ts"],
4
4
  "sourcesContent": [
5
- "import { fileURLToPath } from 'node:url';\nimport {\n\ttype Alxia,\n\ttype AnyAlxia,\n\ttype BaseContext,\n\ttype MaybePromise,\n\toriginalUrl,\n\ttype RouteDefinition,\n\ttype StatusCode,\n} from '@alxia/core';\nimport {\n\tcreateRequestHandler,\n\ttype RequestHandler,\n\tRouterContextProvider,\n\ttype ServerBuild,\n} from 'react-router';\nimport { serveClient } from './assets';\nimport { alxiaContext } from './context';\n\nexport interface ReactRouterOptions<Ctx> {\n\t/**\n\t * React Router's server build: the module itself, or a function that\n\t * returns it — `() => import('virtual:react-router/server-build')` in a\n\t * server entry Vite builds, `() => import('./build/server/index.js')`\n\t * beside a build. A function is called on every request in\n\t * `development`, so an edit is picked up, and once in `production`.\n\t */\n\treadonly build: ServerBuild | (() => MaybePromise<ServerBuild>);\n\t/** React Router's server mode: `production` by default. */\n\treadonly mode?: 'development' | 'production';\n\t/**\n\t * Sets the app's own keys on React Router's context provider, from the\n\t * context alxia's middlewares built. `ctx` is typed by the app at the point of\n\t * `app.plugin`: reading what nothing before it adds is a compile error.\n\t * `alxiaContext` is always set, whether or not this is given.\n\t */\n\treadonly getLoadContext?: (\n\t\tctx: BaseContext & Ctx,\n\t\tcontext: RouterContextProvider,\n\t) => MaybePromise<void>;\n\t/**\n\t * The client build's folder, `build/client`: a path or a `file:` URL.\n\t * Its `assets/` is served immutable, and every other top-level file or\n\t * folder — the copies of `public/` — with an hour's cache, before the\n\t * catch-all. Ignored in `development`, where Vite serves them.\n\t */\n\treadonly client?: string | URL;\n}\n\n/** The methods the catch-all takes. A `HEAD` reaches its `GET`. */\nconst METHODS = ['get', 'post', 'put', 'patch', 'delete'] as const;\n\n/** The handlers `reactRouter()` declared: the catch-all's and the client build's. */\nconst declared = new WeakSet<RouteDefinition['handler']>();\n\n/**\n * Whether `reactRouter()` declared this route: the catch-all, or one of the\n * client build's files. For `@alxia/openapi`'s `matchesSpec`, whose\n * `exclude` leaves them out, so the app's routes are checked against the\n * operations of its OpenAPI document and its pages are not.\n *\n * ```ts\n * matchesSpec(app, operations, { exclude: isReactRouterRoute });\n * ```\n */\nexport function isReactRouterRoute(route: RouteDefinition): boolean {\n\treturn declared.has(route.handler);\n}\n\n/**\n * A React Router framework app, server rendered on `app`: `GET`, `POST`,\n * `PUT`, `PATCH` and `DELETE` at `/*`, behind every middleware declared on `app`\n * before it. Each loader, action and middleware reads what those added\n * through `alxiaOf<App>(context)`. The app's own routes — an `/api`\n * — answer their paths, declared before it or after; the client build's\n * files are served when `client` is given.\n *\n * ```ts\n * const app = base.plugin((app) =>\n * reactRouter(app, { build: () => import('./build/server/index.js'), client: 'build/client' }),\n * );\n * ```\n */\nexport function reactRouter<Ctx extends object, Prefix extends string>(\n\tapp: Alxia<Ctx, Prefix>,\n\toptions: ReactRouterOptions<Ctx>,\n): Alxia<Ctx, Prefix> {\n\tconst mode = options.mode ?? 'production';\n\tconst handle = requestHandler(options.build, mode);\n\tconst getLoadContext = options.getLoadContext;\n\tconst handler = async (ctx: BaseContext & Ctx) => {\n\t\tconst context = new RouterContextProvider();\n\t\tcontext.set(alxiaContext, ctx);\n\t\tawait getLoadContext?.(ctx, context);\n\t\tconst response = await handle(routerRequest(ctx), context);\n\t\treturn ctx.reply(\n\t\t\tresponse.status as StatusCode,\n\t\t\tresponse.body ?? undefined,\n\t\t\t{ headers: response.headers },\n\t\t);\n\t};\n\n\tconst routes = asRoutes(app);\n\tdeclaring(app, () => {\n\t\tif (options.client !== undefined && mode === 'production') {\n\t\t\tserveClient(routes, pathOf(options.client));\n\t\t}\n\t\tfor (const method of METHODS) routes[method]('/*', handler);\n\t});\n\treturn app;\n}\n\n/**\n * The request React Router reads: at the URL the client asked for, which\n * `originalUrl` reads behind the app's trusted proxies (`alxia({ proxy })`),\n * so `request.url` in a loader names the public scheme and host; and a\n * `HEAD` as its `GET`, since React Router answers a `HEAD` with no headers\n * at all, and the core drops the body.\n */\nfunction routerRequest(ctx: BaseContext): Request {\n\tconst href = originalUrl(ctx).href;\n\tconst head = ctx.request.method === 'HEAD';\n\tconst request =\n\t\thref === ctx.url.href ? ctx.request : new Request(href, ctx.request);\n\treturn head ? new Request(request, { method: 'GET' }) : request;\n}\n\n/**\n * Declares the client build's files on `app`, marked for\n * `isReactRouterRoute`: what `reactRouter()` does with `client`, apart, so\n * that `createServer()` serves them before the middlewares of `configure`.\n */\nexport function declareClient(app: AnyAlxia, client: string | URL): void {\n\tdeclaring(app, () => serveClient(asRoutes(app), pathOf(client)));\n}\n\n/** Runs `declare`, and marks every route it added to `app` as ours. */\nfunction declaring(app: AnyAlxia, declare: () => void): void {\n\tconst before = new Set(app.routes);\n\tdeclare();\n\tfor (const route of app.routes) {\n\t\tif (!before.has(route)) declared.add(route.handler);\n\t}\n}\n\n/** The app's route methods, untyped: the catch-all's handler is not one a route type admits. */\nfunction asRoutes(app: AnyAlxia) {\n\treturn app as unknown as {\n\t\tstatic(path: string, source: string, options: object): unknown;\n\t\tfile(path: string, file: string, options: object): unknown;\n\t} & Record<\n\t\t(typeof METHODS)[number],\n\t\t(path: string, handler: unknown) => unknown\n\t>;\n}\n\n/** A handler that resolves a function build once in production, on every request in development. */\nfunction requestHandler(\n\tbuild: ReactRouterOptions<never>['build'],\n\tmode: 'development' | 'production',\n): RequestHandler {\n\tif (typeof build !== 'function' || mode === 'development') {\n\t\treturn createRequestHandler(build, mode);\n\t}\n\tlet resolved: Promise<RequestHandler> | undefined;\n\treturn async (request, context) => {\n\t\tresolved ??= Promise.resolve(build()).then(\n\t\t\t(server) => createRequestHandler(server, mode),\n\t\t\t(error: unknown) => {\n\t\t\t\tresolved = undefined;\n\t\t\t\tthrow error;\n\t\t\t},\n\t\t);\n\t\treturn (await resolved)(request, context);\n\t};\n}\n\nfunction pathOf(client: string | URL): string {\n\treturn client instanceof URL ? fileURLToPath(client) : client;\n}\n",
6
- "/**\n * The client build's files, served before the catch-all: the hashed\n * `assets/` immutable, every other top-level file or folder — what React\n * Router copied from `public/` — with an hour's cache.\n */\nimport { readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** A hashed asset never changes under its name. */\nexport const IMMUTABLE = 'public, max-age=31536000, immutable';\n/** A public file keeps its name across builds: revalidated after an hour. */\nexport const AN_HOUR = 'public, max-age=3600';\n\ninterface Serving {\n\tstatic(path: string, source: string, options: object): unknown;\n\tfile(path: string, file: string, options: object): unknown;\n}\n\n/** Declares the client build's routes on `app`. */\nexport function serveClient(app: Serving, client: string): void {\n\tif (!isDirectory(client)) {\n\t\tthrow new TypeError(\n\t\t\t`reactRouter(): client is ${client}, which is not a directory. Pass the client build, build/client by default.`,\n\t\t);\n\t}\n\tfor (const name of readdirSync(client).sort()) {\n\t\tif (name.startsWith('.')) continue;\n\t\tconst path = join(client, name);\n\t\tconst cacheControl = name === 'assets' ? IMMUTABLE : AN_HOUR;\n\t\t// Declared as a request's URL carries the name: `my file.pdf` is\n\t\t// `/my%20file.pdf`, `café.png` is `/caf%C3%A9.png`.\n\t\tconst route = new URL(`/${name}`, 'http://localhost').pathname;\n\t\ttry {\n\t\t\tif (isDirectory(path)) app.static(route, path, { cacheControl });\n\t\t\telse app.file(route, path, { cacheControl });\n\t\t} catch (error) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`reactRouter(): ${path} cannot be served at a path of its own name; rename it. ${(error as Error).message}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction isDirectory(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n",
7
- "/**\n * `createServer()`: the alxia server of a React Router app, as\n * `@alxia/react-router/vite` builds it. The plugin hands it React Router's\n * build, the mode and the client folder; the app's own `app/server.ts`\n * customises the rest, or is not written at all.\n */\nimport {\n\ttype Alxia,\n\ttype AnyAlxia,\n\talxia,\n\ttype ContextOf,\n\ttype Empty,\n\ttype ListenInfo,\n\ttype ListenOptions,\n\ttype MaybePromise,\n\ttype ProxyTrust,\n} from '@alxia/core';\nimport type { RouterContextProvider, ServerBuild } from 'react-router';\nimport { declareClient, reactRouter } from './react-router';\n\n/** An app as `alxia()` makes it: what `beforeAll`, or `configure`, receives. */\nexport type FreshApp = Alxia<Empty, ''>;\n\n/**\n * What the Vite plugin hands the server, and a test passes to `create`:\n * React Router's server build, its mode, and the client build's folder.\n */\nexport interface ServerWiring {\n\t/**\n\t * React Router's server build, or a function that returns it: called on\n\t * every request in `development`, once in `production`.\n\t */\n\treadonly build: ServerBuild | (() => MaybePromise<ServerBuild>);\n\t/** `development` under `react-router dev`, `production` in a build, and by default. */\n\treadonly mode?: 'development' | 'production';\n\t/** The client build's folder, a path or a `file:` URL: served in `production`. */\n\treadonly client?: string | URL | undefined;\n}\n\nexport interface ServerOptions<Before extends AnyAlxia, App extends AnyAlxia> {\n\t/**\n\t * Runs first, on a new app: what is declared here runs before the\n\t * client's files too — a guard, a rate limit, a logger that should see\n\t * every request. Returns the app, so its types flow to `configure`.\n\t */\n\treadonly beforeAll?: (app: FreshApp) => Before;\n\t/**\n\t * The app the pages run behind: its middlewares, its plugins, its `/api`.\n\t * Declared after the client's files and before the catch-all. Returns\n\t * the app: what it builds is what the loaders read through `alxiaOf`.\n\t */\n\treadonly configure?: (app: Before) => App;\n\t/**\n\t * Sets the app's own keys on React Router's context provider, `ctx`\n\t * typed by `configure`'s app. `alxiaContext` is always set.\n\t */\n\treadonly getLoadContext?: (\n\t\tctx: ContextOf<App>,\n\t\tcontext: RouterContextProvider,\n\t) => MaybePromise<void>;\n\t/**\n\t * The proxies in front of the app, `trustProxy({ trusted })` from\n\t * `@alxia/core`: `alxia({ proxy })`'s option, so `ctx.ip` is the\n\t * client's and React Router's `request.url` the URL it asked for.\n\t */\n\treadonly proxy?: ProxyTrust;\n\t/** Overrides the plugin's server build: rarely wanted. */\n\treadonly build?: ServerWiring['build'];\n\t/** Overrides the plugin's mode, `development` in dev and `production` in a build. */\n\treadonly mode?: 'development' | 'production';\n\t/**\n\t * Overrides the plugin's client folder, `build/client` beside the built\n\t * server. `false` serves none of it: declare the files yourself, in\n\t * `beforeAll` or `configure`.\n\t */\n\treadonly client?: string | URL | false;\n\t/**\n\t * `listen`'s options for `bun build/server/index.js` — `shutdownTimeout`,\n\t * `signals` among them; a `port` or `hostname` here wins over `PORT` (3000)\n\t * and `HOST` (`0.0.0.0`) from the environment.\n\t */\n\treadonly listen?: ListenOptions;\n\t/**\n\t * Called once the built server listens and its `SIGINT` and `SIGTERM` handlers are in place.\n\t * Prints `alxia listening on <url>` by default, and in dev the route\n\t * table (`alxia({ dev })`). An `onListen` in `listen` wins over it.\n\t */\n\treadonly onListen?: (server: Bun.Server<unknown>) => void;\n}\n\n/**\n * The server `createServer()` describes, made into an app by the Vite\n * plugin, by a test, or by a server file of your own.\n */\nexport interface ReactRouterServer<App extends AnyAlxia> {\n\t/**\n\t * The app, serving React Router's build: `build/server/index.js`'s\n\t * default export. A test drives it with `app.request`.\n\t *\n\t * ```ts\n\t * const app = server.create({ build: await import('./build/server/index.js') });\n\t * ```\n\t */\n\tcreate(wiring: ServerWiring): App;\n\t/**\n\t * Listens with `app`, on `listen`, `PORT` and `HOST`, and shuts it down\n\t * gracefully on `SIGINT` or `SIGTERM`, as `@alxia/core`'s `listen` does:\n\t * the requests in flight finish within `shutdownTimeout`, its `onStop`\n\t * hooks run, and the process exits. What `bun build/server/index.js` runs.\n\t */\n\tstart(app: App): Bun.Server<unknown>;\n}\n\n/**\n * The alxia server of a React Router app, for `app/server.ts`. Every option\n * is optional: the Vite plugin wires React Router's build, the mode and the\n * client folder, and without the file uses `createServer()` as it is.\n *\n * ```ts\n * const server = createServer({\n * configure: (app) => app.use(logger()).get('/api/health', ({ reply }) => reply.ok({ ok: true })),\n * });\n * export default server;\n * ```\n *\n * The request runs through `beforeAll`, the client's files, `configure`,\n * then the pages.\n */\nexport function createServer<\n\tBefore extends AnyAlxia = FreshApp,\n\tApp extends AnyAlxia = Before,\n>(options: ServerOptions<Before, App> = {}): ReactRouterServer<App> {\n\treturn {\n\t\tcreate(wiring) {\n\t\t\tconst mode = options.mode ?? wiring.mode ?? 'production';\n\t\t\tconst client =\n\t\t\t\toptions.client === false\n\t\t\t\t\t? undefined\n\t\t\t\t\t: (options.client ?? wiring.client);\n\t\t\t// The app helps the developer in React Router's dev alone: a production\n\t\t\t// build is never in dev, whatever NODE_ENV says.\n\t\t\tconst fresh = alxia({\n\t\t\t\tdev: mode === 'development',\n\t\t\t\t...(options.proxy === undefined ? {} : { proxy: options.proxy }),\n\t\t\t});\n\t\t\t// Without beforeAll or configure, Before and App are their defaults,\n\t\t\t// the app passed through: a type argument given by hand is believed.\n\t\t\tconst before = (options.beforeAll?.(fresh) ?? fresh) as Before;\n\t\t\tif (client !== undefined && mode === 'production') {\n\t\t\t\tdeclareClient(before, client);\n\t\t\t}\n\t\t\tconst app = (options.configure?.(before) ?? before) as App;\n\t\t\tconst getLoadContext = options.getLoadContext;\n\t\t\treactRouter(app, {\n\t\t\t\tbuild: options.build ?? wiring.build,\n\t\t\t\tmode,\n\t\t\t\t...(getLoadContext === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tgetLoadContext: (ctx, context) =>\n\t\t\t\t\t\t\t\tgetLoadContext(ctx as ContextOf<App>, context),\n\t\t\t\t\t\t}),\n\t\t\t});\n\t\t\treturn app;\n\t\t},\n\t\tstart(app) {\n\t\t\tconst own = options.listen?.onListen;\n\t\t\t// `listen` shuts the app down on SIGINT and SIGTERM — readiness 503,\n\t\t\t// the requests in flight drained, the onStop hooks, then the exit —\n\t\t\t// with its handlers in place before it tells onListen: a supervisor\n\t\t\t// may signal as soon as it reads that the server listens.\n\t\t\treturn app.listen({\n\t\t\t\tport: Number(process.env['PORT'] || 3000),\n\t\t\t\thostname: process.env['HOST'] || '0.0.0.0',\n\t\t\t\t...options.listen,\n\t\t\t\tonListen: (info) => {\n\t\t\t\t\tif (own !== undefined) own(info);\n\t\t\t\t\telse if (options.onListen !== undefined) {\n\t\t\t\t\t\toptions.onListen(info.server);\n\t\t\t\t\t} else announce(info);\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** In dev, the route table `listen` prints; else one line. */\nfunction announce({ dev, table, url }: ListenInfo): void {\n\tconsole.log(dev ? table : `alxia listening on ${url}`);\n}\n",
5
+ "import { fileURLToPath } from 'node:url';\nimport {\n\ttype Alxia,\n\ttype AnyAlxia,\n\ttype BaseContext,\n\ttype MaybePromise,\n\toriginalUrl,\n\ttype RouteDefinition,\n\ttype StatusCode,\n} from '@alxia/core';\nimport {\n\tcreateRequestHandler,\n\ttype RequestHandler,\n\tRouterContextProvider,\n\ttype ServerBuild,\n} from 'react-router';\nimport { serveClient } from './assets';\nimport { alxiaContext } from './context';\n\nexport interface ReactRouterOptions<Ctx> {\n\t/**\n\t * React Router's server build: the module itself, or a function that\n\t * returns it — `() => import('virtual:react-router/server-build')` in a\n\t * server entry Vite builds, `() => import('./build/server/index.js')`\n\t * beside a build. A function is called on every request in\n\t * `development`, so an edit is picked up, and once in `production`.\n\t */\n\treadonly build: ServerBuild | (() => MaybePromise<ServerBuild>);\n\t/** React Router's server mode: `production` by default. */\n\treadonly mode?: 'development' | 'production';\n\t/**\n\t * Sets the app's own keys on React Router's context provider, from the\n\t * context alxia's middlewares built. `ctx` is typed by the app at the point of\n\t * `app.plugin`: reading what nothing before it adds is a compile error.\n\t * `alxiaContext` is always set, whether or not this is given.\n\t */\n\treadonly getLoadContext?: (\n\t\tctx: BaseContext & Ctx,\n\t\tcontext: RouterContextProvider,\n\t) => MaybePromise<void>;\n\t/**\n\t * The client build's folder, `build/client`: a path or a `file:` URL.\n\t * Its `assets/` is served immutable, and every other top-level file or\n\t * folder — the copies of `public/` — with an hour's cache, before the\n\t * catch-all. Ignored in `development`, where Vite serves them.\n\t */\n\treadonly client?: string | URL;\n\t/**\n\t * Serves the `.br` and `.gz` copies `alxia()` writes beside the client\n\t * build's files to a browser that accepts them, with `Vary:\n\t * Accept-Encoding`: `true` by default. `false` serves the files as they\n\t * are.\n\t */\n\treadonly precompressed?: boolean;\n}\n\n/** The methods the catch-all takes. A `HEAD` reaches its `GET`. */\nconst METHODS = ['get', 'post', 'put', 'patch', 'delete'] as const;\n\n/** The handlers `reactRouter()` declared: the catch-all's and the client build's. */\nconst declared = new WeakSet<RouteDefinition['handler']>();\n\n/**\n * Whether `reactRouter()` declared this route: the catch-all, or one of the\n * client build's files. For `@alxia/openapi`'s `matchesSpec`, whose\n * `exclude` leaves them out, so the app's routes are checked against the\n * operations of its OpenAPI document and its pages are not.\n *\n * ```ts\n * matchesSpec(app, operations, { exclude: isReactRouterRoute });\n * ```\n */\nexport function isReactRouterRoute(route: RouteDefinition): boolean {\n\treturn declared.has(route.handler);\n}\n\n/**\n * A React Router framework app, server rendered on `app`: `GET`, `POST`,\n * `PUT`, `PATCH` and `DELETE` at `/*`, behind every middleware declared on `app`\n * before it. Each loader, action and middleware reads what those added\n * through `alxiaOf<App>(context)`. The app's own routes — an `/api`\n * — answer their paths, declared before it or after; the client build's\n * files are served when `client` is given.\n *\n * ```ts\n * const app = base.plugin((app) =>\n * reactRouter(app, { build: () => import('./build/server/index.js'), client: 'build/client' }),\n * );\n * ```\n */\nexport function reactRouter<Ctx extends object, Prefix extends string>(\n\tapp: Alxia<Ctx, Prefix>,\n\toptions: ReactRouterOptions<Ctx>,\n): Alxia<Ctx, Prefix> {\n\tconst mode = options.mode ?? 'production';\n\tconst handle = requestHandler(options.build, mode);\n\tconst getLoadContext = options.getLoadContext;\n\tconst handler = async (ctx: BaseContext & Ctx) => {\n\t\tconst context = new RouterContextProvider();\n\t\tcontext.set(alxiaContext, ctx);\n\t\tawait getLoadContext?.(ctx, context);\n\t\tconst response = await handle(routerRequest(ctx), context);\n\t\treturn ctx.reply(\n\t\t\tresponse.status as StatusCode,\n\t\t\tresponse.body ?? undefined,\n\t\t\t{ headers: response.headers },\n\t\t);\n\t};\n\n\tconst routes = asRoutes(app);\n\tdeclaring(app, () => {\n\t\tif (options.client !== undefined && mode === 'production') {\n\t\t\tserveClient(routes, pathOf(options.client), {\n\t\t\t\tprecompressed: options.precompressed ?? true,\n\t\t\t});\n\t\t}\n\t\tfor (const method of METHODS) routes[method]('/*', handler);\n\t});\n\treturn app;\n}\n\n/**\n * The request React Router reads: at the URL the client asked for, which\n * `originalUrl` reads behind the app's trusted proxies (`alxia({ proxy })`),\n * so `request.url` in a loader names the public scheme and host; and a\n * `HEAD` as its `GET`, since React Router answers a `HEAD` with no headers\n * at all, and the core drops the body.\n */\nfunction routerRequest(ctx: BaseContext): Request {\n\tconst href = originalUrl(ctx).href;\n\tconst head = ctx.request.method === 'HEAD';\n\tconst request =\n\t\thref === ctx.url.href ? ctx.request : new Request(href, ctx.request);\n\treturn head ? new Request(request, { method: 'GET' }) : request;\n}\n\n/**\n * Declares the client build's files on `app`, marked for\n * `isReactRouterRoute`: what `reactRouter()` does with `client`, apart, so\n * that `createServer()` serves them before the middlewares of `configure`.\n */\nexport function declareClient(\n\tapp: AnyAlxia,\n\tclient: string | URL,\n\tprecompressed = true,\n): void {\n\tdeclaring(app, () =>\n\t\tserveClient(asRoutes(app), pathOf(client), { precompressed }),\n\t);\n}\n\n/** Runs `declare`, and marks every route it added to `app` as ours. */\nfunction declaring(app: AnyAlxia, declare: () => void): void {\n\tconst before = new Set(app.routes);\n\tdeclare();\n\tfor (const route of app.routes) {\n\t\tif (!before.has(route)) declared.add(route.handler);\n\t}\n}\n\n/** The app's route methods, untyped: the catch-all's handler is not one a route type admits. */\nfunction asRoutes(app: AnyAlxia) {\n\treturn app as unknown as {\n\t\tstatic(path: string, source: string, options: object): unknown;\n\t\tfile(path: string, file: string, options: object): unknown;\n\t} & Record<\n\t\t(typeof METHODS)[number],\n\t\t(path: string, handler: unknown) => unknown\n\t>;\n}\n\n/** A handler that resolves a function build once in production, on every request in development. */\nfunction requestHandler(\n\tbuild: ReactRouterOptions<never>['build'],\n\tmode: 'development' | 'production',\n): RequestHandler {\n\tif (typeof build !== 'function' || mode === 'development') {\n\t\treturn createRequestHandler(build, mode);\n\t}\n\tlet resolved: Promise<RequestHandler> | undefined;\n\treturn async (request, context) => {\n\t\tresolved ??= Promise.resolve(build()).then(\n\t\t\t(server) => createRequestHandler(server, mode),\n\t\t\t(error: unknown) => {\n\t\t\t\tresolved = undefined;\n\t\t\t\tthrow error;\n\t\t\t},\n\t\t);\n\t\treturn (await resolved)(request, context);\n\t};\n}\n\nfunction pathOf(client: string | URL): string {\n\treturn client instanceof URL ? fileURLToPath(client) : client;\n}\n",
6
+ "/**\n * The client build's files, served before the catch-all: the hashed\n * `assets/` immutable, every other top-level file or folder — what React\n * Router copied from `public/` — with an hour's cache.\n */\nimport { readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** A hashed asset never changes under its name. */\nexport const IMMUTABLE = 'public, max-age=31536000, immutable';\n/** A public file keeps its name across builds: revalidated after an hour. */\nexport const AN_HOUR = 'public, max-age=3600';\n\n/** The copies the plugin writes, best first. */\nconst CODINGS = ['br', 'gzip'] as const;\n\ninterface Serving {\n\tstatic(path: string, source: string, options: object): unknown;\n\tfile(path: string, file: string, options: object): unknown;\n}\n\n/** Declares the client build's routes on `app`. */\nexport function serveClient(\n\tapp: Serving,\n\tclient: string,\n\toptions: { readonly precompressed?: boolean } = {},\n): void {\n\tconst precompressed =\n\t\toptions.precompressed === false ? {} : { precompressed: CODINGS };\n\tif (!isDirectory(client)) {\n\t\tthrow new TypeError(\n\t\t\t`reactRouter(): client is ${client}, which is not a directory. Pass the client build, build/client by default.`,\n\t\t);\n\t}\n\tfor (const name of readdirSync(client).sort()) {\n\t\tif (name.startsWith('.')) continue;\n\t\tconst path = join(client, name);\n\t\tconst cacheControl = name === 'assets' ? IMMUTABLE : AN_HOUR;\n\t\t// Declared as a request's URL carries the name: `my file.pdf` is\n\t\t// `/my%20file.pdf`, `café.png` is `/caf%C3%A9.png`.\n\t\tconst route = new URL(`/${name}`, 'http://localhost').pathname;\n\t\ttry {\n\t\t\tif (isDirectory(path))\n\t\t\t\tapp.static(route, path, { cacheControl, ...precompressed });\n\t\t\telse app.file(route, path, { cacheControl, ...precompressed });\n\t\t} catch (error) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`reactRouter(): ${path} cannot be served at a path of its own name; rename it. ${(error as Error).message}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction isDirectory(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n",
7
+ "/**\n * `createServer()`: the alxia server of a React Router app, as\n * `@alxia/react-router/vite` builds it. The plugin hands it React Router's\n * build, the mode and the client folder; the app's own `app/server.ts`\n * customises the rest, or is not written at all.\n */\nimport {\n\ttype Alxia,\n\ttype AnyAlxia,\n\talxia,\n\ttype ContextOf,\n\ttype Empty,\n\ttype ListenInfo,\n\ttype ListenOptions,\n\ttype MaybePromise,\n\ttype ProxyTrust,\n} from '@alxia/core';\nimport type { RouterContextProvider, ServerBuild } from 'react-router';\nimport { declareClient, reactRouter } from './react-router';\n\n/** An app as `alxia()` makes it: what `beforeAll`, or `configure`, receives. */\nexport type FreshApp = Alxia<Empty, ''>;\n\n/**\n * What the Vite plugin hands the server, and a test passes to `create`:\n * React Router's server build, its mode, and the client build's folder.\n */\nexport interface ServerWiring {\n\t/**\n\t * React Router's server build, or a function that returns it: called on\n\t * every request in `development`, once in `production`.\n\t */\n\treadonly build: ServerBuild | (() => MaybePromise<ServerBuild>);\n\t/** `development` under `react-router dev`, `production` in a build, and by default. */\n\treadonly mode?: 'development' | 'production';\n\t/** The client build's folder, a path or a `file:` URL: served in `production`. */\n\treadonly client?: string | URL | undefined;\n}\n\nexport interface ServerOptions<Before extends AnyAlxia, App extends AnyAlxia> {\n\t/**\n\t * Runs first, on a new app: what is declared here runs before the\n\t * client's files too — a guard, a rate limit, a logger that should see\n\t * every request. Returns the app, so its types flow to `configure`.\n\t */\n\treadonly beforeAll?: (app: FreshApp) => Before;\n\t/**\n\t * The app the pages run behind: its middlewares, its plugins, its `/api`.\n\t * Declared after the client's files and before the catch-all. Returns\n\t * the app: what it builds is what the loaders read through `alxiaOf`.\n\t */\n\treadonly configure?: (app: Before) => App;\n\t/**\n\t * Sets the app's own keys on React Router's context provider, `ctx`\n\t * typed by `configure`'s app. `alxiaContext` is always set.\n\t */\n\treadonly getLoadContext?: (\n\t\tctx: ContextOf<App>,\n\t\tcontext: RouterContextProvider,\n\t) => MaybePromise<void>;\n\t/**\n\t * The proxies in front of the app, `trustProxy({ trusted })` from\n\t * `@alxia/core`: `alxia({ proxy })`'s option, so `ctx.ip` is the\n\t * client's and React Router's `request.url` the URL it asked for.\n\t */\n\treadonly proxy?: ProxyTrust;\n\t/** Overrides the plugin's server build: rarely wanted. */\n\treadonly build?: ServerWiring['build'];\n\t/** Overrides the plugin's mode, `development` in dev and `production` in a build. */\n\treadonly mode?: 'development' | 'production';\n\t/**\n\t * Overrides the plugin's client folder, `build/client` beside the built\n\t * server. `false` serves none of it: declare the files yourself, in\n\t * `beforeAll` or `configure`.\n\t */\n\treadonly client?: string | URL | false;\n\t/**\n\t * Serves the client's `.br` and `.gz` copies, which `alxia()` writes at\n\t * build time, to a browser that accepts them: `true` by default.\n\t * `false` serves the files as they are.\n\t */\n\treadonly precompressed?: boolean;\n\t/**\n\t * `listen`'s options for `bun build/server/index.js` — `shutdownTimeout`,\n\t * `signals` among them; a `port` or `hostname` here wins over `PORT` (3000)\n\t * and `HOST` (`0.0.0.0`) from the environment.\n\t */\n\treadonly listen?: ListenOptions;\n\t/**\n\t * Called once the built server listens and its `SIGINT` and `SIGTERM` handlers are in place.\n\t * Prints `alxia listening on <url>` by default, and in dev the route\n\t * table (`alxia({ dev })`). An `onListen` in `listen` wins over it.\n\t */\n\treadonly onListen?: (server: Bun.Server<unknown>) => void;\n}\n\n/**\n * The server `createServer()` describes, made into an app by the Vite\n * plugin, by a test, or by a server file of your own.\n */\nexport interface ReactRouterServer<App extends AnyAlxia> {\n\t/**\n\t * The app, serving React Router's build: `build/server/index.js`'s\n\t * default export. A test drives it with `app.request`.\n\t *\n\t * ```ts\n\t * const app = server.create({ build: await import('./build/server/index.js') });\n\t * ```\n\t */\n\tcreate(wiring: ServerWiring): App;\n\t/**\n\t * Listens with `app`, on `listen`, `PORT` and `HOST`, and shuts it down\n\t * gracefully on `SIGINT` or `SIGTERM`, as `@alxia/core`'s `listen` does:\n\t * the requests in flight finish within `shutdownTimeout`, its `onStop`\n\t * hooks run, and the process exits. What `bun build/server/index.js` runs.\n\t */\n\tstart(app: App): Bun.Server<unknown>;\n}\n\n/**\n * The alxia server of a React Router app, for `app/server.ts`. Every option\n * is optional: the Vite plugin wires React Router's build, the mode and the\n * client folder, and without the file uses `createServer()` as it is.\n *\n * ```ts\n * const server = createServer({\n * configure: (app) => app.use(logger()).get('/api/health', ({ reply }) => reply.ok({ ok: true })),\n * });\n * export default server;\n * ```\n *\n * The request runs through `beforeAll`, the client's files, `configure`,\n * then the pages.\n */\nexport function createServer<\n\tBefore extends AnyAlxia = FreshApp,\n\tApp extends AnyAlxia = Before,\n>(options: ServerOptions<Before, App> = {}): ReactRouterServer<App> {\n\treturn {\n\t\tcreate(wiring) {\n\t\t\tconst mode = options.mode ?? wiring.mode ?? 'production';\n\t\t\tconst client =\n\t\t\t\toptions.client === false\n\t\t\t\t\t? undefined\n\t\t\t\t\t: (options.client ?? wiring.client);\n\t\t\t// The app helps the developer in React Router's dev alone: a production\n\t\t\t// build is never in dev, whatever NODE_ENV says.\n\t\t\tconst fresh = alxia({\n\t\t\t\tdev: mode === 'development',\n\t\t\t\t...(options.proxy === undefined ? {} : { proxy: options.proxy }),\n\t\t\t});\n\t\t\t// Without beforeAll or configure, Before and App are their defaults,\n\t\t\t// the app passed through: a type argument given by hand is believed.\n\t\t\tconst before = (options.beforeAll?.(fresh) ?? fresh) as Before;\n\t\t\tif (client !== undefined && mode === 'production') {\n\t\t\t\tdeclareClient(before, client, options.precompressed ?? true);\n\t\t\t}\n\t\t\tconst app = (options.configure?.(before) ?? before) as App;\n\t\t\tconst getLoadContext = options.getLoadContext;\n\t\t\treactRouter(app, {\n\t\t\t\tbuild: options.build ?? wiring.build,\n\t\t\t\tmode,\n\t\t\t\t...(getLoadContext === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tgetLoadContext: (ctx, context) =>\n\t\t\t\t\t\t\t\tgetLoadContext(ctx as ContextOf<App>, context),\n\t\t\t\t\t\t}),\n\t\t\t});\n\t\t\treturn app;\n\t\t},\n\t\tstart(app) {\n\t\t\tconst own = options.listen?.onListen;\n\t\t\t// `listen` shuts the app down on SIGINT and SIGTERM — readiness 503,\n\t\t\t// the requests in flight drained, the onStop hooks, then the exit —\n\t\t\t// with its handlers in place before it tells onListen: a supervisor\n\t\t\t// may signal as soon as it reads that the server listens.\n\t\t\treturn app.listen({\n\t\t\t\tport: Number(process.env['PORT'] || 3000),\n\t\t\t\thostname: process.env['HOST'] || '0.0.0.0',\n\t\t\t\t...options.listen,\n\t\t\t\tonListen: (info) => {\n\t\t\t\t\tif (own !== undefined) own(info);\n\t\t\t\t\telse if (options.onListen !== undefined) {\n\t\t\t\t\t\toptions.onListen(info.server);\n\t\t\t\t\t} else announce(info);\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** In dev, the route table `listen` prints; else one line. */\nfunction announce({ dev, table, url }: ListenInfo): void {\n\tconsole.log(dev ? table : `alxia listening on ${url}`);\n}\n",
8
8
  "/**\n * `withAlxia(fn)`: a loader, an action or a middleware handed the alxia\n * context as `alxia`, typed even under the generated `Route.*Args`.\n */\nimport type { AnyAlxia } from '@alxia/core';\nimport {\n\ttype AlxiaContextOf,\n\talxiaOf,\n\ttype ProviderLike,\n\ttype RegisteredApp,\n} from './context';\nimport type { ReactRouterServer } from './server';\n\n/**\n * What `withAlxia` adds to React Router's arguments: `alxia`, what\n * `alxiaOf<App>(context)` returns. Typed by `Register` by default; name a\n * server, `AlxiaArgs<typeof server>`, as `alxiaOf<typeof server>` does.\n */\nexport interface AlxiaArgs<\n\tApp extends AnyAlxia | ReactRouterServer<AnyAlxia> = RegisteredApp,\n> {\n\treadonly alxia: AlxiaContextOf<App>;\n}\n\n/**\n * A loader, an action or a middleware given `alxia`, the alxia context, beside\n * React Router's arguments. Annotate the parameter as the generated arguments\n * and `AlxiaArgs`:\n *\n * ```ts\n * export const loader = withAlxia(({ alxia, params }: Route.LoaderArgs & AlxiaArgs) => {\n * return { name: alxia.user?.name ?? null, id: params.id };\n * });\n * ```\n *\n * It returns a function of React Router's arguments alone (`Args` without\n * `alxia`), with `fn`'s return type, so `useLoaderData<typeof loader>` and `Route.ComponentProps` read what\n * `fn` returns. A middleware's `next` is passed on. Throws `alxiaOf`'s error\n * on a request that did not come through `reactRouter()`.\n */\nexport function withAlxia<\n\t// `unknown`, not `AlxiaArgs<AnyAlxia>`, whose `alxia` is `any`: an `fn`\n\t// left unannotated reads nothing of it.\n\tArgs extends { readonly alxia: unknown; readonly context: ProviderLike },\n\tRest extends unknown[],\n\tResult,\n>(\n\tfn: (args: Args, ...rest: Rest) => Result,\n): (args: Omit<Args, 'alxia'>, ...rest: Rest) => Result {\n\treturn (args, ...rest) =>\n\t\tfn({ ...args, alxia: alxiaOf(args.context) } as unknown as Args, ...rest);\n}\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "121DFAE14BF4BF9464756E2164756E21",
10
+ "mappings": "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",
11
+ "debugId": "6C7DF5EFFD100B0D64756E2164756E21",
12
12
  "names": []
13
13
  }
@@ -25,6 +25,13 @@ export interface ReactRouterOptions<Ctx> {
25
25
  * catch-all. Ignored in `development`, where Vite serves them.
26
26
  */
27
27
  readonly client?: string | URL;
28
+ /**
29
+ * Serves the `.br` and `.gz` copies `alxia()` writes beside the client
30
+ * build's files to a browser that accepts them, with `Vary:
31
+ * Accept-Encoding`: `true` by default. `false` serves the files as they
32
+ * are.
33
+ */
34
+ readonly precompressed?: boolean;
28
35
  }
29
36
  /**
30
37
  * Whether `reactRouter()` declared this route: the catch-all, or one of the
@@ -57,5 +64,5 @@ export declare function reactRouter<Ctx extends object, Prefix extends string>(a
57
64
  * `isReactRouterRoute`: what `reactRouter()` does with `client`, apart, so
58
65
  * that `createServer()` serves them before the middlewares of `configure`.
59
66
  */
60
- export declare function declareClient(app: AnyAlxia, client: string | URL): void;
67
+ export declare function declareClient(app: AnyAlxia, client: string | URL, precompressed?: boolean): void;
61
68
  //# sourceMappingURL=react-router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-router.d.ts","sourceRoot":"","sources":["../src/react-router.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,YAAY,EAEjB,KAAK,eAAe,EAEpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAGN,qBAAqB,EACrB,KAAK,WAAW,EAChB,MAAM,cAAc,CAAC;AAItB,MAAM,WAAW,kBAAkB,CAAC,GAAG;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;IAChE,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACzB,GAAG,EAAE,WAAW,GAAG,GAAG,EACtB,OAAO,EAAE,qBAAqB,KAC1B,YAAY,CAAC,IAAI,CAAC,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;CAC/B;AAQD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAElE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,GAAG,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,EACpE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,EACvB,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,GAC9B,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAwBpB;AAiBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAEvE"}
1
+ {"version":3,"file":"react-router.d.ts","sourceRoot":"","sources":["../src/react-router.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,YAAY,EAEjB,KAAK,eAAe,EAEpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAGN,qBAAqB,EACrB,KAAK,WAAW,EAChB,MAAM,cAAc,CAAC;AAItB,MAAM,WAAW,kBAAkB,CAAC,GAAG;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;IAChE,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACzB,GAAG,EAAE,WAAW,GAAG,GAAG,EACtB,OAAO,EAAE,qBAAqB,KAC1B,YAAY,CAAC,IAAI,CAAC,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACjC;AAQD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAElE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,GAAG,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,EACpE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,EACvB,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,GAC9B,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CA0BpB;AAiBD;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,MAAM,GAAG,GAAG,EACpB,aAAa,UAAO,GAClB,IAAI,CAIN"}
package/dist/server.d.ts CHANGED
@@ -57,6 +57,12 @@ export interface ServerOptions<Before extends AnyAlxia, App extends AnyAlxia> {
57
57
  * `beforeAll` or `configure`.
58
58
  */
59
59
  readonly client?: string | URL | false;
60
+ /**
61
+ * Serves the client's `.br` and `.gz` copies, which `alxia()` writes at
62
+ * build time, to a browser that accepts them: `true` by default.
63
+ * `false` serves the files as they are.
64
+ */
65
+ readonly precompressed?: boolean;
60
66
  /**
61
67
  * `listen`'s options for `bun build/server/index.js` — `shutdownTimeout`,
62
68
  * `signals` among them; a `port` or `hostname` here wins over `PORT` (3000)
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACN,KAAK,KAAK,EACV,KAAK,QAAQ,EAEb,KAAK,SAAS,EACd,KAAK,KAAK,EAEV,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGvE,gFAAgF;AAChF,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;IAChE,uFAAuF;IACvF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAC7C,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa,CAAC,MAAM,SAAS,QAAQ,EAAE,GAAG,SAAS,QAAQ;IAC3E;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC;IAC1C;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACzB,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EACnB,OAAO,EAAE,qBAAqB,KAC1B,YAAY,CAAC,IAAI,CAAC,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACvC,qFAAqF;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;CAC1D;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,GAAG,SAAS,QAAQ;IACtD;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,GAAG,CAAC;IAClC;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC3B,MAAM,SAAS,QAAQ,GAAG,QAAQ,EAClC,GAAG,SAAS,QAAQ,GAAG,MAAM,EAC5B,OAAO,GAAE,aAAa,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAqDlE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACN,KAAK,KAAK,EACV,KAAK,QAAQ,EAEb,KAAK,SAAS,EACd,KAAK,KAAK,EAEV,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGvE,gFAAgF;AAChF,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;IAChE,uFAAuF;IACvF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAC7C,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa,CAAC,MAAM,SAAS,QAAQ,EAAE,GAAG,SAAS,QAAQ;IAC3E;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC;IAC1C;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACzB,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EACnB,OAAO,EAAE,qBAAqB,KAC1B,YAAY,CAAC,IAAI,CAAC,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACvC,qFAAqF;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;CAC1D;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAAC,GAAG,SAAS,QAAQ;IACtD;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,GAAG,CAAC;IAClC;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC3B,MAAM,SAAS,QAAQ,GAAG,QAAQ,EAClC,GAAG,SAAS,QAAQ,GAAG,MAAM,EAC5B,OAAO,GAAE,aAAa,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAqDlE"}
@@ -0,0 +1,18 @@
1
+ export interface PrecompressOptions {
2
+ /** The smallest file, in bytes, that gets copies: 1024 by default. */
3
+ readonly minSize?: number;
4
+ }
5
+ export interface Precompressed {
6
+ /** The files that got copies. */
7
+ readonly files: number;
8
+ /** Their size before, and the size of their brotli copies. */
9
+ readonly bytes: number;
10
+ readonly brotliBytes: number;
11
+ }
12
+ /**
13
+ * Writes `<file>.br` and `<file>.gz` beside each compressible file of
14
+ * `client` of at least `minSize` bytes, whichever is smaller than the file
15
+ * itself. Brotli at its best quality: it runs once, at build time.
16
+ */
17
+ export declare function precompressClient(client: string, options?: PrecompressOptions): Promise<Precompressed>;
18
+ //# sourceMappingURL=compress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/vite/compress.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,kBAAkB;IAClC,sEAAsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAUD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC9B,OAAO,CAAC,aAAa,CAAC,CAqCxB"}
@@ -1,5 +1,7 @@
1
1
  import type { Plugin } from 'vite';
2
+ import { type PrecompressOptions } from './compress';
2
3
  import { type AlxiaWorkerOptions } from './worker';
4
+ export type { PrecompressOptions } from './compress';
3
5
  export type { AlxiaWorkerOptions } from './worker';
4
6
  export interface AlxiaOptions {
5
7
  /**
@@ -17,6 +19,14 @@ export interface AlxiaOptions {
17
19
  * nothing without it; `false` builds none. Needs Bun.
18
20
  */
19
21
  readonly worker?: false | string | AlxiaWorkerOptions;
22
+ /**
23
+ * Writes `.br` and `.gz` copies beside the client build's compressible
24
+ * files (JavaScript, CSS, HTML, SVG, JSON, text, WebAssembly, source
25
+ * maps, fonts) of at least `minSize` bytes (1024), after the service
26
+ * worker is built: the server sends them to a browser that accepts them.
27
+ * On by default; `false` writes none.
28
+ */
29
+ readonly precompress?: false | PrecompressOptions;
20
30
  }
21
31
  /**
22
32
  * The Vite plugin that makes alxia the server of a React Router app,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAC;AAgBnD,OAAO,EAAE,KAAK,kBAAkB,EAAkB,MAAM,UAAU,CAAC;AAEnE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,kBAAkB,CAAC;CACtD;AAwBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,CA4ExD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAC;AAEnD,OAAO,EAAE,KAAK,kBAAkB,EAAqB,MAAM,YAAY,CAAC;AAexE,OAAO,EAAE,KAAK,kBAAkB,EAAkB,MAAM,UAAU,CAAC;AAEnE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,kBAAkB,CAAC;IACtD;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,GAAG,kBAAkB,CAAC;CAClD;AAwBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,CAqFxD"}
@@ -8,7 +8,7 @@ import {
8
8
  } from "../chunks/index-6jf7zpxz.js";
9
9
 
10
10
  // src/vite/index.ts
11
- import { relative as relative3 } from "node:path";
11
+ import { join as join4, relative as relative3 } from "node:path";
12
12
 
13
13
  // src/vite/bun.ts
14
14
  import { builtinModules } from "node:module";
@@ -58,9 +58,85 @@ function ssrEnvironment(options, command) {
58
58
  return { ...added, resolve: { ...added.resolve, ...bundled.resolve } };
59
59
  }
60
60
 
61
+ // src/vite/compress.ts
62
+ import { readdir, readFile, rm, writeFile } from "node:fs/promises";
63
+ import { extname, join } from "node:path";
64
+ import { promisify } from "node:util";
65
+ import { brotliCompress, constants, gzip } from "node:zlib";
66
+ var brotli = promisify(brotliCompress);
67
+ var deflate = promisify(gzip);
68
+ var COMPRESSIBLE = new Set([
69
+ ".js",
70
+ ".mjs",
71
+ ".cjs",
72
+ ".css",
73
+ ".html",
74
+ ".htm",
75
+ ".svg",
76
+ ".json",
77
+ ".map",
78
+ ".txt",
79
+ ".xml",
80
+ ".webmanifest",
81
+ ".wasm",
82
+ ".ico",
83
+ ".ttf",
84
+ ".otf",
85
+ ".eot"
86
+ ]);
87
+ async function* walk(dir) {
88
+ for (const entry of await readdir(dir, { withFileTypes: true })) {
89
+ const path = join(dir, entry.name);
90
+ if (entry.isDirectory())
91
+ yield* walk(path);
92
+ else if (entry.isFile())
93
+ yield path;
94
+ }
95
+ }
96
+ async function precompressClient(client, options = {}) {
97
+ const minSize = options.minSize ?? 1024;
98
+ let files = 0;
99
+ let bytes = 0;
100
+ let brotliBytes = 0;
101
+ for await (const path of walk(client)) {
102
+ if (!COMPRESSIBLE.has(extname(path).toLowerCase()))
103
+ continue;
104
+ const body = await readFile(path);
105
+ if (body.length < minSize)
106
+ continue;
107
+ const [br, gz] = await Promise.all([
108
+ brotli(body, {
109
+ params: {
110
+ [constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MAX_QUALITY,
111
+ [constants.BROTLI_PARAM_SIZE_HINT]: body.length
112
+ }
113
+ }),
114
+ deflate(body, { level: 9 })
115
+ ]);
116
+ let written = false;
117
+ for (const [extension, copy] of [
118
+ ["br", br],
119
+ ["gz", gz]
120
+ ]) {
121
+ if (copy.length < body.length) {
122
+ await writeFile(`${path}.${extension}`, copy);
123
+ written = true;
124
+ } else {
125
+ await rm(`${path}.${extension}`, { force: true });
126
+ }
127
+ }
128
+ if (!written)
129
+ continue;
130
+ files += 1;
131
+ bytes += body.length;
132
+ brotliBytes += Math.min(br.length, body.length);
133
+ }
134
+ return { files, bytes, brotliBytes };
135
+ }
136
+
61
137
  // src/vite/config.ts
62
138
  import { existsSync } from "node:fs";
63
- import { dirname, isAbsolute, join, relative, resolve } from "node:path";
139
+ import { dirname, isAbsolute, join as join2, relative, resolve } from "node:path";
64
140
  var SERVER = "virtual:alxia-react-router/server";
65
141
  var DEFAULT = `${SERVER}-default`;
66
142
  function contextOf(config) {
@@ -81,17 +157,17 @@ function serverFile(entry, config) {
81
157
  }
82
158
  return file;
83
159
  }
84
- const file = join(contextOf(config).appDirectory, "server.ts");
160
+ const file = join2(contextOf(config).appDirectory, "server.ts");
85
161
  return existsSync(file) ? file : undefined;
86
162
  }
87
163
  function serverBuildPath(config) {
88
164
  const rr = contextOf(config);
89
- const outDir = resolve(config.root, config.environments["ssr"]?.build.outDir ?? join(rr.buildDirectory, "server"));
90
- return join(outDir, rr.serverBuildFile);
165
+ const outDir = resolve(config.root, config.environments["ssr"]?.build.outDir ?? join2(rr.buildDirectory, "server"));
166
+ return join2(outDir, rr.serverBuildFile);
91
167
  }
92
168
  function clientPath(config) {
93
169
  const built = dirname(serverBuildPath(config));
94
- const path = relative(built, join(contextOf(config).buildDirectory, "client"));
170
+ const path = relative(built, join2(contextOf(config).buildDirectory, "client"));
95
171
  return path.startsWith(".") ? path : `./${path}`;
96
172
  }
97
173
  function serverBuildOptions(rolldown) {
@@ -402,7 +478,7 @@ function requireBun(command, hint = `bun --bun ${command}`, onBun = globalThis.B
402
478
 
403
479
  // src/vite/worker.ts
404
480
  import { existsSync as existsSync3 } from "node:fs";
405
- import { basename, isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "node:path";
481
+ import { basename, isAbsolute as isAbsolute2, join as join3, resolve as resolve2 } from "node:path";
406
482
  function workerFile(option, config) {
407
483
  if (option === false)
408
484
  return;
@@ -414,7 +490,7 @@ function workerFile(option, config) {
414
490
  }
415
491
  return file;
416
492
  }
417
- const file = join2(contextOf(config).appDirectory, "service-worker.ts");
493
+ const file = join3(contextOf(config).appDirectory, "service-worker.ts");
418
494
  return existsSync3(file) ? file : undefined;
419
495
  }
420
496
  var MB = (bytes) => (bytes / 1024 / 1024).toFixed(2);
@@ -429,7 +505,7 @@ async function buildAppWorker(config, option) {
429
505
  ...rest,
430
506
  file,
431
507
  root: config.root,
432
- client: join2(contextOf(config).buildDirectory, "client")
508
+ client: join3(contextOf(config).buildDirectory, "client")
433
509
  }).catch((error) => {
434
510
  throw new Error(`${NAME}: ${error.message}`, { cause: error });
435
511
  });
@@ -500,8 +576,13 @@ function alxia(options = {}) {
500
576
  buildApp: {
501
577
  order: "post",
502
578
  async handler() {
503
- if (config !== undefined)
504
- await buildAppWorker(config, options.worker);
579
+ if (config === undefined)
580
+ return;
581
+ await buildAppWorker(config, options.worker);
582
+ if (!enabled || options.precompress === false)
583
+ return;
584
+ const done = await precompressClient(join4(contextOf(config).buildDirectory, "client"), options.precompress);
585
+ config.logger.info(`✓ ${done.files} client files precompressed (${(done.bytes / 1024).toFixed(0)} kB → ${(done.brotliBytes / 1024).toFixed(0)} kB brotli)`);
505
586
  }
506
587
  },
507
588
  configureServer(server) {
@@ -522,5 +603,5 @@ export {
522
603
  alxia
523
604
  };
524
605
 
525
- //# debugId=7F0E7AC67885D01F64756E2164756E21
606
+ //# debugId=3DE9F1517A9D4E4F64756E2164756E21
526
607
  //# sourceMappingURL=index.js.map
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/vite/index.ts", "../src/vite/bun.ts", "../src/vite/bundle.ts", "../src/vite/config.ts", "../src/vite/node.ts", "../src/vite/socket.ts", "../src/vite/dev.ts", "../src/vite/inline.ts", "../src/vite/preview.ts", "../src/vite/runtime.ts", "../src/vite/worker.ts"],
3
+ "sources": ["../src/vite/index.ts", "../src/vite/bun.ts", "../src/vite/bundle.ts", "../src/vite/compress.ts", "../src/vite/config.ts", "../src/vite/node.ts", "../src/vite/socket.ts", "../src/vite/dev.ts", "../src/vite/inline.ts", "../src/vite/preview.ts", "../src/vite/runtime.ts", "../src/vite/worker.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * `@alxia/react-router/vite`: `alxia()`, the Vite plugin that makes alxia\n * the server of a React Router app, under `react-router dev` and in\n * `react-router build`, with or without an `app/server.ts`.\n */\nimport { relative } from 'node:path';\n// Types only: the plugin runs on whichever Vite the app has, never on a\n// copy of this package's own.\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport { ssrEnvironment } from './bundle';\nimport {\n\tclientPath,\n\tcontextOf,\n\tDEFAULT,\n\tisChildCompiler,\n\tSERVER,\n\tserverBuildOptions,\n\tserverFile,\n} from './config';\nimport { serveDev } from './dev';\nimport { NAME, PASS_THROUGH, serverEntry } from './entry';\nimport { inlineAliases, inlinedFile } from './inline';\nimport { servePreview } from './preview';\nimport { requireBun } from './runtime';\nimport { type AlxiaWorkerOptions, buildAppWorker } from './worker';\n\nexport type { AlxiaWorkerOptions } from './worker';\n\nexport interface AlxiaOptions {\n\t/**\n\t * The server file, relative to Vite's root: a module whose default export\n\t * is `createServer()` from `@alxia/react-router`. By default `server.ts`\n\t * in React Router's app directory, `app/server.ts`, when it exists, and\n\t * otherwise `createServer()` with no options.\n\t */\n\treadonly entry?: string;\n\t/**\n\t * The service worker, bundled into `build/client/service-worker.js` after\n\t * `react-router build`, with its precache list: a file relative to Vite's\n\t * root, or options (`file`, `contract`, `offline`, `precacheAssets`,\n\t * `minify`). By default `app/service-worker.ts` when it exists, and\n\t * nothing without it; `false` builds none. Needs Bun.\n\t */\n\treadonly worker?: false | string | AlxiaWorkerOptions;\n}\n\nconst RESOLVED_SERVER = `\\0${SERVER}`;\nconst RESOLVED_DEFAULT = `\\0${DEFAULT}`;\n\n/**\n * Whether there is a server to be: not in the Vite server React Router\n * compiles route modules in, nor in a single-page app. Throws when the\n * server build would be split in several.\n */\nfunction servesApp(resolved: ResolvedConfig): boolean {\n\t// React Router compiles route modules in a Vite server of its own,\n\t// with every plugin but its own: there is nothing to serve there.\n\tif (isChildCompiler(resolved)) return false;\n\tconst rr = contextOf(resolved);\n\t// A single-page app has no server to be.\n\tif (rr.ssr && rr.serverBundles !== undefined) {\n\t\tthrow new Error(\n\t\t\t`${NAME}: serverBundles splits React Router's server build in several, and alxia serves one. Remove serverBundles from react-router.config.ts.`,\n\t\t);\n\t}\n\treturn rr.ssr;\n}\n\n/**\n * The Vite plugin that makes alxia the server of a React Router app,\n * anywhere in `plugins`:\n *\n * ```ts\n * export default defineConfig({ plugins: [alxia(), reactRouter()] });\n * ```\n *\n * - **`react-router dev`**: every request Vite does not answer itself —\n * pages, data, `/api` — goes to the server, loaded through Vite's SSR\n * runner. HMR, an edit to the server, the app's own context keys and\n * its WebSocket routes work, with no restart.\n * - **`react-router build`**: `build/server/index.js` is the server, with\n * React Router's build inside it. `bun build/server/index.js` listens on\n * `PORT` (3000) and `HOST` (`0.0.0.0`); importing it starts nothing.\n * - **`vite preview`**: every request goes to that built server, as it\n * would answer it; so does React Router's prerendering.\n * - **Built for Bun**: the `ssr` environment resolves packages with the\n * `bun` export condition, leaves `bun` and `bun:*` external, and targets\n * `esnext` unless the app set a target. What the app set is kept.\n * - **Self-contained**: `react-router build` bundles every package into\n * `build/server/index.js` (`ssr.noExternal: true`), so `build/` runs with\n * no `node_modules`. `ssr.external` keeps the packages it names external,\n * and `ssr.external: true` all of them.\n *\n * The server is `app/server.ts`'s default export, `createServer()` from\n * `@alxia/react-router`, or without that file `createServer()` as it is.\n */\nexport function alxia(options: AlxiaOptions = {}): Plugin {\n\tlet config: ResolvedConfig | undefined;\n\tlet enabled = true;\n\n\treturn {\n\t\tname: NAME,\n\t\t// Before React Router's plugin, wherever it is listed: its config reads\n\t\t// the server build's input from this one's, and its dev middleware,\n\t\t// which would render the pages without alxia, comes after this one's.\n\t\tenforce: 'pre',\n\t\tconfig(_config, env) {\n\t\t\tif (env.command === 'serve') return inlineAliases();\n\t\t\tif (env.command !== 'build') return;\n\t\t\t// Vite 7's types know neither `rolldownVersion` nor `rolldownOptions`.\n\t\t\tconst meta = this.meta as { readonly rolldownVersion?: string };\n\t\t\tconst bundler = serverBuildOptions(meta.rolldownVersion !== undefined);\n\t\t\treturn { environments: { ssr: { build: bundler as never } } };\n\t\t},\n\t\tconfigEnvironment(name, options, env) {\n\t\t\t// After every config hook, React Router's included: the server\n\t\t\t// environment as the app and the plugins left it, built for Bun.\n\t\t\t// An app that chose `ssr.target: 'webworker'` keeps Vite's own.\n\t\t\tif (name !== 'ssr' || env.isSsrTargetWebworker === true) return;\n\t\t\treturn ssrEnvironment(options, env.command);\n\t\t},\n\t\tconfigResolved(resolved) {\n\t\t\tconfig = resolved;\n\t\t\tenabled = servesApp(resolved);\n\t\t},\n\t\tresolveId(id) {\n\t\t\tif (id === SERVER) return RESOLVED_SERVER;\n\t\t\tif (id === DEFAULT) return RESOLVED_DEFAULT;\n\t\t\t// An absolute path is never external: see inline.ts.\n\t\t\tif (this.environment?.name === 'ssr') return inlinedFile(id);\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== RESOLVED_SERVER && id !== RESOLVED_DEFAULT) return;\n\t\t\tif (config === undefined) return;\n\t\t\t// Disabled, a single-page app: React Router still builds its server\n\t\t\t// build, to render index.html, from this input.\n\t\t\tif (!enabled) return PASS_THROUGH;\n\t\t\tconst dev = config.command === 'serve';\n\t\t\tconst file =\n\t\t\t\tid === RESOLVED_DEFAULT ? undefined : serverFile(options.entry, config);\n\t\t\treturn serverEntry({\n\t\t\t\tfile,\n\t\t\t\tlabel: file === undefined ? '' : relative(config.root, file),\n\t\t\t\tdev,\n\t\t\t\tclient: dev ? undefined : clientPath(config),\n\t\t\t});\n\t\t},\n\t\tbuildApp: {\n\t\t\t// After React Router's builder: its client build, the one the worker reads.\n\t\t\torder: 'post',\n\t\t\tasync handler() {\n\t\t\t\tif (config !== undefined) await buildAppWorker(config, options.worker);\n\t\t\t},\n\t\t},\n\t\tconfigureServer(server) {\n\t\t\tif (!enabled) return;\n\t\t\trequireBun('react-router dev');\n\t\t\treturn serveDev(server, options.entry);\n\t\t},\n\t\tconfigurePreviewServer(server) {\n\t\t\tif (!enabled) return;\n\t\t\t// React Router prerenders through a preview server of its own,\n\t\t\t// resolved as `serve` too: the message cannot tell the two apart.\n\t\t\trequireBun(\n\t\t\t\t'vite preview, or a react-router build that prerenders,',\n\t\t\t\t'bun --bun vite preview or bun --bun react-router build',\n\t\t\t);\n\t\t\t// Before Vite's own files: the built server answers every request.\n\t\t\tservePreview(server);\n\t\t},\n\t};\n}\n",
5
+ "/**\n * `@alxia/react-router/vite`: `alxia()`, the Vite plugin that makes alxia\n * the server of a React Router app, under `react-router dev` and in\n * `react-router build`, with or without an `app/server.ts`.\n */\nimport { join, relative } from 'node:path';\n// Types only: the plugin runs on whichever Vite the app has, never on a\n// copy of this package's own.\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport { ssrEnvironment } from './bundle';\nimport { type PrecompressOptions, precompressClient } from './compress';\nimport {\n\tclientPath,\n\tcontextOf,\n\tDEFAULT,\n\tisChildCompiler,\n\tSERVER,\n\tserverBuildOptions,\n\tserverFile,\n} from './config';\nimport { serveDev } from './dev';\nimport { NAME, PASS_THROUGH, serverEntry } from './entry';\nimport { inlineAliases, inlinedFile } from './inline';\nimport { servePreview } from './preview';\nimport { requireBun } from './runtime';\nimport { type AlxiaWorkerOptions, buildAppWorker } from './worker';\n\nexport type { PrecompressOptions } from './compress';\nexport type { AlxiaWorkerOptions } from './worker';\n\nexport interface AlxiaOptions {\n\t/**\n\t * The server file, relative to Vite's root: a module whose default export\n\t * is `createServer()` from `@alxia/react-router`. By default `server.ts`\n\t * in React Router's app directory, `app/server.ts`, when it exists, and\n\t * otherwise `createServer()` with no options.\n\t */\n\treadonly entry?: string;\n\t/**\n\t * The service worker, bundled into `build/client/service-worker.js` after\n\t * `react-router build`, with its precache list: a file relative to Vite's\n\t * root, or options (`file`, `contract`, `offline`, `precacheAssets`,\n\t * `minify`). By default `app/service-worker.ts` when it exists, and\n\t * nothing without it; `false` builds none. Needs Bun.\n\t */\n\treadonly worker?: false | string | AlxiaWorkerOptions;\n\t/**\n\t * Writes `.br` and `.gz` copies beside the client build's compressible\n\t * files (JavaScript, CSS, HTML, SVG, JSON, text, WebAssembly, source\n\t * maps, fonts) of at least `minSize` bytes (1024), after the service\n\t * worker is built: the server sends them to a browser that accepts them.\n\t * On by default; `false` writes none.\n\t */\n\treadonly precompress?: false | PrecompressOptions;\n}\n\nconst RESOLVED_SERVER = `\\0${SERVER}`;\nconst RESOLVED_DEFAULT = `\\0${DEFAULT}`;\n\n/**\n * Whether there is a server to be: not in the Vite server React Router\n * compiles route modules in, nor in a single-page app. Throws when the\n * server build would be split in several.\n */\nfunction servesApp(resolved: ResolvedConfig): boolean {\n\t// React Router compiles route modules in a Vite server of its own,\n\t// with every plugin but its own: there is nothing to serve there.\n\tif (isChildCompiler(resolved)) return false;\n\tconst rr = contextOf(resolved);\n\t// A single-page app has no server to be.\n\tif (rr.ssr && rr.serverBundles !== undefined) {\n\t\tthrow new Error(\n\t\t\t`${NAME}: serverBundles splits React Router's server build in several, and alxia serves one. Remove serverBundles from react-router.config.ts.`,\n\t\t);\n\t}\n\treturn rr.ssr;\n}\n\n/**\n * The Vite plugin that makes alxia the server of a React Router app,\n * anywhere in `plugins`:\n *\n * ```ts\n * export default defineConfig({ plugins: [alxia(), reactRouter()] });\n * ```\n *\n * - **`react-router dev`**: every request Vite does not answer itself —\n * pages, data, `/api` — goes to the server, loaded through Vite's SSR\n * runner. HMR, an edit to the server, the app's own context keys and\n * its WebSocket routes work, with no restart.\n * - **`react-router build`**: `build/server/index.js` is the server, with\n * React Router's build inside it. `bun build/server/index.js` listens on\n * `PORT` (3000) and `HOST` (`0.0.0.0`); importing it starts nothing.\n * - **`vite preview`**: every request goes to that built server, as it\n * would answer it; so does React Router's prerendering.\n * - **Built for Bun**: the `ssr` environment resolves packages with the\n * `bun` export condition, leaves `bun` and `bun:*` external, and targets\n * `esnext` unless the app set a target. What the app set is kept.\n * - **Self-contained**: `react-router build` bundles every package into\n * `build/server/index.js` (`ssr.noExternal: true`), so `build/` runs with\n * no `node_modules`. `ssr.external` keeps the packages it names external,\n * and `ssr.external: true` all of them.\n *\n * The server is `app/server.ts`'s default export, `createServer()` from\n * `@alxia/react-router`, or without that file `createServer()` as it is.\n */\nexport function alxia(options: AlxiaOptions = {}): Plugin {\n\tlet config: ResolvedConfig | undefined;\n\tlet enabled = true;\n\n\treturn {\n\t\tname: NAME,\n\t\t// Before React Router's plugin, wherever it is listed: its config reads\n\t\t// the server build's input from this one's, and its dev middleware,\n\t\t// which would render the pages without alxia, comes after this one's.\n\t\tenforce: 'pre',\n\t\tconfig(_config, env) {\n\t\t\tif (env.command === 'serve') return inlineAliases();\n\t\t\tif (env.command !== 'build') return;\n\t\t\t// Vite 7's types know neither `rolldownVersion` nor `rolldownOptions`.\n\t\t\tconst meta = this.meta as { readonly rolldownVersion?: string };\n\t\t\tconst bundler = serverBuildOptions(meta.rolldownVersion !== undefined);\n\t\t\treturn { environments: { ssr: { build: bundler as never } } };\n\t\t},\n\t\tconfigEnvironment(name, options, env) {\n\t\t\t// After every config hook, React Router's included: the server\n\t\t\t// environment as the app and the plugins left it, built for Bun.\n\t\t\t// An app that chose `ssr.target: 'webworker'` keeps Vite's own.\n\t\t\tif (name !== 'ssr' || env.isSsrTargetWebworker === true) return;\n\t\t\treturn ssrEnvironment(options, env.command);\n\t\t},\n\t\tconfigResolved(resolved) {\n\t\t\tconfig = resolved;\n\t\t\tenabled = servesApp(resolved);\n\t\t},\n\t\tresolveId(id) {\n\t\t\tif (id === SERVER) return RESOLVED_SERVER;\n\t\t\tif (id === DEFAULT) return RESOLVED_DEFAULT;\n\t\t\t// An absolute path is never external: see inline.ts.\n\t\t\tif (this.environment?.name === 'ssr') return inlinedFile(id);\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== RESOLVED_SERVER && id !== RESOLVED_DEFAULT) return;\n\t\t\tif (config === undefined) return;\n\t\t\t// Disabled, a single-page app: React Router still builds its server\n\t\t\t// build, to render index.html, from this input.\n\t\t\tif (!enabled) return PASS_THROUGH;\n\t\t\tconst dev = config.command === 'serve';\n\t\t\tconst file =\n\t\t\t\tid === RESOLVED_DEFAULT ? undefined : serverFile(options.entry, config);\n\t\t\treturn serverEntry({\n\t\t\t\tfile,\n\t\t\t\tlabel: file === undefined ? '' : relative(config.root, file),\n\t\t\t\tdev,\n\t\t\t\tclient: dev ? undefined : clientPath(config),\n\t\t\t});\n\t\t},\n\t\tbuildApp: {\n\t\t\t// After React Router's builder: its client build, the one the worker reads.\n\t\t\torder: 'post',\n\t\t\tasync handler() {\n\t\t\t\tif (config === undefined) return;\n\t\t\t\tawait buildAppWorker(config, options.worker);\n\t\t\t\tif (!enabled || options.precompress === false) return;\n\t\t\t\tconst done = await precompressClient(\n\t\t\t\t\tjoin(contextOf(config).buildDirectory, 'client'),\n\t\t\t\t\toptions.precompress,\n\t\t\t\t);\n\t\t\t\tconfig.logger.info(\n\t\t\t\t\t`✓ ${done.files} client files precompressed (${(done.bytes / 1024).toFixed(0)} kB → ${(done.brotliBytes / 1024).toFixed(0)} kB brotli)`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\tconfigureServer(server) {\n\t\t\tif (!enabled) return;\n\t\t\trequireBun('react-router dev');\n\t\t\treturn serveDev(server, options.entry);\n\t\t},\n\t\tconfigurePreviewServer(server) {\n\t\t\tif (!enabled) return;\n\t\t\t// React Router prerenders through a preview server of its own,\n\t\t\t// resolved as `serve` too: the message cannot tell the two apart.\n\t\t\trequireBun(\n\t\t\t\t'vite preview, or a react-router build that prerenders,',\n\t\t\t\t'bun --bun vite preview or bun --bun react-router build',\n\t\t\t);\n\t\t\t// Before Vite's own files: the built server answers every request.\n\t\t\tservePreview(server);\n\t\t},\n\t};\n}\n",
6
6
  "/**\n * The server build, for Bun: what the plugin adds to Vite's `ssr`\n * environment so that `build/server/index.js` is built for the runtime\n * that runs it, and so is the module the dev server loads.\n */\nimport { builtinModules } from 'node:module';\nimport type { EnvironmentOptions } from 'vite';\n\n/** The export condition Bun resolves a package by, and the plugin adds. */\nconst BUN_CONDITION = 'bun';\n\n/**\n * Vite's own builtins for a server environment (its `nodeLikeBuiltins`),\n * which it uses when the config names none: Node's modules, `node:*` and\n * `bun:*`. Bare `bun` is among Node's modules only when Vite runs on Bun.\n */\nconst VITE_BUILTINS: readonly (string | RegExp)[] = [\n\t...builtinModules.filter((id) => !id.includes(':')),\n\t/^node:/,\n\t/^bun:/,\n];\n\n/**\n * Vite's default conditions for a server environment, and for its\n * externals, which it uses when the config names none. React Router's\n * plugin always names them; these are for a config where nothing did.\n */\nconst VITE_CONDITIONS = ['module', 'node', 'development|production'];\nconst VITE_EXTERNAL_CONDITIONS = ['node', 'module-sync'];\n\n/** Bun's own modules, which no bundler should try to resolve: `bun` and `bun:*`. */\nconst BUN_BUILTINS: readonly (string | RegExp)[] = [BUN_CONDITION, /^bun:/];\n\n/**\n * What to merge into `present` so that it holds `wanted`: Vite replaces its\n * default with any value set, so an unset option gets the default too.\n * Strings compare by value, patterns by source.\n */\nfunction adding<T extends string | RegExp>(\n\tpresent: readonly T[] | undefined,\n\tfallback: readonly T[],\n\twanted: readonly T[],\n): T[] {\n\tconst list = present ?? fallback;\n\tconst has = (item: T) =>\n\t\tlist.some((other) =>\n\t\t\ttypeof item === 'string'\n\t\t\t\t? other === item\n\t\t\t\t: other instanceof RegExp && other.source === item.source,\n\t\t);\n\treturn [\n\t\t...(present === undefined ? fallback : []),\n\t\t...wanted.filter((item) => !has(item)),\n\t];\n}\n\n/**\n * What the plugin adds to the `ssr` environment, given its options as the\n * config and every plugin's `config` hook left them. Vite merges the\n * result into them, concatenating arrays, so what the app set is kept:\n *\n * - `resolve.conditions` and `resolve.externalConditions` gain `bun`, so a\n * package that exports a `bun` variant is bundled, and checked, as Bun\n * would load it. Which variant wins stays the package's own order.\n * - `resolve.builtins` gains `bun` and `bun:*`: left external, whichever\n * runtime runs Vite. Vite's own builtins are kept when the app names none.\n * - `build.target` is `esnext`, Bun's, unless the app set one, at the top\n * level or on the environment.\n *\n * `ssr.target` stays `node`: Bun runs Node's modules, and `webworker`\n * would bundle every dependency with the browser's conditions. An app that\n * sets `webworker` itself gets none of this: the plugin leaves that\n * environment to Vite's own defaults.\n */\nexport function bunEnvironment(\n\toptions: EnvironmentOptions,\n): EnvironmentOptions {\n\tconst resolve = options.resolve ?? {};\n\tconst added: EnvironmentOptions = {\n\t\tresolve: {\n\t\t\tconditions: adding(resolve.conditions, VITE_CONDITIONS, [BUN_CONDITION]),\n\t\t\texternalConditions: adding(\n\t\t\t\tresolve.externalConditions,\n\t\t\t\tVITE_EXTERNAL_CONDITIONS,\n\t\t\t\t[BUN_CONDITION],\n\t\t\t),\n\t\t\tbuiltins: adding(resolve.builtins, VITE_BUILTINS, BUN_BUILTINS),\n\t\t},\n\t};\n\tif (options.build?.target === undefined) {\n\t\tadded.build = { target: 'esnext' };\n\t}\n\treturn added;\n}\n",
7
7
  "/**\n * The server build, self-contained: every dependency bundled into\n * `build/server/index.js`, so that running it needs `build/` and Bun, and\n * no `node_modules`. A Docker image's final stage copies `build/` alone.\n */\nimport type { EnvironmentOptions } from 'vite';\nimport { bunEnvironment } from './bun';\n\n/**\n * What the plugin adds to the `ssr` environment under `react-router build`,\n * given its options as the config and the plugins left them:\n * `resolve.noExternal: true`, every package bundled. Never in dev, where\n * Vite's SSR runner loads the packages from `node_modules`.\n *\n * What the app set wins:\n *\n * - `ssr.external: ['sharp']`, or the same on `environments.ssr.resolve`,\n * keeps those packages external, imported from `node_modules` at\n * runtime: Vite reads `external` before `noExternal`. Bun's own modules,\n * `bun` and `bun:*`, and Node's are builtins, external whatever this says.\n * - `ssr.external: true` keeps every package external, Vite's own default:\n * the plugin adds nothing then.\n * - `ssr.noExternal`, a list, is a subset of everything: it changes nothing.\n *\n * React Router's own plugin reads `noExternal: true` and adds no externals\n * of its own; it runs after this one, which is `enforce: 'pre'`.\n */\nexport function bundledEnvironment(\n\toptions: EnvironmentOptions,\n): EnvironmentOptions | undefined {\n\tif (options.resolve?.external === true) return undefined;\n\treturn { resolve: { noExternal: true } };\n}\n\n/**\n * Everything the plugin adds to the `ssr` environment: built for Bun under\n * either command, and self-contained under `build` alone. In dev, Vite's\n * SSR runner loads the packages from `node_modules`.\n */\nexport function ssrEnvironment(\n\toptions: EnvironmentOptions,\n\tcommand: 'build' | 'serve',\n): EnvironmentOptions {\n\tconst added = bunEnvironment(options);\n\tconst bundled = command === 'build' ? bundledEnvironment(options) : undefined;\n\tif (bundled === undefined) return added;\n\treturn { ...added, resolve: { ...added.resolve, ...bundled.resolve } };\n}\n",
8
+ "/**\n * The client build's compressed copies: `app.js.br` and `app.js.gz` beside\n * every compressible file, which `app.static(…, { precompressed })` serves\n * to a browser that accepts them, so the server never compresses on a request.\n */\nimport { readdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { extname, join } from 'node:path';\nimport { promisify } from 'node:util';\nimport { brotliCompress, constants, gzip } from 'node:zlib';\n\nconst brotli = promisify(brotliCompress);\nconst deflate = promisify(gzip);\n\n/** What compresses well: text, and the formats built on it. */\nconst COMPRESSIBLE = new Set([\n\t'.js',\n\t'.mjs',\n\t'.cjs',\n\t'.css',\n\t'.html',\n\t'.htm',\n\t'.svg',\n\t'.json',\n\t'.map',\n\t'.txt',\n\t'.xml',\n\t'.webmanifest',\n\t'.wasm',\n\t'.ico',\n\t'.ttf',\n\t'.otf',\n\t'.eot',\n]);\n\nexport interface PrecompressOptions {\n\t/** The smallest file, in bytes, that gets copies: 1024 by default. */\n\treadonly minSize?: number;\n}\n\nexport interface Precompressed {\n\t/** The files that got copies. */\n\treadonly files: number;\n\t/** Their size before, and the size of their brotli copies. */\n\treadonly bytes: number;\n\treadonly brotliBytes: number;\n}\n\nasync function* walk(dir: string): AsyncGenerator<string> {\n\tfor (const entry of await readdir(dir, { withFileTypes: true })) {\n\t\tconst path = join(dir, entry.name);\n\t\tif (entry.isDirectory()) yield* walk(path);\n\t\telse if (entry.isFile()) yield path;\n\t}\n}\n\n/**\n * Writes `<file>.br` and `<file>.gz` beside each compressible file of\n * `client` of at least `minSize` bytes, whichever is smaller than the file\n * itself. Brotli at its best quality: it runs once, at build time.\n */\nexport async function precompressClient(\n\tclient: string,\n\toptions: PrecompressOptions = {},\n): Promise<Precompressed> {\n\tconst minSize = options.minSize ?? 1024;\n\tlet files = 0;\n\tlet bytes = 0;\n\tlet brotliBytes = 0;\n\tfor await (const path of walk(client)) {\n\t\tif (!COMPRESSIBLE.has(extname(path).toLowerCase())) continue;\n\t\tconst body = await readFile(path);\n\t\tif (body.length < minSize) continue;\n\t\tconst [br, gz] = await Promise.all([\n\t\t\tbrotli(body, {\n\t\t\t\tparams: {\n\t\t\t\t\t[constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MAX_QUALITY,\n\t\t\t\t\t[constants.BROTLI_PARAM_SIZE_HINT]: body.length,\n\t\t\t\t},\n\t\t\t}),\n\t\t\tdeflate(body, { level: 9 }),\n\t\t]);\n\t\tlet written = false;\n\t\tfor (const [extension, copy] of [\n\t\t\t['br', br],\n\t\t\t['gz', gz],\n\t\t] as const) {\n\t\t\tif (copy.length < body.length) {\n\t\t\t\tawait writeFile(`${path}.${extension}`, copy);\n\t\t\t\twritten = true;\n\t\t\t} else {\n\t\t\t\t// A copy left by an earlier build would be stale.\n\t\t\t\tawait rm(`${path}.${extension}`, { force: true });\n\t\t\t}\n\t\t}\n\t\tif (!written) continue;\n\t\tfiles += 1;\n\t\tbytes += body.length;\n\t\tbrotliBytes += Math.min(br.length, body.length);\n\t}\n\treturn { files, bytes, brotliBytes };\n}\n",
8
9
  "/**\n * What the plugin reads of Vite's and React Router's config: the server\n * file, the client folder, and the server build's bundler options.\n */\nimport { existsSync } from 'node:fs';\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path';\nimport type { ResolvedConfig } from 'vite';\nimport { NAME } from './entry';\n\n/** The server build's input, and in dev the module the requests go to. */\nexport const SERVER = 'virtual:alxia-react-router/server';\n/** The same, when there is no server file: `createServer()` as it is. */\nexport const DEFAULT = `${SERVER}-default`;\n\n/** What the plugin reads of React Router's own config. */\nexport interface ReactRouterConfig {\n\treadonly appDirectory: string;\n\treadonly buildDirectory: string;\n\treadonly serverBuildFile: string;\n\treadonly ssr: boolean;\n\treadonly serverBundles?: unknown;\n}\n\n/** React Router's config, which its plugin puts on Vite's. */\nexport function contextOf(config: object): ReactRouterConfig {\n\tconst context = (\n\t\tconfig as {\n\t\t\treadonly __reactRouterPluginContext?: {\n\t\t\t\treadonly reactRouterConfig: ReactRouterConfig;\n\t\t\t};\n\t\t}\n\t).__reactRouterPluginContext;\n\tif (context === undefined) {\n\t\tthrow new Error(\n\t\t\t`${NAME}: React Router's Vite plugin is not in this config. Add reactRouter() from @react-router/dev/vite beside alxia() in vite.config.ts.`,\n\t\t);\n\t}\n\treturn context.reactRouterConfig;\n}\n\n/** React Router's child compiler: a Vite server without its plugin, cached apart. */\nexport function isChildCompiler(config: ResolvedConfig): boolean {\n\treturn (\n\t\t(config as { readonly __reactRouterPluginContext?: unknown })\n\t\t\t.__reactRouterPluginContext === undefined &&\n\t\tconfig.cacheDir.endsWith('.vite-child-compiler')\n\t);\n}\n\n/**\n * The server file: `entry`, which must exist, or `app/server.ts` when it\n * does, or `undefined` for the default server.\n */\nexport function serverFile(\n\tentry: string | undefined,\n\tconfig: ResolvedConfig,\n): string | undefined {\n\tif (entry !== undefined) {\n\t\tconst file = isAbsolute(entry) ? entry : resolve(config.root, entry);\n\t\tif (!existsSync(file)) {\n\t\t\tthrow new Error(\n\t\t\t\t`${NAME}: the entry ${entry} does not exist. Create it, or leave entry out to use app/server.ts, or the default server without it.`,\n\t\t\t);\n\t\t}\n\t\treturn file;\n\t}\n\tconst file = join(contextOf(config).appDirectory, 'server.ts');\n\treturn existsSync(file) ? file : undefined;\n}\n\n/** The built server, absolute: `build/server/index.js`. */\nexport function serverBuildPath(config: ResolvedConfig): string {\n\tconst rr = contextOf(config);\n\tconst outDir = resolve(\n\t\tconfig.root,\n\t\tconfig.environments['ssr']?.build.outDir ??\n\t\t\tjoin(rr.buildDirectory, 'server'),\n\t);\n\treturn join(outDir, rr.serverBuildFile);\n}\n\n/** `build/client`, relative to the built `build/server/index.js`. */\nexport function clientPath(config: ResolvedConfig): string {\n\tconst built = dirname(serverBuildPath(config));\n\tconst path = relative(\n\t\tbuilt,\n\t\tjoin(contextOf(config).buildDirectory, 'client'),\n\t);\n\treturn path.startsWith('.') ? path : `./${path}`;\n}\n\n/**\n * The ssr build's options: one file, `build/server/index.js`, the server\n * and React Router's build together. Rolldown, under Vite 8, names the\n * option otherwise.\n */\nexport function serverBuildOptions(rolldown: boolean): object {\n\treturn rolldown\n\t\t? {\n\t\t\t\trolldownOptions: {\n\t\t\t\t\tinput: SERVER,\n\t\t\t\t\toutput: { codeSplitting: false },\n\t\t\t\t},\n\t\t\t}\n\t\t: {\n\t\t\t\trollupOptions: {\n\t\t\t\t\tinput: SERVER,\n\t\t\t\t\toutput: { inlineDynamicImports: true },\n\t\t\t\t},\n\t\t\t};\n}\n",
9
10
  "/**\n * The few lines between Vite's dev and preview servers, which speak\n * `node:http`, and an alxia app, which speaks `Request` and `Response`: no\n * dependency, Bun's own `node:http` and `node:stream` underneath.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { Readable } from 'node:stream';\n\n/** What Connect, Vite's middleware stack, adds to a request: the URL before any rewrite. */\ntype ConnectRequest = IncomingMessage & {\n\treadonly originalUrl?: string | undefined;\n};\n\n/** The `Request` a Node request stands for. Aborted when the client goes away. */\nexport function toRequest(req: ConnectRequest, res: ServerResponse): Request {\n\tconst secure = (req.socket as { encrypted?: boolean }).encrypted === true;\n\tconst url = new URL(\n\t\treq.originalUrl ?? req.url ?? '/',\n\t\t`${secure ? 'https' : 'http'}://${req.headers.host ?? 'localhost'}`,\n\t);\n\tconst headers = new Headers();\n\tconst raw = req.rawHeaders;\n\tfor (let i = 0; i + 1 < raw.length; i += 2) {\n\t\tconst name = raw[i] as string;\n\t\t// HTTP/2's pseudo-headers (`:path`, `:method`) are not headers.\n\t\tif (!name.startsWith(':')) headers.append(name, raw[i + 1] as string);\n\t}\n\tconst controller = new AbortController();\n\tres.once('close', () => {\n\t\tif (!res.writableFinished) controller.abort();\n\t});\n\tconst method = req.method ?? 'GET';\n\tconst init: RequestInit & { duplex?: 'half' } = {\n\t\tmethod,\n\t\theaders,\n\t\tsignal: controller.signal,\n\t};\n\tif (method !== 'GET' && method !== 'HEAD') {\n\t\tinit.body = Readable.toWeb(req) as unknown as ReadableStream<Uint8Array>;\n\t\tinit.duplex = 'half';\n\t}\n\treturn new Request(url, init);\n}\n\n/** Writes `response` to `res`, streaming its body chunk by chunk as it comes. */\nexport async function send(\n\tres: ServerResponse,\n\tresponse: Response,\n): Promise<void> {\n\tres.statusCode = response.status;\n\tif (response.statusText !== '') res.statusMessage = response.statusText;\n\tfor (const [name, value] of response.headers) {\n\t\tif (name !== 'set-cookie') res.setHeader(name, value);\n\t}\n\tconst cookies = response.headers.getSetCookie();\n\tif (cookies.length > 0) res.setHeader('set-cookie', cookies);\n\tif (response.body === null) {\n\t\tres.end();\n\t\treturn;\n\t}\n\tres.flushHeaders();\n\tconst reader = response.body.getReader();\n\tconst cancel = () => void reader.cancel().catch(() => {});\n\tres.once('close', cancel);\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tif (res.destroyed) return;\n\t\t\tif (!res.write(value)) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tconst go = () => {\n\t\t\t\t\t\tres.off('drain', go);\n\t\t\t\t\t\tres.off('close', go);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t};\n\t\t\t\t\tres.on('drain', go);\n\t\t\t\t\tres.on('close', go);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tres.end();\n\t} finally {\n\t\tres.off('close', cancel);\n\t}\n}\n",
10
11
  "/**\n * Under `react-router dev` and `vite preview`: the app's WebSocket routes. Vite's server is a\n * `node:http` one, and an alxia socket is `Bun.serve`'s upgrade, so each\n * upgrade Vite leaves is relayed, bytes as they come, to a `Bun.serve` of\n * the app's own on a loopback port: its middlewares, its validation, its socket\n * handlers, exactly as `listen` runs them.\n */\nimport type { IncomingMessage } from 'node:http';\nimport { connect, type Socket } from 'node:net';\nimport type { DevApp } from './dev';\nimport { NAME } from './entry';\n\n/** The subprotocols of Vite's own socket, the HMR one and its ping: Vite answers them. */\nconst VITE = new Set(['vite-hmr', 'vite-ping']);\n\n/** Whether the upgrade asks for Vite's own socket. */\nexport function isVites(req: Pick<IncomingMessage, 'headers'>): boolean {\n\tconst protocols = req.headers['sec-websocket-protocol'];\n\tif (protocols === undefined) return false;\n\treturn protocols.split(',').some((protocol) => VITE.has(protocol.trim()));\n}\n\n/** One entry of Vite's `server.proxy`, as far as its sockets go. */\ntype ProxyEntry = string | { readonly ws?: boolean; readonly target?: unknown };\n\n/**\n * Whether Vite's `server.proxy` relays this upgrade itself: an entry whose\n * context matches the URL, as Vite matches it (`^…` a RegExp, otherwise a\n * prefix), and that proxies sockets (`ws: true`, or a `ws:`/`wss:` target).\n */\nexport function isProxied(\n\turl: string,\n\tproxy: Readonly<Record<string, ProxyEntry>> | undefined,\n): boolean {\n\tfor (const [context, entry] of Object.entries(proxy ?? {})) {\n\t\tconst matches =\n\t\t\t(context.startsWith('^') && new RegExp(context).test(url)) ||\n\t\t\turl.startsWith(context);\n\t\tif (!matches) continue;\n\t\tconst options = typeof entry === 'string' ? { target: entry } : entry;\n\t\tconst target = String(options.target ?? '');\n\t\tif (\n\t\t\toptions.ws === true ||\n\t\t\ttarget.startsWith('ws:') ||\n\t\t\ttarget.startsWith('wss:')\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/** The request line and headers of `req`, as they came: what the side server reads. */\nexport function head(\n\treq: Pick<IncomingMessage, 'method' | 'url' | 'rawHeaders'>,\n): string {\n\tconst lines = [`${req.method ?? 'GET'} ${req.url ?? '/'} HTTP/1.1`];\n\tconst raw = req.rawHeaders;\n\tfor (let i = 0; i + 1 < raw.length; i += 2) {\n\t\tlines.push(`${raw[i]}: ${raw[i + 1]}`);\n\t}\n\treturn `${lines.join('\\r\\n')}\\r\\n\\r\\n`;\n}\n\n/** The side servers: the current app's, and those an edit retired, until their sockets close. */\nexport interface Sides {\n\tcurrent:\n\t\t| { readonly app: DevApp; readonly side: Bun.Server<unknown> }\n\t\t| undefined;\n\treadonly retired: Set<Bun.Server<unknown>>;\n}\n\n/**\n * The side server of `app`, started on its first upgrade. A new app, an\n * edit's, retires the previous one: no new connection, and the sockets open\n * on it stay, with the handlers they opened with, until they close.\n */\nexport function sideFor(sides: Sides, app: DevApp): Bun.Server<unknown> {\n\tif (sides.current?.app === app) return sides.current.side;\n\tconst side = Bun.serve({\n\t\tport: 0,\n\t\thostname: '127.0.0.1',\n\t\tfetch: (request, bun) => app.fetch(request, bun),\n\t\twebsocket: app.websocket,\n\t} as Bun.Serve.Options<never>) as Bun.Server<unknown>;\n\tconst old = sides.current?.side;\n\tif (old !== undefined) {\n\t\tsides.retired.add(old);\n\t\tvoid old.stop().then(() => sides.retired.delete(old));\n\t}\n\tsides.current = { app, side };\n\treturn side;\n}\n\n/** Stops every side server, open sockets and all: Vite's server closed. */\nexport function closeAll(sides: Sides): void {\n\tfor (const side of [...sides.retired, sides.current?.side]) {\n\t\tvoid side?.stop(true);\n\t}\n\tsides.current = undefined;\n\tsides.retired.clear();\n}\n\n/** Relays the upgrade on `socket` to the side server on `port`, both ways. */\nfunction relay(\n\treq: IncomingMessage,\n\tsocket: Socket,\n\tbytes: Buffer,\n\tport: number,\n): void {\n\tconst upstream = connect(port, '127.0.0.1', () => {\n\t\tupstream.write(head(req));\n\t\tif (bytes.length > 0) upstream.write(bytes);\n\t\tupstream.pipe(socket);\n\t\tsocket.pipe(upstream);\n\t});\n\tupstream.on('error', () => socket.destroy());\n\tupstream.on('close', () => socket.destroy());\n\tsocket.on('close', () => upstream.destroy());\n}\n\n/** The side server of an app, which its sockets are open on: what `bridgeSockets` returns. */\nexport type SideOf = (app: DevApp) => Bun.Server<unknown> | undefined;\n\n/** What the relay listens to on Vite's HTTP server, HTTP/1 or HTTP/2 alike. */\ninterface Upgrades {\n\ton(\n\t\tevent: 'upgrade',\n\t\tlistener: (req: IncomingMessage, socket: Socket, bytes: Buffer) => void,\n\t): unknown;\n\tonce(event: 'close', listener: () => void): unknown;\n}\n\n/** What the relay needs of the server it listens on: Vite's dev server or its preview. */\nexport interface Bridge {\n\t/** Vite's `server.proxy` (or `preview.proxy`): the upgrades it relays are its own. */\n\treadonly proxy: Readonly<Record<string, ProxyEntry>> | undefined;\n\t/** The app, as it is now. */\n\treadonly load: () => Promise<DevApp>;\n\t/** Where an upgrade that failed is printed: Vite's logger. */\n\treadonly logger: { error(message: string): void };\n\t/** Maps an error's stack to the source, as Vite's `ssrFixStacktrace` does. */\n\treadonly fix?: (error: Error) => void;\n}\n\n/** An upgrade the app could not take: reported, and a 500 to the client. */\nfunction refuse(bridge: Bridge, socket: Socket, error: unknown): void {\n\tif (error instanceof Error) bridge.fix?.(error);\n\tbridge.logger.error(\n\t\t`${NAME}: a WebSocket upgrade failed: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`,\n\t);\n\tif (socket.writable) {\n\t\tsocket.end(\n\t\t\t'HTTP/1.1 500 Internal Server Error\\r\\nConnection: close\\r\\nContent-Length: 0\\r\\n\\r\\n',\n\t\t);\n\t}\n}\n\n/**\n * Relays the app's upgrades on Vite's HTTP server to a side server of the\n * app. Vite's own socket and the sockets its proxy relays are left to\n * Vite. Without an HTTP server (Vite's middleware mode), there is nothing\n * to listen on.\n *\n * Returns the side server of an app, for its HTTP requests' `ctx.server`:\n * the server its sockets are open on, so that a `publish` from a loader or\n * an action reaches them. `undefined` in middleware mode, and once Vite's\n * server closed.\n */\nexport function bridgeSockets(http: Upgrades | null, bridge: Bridge): SideOf {\n\tif (http === null) return () => undefined;\n\tconst sides: Sides = { current: undefined, retired: new Set() };\n\tlet closed = false;\n\thttp.on('upgrade', (req: IncomingMessage, socket: Socket, bytes: Buffer) => {\n\t\tif (isVites(req) || isProxied(req.url ?? '/', bridge.proxy)) return;\n\t\tsocket.on('error', () => socket.destroy());\n\t\tbridge\n\t\t\t.load()\n\t\t\t.then((app) => {\n\t\t\t\tif (socket.destroyed) return;\n\t\t\t\trelay(req, socket, bytes, sideFor(sides, app).port as number);\n\t\t\t})\n\t\t\t.catch((error: unknown) => refuse(bridge, socket, error));\n\t});\n\thttp.once('close', () => {\n\t\tclosed = true;\n\t\tcloseAll(sides);\n\t});\n\treturn (app) => (closed ? undefined : sideFor(sides, app));\n}\n",
@@ -14,7 +15,7 @@
14
15
  "import { NAME } from './entry';\n\n/**\n * Refuses, with what to do, a dev or preview server running on Node. The\n * React Router CLI's `#!/usr/bin/env node` runs it on Node whenever a node\n * is installed, even from `bun run dev`, and alxia's server then fails on\n * its first request with `ReferenceError: Bun is not defined`.\n */\nexport function requireBun(\n\tcommand: string,\n\thint = `bun --bun ${command}`,\n\tonBun = (globalThis as { Bun?: unknown }).Bun !== undefined,\n\treason = \"and alxia's server runs on Bun\",\n): void {\n\tif (onBun) return;\n\tthrow new Error(\n\t\t`${NAME}: ${command} is running on Node, ${reason}. Add a bunfig.toml beside package.json with \"[run]\" and \"bun = true\", so bun run starts it on Bun, or run it as ${hint}.`,\n\t);\n}\n",
15
16
  "/**\n * The service worker, built by `alxia()` once React Router has built the\n * client: `app/service-worker.ts` is the opt-in, as `app/server.ts` is.\n */\nimport { existsSync } from 'node:fs';\nimport { basename, isAbsolute, join, resolve } from 'node:path';\nimport type { ResolvedConfig } from 'vite';\nimport { type BuildWorkerOptions, buildWorker } from '../pwa/build';\nimport { contextOf } from './config';\nimport { NAME } from './entry';\nimport type { AlxiaOptions } from './index';\nimport { requireBun } from './runtime';\n\n/** `buildWorker()`'s options but where: the plugin knows the root, the client build and, by default, the file. */\nexport type AlxiaWorkerOptions = Omit<\n\tBuildWorkerOptions,\n\t'root' | 'client' | 'file'\n> & { readonly file?: string };\n\n/**\n * The worker's source, absolute, or `undefined` when there is none to\n * build: `worker: false`, or no `app/service-worker.ts` and no named file.\n * Throws when a named file does not exist.\n */\nexport function workerFile(\n\toption: AlxiaOptions['worker'],\n\tconfig: ResolvedConfig,\n): string | undefined {\n\tif (option === false) return undefined;\n\tconst named = typeof option === 'string' ? option : option?.file;\n\tif (named !== undefined) {\n\t\tconst file = isAbsolute(named) ? named : resolve(config.root, named);\n\t\tif (!existsSync(file)) {\n\t\t\tthrow new Error(\n\t\t\t\t`${NAME}: the worker ${named} does not exist. Create it, or leave worker out to build app/service-worker.ts when it exists.`,\n\t\t\t);\n\t\t}\n\t\treturn file;\n\t}\n\tconst file = join(contextOf(config).appDirectory, 'service-worker.ts');\n\treturn existsSync(file) ? file : undefined;\n}\n\nconst MB = (bytes: number) => (bytes / 1024 / 1024).toFixed(2);\nconst KB = (bytes: number) => (bytes / 1024).toFixed(1);\n\n/** Builds the worker into `build/client`, if the app has one. */\nexport async function buildAppWorker(\n\tconfig: ResolvedConfig,\n\toption: AlxiaOptions['worker'],\n): Promise<void> {\n\tconst file = workerFile(option, config);\n\tif (file === undefined) return;\n\trequireBun(\n\t\t'react-router build with a service worker',\n\t\t'bun --bun react-router build',\n\t\tundefined,\n\t\t'and the worker is bundled by Bun.build',\n\t);\n\tconst rest = typeof option === 'object' ? option : {};\n\tconst built = await buildWorker({\n\t\t...rest,\n\t\tfile,\n\t\troot: config.root,\n\t\tclient: join(contextOf(config).buildDirectory, 'client'),\n\t}).catch((error: unknown) => {\n\t\tthrow new Error(`${NAME}: ${(error as Error).message}`, { cause: error });\n\t});\n\tconfig.logger.info(\n\t\t`✓ ${basename(built.file)}: ${built.precache.length} files precached (${MB(built.precacheBytes)} MB), worker ${KB(built.bytes)} kB`,\n\t);\n}\n"
16
17
  ],
17
- "mappings": "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",
18
- "debugId": "7F0E7AC67885D01F64756E2164756E21",
18
+ "mappings": "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",
19
+ "debugId": "3DE9F1517A9D4E4F64756E2164756E21",
19
20
  "names": []
20
21
  }
@@ -176,3 +176,25 @@ Dotfiles are skipped. In dev, Vite serves them.
176
176
  A folder that is not one, or a file whose name no route can carry, is
177
177
  refused when the server starts: see
178
178
  [the troubleshooting entries](../troubleshooting.md#typeerror-reactrouter-client-is--which-is-not-a-directory-).
179
+
180
+ ### Compressed
181
+
182
+ `react-router build` writes a `.br` and a `.gz` copy beside each
183
+ compressible file of `build/client` (JavaScript, CSS, HTML, SVG, JSON,
184
+ text, XML, WebAssembly, source maps, fonts) of at least 1 kB, and the
185
+ server sends the copy a browser's `Accept-Encoding` asks for, with
186
+ `Content-Encoding`, `Vary: Accept-Encoding` and the same `Cache-Control`.
187
+ The files are read from disk as they are, never compressed on a request.
188
+ Files at the top of `build/client`, such as a large `sprite.svg`, get it
189
+ too. A file with no copy, or a client that accepts none, gets the file.
190
+
191
+ ```ts
192
+ // vite.config.ts: the threshold, or no copies at all
193
+ alxia({ precompress: { minSize: 4096 } });
194
+ alxia({ precompress: false });
195
+ ```
196
+
197
+ ```ts
198
+ // app/server.ts: serve the files as they are, such as behind a proxy that compresses
199
+ export default createServer({ precompressed: false });
200
+ ```
@@ -113,6 +113,7 @@ Every option is optional:
113
113
  | `beforeAll(app)` | runs first, on a new app. What it declares applies to the client's files too: a rate limit, a guard on everything, a logger that should see every asset. It returns the app, which `configure` then receives |
114
114
  | `getLoadContext(ctx, context)` | sets the app's own keys on React Router's provider, `ctx` typed by `configure`'s app |
115
115
  | `build`, `mode`, `client` | override what the plugin wires; see [Escape hatches](#escape-hatches) |
116
+ | `precompressed` | `false` serves the client's files as they are, without their `.br` and `.gz` copies; see [Compressed](beside-the-pages.md#compressed) |
116
117
  | `listen` | `listen`'s options for `bun build/server/index.js`: `port`, `hostname`, `idleTimeout`, `maxRequestBodySize`, `tls`, `onListen`. A `port` or `hostname` given here wins over `PORT` and `HOST`; an `onListen` here, told `@alxia/core`'s `ListenInfo` — `url`, `routes`, `table`, `dev` — wins over the option below |
117
118
  | `onListen(server)` | called once the built server listens and its `SIGINT` and `SIGTERM` handlers are in place, in place of the `alxia listening on …` line (and, in dev, of the route table); a signal sent from then on runs the `onStop` hooks |
118
119
 
@@ -282,6 +283,7 @@ bun run build && bun server.ts
282
283
  | `mode` | React Router's server mode, `production` by default |
283
284
  | `getLoadContext(ctx, context)` | as `createServer`'s |
284
285
  | `client` | the client build's folder, a path or a `file:` URL, served before the catch-all in `production` |
286
+ | `precompressed` | `true` by default: serves the client's `.br` and `.gz` copies to a browser that accepts them; `false` serves the files as they are |
285
287
 
286
288
  `reactRouter()` goes through `app.plugin`, as `@alxia/graphql`'s `graphql(app, …)`
287
289
  does: that is how it knows the app's context type. A `HEAD` is handed to
@@ -77,6 +77,12 @@ service worker when the app has an `app/service-worker.ts` (`worker: false`
77
77
  turns it off): `build/client/service-worker.js`, with the precache list read
78
78
  from the client build ([the PWA guide](pwa.md#zero-config-alxia-builds-it)).
79
79
 
80
+ Then it writes the compressed copies of the client build, `.br` and `.gz`
81
+ beside each compressible file, which the server serves to a browser that
82
+ accepts them ([the client's files](beside-the-pages.md#compressed)).
83
+ `precompress: false` turns it off, `precompress: { minSize }` moves the 1 kB
84
+ threshold.
85
+
80
86
  React Router's `serverBundles` split the server build in several, and
81
87
  alxia serves one: the plugin refuses them. With `ssr: false`, a
82
88
  single-page app, the plugin does nothing but build the service worker (when
package/docs/roadmap.md CHANGED
@@ -7,6 +7,12 @@ number on it. Every release, with each change it made, is in
7
7
 
8
8
  ## Now
9
9
 
10
+ - **The client build, served compressed.** `react-router build` writes `.br`
11
+ and `.gz` copies beside the compressible files of `build/client`, and the
12
+ server sends the one a browser accepts, with `Vary: Accept-Encoding` and
13
+ the same cache headers. See [the client's
14
+ files](guide/beside-the-pages.md#compressed).
15
+
10
16
  - **`@alxia/react-router/session/react`: the page's hooks around the session
11
17
  flows.** `useSignOut`, `useLinkParam` (a mail link's parameter, read once and optionally dropped
12
18
  from the address bar, or with `live: true` following the URL) and `useCodeField` /
@@ -25,6 +25,7 @@ a loader, a message React Router or the browser prints, or an error from
25
25
  - [``You made a POST request to "/" but did not provide an `action` for route "root", so there is no way to handle the request.``](#you-made-a-post-request-to--but-did-not-provide-an-action-for-route-root-so-there-is-no-way-to-handle-the-request)
26
26
  - [`TypeError: reactRouter(): client is …, which is not a directory. …`](#typeerror-reactrouter-client-is--which-is-not-a-directory-)
27
27
  - [`TypeError: reactRouter(): … cannot be served at a path of its own name; rename it. …`](#typeerror-reactrouter--cannot-be-served-at-a-path-of-its-own-name-rename-it-)
28
+ - [The client's files are served uncompressed](#the-clients-files-are-served-uncompressed)
28
29
  - [`Refused to execute inline script because it violates the following Content Security Policy directive: "default-src 'none'"`](#refused-to-execute-inline-script-because-it-violates-the-following-content-security-policy-directive-default-src-none)
29
30
  - [`Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-…'"`](#refused-to-execute-inline-script-because-it-violates-the-following-content-security-policy-directive-script-src-self-nonce-)
30
31
  - [`A tree hydrated but some attributes of the server rendered HTML didn't match the client properties`](#a-tree-hydrated-but-some-attributes-of-the-server-rendered-html-didnt-match-the-client-properties)
@@ -565,6 +566,31 @@ export async function loader({ request }: Route.LoaderArgs) {
565
566
 
566
567
  The rows stay, `error` is `true`, and `loadMore` retries.
567
568
 
569
+ ### The client's files are served uncompressed
570
+
571
+ A response for a script, a stylesheet or an SVG has no `Content-Encoding`,
572
+ though the request sent `Accept-Encoding: br, gzip`.
573
+
574
+ **When:** the server answers from `build/client`, and no `.br` or `.gz`
575
+ sits beside the file.
576
+
577
+ **Why:** the server never compresses on a request: it serves the copies
578
+ `react-router build` writes. They are missing when `alxia({ precompress:
579
+ false })` is set, when the build did not go through `alxia()` (a
580
+ `build/client` copied from a build before the option, or made by another
581
+ tool), when the file is under 1 kB or not compressible (an image, say), or
582
+ when `createServer({ precompressed: false })` is set. A compressed copy that
583
+ is not smaller than the file is not written.
584
+
585
+ A single-page app (`ssr: false` in `react-router.config.ts`) has no alxia server: the plugin builds the service worker only and writes no copies, so whatever serves `build/client` has to compress it.
586
+
587
+ **Fix:** build with the plugin, and check the copies exist:
588
+
589
+ ```sh
590
+ bun run build && ls build/client/assets | grep -E '\.(br|gz)$'
591
+ curl -sI -H 'Accept-Encoding: br' http://localhost:3000/assets/entry.js | grep -i content-encoding
592
+ ```
593
+
568
594
  ### `Refused to execute inline script because it violates the following Content Security Policy directive: "default-src 'none'"`
569
595
 
570
596
  The browser's console prints it; the page renders on the server, then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alxia/react-router",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "alxia as the server of a React Router framework app: server rendering behind the app's hooks, loaders reading its typed context, the client's assets served; the code with no UI an installable app shares (`/pwa`), its hooks (`/pwa/react`), `noCache` for the worker's script (`/pwa/server`), the service worker on Workbox (`/pwa/worker`) and its build (`/pwa/build`), an API's refusals worded for the page (`/errors`), the BFF session: cookies, sign-in, step-up and mail links (`/session`), its page hooks (`/session/react`) and what it shares with the page (`/session/model`), a GraphQL subscription relayed to the browser over SSE (`/subscription`), the page's CSP nonce and inline boot scripts (`/document`) and a streaming `entry.server` (`/entry`)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -135,10 +135,10 @@
135
135
  ]
136
136
  },
137
137
  "devDependencies": {
138
- "@alxia/compress": "^0.3.11",
139
- "@alxia/core": "^0.16.0",
140
- "@alxia/openapi": "^0.6.11",
141
- "@nxgt/graphql-client": "^0.4.0",
138
+ "@alxia/compress": "^0.3.12",
139
+ "@alxia/core": "^0.17.0",
140
+ "@alxia/openapi": "^0.6.12",
141
+ "@nxgt/graphql-client": "^0.5.0",
142
142
  "@nxgt/janus": "^0.29.0",
143
143
  "@react-router/dev": "^8.5.0",
144
144
  "@types/bun": "^1.4.4",
@@ -161,7 +161,7 @@
161
161
  "zod": "^4.2.0"
162
162
  },
163
163
  "peerDependencies": {
164
- "@alxia/core": "^0.16.0",
164
+ "@alxia/core": "^0.17.0",
165
165
  "isbot": "^5.0.0",
166
166
  "react": "^19.0.0",
167
167
  "react-dom": "^19.0.0",