@blacklizard/inertia-express 1.0.0 → 1.1.1
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 +28 -0
- package/dist/express/index.d.ts +44 -1
- package/dist/express/index.d.ts.map +1 -1
- package/dist/express/index.js +73 -1
- package/dist/express/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -360,6 +360,34 @@ inertia({
|
|
|
360
360
|
|
|
361
361
|
`watchMtime: false` reads once on boot — slightly faster but requires a process restart to pick up new builds.
|
|
362
362
|
|
|
363
|
+
### Asset URLs for the root view
|
|
364
|
+
|
|
365
|
+
`viteManifestAssets` resolves the CSS and JS web URLs for a single manifest entry so the root view can stamp `<link>` and `<script>` tags without re-implementing manifest parsing. Same mtime caching as `viteManifestVersion`.
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
import { encodePageScript, viteManifestAssets } from "@blacklizard/inertia-express";
|
|
369
|
+
|
|
370
|
+
const resolveAssets = viteManifestAssets({
|
|
371
|
+
manifestPath: "public/build/.vite/manifest.json",
|
|
372
|
+
entry: "src/app.ts",
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
inertia({
|
|
376
|
+
rootView: async ({ page }) => {
|
|
377
|
+
const { css, js } = await resolveAssets();
|
|
378
|
+
return `<!doctype html>
|
|
379
|
+
<html><head>${css ? `<link rel="stylesheet" href="${css}">` : ""}</head>
|
|
380
|
+
<body>
|
|
381
|
+
<div id="app"></div>
|
|
382
|
+
<script data-page="app" type="application/json">${encodePageScript(page)}</script>
|
|
383
|
+
${js ? `<script type="module" src="${js}"></script>` : ""}
|
|
384
|
+
</body></html>`;
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Returns `{ css: null, js: null }` when the manifest is missing, unparseable, or the entry key is absent — the root view stays renderable while assets are still being built. CSS is the first entry from the `css[]` array; if your entry emits multiple CSS files and you need them all, read the manifest yourself.
|
|
390
|
+
|
|
363
391
|
## Prerender / static export
|
|
364
392
|
|
|
365
393
|
Two output modes (combinable):
|
package/dist/express/index.d.ts
CHANGED
|
@@ -468,6 +468,33 @@ interface ViteManifestVersionOptions {
|
|
|
468
468
|
*/
|
|
469
469
|
watchMtime?: boolean;
|
|
470
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* Inputs to {@link viteManifestAssets}.
|
|
473
|
+
*/
|
|
474
|
+
interface ViteManifestAssetsOptions {
|
|
475
|
+
/** Path to `manifest.json`. */
|
|
476
|
+
manifestPath: string;
|
|
477
|
+
/**
|
|
478
|
+
* Manifest key for the entry to resolve. Typically the source path of
|
|
479
|
+
* the client entry, e.g. `src/app.ts` or `src/main.tsx`.
|
|
480
|
+
*/
|
|
481
|
+
entry: string;
|
|
482
|
+
/**
|
|
483
|
+
* If `true` (default), the manifest is re-read on every call when its
|
|
484
|
+
* mtime has advanced. Set to `false` to read once on boot.
|
|
485
|
+
*/
|
|
486
|
+
watchMtime?: boolean;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Resolved asset URLs for a single Vite manifest entry. URLs are web paths
|
|
490
|
+
* with a leading `/`, ready to drop into the HTML shell.
|
|
491
|
+
*/
|
|
492
|
+
interface ViteManifestAssets {
|
|
493
|
+
/** First CSS file declared by the entry, or `null` when absent. */
|
|
494
|
+
css: string | null;
|
|
495
|
+
/** Compiled JS file for the entry, or `null` when absent. */
|
|
496
|
+
js: string | null;
|
|
497
|
+
}
|
|
471
498
|
/**
|
|
472
499
|
* Build a stable asset version from a Vite-generated `manifest.json`.
|
|
473
500
|
*
|
|
@@ -490,6 +517,22 @@ interface ViteManifestVersionOptions {
|
|
|
490
517
|
* @param options Path to the manifest plus the mtime-watch flag.
|
|
491
518
|
*/
|
|
492
519
|
declare function viteManifestVersion(options: ViteManifestVersionOptions): () => Promise<string | null>;
|
|
520
|
+
/**
|
|
521
|
+
* Resolve the asset URLs (`css`, `js`) for a single Vite manifest entry.
|
|
522
|
+
*
|
|
523
|
+
* Reads the manifest produced by `vite build --manifest` (or
|
|
524
|
+
* `@inertiajs/vite-plugin`), locates the entry by manifest key, and
|
|
525
|
+
* returns its compiled JS file plus the first declared CSS file as web
|
|
526
|
+
* paths suitable to drop into the HTML shell's `<link>` and `<script>`
|
|
527
|
+
* tags. Caches by mtime the same way as {@link viteManifestVersion}.
|
|
528
|
+
*
|
|
529
|
+
* Returns `{ css: null, js: null }` when the manifest is missing,
|
|
530
|
+
* unparseable, or the entry key is absent — the root view stays
|
|
531
|
+
* renderable while assets are still being built.
|
|
532
|
+
*
|
|
533
|
+
* @param options Path to the manifest, entry key, and the mtime-watch flag.
|
|
534
|
+
*/
|
|
535
|
+
declare function viteManifestAssets(options: ViteManifestAssetsOptions): () => Promise<ViteManifestAssets>;
|
|
493
536
|
//#endregion
|
|
494
|
-
export { type AlwaysProp, type ComputeCacheKeyInput, type DeepMergeProp, type DeferredProp, type EdgeCacheDecision, type EdgeCachePolicy, INERTIA_HEADERS, INERTIA_LOCATION_STATUS, INERTIA_REDIRECT_STATUS, type InertiaCacheOptions, type InertiaMiddlewareOptions, type InertiaPage, type InertiaRequestInfo, type InertiaResponseOptions, type InertiaSsrFetcherOptions, type LazyProp, type MemoryCacheStoreOptions, type MergeProp, type OptionalProp, type PageProps, type PrerenderOptions, type PrerenderRouteResult, type PrerenderSummary, type RootViewInput, type RootViewRenderer, type SharedPropsInput, type SsrCacheEntry, type SsrCacheStore, type SsrRenderer, type SsrRendererInput, type SsrResult, type ValidationErrors, type VersionResolver, type ViteManifestVersionOptions, always, applyEdgeCache, canonicalStringify, computeSsrCacheKey, createInertiaSsrFetcher, createMemoryCacheStore, deepMerge, inertia as default, inertia, defer, encodePageScript, lazy, merge, optional, prerender, sendInertiaLocation, sendInertiaResponse, sendVersionMismatch, viteManifestVersion };
|
|
537
|
+
export { type AlwaysProp, type ComputeCacheKeyInput, type DeepMergeProp, type DeferredProp, type EdgeCacheDecision, type EdgeCachePolicy, INERTIA_HEADERS, INERTIA_LOCATION_STATUS, INERTIA_REDIRECT_STATUS, type InertiaCacheOptions, type InertiaMiddlewareOptions, type InertiaPage, type InertiaRequestInfo, type InertiaResponseOptions, type InertiaSsrFetcherOptions, type LazyProp, type MemoryCacheStoreOptions, type MergeProp, type OptionalProp, type PageProps, type PrerenderOptions, type PrerenderRouteResult, type PrerenderSummary, type RootViewInput, type RootViewRenderer, type SharedPropsInput, type SsrCacheEntry, type SsrCacheStore, type SsrRenderer, type SsrRendererInput, type SsrResult, type ValidationErrors, type VersionResolver, type ViteManifestAssets, type ViteManifestAssetsOptions, type ViteManifestVersionOptions, always, applyEdgeCache, canonicalStringify, computeSsrCacheKey, createInertiaSsrFetcher, createMemoryCacheStore, deepMerge, inertia as default, inertia, defer, encodePageScript, lazy, merge, optional, prerender, sendInertiaLocation, sendInertiaResponse, sendVersionMismatch, viteManifestAssets, viteManifestVersion };
|
|
495
538
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/express/edge-cache.ts","../../src/express/types.ts","../../src/express/middleware.ts","../../src/express/memory-store.ts","../../src/express/prerender.ts","../../src/express/response.ts","../../src/express/ssr-fetcher.ts","../../src/express/vite-manifest.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/express/edge-cache.ts","../../src/express/types.ts","../../src/express/middleware.ts","../../src/express/memory-store.ts","../../src/express/prerender.ts","../../src/express/response.ts","../../src/express/ssr-fetcher.ts","../../src/express/vite-manifest.ts"],"mappings":"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"}
|
package/dist/express/index.js
CHANGED
|
@@ -777,6 +777,10 @@ function createInertiaSsrFetcher(options) {
|
|
|
777
777
|
}
|
|
778
778
|
//#endregion
|
|
779
779
|
//#region src/express/vite-manifest.ts
|
|
780
|
+
const EMPTY_ASSETS = {
|
|
781
|
+
css: null,
|
|
782
|
+
js: null
|
|
783
|
+
};
|
|
780
784
|
/**
|
|
781
785
|
* Build a stable asset version from a Vite-generated `manifest.json`.
|
|
782
786
|
*
|
|
@@ -839,6 +843,74 @@ function viteManifestVersion(options) {
|
|
|
839
843
|
}
|
|
840
844
|
return read;
|
|
841
845
|
}
|
|
846
|
+
/**
|
|
847
|
+
* Web-path normalize a manifest-relative file string. Adds a leading `/`
|
|
848
|
+
* and collapses any pre-existing leading slashes so the result is always
|
|
849
|
+
* a single-rooted absolute web path.
|
|
850
|
+
*
|
|
851
|
+
* @param file Manifest-relative file string.
|
|
852
|
+
*/
|
|
853
|
+
function toWebPath(file) {
|
|
854
|
+
return `/${file.replace(/^\/+/, "")}`;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Resolve the asset URLs (`css`, `js`) for a single Vite manifest entry.
|
|
858
|
+
*
|
|
859
|
+
* Reads the manifest produced by `vite build --manifest` (or
|
|
860
|
+
* `@inertiajs/vite-plugin`), locates the entry by manifest key, and
|
|
861
|
+
* returns its compiled JS file plus the first declared CSS file as web
|
|
862
|
+
* paths suitable to drop into the HTML shell's `<link>` and `<script>`
|
|
863
|
+
* tags. Caches by mtime the same way as {@link viteManifestVersion}.
|
|
864
|
+
*
|
|
865
|
+
* Returns `{ css: null, js: null }` when the manifest is missing,
|
|
866
|
+
* unparseable, or the entry key is absent — the root view stays
|
|
867
|
+
* renderable while assets are still being built.
|
|
868
|
+
*
|
|
869
|
+
* @param options Path to the manifest, entry key, and the mtime-watch flag.
|
|
870
|
+
*/
|
|
871
|
+
function viteManifestAssets(options) {
|
|
872
|
+
const watchMtime = options.watchMtime ?? true;
|
|
873
|
+
let cached = null;
|
|
874
|
+
/**
|
|
875
|
+
* Resolve to the current asset URLs, or `{ css: null, js: null }` when
|
|
876
|
+
* the manifest can't be read, parsed, or the entry is missing.
|
|
877
|
+
*/
|
|
878
|
+
async function read() {
|
|
879
|
+
let mtimeMs;
|
|
880
|
+
try {
|
|
881
|
+
mtimeMs = (await stat(options.manifestPath)).mtimeMs;
|
|
882
|
+
} catch {
|
|
883
|
+
return EMPTY_ASSETS;
|
|
884
|
+
}
|
|
885
|
+
if (cached && (!watchMtime || cached.mtimeMs === mtimeMs)) return cached.assets;
|
|
886
|
+
let raw;
|
|
887
|
+
try {
|
|
888
|
+
raw = await readFile(options.manifestPath, "utf8");
|
|
889
|
+
} catch {
|
|
890
|
+
return EMPTY_ASSETS;
|
|
891
|
+
}
|
|
892
|
+
let parsed;
|
|
893
|
+
try {
|
|
894
|
+
parsed = JSON.parse(raw);
|
|
895
|
+
} catch {
|
|
896
|
+
return EMPTY_ASSETS;
|
|
897
|
+
}
|
|
898
|
+
const entry = parsed[options.entry];
|
|
899
|
+
if (!entry || typeof entry !== "object") return EMPTY_ASSETS;
|
|
900
|
+
const { file, css: cssList } = entry;
|
|
901
|
+
const firstCss = Array.isArray(cssList) && typeof cssList[0] === "string" ? cssList[0] : null;
|
|
902
|
+
const assets = {
|
|
903
|
+
css: firstCss !== null ? toWebPath(firstCss) : null,
|
|
904
|
+
js: typeof file === "string" ? toWebPath(file) : null
|
|
905
|
+
};
|
|
906
|
+
cached = {
|
|
907
|
+
mtimeMs,
|
|
908
|
+
assets
|
|
909
|
+
};
|
|
910
|
+
return assets;
|
|
911
|
+
}
|
|
912
|
+
return read;
|
|
913
|
+
}
|
|
842
914
|
//#endregion
|
|
843
915
|
//#region src/express/index.ts
|
|
844
916
|
/**
|
|
@@ -849,6 +921,6 @@ function viteManifestVersion(options) {
|
|
|
849
921
|
*/
|
|
850
922
|
var express_default = inertia;
|
|
851
923
|
//#endregion
|
|
852
|
-
export { INERTIA_HEADERS, INERTIA_LOCATION_STATUS, INERTIA_REDIRECT_STATUS, always, applyEdgeCache, canonicalStringify, computeSsrCacheKey, createInertiaSsrFetcher, createMemoryCacheStore, deepMerge, express_default as default, defer, encodePageScript, inertia, lazy, merge, optional, prerender, sendInertiaLocation, sendInertiaResponse, sendVersionMismatch, viteManifestVersion };
|
|
924
|
+
export { INERTIA_HEADERS, INERTIA_LOCATION_STATUS, INERTIA_REDIRECT_STATUS, always, applyEdgeCache, canonicalStringify, computeSsrCacheKey, createInertiaSsrFetcher, createMemoryCacheStore, deepMerge, express_default as default, defer, encodePageScript, inertia, lazy, merge, optional, prerender, sendInertiaLocation, sendInertiaResponse, sendVersionMismatch, viteManifestAssets, viteManifestVersion };
|
|
853
925
|
|
|
854
926
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/express/edge-cache.ts","../../src/express/response.ts","../../src/express/middleware.ts","../../src/express/memory-store.ts","../../src/express/prerender.ts","../../src/express/ssr-fetcher.ts","../../src/express/vite-manifest.ts","../../src/express/index.ts"],"sourcesContent":["import type { Request, Response } from 'express';\n\nimport type { InertiaPage } from '../core/index.js';\n\n/**\n * Decision returned by an `edgeCache` policy. Returning `null` (or a\n * negative number) opts out of edge caching — no `Cache-Control` is set\n * beyond what your handler set itself.\n */\nexport interface EdgeCacheDecision {\n /** `s-maxage` value for shared/CDN caches, in seconds. */\n sMaxAge: number;\n /** `max-age` for the browser cache. Default 0 (revalidate immediately). */\n maxAge?: number;\n /**\n * `stale-while-revalidate` window. Lets CDNs serve a slightly stale\n * response while fetching a fresh one in the background.\n */\n staleWhileRevalidate?: number;\n /**\n * Additional `Vary` values. The middleware always emits `Vary: Accept,\n * X-Inertia` — this lets you append more (e.g. `Cookie`, `Accept-Language`).\n */\n vary?: string[];\n}\n\n/**\n * Per-response edge-cache decision: receives the request, response, and\n * resolved page, returns an {@link EdgeCacheDecision} or `null` to opt out.\n */\nexport type EdgeCachePolicy = (input: { req: Request; res: Response; page: InertiaPage }) => EdgeCacheDecision | null;\n\n/**\n * Apply an edge-cache decision to the response. Called automatically by\n * the middleware when an `edgeCache` policy is configured. Exported so\n * you can call it from custom code paths too.\n *\n * No-op when `decision` is `null`, when `sMaxAge <= 0`, or when the response\n * is 3xx+ (4xx/5xx must not be cached at the edge). The middleware also skips\n * Inertia XHR responses before calling this — that filter lives at the call\n * site, not here, since `applyEdgeCache` only sees the decision + status.\n *\n * `Vary` values from the decision are merged into the existing header,\n * de-duplicated by trimmed string.\n *\n * @param decision Policy output (or `null` to opt out).\n * @param res Outgoing Express response (mutated: sets `Cache-Control`, `Vary`).\n */\nexport function applyEdgeCache(decision: EdgeCacheDecision | null, res: Response): void {\n if (decision === null || decision.sMaxAge <= 0) {\n return;\n }\n\n if (res.statusCode >= 300) {\n return;\n }\n\n const parts: string[] = ['public', `s-maxage=${decision.sMaxAge}`, `max-age=${decision.maxAge ?? 0}`];\n\n if (decision.staleWhileRevalidate && decision.staleWhileRevalidate > 0) {\n parts.push(`stale-while-revalidate=${decision.staleWhileRevalidate}`);\n }\n\n res.setHeader('Cache-Control', parts.join(', '));\n\n if (decision.vary && decision.vary.length > 0) {\n const existing = res.getHeader('Vary');\n const all = new Set<string>();\n\n if (typeof existing === 'string') {\n existing.split(',').forEach((v) => all.add(v.trim()));\n }\n\n decision.vary.forEach((v) => {\n const trimmed = v.trim();\n\n if (trimmed) {\n all.add(trimmed);\n }\n });\n\n res.setHeader('Vary', Array.from(all).join(', '));\n }\n}\n","import {\n buildPage,\n computeSsrCacheKey,\n encodePageScript,\n INERTIA_HEADERS,\n INERTIA_LOCATION_STATUS,\n isVersionMismatch,\n parseInertiaRequest,\n renderDefaultHtml,\n resolveVersion,\n} from '../core';\nimport { applyEdgeCache } from './edge-cache.js';\n\nimport type { Request, Response } from 'express';\n\nimport type {\n InertiaPage, InertiaRequestInfo, PageProps, SharedPropsInput, SsrCacheEntry,\n} from '../core';\nimport type {\n InertiaCacheOptions, InertiaMiddlewareOptions, InertiaResponseOptions, SsrResult,\n} from './types.js';\n\ninterface RenderContext {\n options: InertiaMiddlewareOptions;\n}\n\n/**\n * Resolve the shared-props input for a request. When `flashFromSession` is\n * enabled, session-stored validation errors and flash data are merged in\n * automatically (read-once — they are cleared after being read). Explicit\n * `sharedProps` keys win on collision.\n *\n * @param ctx Render context carrying the middleware options.\n * @param res Express response, scanned for `res.locals.inertiaErrors` as a\n * fallback when no session is wired.\n */\nfunction composeSharedProps(ctx: RenderContext, res: Response): SharedPropsInput<Request> {\n const base = ctx.options.sharedProps;\n\n if (!ctx.options.flashFromSession) {\n return base ?? {};\n }\n\n return async (req: Request): Promise<PageProps> => {\n let baseProps: PageProps = {};\n\n if (base) {\n baseProps = typeof base === 'function' ? ((await base(req)) ?? {}) : base;\n }\n\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n const errors = (session?.errors as PageProps | undefined)\n ?? (res.locals.inertiaErrors as PageProps | undefined)\n ?? {};\n const flash = session?.flash ?? null;\n\n if (session) {\n // Flash data is read-once: clear it so it does not leak into later visits.\n session.errors = undefined;\n session.flash = undefined;\n }\n\n return { errors, flash, ...baseProps };\n };\n}\n\n/**\n * Send the Inertia version-mismatch response: 409 with `X-Inertia-Location`\n * pointing back at the same URL so the client performs a hard reload.\n *\n * @param res Outgoing Express response.\n * @param url Location to send the client to (typically the requested URL).\n */\nexport function sendVersionMismatch(res: Response, url: string): void {\n res.status(INERTIA_LOCATION_STATUS).setHeader(INERTIA_HEADERS.location, url).end();\n}\n\n/**\n * Send an external Inertia redirect. For Inertia (XHR) requests this returns\n * 409 + `X-Inertia-Location` so the client performs a window.location nav.\n * For plain browser requests it falls back to a normal 302 redirect.\n *\n * @param req Incoming Express request; `req.inertia` is reused when present.\n * @param res Outgoing Express response.\n * @param target Destination URL.\n */\nexport function sendInertiaLocation(req: Request, res: Response, target: string): void {\n const info = req.inertia\n ?? parseInertiaRequest({\n headers: req.headers,\n method: req.method,\n url: req.originalUrl ?? req.url,\n });\n\n if (info.isInertia) {\n res.status(INERTIA_LOCATION_STATUS).setHeader(INERTIA_HEADERS.location, target).end();\n\n return;\n }\n\n res.redirect(302, target);\n}\n\n/**\n * Merge `Accept` and `X-Inertia` into an existing `Vary` header value,\n * deduplicating case-insensitively so the header never accumulates repeats\n * when the middleware and the response both contribute tokens.\n *\n * @param existing Current header value as Node returns it (string, number,\n * string[], or undefined).\n */\nfunction mergeVary(existing: string | number | string[] | undefined): string {\n const tokens: string[] = [];\n const seen = new Set<string>();\n\n const add = (token: string): void => {\n const trimmed = token.trim();\n const key = trimmed.toLowerCase();\n\n if (trimmed && !seen.has(key)) {\n seen.add(key);\n tokens.push(trimmed);\n }\n };\n\n if (existing !== undefined) {\n String(existing).split(',').forEach((part) => add(part));\n }\n\n add('Accept');\n add('X-Inertia');\n\n return tokens.join(', ');\n}\n\n/**\n * Coerce SSR head output (string, string[], or absent) to a single string\n * suitable for injection into the document `<head>`.\n *\n * @param head Head fragment(s) from the SSR renderer.\n */\nfunction flattenSsrHead(head: string | string[] | undefined): string | undefined {\n if (head === undefined) {\n return undefined;\n }\n\n if (Array.isArray(head)) {\n return head.join('');\n }\n\n return head;\n}\n\n/**\n * Default rule deciding whether a rendered page is safe to cache. Cacheable\n * iff the request is a non-Inertia GET and the page carries no flash\n * messages or validation errors (those are per-visit state).\n *\n * @param input Express request and the resolved page object.\n */\nfunction defaultCacheVary(input: { req: Request; page: InertiaPage }): boolean {\n const { req, page } = input;\n\n if (req.method !== 'GET') {\n return false;\n }\n\n // Inertia XHR (JSON) responses vary per visit — caching them at the view\n // layer would serve stale partial reloads to the wrong client.\n if (req.inertia?.isInertia) {\n return false;\n }\n\n const props = page.props as Record<string, unknown>;\n\n if (props && typeof props === 'object') {\n const flash = props.flash as Record<string, unknown> | undefined;\n\n if (flash && Object.keys(flash).length > 0) {\n return false;\n }\n\n const errors = props.errors as Record<string, unknown> | undefined;\n\n if (errors && Object.keys(errors).length > 0) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Wrap `cache.store.get` so a thrown store error is reported via `onError`\n * and reported as a miss instead of bubbling out to the request handler.\n *\n * @param cache Resolved cache options.\n * @param key Cache key.\n */\nasync function safeCacheGet(cache: InertiaCacheOptions, key: string): Promise<SsrCacheEntry | null> {\n try {\n return await cache.store.get(key);\n } catch (err) {\n cache.onError?.('get', err);\n\n return null;\n }\n}\n\n/**\n * Wrap `cache.store.set` so a thrown store error is reported via `onError`\n * but never propagates — cache writes are fire-and-forget.\n *\n * @param cache Resolved cache options.\n * @param key Cache key.\n * @param entry Value to store.\n * @param ttl Time-to-live in seconds.\n */\nasync function safeCacheSet(cache: InertiaCacheOptions, key: string, entry: SsrCacheEntry, ttl: number): Promise<void> {\n try {\n await cache.store.set(key, entry, ttl);\n } catch (err) {\n cache.onError?.('set', err);\n }\n}\n\n/**\n * Render the final HTML body. When an SSR result is available, expose it via\n * `res.locals.ssr` so a custom `rootView` can read it, then either call\n * `rootView` or fall back to {@link renderDefaultHtml}.\n *\n * @param ctx Render context carrying the middleware options.\n * @param page Resolved page object.\n * @param ssrResult SSR renderer output, or `null` when SSR is skipped.\n * @param req Incoming request.\n * @param res Outgoing response.\n */\nasync function renderRootViewWithSsr(\n ctx: RenderContext,\n page: InertiaPage,\n ssrResult: SsrResult | null,\n req: Request,\n res: Response,\n): Promise<string> {\n if (ssrResult) {\n res.locals.ssr = ssrResult;\n\n if (ctx.options.rootView) {\n return ctx.options.rootView({ page, req, res });\n }\n\n return renderDefaultHtml({\n page,\n head: flattenSsrHead(ssrResult.head),\n ssrBody: ssrResult.bodyIsFullRoot ? undefined : ssrResult.body,\n ssrFull: ssrResult.bodyIsFullRoot ? ssrResult.body : undefined,\n });\n }\n\n if (ctx.options.rootView) {\n return ctx.options.rootView({ page, req, res });\n }\n\n return renderDefaultHtml({ page });\n}\n\n/**\n * Apply the configured `edgeCache` policy unless this is an Inertia XHR\n * response (those vary per visit and must not be cached at the edge).\n *\n * @param ctx Render context carrying the middleware options.\n * @param page Resolved page object.\n * @param req Incoming request.\n * @param res Outgoing response.\n */\nfunction maybeApplyEdgeCache(ctx: RenderContext, page: InertiaPage, req: Request, res: Response): void {\n if (!ctx.options.edgeCache) {\n return;\n }\n\n if (req.inertia?.isInertia) {\n return;\n }\n\n const decision = ctx.options.edgeCache({ req, res, page });\n applyEdgeCache(decision, res);\n}\n\n/**\n * Build and send an Inertia response. Handles version-mismatch detection,\n * partial-reload filtering, JSON vs HTML, SSR, view caching, and edge\n * cache headers. The status code already on `res` (e.g. `res.status(404)`)\n * is preserved on both the JSON and HTML branches.\n *\n * @param req Incoming Express request.\n * @param res Outgoing Express response.\n * @param ctx Render context carrying the middleware options.\n * @param component Inertia component name to render.\n * @param props Page-specific props (merged with shared props).\n * @param options Optional per-response overrides (url, clearHistory, encryptHistory).\n */\nexport async function sendInertiaResponse(\n req: Request,\n res: Response,\n ctx: RenderContext,\n component: string,\n props: PageProps,\n options: InertiaResponseOptions = {},\n): Promise<void> {\n const info: InertiaRequestInfo = req.inertia\n ?? parseInertiaRequest({\n headers: req.headers,\n method: req.method,\n url: options.url ?? req.originalUrl ?? req.url,\n });\n\n const url = options.url ?? info.url;\n const version = await resolveVersion(ctx.options.version, req);\n\n if (info.isInertia && info.method === 'GET' && isVersionMismatch(version, info.version)) {\n sendVersionMismatch(res, url);\n\n return;\n }\n\n const page = await buildPage<Request>({\n component,\n props,\n request: { ...info, url },\n req,\n shared: composeSharedProps(ctx, res),\n version,\n options: {\n clearHistory: options.clearHistory,\n encryptHistory: options.encryptHistory,\n },\n });\n\n res.setHeader('Vary', mergeVary(res.getHeader('Vary')));\n\n if (info.isInertia) {\n res\n .status(res.statusCode)\n .setHeader('Content-Type', 'application/json; charset=utf-8')\n .setHeader(INERTIA_HEADERS.inertia, 'true');\n res.send(JSON.stringify(page));\n\n return;\n }\n\n // HTML branch — SSR + cache.\n const { cache } = ctx.options;\n const cacheVary = cache?.vary ?? defaultCacheVary;\n const cacheable = cache !== undefined && cacheVary({ req, page });\n let cacheKey: string | null = null;\n\n if (cacheable && cache) {\n cacheKey = computeSsrCacheKey({\n prefix: cache.keyPrefix ?? 'inertia:ssr',\n version,\n component,\n props: page.props,\n discriminator: cache.discriminator?.(req),\n });\n const hit = await safeCacheGet(cache, cacheKey);\n\n if (hit) {\n res.setHeader('X-Inertia-Cache', 'HIT');\n const html = await renderRootViewWithSsr(\n ctx,\n hit.page,\n {\n head: hit.head,\n body: hit.body,\n bodyIsFullRoot: hit.bodyIsFullRoot,\n },\n req,\n res,\n );\n maybeApplyEdgeCache(ctx, hit.page, req, res);\n res.status(res.statusCode).setHeader('Content-Type', 'text/html; charset=utf-8').send(html);\n\n return;\n }\n\n res.setHeader('X-Inertia-Cache', 'MISS');\n }\n\n let ssrResult: SsrResult | null = null;\n\n if (ctx.options.ssr) {\n ssrResult = await ctx.options.ssr({ page, req, res });\n }\n\n const html = await renderRootViewWithSsr(ctx, page, ssrResult, req, res);\n\n if (cacheable && cache && cacheKey && ssrResult) {\n const entry: SsrCacheEntry = {\n head: ssrResult.head ?? '',\n body: ssrResult.body,\n bodyIsFullRoot: ssrResult.bodyIsFullRoot,\n storedAt: new Date().toISOString(),\n page,\n };\n // Fire-and-forget — safeCacheSet swallows its own errors.\n safeCacheSet(cache, cacheKey, entry, cache.ttlSeconds ?? 300).catch(() => {});\n }\n\n maybeApplyEdgeCache(ctx, page, req, res);\n res.status(res.statusCode).setHeader('Content-Type', 'text/html; charset=utf-8').send(html);\n}\n\nexport { encodePageScript };\n","import { format } from 'node:util';\n\nimport { sendInertiaLocation, sendInertiaResponse } from './response.js';\nimport { inertiaRedirectStatus, parseInertiaRequest, scopeErrors } from '../core/index.js';\n\nimport type { NextFunction, Request, Response } from 'express';\n\nimport type { InertiaMiddlewareOptions, InertiaResponseOptions } from './types.js';\nimport type { PageProps, ValidationErrors } from '../core/index.js';\n\n/**\n * Build the `connect-flash`-compatible `req.flash()` method for a request.\n * Provided so this package is a drop-in replacement for `connect-flash`: the\n * returned function matches its semantics exactly — a setter call appends to\n * a per-type bucket in `req.session.flash` and returns the new bucket length,\n * a getter call reads and clears. Throws when no session is wired, just like\n * `connect-flash`.\n *\n * @param req Express request whose `session` holds the flash buckets.\n */\nfunction createFlash(req: Request): Request['flash'] {\n return ((type?: string, msg?: unknown, ...rest: unknown[]): number | string[] | Record<string, string[]> => {\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n\n if (session === undefined) {\n throw new Error('req.flash() requires sessions');\n }\n\n const msgs = (session.flash as Record<string, string[]> | undefined) ?? {};\n session.flash = msgs;\n\n // Setter: `req.flash(type, msg)` appends and returns the new count.\n if (type && msg) {\n let bucket = msgs[type];\n\n if (bucket === undefined) {\n bucket = [];\n msgs[type] = bucket;\n }\n\n if (rest.length > 0) {\n // util.format interpolation: req.flash('info', 'Hello %s', name).\n return bucket.push(format(msg, ...rest));\n }\n\n if (Array.isArray(msg)) {\n msg.forEach((val) => bucket.push(val as string));\n\n return bucket.length;\n }\n\n return bucket.push(msg as string);\n }\n\n // Getter: `req.flash(type)` returns and clears that one bucket.\n if (type) {\n const arr = msgs[type] ?? [];\n delete msgs[type];\n\n return arr;\n }\n\n // Getter: `req.flash()` returns and clears every bucket.\n session.flash = {};\n\n return msgs;\n }) as Request['flash'];\n}\n\n/**\n * Create the Inertia.js Express middleware.\n *\n * The middleware:\n * - Parses Inertia headers into `req.inertia`.\n * - Adds `req.flash(type?, msg?)` — a `connect-flash`-compatible API.\n * - Adds `res.inertia(component, props, options)`.\n * - Adds `res.inertiaLocation(url)` for external redirects.\n * - Adds `res.inertiaErrors(errors, bag?)` to flash validation errors.\n * - Adds `res.inertiaFlash(data)` to flash arbitrary data.\n * - Auto-promotes redirects after PUT/PATCH/DELETE to 303 for Inertia visits.\n *\n * Mount before your route handlers:\n *\n * ```ts\n * app.use(inertia({ rootView: ..., sharedProps: ... }));\n * ```\n *\n * @param options Middleware configuration; defaults to an empty object.\n */\nexport function inertia(options: InertiaMiddlewareOptions = {}) {\n const ctx = { options };\n\n return function inertiaMiddleware(req: Request, res: Response, next: NextFunction): void {\n const info = parseInertiaRequest({\n headers: req.headers,\n method: req.method,\n url: req.originalUrl ?? req.url,\n });\n req.inertia = info;\n\n // req.flash() — connect-flash compatible. See createFlash above.\n req.flash = createFlash(req);\n\n // res.inertia() — the main render helper.\n res.inertia = async (\n component: string,\n props: PageProps = {},\n opts: InertiaResponseOptions = {},\n ): Promise<void> => {\n try {\n await sendInertiaResponse(req, res, ctx, component, props, opts);\n } catch (err) {\n next(err);\n }\n };\n\n // res.inertiaLocation() — external redirect.\n res.inertiaLocation = (url: string): void => {\n sendInertiaLocation(req, res, url);\n };\n\n // res.inertiaErrors() — stash validation errors for the next request.\n // No-ops gracefully when no session is configured.\n res.inertiaErrors = (errors: ValidationErrors, bag?: string): void => {\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n const scoped = scopeErrors(errors, bag ?? null);\n\n if (session) {\n const existing = (session.errors as PageProps | undefined) ?? {};\n session.errors = { ...existing, ...(scoped.errors as PageProps) };\n } else {\n // Without a session, expose them on res.locals so a custom shared-prop\n // resolver can pick them up for the same response.\n res.locals.inertiaErrors = scoped.errors;\n }\n };\n\n // res.inertiaFlash() — stash flash data for the next request.\n // No-ops gracefully when no session is configured.\n res.inertiaFlash = (data: Record<string, unknown>): void => {\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n\n if (session) {\n session.flash = data;\n }\n };\n\n // Promote redirects after PUT/PATCH/DELETE to 303 so the follow-up GET\n // is correctly issued by every browser.\n if (info.isInertia) {\n const originalRedirect = res.redirect.bind(res);\n // Express's `res.redirect` signature is either (url) or (status, url) —\n // handle both. The deprecated (url, status) form was removed in v5.\n res.redirect = ((arg1: number | string, arg2?: string | number) => {\n let status: number;\n let url: string;\n\n if (typeof arg1 === 'number') {\n status = arg1;\n url = String(arg2);\n } else {\n status = inertiaRedirectStatus(req.method, 302);\n url = arg1;\n }\n\n // If the user explicitly passed a 302 from a non-GET, bump to 303.\n if (status === 302 && (req.method === 'PUT' || req.method === 'PATCH' || req.method === 'DELETE')) {\n status = 303;\n }\n\n originalRedirect(status, url);\n });\n }\n\n // Make sure CDNs / shared caches don't mix Inertia JSON and HTML variants.\n const existingVary = res.getHeader('Vary');\n\n if (!existingVary) {\n res.setHeader('Vary', 'Accept, X-Inertia');\n }\n\n next();\n };\n}\n\nexport default inertia;\n","import type { SsrCacheEntry, SsrCacheStore } from '../core/index.js';\n\n/**\n * In-process LRU + TTL cache for SSR responses.\n *\n * Suitable as L1 cache in front of Redis (`@blacklizard/inertia-cache-redis`)\n * or by itself for low-traffic / single-instance deployments.\n *\n * Notes:\n * - Bounded by entry count (`max`), not bytes. Keep it conservative.\n * - TTL is enforced lazily on `get()` — expired entries are removed at\n * read time and never returned.\n * - Not safe across processes. For multi-pod web tiers, layer Redis on top.\n */\nexport interface MemoryCacheStoreOptions {\n /** Maximum number of entries before LRU eviction kicks in. Default 500. */\n max?: number;\n}\n\ninterface Slot {\n entry: SsrCacheEntry;\n expiresAt: number;\n}\n\n/**\n * Build an in-process LRU + TTL {@link SsrCacheStore}. See\n * {@link MemoryCacheStoreOptions} for the full contract.\n *\n * @param options Store configuration; defaults applied when omitted.\n */\nexport function createMemoryCacheStore(options: MemoryCacheStoreOptions = {}): SsrCacheStore {\n const max = options.max ?? 500;\n const map = new Map<string, Slot>();\n\n /**\n * Drop oldest-inserted entries until `map.size <= max`. Relies on `Map`'s\n * insertion-order iteration to identify the LRU entry.\n */\n function evict(): void {\n while (map.size > max) {\n const oldest = map.keys().next().value;\n\n if (oldest === undefined) {\n return;\n }\n\n map.delete(oldest);\n }\n }\n\n return {\n /**\n * Return the cached entry or `null` on miss / expired. Touched entries\n * are reinserted so they become the most-recently-used.\n *\n * @param key Cache key.\n */\n async get(key) {\n const slot = map.get(key);\n\n if (!slot) {\n return null;\n }\n\n if (slot.expiresAt < Date.now()) {\n map.delete(key);\n\n return null;\n }\n\n // LRU bump: re-insert to move to end of insertion order.\n map.delete(key);\n map.set(key, slot);\n\n return slot.entry;\n },\n /**\n * Write an entry with the given TTL, replacing any prior value. Runs LRU\n * eviction afterward so `max` is never exceeded.\n *\n * @param key Cache key.\n * @param entry Value to store.\n * @param ttlSeconds Time-to-live in seconds.\n */\n async set(key, entry, ttlSeconds) {\n const expiresAt = Date.now() + ttlSeconds * 1000;\n map.delete(key);\n map.set(key, { entry, expiresAt });\n evict();\n },\n /**\n * Remove an entry. Idempotent — missing keys are silently ignored.\n *\n * @param key Cache key.\n */\n async delete(key) {\n map.delete(key);\n },\n };\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\n/**\n * Inputs to {@link prerender}.\n */\nexport interface PrerenderOptions {\n /** Origin to fetch from, e.g. `http://127.0.0.1:3000`. */\n baseUrl: string;\n /** List of paths to render. Each must start with `/`. */\n routes: string[];\n /** Output mode. Default `\"warmup\"`. */\n mode?: 'static' | 'warmup' | 'both';\n /** Output directory for static HTML. Required when mode includes `\"static\"`. */\n outDir?: string;\n /** Concurrency limit. Default 4. */\n concurrency?: number;\n /** Per-request timeout, ms. Default 30000. */\n timeoutMs?: number;\n /** Extra request headers (auth, host override, A/B bucket pinning, etc.). */\n headers?: Record<string, string>;\n /** Optional fetch override (for testing). */\n fetch?: typeof fetch;\n}\n\n/**\n * Per-route outcome from a prerender run. `status` is `null` and `error` is\n * populated when the request failed before producing a response.\n */\nexport interface PrerenderRouteResult {\n route: string;\n status: number | null;\n bytes: number;\n outputPath?: string;\n error?: string;\n durationMs: number;\n}\n\n/**\n * Aggregate result returned by {@link prerender}. `ok + failed === total`;\n * a route counts as `ok` when it returned a 2xx/3xx status and no error.\n */\nexport interface PrerenderSummary {\n total: number;\n ok: number;\n failed: number;\n results: PrerenderRouteResult[];\n}\n\n/**\n * Map an HTTP route to an on-disk static-output path. `/` maps to\n * `<outDir>/index.html`; `/foo/bar` to `<outDir>/foo/bar/index.html`.\n * Query strings are stripped before computing the path — reverse proxies\n * (nginx, Caddy, CloudFront) split the URL at `?` when looking up static\n * files, so embedding the query string in a directory name produces a path\n * that can never be served.\n *\n * @param outDir Static-output root.\n * @param route HTTP path (with optional query string) being prerendered.\n */\nfunction routeToFile(outDir: string, route: string): string {\n // Extract path-only; discard query string and fragment.\n const { pathname } = new URL(route, 'http://x');\n const trimmed = pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n\n if (!trimmed) {\n return join(outDir, 'index.html');\n }\n\n return join(outDir, trimmed, 'index.html');\n}\n\n/**\n * Write the rendered HTML to disk when the mode includes static output.\n * Returns the file path written, or `undefined` for warmup-only modes.\n * Throws when static output is requested without an `outDir`.\n *\n * @param options Shared prerender options — `outDir` lives here.\n * @param route HTTP path being rendered; mapped to the on-disk path.\n * @param html Rendered response body to write.\n * @param mode Resolved output mode for this run.\n */\nasync function maybeWriteStatic(\n options: PrerenderOptions,\n route: string,\n html: string,\n mode: 'static' | 'warmup' | 'both',\n): Promise<string | undefined> {\n if (mode !== 'static' && mode !== 'both') {\n return undefined;\n }\n\n if (!options.outDir) {\n throw new Error(`outDir is required when mode is \"${mode}\"`);\n }\n\n const outputPath = routeToFile(options.outDir, route);\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, html, 'utf8');\n\n return outputPath;\n}\n\n/**\n * Fetch a single route, optionally write its body to disk, and return a\n * {@link PrerenderRouteResult}. Never throws — failures are returned with\n * `status: null` and an `error` message so the calling loop keeps going.\n *\n * @param options Shared prerender options (baseUrl, mode, outDir, etc.).\n * @param route HTTP path to render.\n */\nasync function runOne(options: PrerenderOptions, route: string): Promise<PrerenderRouteResult> {\n const fetchImpl = options.fetch ?? fetch;\n const mode = options.mode ?? 'warmup';\n const start = Date.now();\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), options.timeoutMs ?? 30000);\n\n try {\n const url = new URL(route, options.baseUrl).toString();\n const res = await fetchImpl(url, {\n method: 'GET',\n headers: { Accept: 'text/html', ...options.headers },\n signal: ctrl.signal,\n });\n const html = await res.text();\n const outputPath = await maybeWriteStatic(options, route, html, mode);\n\n return {\n route,\n status: res.status,\n bytes: Buffer.byteLength(html),\n outputPath,\n durationMs: Date.now() - start,\n };\n } catch (err) {\n return {\n route,\n status: null,\n bytes: 0,\n error: (err as Error).message,\n durationMs: Date.now() - start,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Run the prerender pipeline. Programmatic entry-point for the\n * `bin/inertia-prerender` CLI.\n *\n * Two output modes (which can be combined via `\"both\"`):\n *\n * - **`warmup`** (default) — fetches each route, discards the body. Use to\n * populate the SSR view cache after a deploy so the first real visitor\n * doesn't pay the SSR latency cost.\n * - **`static`** — fetches each route and writes the response body to\n * `<outDir>/<route>/index.html`. Serve those files directly via\n * nginx/CDN, bypassing Express entirely.\n *\n * Bounded-concurrency: `concurrency` workers consume routes from a shared\n * counter; the returned `results` preserve input order. Failures on\n * individual routes never halt the run — the per-route summary lets a CI\n * step choose to fail-loud.\n *\n * @param options Pipeline configuration — see {@link PrerenderOptions}.\n */\nexport async function prerender(options: PrerenderOptions): Promise<PrerenderSummary> {\n const concurrency = Math.max(1, options.concurrency ?? 4);\n const results: PrerenderRouteResult[] = new Array(options.routes.length);\n let next = 0;\n\n /**\n * Claim the next route index and process it, then recurse. Recursion\n * (instead of a loop) avoids both `while`-spin and `no-await-in-loop`.\n */\n async function worker(): Promise<void> {\n const i = next;\n next += 1;\n\n if (i >= options.routes.length) {\n return;\n }\n\n const route = options.routes[i] ?? '';\n results[i] = await runOne(options, route);\n await worker();\n }\n\n await Promise.all(Array.from({ length: Math.min(concurrency, options.routes.length) }, async () => worker()));\n\n const ok = results.filter((r) => r && r.status !== null && r.status < 400 && !r.error).length;\n const failed = results.length - ok;\n\n return {\n total: results.length, ok, failed, results,\n };\n}\n","import type { SsrRenderer, SsrResult } from './types.js';\nimport type { InertiaPage } from '../core/index.js';\n\n/**\n * Inputs to {@link createInertiaSsrFetcher}.\n */\nexport interface InertiaSsrFetcherOptions {\n /** SSR endpoint URL — typically your internal LB DNS, e.g. `http://ssr.internal/render`. */\n url: string;\n /** Per-attempt timeout in milliseconds. Default 5000. */\n timeoutMs?: number;\n /** Number of retry attempts after the first failure. Default 2 (so up to 3 total tries). */\n retries?: number;\n /** Initial backoff in ms; doubles per retry. Default 100. */\n retryBaseMs?: number;\n /**\n * Circuit breaker: open after this many consecutive failures.\n * Set to `0` (or `Infinity`) to disable. Default 5.\n */\n breakerThreshold?: number;\n /** How long the breaker stays open before allowing one probe. Default 30000. */\n breakerCooldownMs?: number;\n /** Failure mode. Default `\"client\"`. */\n fallback?: 'client' | 'throw';\n /** Override fetch implementation (testing). */\n fetch?: typeof fetch;\n /** Extra headers sent with each render request. */\n headers?: Record<string, string>;\n}\n\nconst EMPTY_RESULT: SsrResult = { body: '', head: '' };\n\ninterface BreakerState {\n failures: number;\n openedAt: number | null;\n}\n\n/**\n * Resolve after the given number of milliseconds.\n *\n * @param ms Delay in milliseconds.\n */\nasync function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\n/**\n * Build an {@link SsrRenderer} that POSTs the page object to a separate Node\n * SSR process (or load-balanced pool) and returns the rendered\n * `{ head, body }`.\n *\n * Matches the wire protocol used by `@inertiajs/{vue3,react,svelte}/server`\n * `createServer()`: `POST <url>` with `application/json` body containing the\n * page object, response is `{ head: string[], body: string }`.\n *\n * Adds production hardening on top of the bare protocol:\n * - Per-attempt timeout (default 5000ms) via `AbortController`.\n * - Recursive retry with exponential backoff (`retryBaseMs * 2^attempt`).\n * - Circuit breaker — opens after `breakerThreshold` consecutive failed\n * *requests* (not attempts); half-opens after `breakerCooldownMs` so a\n * probe request can re-close it on success.\n * - `fallback`: `\"client\"` returns an empty SSR result so the client\n * renders alone; `\"throw\"` rethrows so Express's error handler can react.\n *\n * @param options Fetcher configuration — see {@link InertiaSsrFetcherOptions}.\n */\nexport function createInertiaSsrFetcher(options: InertiaSsrFetcherOptions): SsrRenderer {\n const fetchImpl = options.fetch ?? fetch;\n const timeoutMs = options.timeoutMs ?? 5000;\n const retries = options.retries ?? 2;\n const retryBaseMs = options.retryBaseMs ?? 100;\n const breakerThreshold = options.breakerThreshold ?? 5;\n const breakerCooldownMs = options.breakerCooldownMs ?? 30000;\n const fallback = options.fallback ?? 'client';\n const breakerEnabled = breakerThreshold > 0 && Number.isFinite(breakerThreshold);\n\n const state: BreakerState = { failures: 0, openedAt: null };\n\n /**\n * Returns `true` while the breaker is open and within its cooldown window;\n * a return of `false` after a previous failure means we are half-open and\n * the caller may attempt a probe request.\n */\n function breakerOpen(): boolean {\n if (!breakerEnabled || state.openedAt === null) {\n return false;\n }\n\n if (Date.now() - state.openedAt >= breakerCooldownMs) {\n // Half-open: let the next request probe.\n return false;\n }\n\n return true;\n }\n\n /**\n * Reset the breaker after a successful render.\n */\n function recordSuccess(): void {\n state.failures = 0;\n state.openedAt = null;\n }\n\n /**\n * Increment the failure counter; open the breaker when the threshold is hit.\n */\n function recordFailure(): void {\n state.failures += 1;\n\n if (breakerEnabled && state.failures >= breakerThreshold) {\n state.openedAt = Date.now();\n }\n }\n\n /**\n * Fire one SSR request — the unit the retry loop wraps. Throws on\n * timeout, network error, or non-2xx response.\n *\n * @param page Page object to send to the SSR server.\n */\n async function attempt(page: InertiaPage): Promise<SsrResult> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const res = await fetchImpl(options.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n body: JSON.stringify(page),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n throw new Error(`Inertia SSR request failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as Partial<SsrResult>;\n\n return {\n body: json.body ?? '',\n head: json.head,\n bodyIsFullRoot: json.bodyIsFullRoot,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n return async ({ page }: { page: InertiaPage }): Promise<SsrResult> => {\n if (breakerOpen()) {\n if (fallback === 'throw') {\n throw new Error('Inertia SSR circuit breaker is open');\n }\n\n return EMPTY_RESULT;\n }\n\n /**\n * Run one render attempt, recursing with exponential backoff until the\n * retry budget is spent. Records breaker success on the first win.\n *\n * @param remaining Retry attempts left before the error propagates.\n */\n const attemptWithRetry = async (remaining: number): Promise<SsrResult> => {\n try {\n const result = await attempt(page);\n recordSuccess();\n\n return result;\n } catch (err) {\n if (remaining <= 0) {\n throw err;\n }\n\n await sleep(retryBaseMs * 2 ** (retries - remaining));\n\n return attemptWithRetry(remaining - 1);\n }\n };\n\n try {\n return await attemptWithRetry(retries);\n } catch (lastError) {\n recordFailure();\n\n if (fallback === 'throw') {\n throw lastError;\n }\n\n return EMPTY_RESULT;\n }\n };\n}\n","import { createHash } from 'node:crypto';\nimport { readFile, stat } from 'node:fs/promises';\n\n/**\n * Inputs to {@link viteManifestVersion}.\n */\nexport interface ViteManifestVersionOptions {\n /** Path to `manifest.json`. */\n manifestPath: string;\n /**\n * If `true` (default), the manifest is re-read on every call when its\n * mtime has advanced. Set to `false` to read once on boot — slightly\n * faster but requires a process restart to pick up new builds.\n */\n watchMtime?: boolean;\n}\n\ninterface CacheEntry {\n mtimeMs: number;\n version: string;\n}\n\n/**\n * Build a stable asset version from a Vite-generated `manifest.json`.\n *\n * Compatible with both `@inertiajs/vite-plugin` output and the standard\n * `--manifest` option from `vite build`. The returned function is suitable\n * to pass directly as the `version` option of the Inertia middleware.\n *\n * Strategy:\n * - Read the manifest file.\n * - Hash a canonicalized list of `(key -> file)` entries (only the `file`\n * field per entry, so unrelated manifest metadata never perturbs the hash).\n * - Cache the result; re-read only after the file's mtime changes (when\n * `watchMtime` is true) or never re-read (when false).\n * - Returns `null` when the manifest file is absent or unparseable.\n *\n * A new manifest (different hashed output paths) yields a new version, which\n * the middleware embeds in the SSR cache key — so a deploy atomically\n * invalidates every existing cache entry.\n *\n * @param options Path to the manifest plus the mtime-watch flag.\n */\nexport function viteManifestVersion(options: ViteManifestVersionOptions): () => Promise<string | null> {\n const watchMtime = options.watchMtime ?? true;\n let cached: CacheEntry | null = null;\n\n /**\n * Resolve to the current version string, or `null` when the manifest can't\n * be read or parsed. Hits the in-memory cache when the mtime is unchanged.\n */\n async function read(): Promise<string | null> {\n let mtimeMs: number;\n\n try {\n const s = await stat(options.manifestPath);\n mtimeMs = s.mtimeMs;\n } catch {\n return null;\n }\n\n if (cached && (!watchMtime || cached.mtimeMs === mtimeMs)) {\n return cached.version;\n }\n\n let raw: string;\n\n try {\n raw = await readFile(options.manifestPath, 'utf8');\n } catch {\n return null;\n }\n\n let parsed: Record<string, unknown>;\n\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n\n // Canonical input: keys sorted, value extracts the `file` property when\n // the entry is a Vite manifest object (so unrelated metadata doesn't\n // perturb the hash).\n const lines: string[] = Object.keys(parsed)\n .sort()\n .map((key) => {\n const entry = parsed[key];\n\n if (entry && typeof entry === 'object' && 'file' in entry) {\n return `${key}=${(entry as { file: string }).file}`;\n }\n\n return `${key}=${JSON.stringify(entry)}`;\n });\n\n const version = createHash('sha256').update(lines.join('\\n')).digest('hex').slice(0, 16);\n\n cached = { mtimeMs, version };\n\n return version;\n }\n\n return read;\n}\n","/**\n * Express adapter for Inertia.js v3.\n *\n * Default entry point of `@blacklizard/inertia-express`. The framework-agnostic\n * core is available at `@blacklizard/inertia-express/core`.\n */\n\nimport { inertia } from './middleware.js';\n\nexport type {\n AlwaysProp,\n ComputeCacheKeyInput,\n DeepMergeProp,\n DeferredProp,\n InertiaPage,\n InertiaRequestInfo,\n LazyProp,\n MergeProp,\n OptionalProp,\n PageProps,\n SharedPropsInput,\n SsrCacheEntry,\n SsrCacheStore,\n ValidationErrors,\n VersionResolver,\n} from '../core/index.js';\n// Re-export the most commonly used core helpers so users only need a single\n// import path for typical apps.\nexport {\n always,\n canonicalStringify,\n computeSsrCacheKey,\n deepMerge,\n defer,\n INERTIA_HEADERS,\n INERTIA_LOCATION_STATUS,\n INERTIA_REDIRECT_STATUS,\n lazy,\n merge,\n optional,\n} from '../core/index.js';\nexport type { EdgeCacheDecision, EdgeCachePolicy } from './edge-cache.js';\nexport { applyEdgeCache } from './edge-cache.js';\nexport type { MemoryCacheStoreOptions } from './memory-store.js';\nexport { createMemoryCacheStore } from './memory-store.js';\nexport { inertia };\nexport default inertia;\nexport type {\n PrerenderOptions,\n PrerenderRouteResult,\n PrerenderSummary,\n} from './prerender.js';\nexport { prerender } from './prerender.js';\nexport {\n encodePageScript,\n sendInertiaLocation,\n sendInertiaResponse,\n sendVersionMismatch,\n} from './response.js';\nexport type { InertiaSsrFetcherOptions } from './ssr-fetcher.js';\nexport { createInertiaSsrFetcher } from './ssr-fetcher.js';\nexport type {\n InertiaCacheOptions,\n InertiaMiddlewareOptions,\n InertiaResponseOptions,\n RootViewInput,\n RootViewRenderer,\n SsrRenderer,\n SsrRendererInput,\n SsrResult,\n} from './types.js';\nexport type { ViteManifestVersionOptions } from './vite-manifest.js';\nexport { viteManifestVersion } from './vite-manifest.js';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/express/edge-cache.ts","../../src/express/response.ts","../../src/express/middleware.ts","../../src/express/memory-store.ts","../../src/express/prerender.ts","../../src/express/ssr-fetcher.ts","../../src/express/vite-manifest.ts","../../src/express/index.ts"],"sourcesContent":["import type { Request, Response } from 'express';\n\nimport type { InertiaPage } from '../core/index.js';\n\n/**\n * Decision returned by an `edgeCache` policy. Returning `null` (or a\n * negative number) opts out of edge caching — no `Cache-Control` is set\n * beyond what your handler set itself.\n */\nexport interface EdgeCacheDecision {\n /** `s-maxage` value for shared/CDN caches, in seconds. */\n sMaxAge: number;\n /** `max-age` for the browser cache. Default 0 (revalidate immediately). */\n maxAge?: number;\n /**\n * `stale-while-revalidate` window. Lets CDNs serve a slightly stale\n * response while fetching a fresh one in the background.\n */\n staleWhileRevalidate?: number;\n /**\n * Additional `Vary` values. The middleware always emits `Vary: Accept,\n * X-Inertia` — this lets you append more (e.g. `Cookie`, `Accept-Language`).\n */\n vary?: string[];\n}\n\n/**\n * Per-response edge-cache decision: receives the request, response, and\n * resolved page, returns an {@link EdgeCacheDecision} or `null` to opt out.\n */\nexport type EdgeCachePolicy = (input: { req: Request; res: Response; page: InertiaPage }) => EdgeCacheDecision | null;\n\n/**\n * Apply an edge-cache decision to the response. Called automatically by\n * the middleware when an `edgeCache` policy is configured. Exported so\n * you can call it from custom code paths too.\n *\n * No-op when `decision` is `null`, when `sMaxAge <= 0`, or when the response\n * is 3xx+ (4xx/5xx must not be cached at the edge). The middleware also skips\n * Inertia XHR responses before calling this — that filter lives at the call\n * site, not here, since `applyEdgeCache` only sees the decision + status.\n *\n * `Vary` values from the decision are merged into the existing header,\n * de-duplicated by trimmed string.\n *\n * @param decision Policy output (or `null` to opt out).\n * @param res Outgoing Express response (mutated: sets `Cache-Control`, `Vary`).\n */\nexport function applyEdgeCache(decision: EdgeCacheDecision | null, res: Response): void {\n if (decision === null || decision.sMaxAge <= 0) {\n return;\n }\n\n if (res.statusCode >= 300) {\n return;\n }\n\n const parts: string[] = ['public', `s-maxage=${decision.sMaxAge}`, `max-age=${decision.maxAge ?? 0}`];\n\n if (decision.staleWhileRevalidate && decision.staleWhileRevalidate > 0) {\n parts.push(`stale-while-revalidate=${decision.staleWhileRevalidate}`);\n }\n\n res.setHeader('Cache-Control', parts.join(', '));\n\n if (decision.vary && decision.vary.length > 0) {\n const existing = res.getHeader('Vary');\n const all = new Set<string>();\n\n if (typeof existing === 'string') {\n existing.split(',').forEach((v) => all.add(v.trim()));\n }\n\n decision.vary.forEach((v) => {\n const trimmed = v.trim();\n\n if (trimmed) {\n all.add(trimmed);\n }\n });\n\n res.setHeader('Vary', Array.from(all).join(', '));\n }\n}\n","import {\n buildPage,\n computeSsrCacheKey,\n encodePageScript,\n INERTIA_HEADERS,\n INERTIA_LOCATION_STATUS,\n isVersionMismatch,\n parseInertiaRequest,\n renderDefaultHtml,\n resolveVersion,\n} from '../core';\nimport { applyEdgeCache } from './edge-cache.js';\n\nimport type { Request, Response } from 'express';\n\nimport type {\n InertiaPage, InertiaRequestInfo, PageProps, SharedPropsInput, SsrCacheEntry,\n} from '../core';\nimport type {\n InertiaCacheOptions, InertiaMiddlewareOptions, InertiaResponseOptions, SsrResult,\n} from './types.js';\n\ninterface RenderContext {\n options: InertiaMiddlewareOptions;\n}\n\n/**\n * Resolve the shared-props input for a request. When `flashFromSession` is\n * enabled, session-stored validation errors and flash data are merged in\n * automatically (read-once — they are cleared after being read). Explicit\n * `sharedProps` keys win on collision.\n *\n * @param ctx Render context carrying the middleware options.\n * @param res Express response, scanned for `res.locals.inertiaErrors` as a\n * fallback when no session is wired.\n */\nfunction composeSharedProps(ctx: RenderContext, res: Response): SharedPropsInput<Request> {\n const base = ctx.options.sharedProps;\n\n if (!ctx.options.flashFromSession) {\n return base ?? {};\n }\n\n return async (req: Request): Promise<PageProps> => {\n let baseProps: PageProps = {};\n\n if (base) {\n baseProps = typeof base === 'function' ? ((await base(req)) ?? {}) : base;\n }\n\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n const errors = (session?.errors as PageProps | undefined)\n ?? (res.locals.inertiaErrors as PageProps | undefined)\n ?? {};\n const flash = session?.flash ?? null;\n\n if (session) {\n // Flash data is read-once: clear it so it does not leak into later visits.\n session.errors = undefined;\n session.flash = undefined;\n }\n\n return { errors, flash, ...baseProps };\n };\n}\n\n/**\n * Send the Inertia version-mismatch response: 409 with `X-Inertia-Location`\n * pointing back at the same URL so the client performs a hard reload.\n *\n * @param res Outgoing Express response.\n * @param url Location to send the client to (typically the requested URL).\n */\nexport function sendVersionMismatch(res: Response, url: string): void {\n res.status(INERTIA_LOCATION_STATUS).setHeader(INERTIA_HEADERS.location, url).end();\n}\n\n/**\n * Send an external Inertia redirect. For Inertia (XHR) requests this returns\n * 409 + `X-Inertia-Location` so the client performs a window.location nav.\n * For plain browser requests it falls back to a normal 302 redirect.\n *\n * @param req Incoming Express request; `req.inertia` is reused when present.\n * @param res Outgoing Express response.\n * @param target Destination URL.\n */\nexport function sendInertiaLocation(req: Request, res: Response, target: string): void {\n const info = req.inertia\n ?? parseInertiaRequest({\n headers: req.headers,\n method: req.method,\n url: req.originalUrl ?? req.url,\n });\n\n if (info.isInertia) {\n res.status(INERTIA_LOCATION_STATUS).setHeader(INERTIA_HEADERS.location, target).end();\n\n return;\n }\n\n res.redirect(302, target);\n}\n\n/**\n * Merge `Accept` and `X-Inertia` into an existing `Vary` header value,\n * deduplicating case-insensitively so the header never accumulates repeats\n * when the middleware and the response both contribute tokens.\n *\n * @param existing Current header value as Node returns it (string, number,\n * string[], or undefined).\n */\nfunction mergeVary(existing: string | number | string[] | undefined): string {\n const tokens: string[] = [];\n const seen = new Set<string>();\n\n const add = (token: string): void => {\n const trimmed = token.trim();\n const key = trimmed.toLowerCase();\n\n if (trimmed && !seen.has(key)) {\n seen.add(key);\n tokens.push(trimmed);\n }\n };\n\n if (existing !== undefined) {\n String(existing).split(',').forEach((part) => add(part));\n }\n\n add('Accept');\n add('X-Inertia');\n\n return tokens.join(', ');\n}\n\n/**\n * Coerce SSR head output (string, string[], or absent) to a single string\n * suitable for injection into the document `<head>`.\n *\n * @param head Head fragment(s) from the SSR renderer.\n */\nfunction flattenSsrHead(head: string | string[] | undefined): string | undefined {\n if (head === undefined) {\n return undefined;\n }\n\n if (Array.isArray(head)) {\n return head.join('');\n }\n\n return head;\n}\n\n/**\n * Default rule deciding whether a rendered page is safe to cache. Cacheable\n * iff the request is a non-Inertia GET and the page carries no flash\n * messages or validation errors (those are per-visit state).\n *\n * @param input Express request and the resolved page object.\n */\nfunction defaultCacheVary(input: { req: Request; page: InertiaPage }): boolean {\n const { req, page } = input;\n\n if (req.method !== 'GET') {\n return false;\n }\n\n // Inertia XHR (JSON) responses vary per visit — caching them at the view\n // layer would serve stale partial reloads to the wrong client.\n if (req.inertia?.isInertia) {\n return false;\n }\n\n const props = page.props as Record<string, unknown>;\n\n if (props && typeof props === 'object') {\n const flash = props.flash as Record<string, unknown> | undefined;\n\n if (flash && Object.keys(flash).length > 0) {\n return false;\n }\n\n const errors = props.errors as Record<string, unknown> | undefined;\n\n if (errors && Object.keys(errors).length > 0) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Wrap `cache.store.get` so a thrown store error is reported via `onError`\n * and reported as a miss instead of bubbling out to the request handler.\n *\n * @param cache Resolved cache options.\n * @param key Cache key.\n */\nasync function safeCacheGet(cache: InertiaCacheOptions, key: string): Promise<SsrCacheEntry | null> {\n try {\n return await cache.store.get(key);\n } catch (err) {\n cache.onError?.('get', err);\n\n return null;\n }\n}\n\n/**\n * Wrap `cache.store.set` so a thrown store error is reported via `onError`\n * but never propagates — cache writes are fire-and-forget.\n *\n * @param cache Resolved cache options.\n * @param key Cache key.\n * @param entry Value to store.\n * @param ttl Time-to-live in seconds.\n */\nasync function safeCacheSet(cache: InertiaCacheOptions, key: string, entry: SsrCacheEntry, ttl: number): Promise<void> {\n try {\n await cache.store.set(key, entry, ttl);\n } catch (err) {\n cache.onError?.('set', err);\n }\n}\n\n/**\n * Render the final HTML body. When an SSR result is available, expose it via\n * `res.locals.ssr` so a custom `rootView` can read it, then either call\n * `rootView` or fall back to {@link renderDefaultHtml}.\n *\n * @param ctx Render context carrying the middleware options.\n * @param page Resolved page object.\n * @param ssrResult SSR renderer output, or `null` when SSR is skipped.\n * @param req Incoming request.\n * @param res Outgoing response.\n */\nasync function renderRootViewWithSsr(\n ctx: RenderContext,\n page: InertiaPage,\n ssrResult: SsrResult | null,\n req: Request,\n res: Response,\n): Promise<string> {\n if (ssrResult) {\n res.locals.ssr = ssrResult;\n\n if (ctx.options.rootView) {\n return ctx.options.rootView({ page, req, res });\n }\n\n return renderDefaultHtml({\n page,\n head: flattenSsrHead(ssrResult.head),\n ssrBody: ssrResult.bodyIsFullRoot ? undefined : ssrResult.body,\n ssrFull: ssrResult.bodyIsFullRoot ? ssrResult.body : undefined,\n });\n }\n\n if (ctx.options.rootView) {\n return ctx.options.rootView({ page, req, res });\n }\n\n return renderDefaultHtml({ page });\n}\n\n/**\n * Apply the configured `edgeCache` policy unless this is an Inertia XHR\n * response (those vary per visit and must not be cached at the edge).\n *\n * @param ctx Render context carrying the middleware options.\n * @param page Resolved page object.\n * @param req Incoming request.\n * @param res Outgoing response.\n */\nfunction maybeApplyEdgeCache(ctx: RenderContext, page: InertiaPage, req: Request, res: Response): void {\n if (!ctx.options.edgeCache) {\n return;\n }\n\n if (req.inertia?.isInertia) {\n return;\n }\n\n const decision = ctx.options.edgeCache({ req, res, page });\n applyEdgeCache(decision, res);\n}\n\n/**\n * Build and send an Inertia response. Handles version-mismatch detection,\n * partial-reload filtering, JSON vs HTML, SSR, view caching, and edge\n * cache headers. The status code already on `res` (e.g. `res.status(404)`)\n * is preserved on both the JSON and HTML branches.\n *\n * @param req Incoming Express request.\n * @param res Outgoing Express response.\n * @param ctx Render context carrying the middleware options.\n * @param component Inertia component name to render.\n * @param props Page-specific props (merged with shared props).\n * @param options Optional per-response overrides (url, clearHistory, encryptHistory).\n */\nexport async function sendInertiaResponse(\n req: Request,\n res: Response,\n ctx: RenderContext,\n component: string,\n props: PageProps,\n options: InertiaResponseOptions = {},\n): Promise<void> {\n const info: InertiaRequestInfo = req.inertia\n ?? parseInertiaRequest({\n headers: req.headers,\n method: req.method,\n url: options.url ?? req.originalUrl ?? req.url,\n });\n\n const url = options.url ?? info.url;\n const version = await resolveVersion(ctx.options.version, req);\n\n if (info.isInertia && info.method === 'GET' && isVersionMismatch(version, info.version)) {\n sendVersionMismatch(res, url);\n\n return;\n }\n\n const page = await buildPage<Request>({\n component,\n props,\n request: { ...info, url },\n req,\n shared: composeSharedProps(ctx, res),\n version,\n options: {\n clearHistory: options.clearHistory,\n encryptHistory: options.encryptHistory,\n },\n });\n\n res.setHeader('Vary', mergeVary(res.getHeader('Vary')));\n\n if (info.isInertia) {\n res\n .status(res.statusCode)\n .setHeader('Content-Type', 'application/json; charset=utf-8')\n .setHeader(INERTIA_HEADERS.inertia, 'true');\n res.send(JSON.stringify(page));\n\n return;\n }\n\n // HTML branch — SSR + cache.\n const { cache } = ctx.options;\n const cacheVary = cache?.vary ?? defaultCacheVary;\n const cacheable = cache !== undefined && cacheVary({ req, page });\n let cacheKey: string | null = null;\n\n if (cacheable && cache) {\n cacheKey = computeSsrCacheKey({\n prefix: cache.keyPrefix ?? 'inertia:ssr',\n version,\n component,\n props: page.props,\n discriminator: cache.discriminator?.(req),\n });\n const hit = await safeCacheGet(cache, cacheKey);\n\n if (hit) {\n res.setHeader('X-Inertia-Cache', 'HIT');\n const html = await renderRootViewWithSsr(\n ctx,\n hit.page,\n {\n head: hit.head,\n body: hit.body,\n bodyIsFullRoot: hit.bodyIsFullRoot,\n },\n req,\n res,\n );\n maybeApplyEdgeCache(ctx, hit.page, req, res);\n res.status(res.statusCode).setHeader('Content-Type', 'text/html; charset=utf-8').send(html);\n\n return;\n }\n\n res.setHeader('X-Inertia-Cache', 'MISS');\n }\n\n let ssrResult: SsrResult | null = null;\n\n if (ctx.options.ssr) {\n ssrResult = await ctx.options.ssr({ page, req, res });\n }\n\n const html = await renderRootViewWithSsr(ctx, page, ssrResult, req, res);\n\n if (cacheable && cache && cacheKey && ssrResult) {\n const entry: SsrCacheEntry = {\n head: ssrResult.head ?? '',\n body: ssrResult.body,\n bodyIsFullRoot: ssrResult.bodyIsFullRoot,\n storedAt: new Date().toISOString(),\n page,\n };\n // Fire-and-forget — safeCacheSet swallows its own errors.\n safeCacheSet(cache, cacheKey, entry, cache.ttlSeconds ?? 300).catch(() => {});\n }\n\n maybeApplyEdgeCache(ctx, page, req, res);\n res.status(res.statusCode).setHeader('Content-Type', 'text/html; charset=utf-8').send(html);\n}\n\nexport { encodePageScript };\n","import { format } from 'node:util';\n\nimport { sendInertiaLocation, sendInertiaResponse } from './response.js';\nimport { inertiaRedirectStatus, parseInertiaRequest, scopeErrors } from '../core/index.js';\n\nimport type { NextFunction, Request, Response } from 'express';\n\nimport type { InertiaMiddlewareOptions, InertiaResponseOptions } from './types.js';\nimport type { PageProps, ValidationErrors } from '../core/index.js';\n\n/**\n * Build the `connect-flash`-compatible `req.flash()` method for a request.\n * Provided so this package is a drop-in replacement for `connect-flash`: the\n * returned function matches its semantics exactly — a setter call appends to\n * a per-type bucket in `req.session.flash` and returns the new bucket length,\n * a getter call reads and clears. Throws when no session is wired, just like\n * `connect-flash`.\n *\n * @param req Express request whose `session` holds the flash buckets.\n */\nfunction createFlash(req: Request): Request['flash'] {\n return ((type?: string, msg?: unknown, ...rest: unknown[]): number | string[] | Record<string, string[]> => {\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n\n if (session === undefined) {\n throw new Error('req.flash() requires sessions');\n }\n\n const msgs = (session.flash as Record<string, string[]> | undefined) ?? {};\n session.flash = msgs;\n\n // Setter: `req.flash(type, msg)` appends and returns the new count.\n if (type && msg) {\n let bucket = msgs[type];\n\n if (bucket === undefined) {\n bucket = [];\n msgs[type] = bucket;\n }\n\n if (rest.length > 0) {\n // util.format interpolation: req.flash('info', 'Hello %s', name).\n return bucket.push(format(msg, ...rest));\n }\n\n if (Array.isArray(msg)) {\n msg.forEach((val) => bucket.push(val as string));\n\n return bucket.length;\n }\n\n return bucket.push(msg as string);\n }\n\n // Getter: `req.flash(type)` returns and clears that one bucket.\n if (type) {\n const arr = msgs[type] ?? [];\n delete msgs[type];\n\n return arr;\n }\n\n // Getter: `req.flash()` returns and clears every bucket.\n session.flash = {};\n\n return msgs;\n }) as Request['flash'];\n}\n\n/**\n * Create the Inertia.js Express middleware.\n *\n * The middleware:\n * - Parses Inertia headers into `req.inertia`.\n * - Adds `req.flash(type?, msg?)` — a `connect-flash`-compatible API.\n * - Adds `res.inertia(component, props, options)`.\n * - Adds `res.inertiaLocation(url)` for external redirects.\n * - Adds `res.inertiaErrors(errors, bag?)` to flash validation errors.\n * - Adds `res.inertiaFlash(data)` to flash arbitrary data.\n * - Auto-promotes redirects after PUT/PATCH/DELETE to 303 for Inertia visits.\n *\n * Mount before your route handlers:\n *\n * ```ts\n * app.use(inertia({ rootView: ..., sharedProps: ... }));\n * ```\n *\n * @param options Middleware configuration; defaults to an empty object.\n */\nexport function inertia(options: InertiaMiddlewareOptions = {}) {\n const ctx = { options };\n\n return function inertiaMiddleware(req: Request, res: Response, next: NextFunction): void {\n const info = parseInertiaRequest({\n headers: req.headers,\n method: req.method,\n url: req.originalUrl ?? req.url,\n });\n req.inertia = info;\n\n // req.flash() — connect-flash compatible. See createFlash above.\n req.flash = createFlash(req);\n\n // res.inertia() — the main render helper.\n res.inertia = async (\n component: string,\n props: PageProps = {},\n opts: InertiaResponseOptions = {},\n ): Promise<void> => {\n try {\n await sendInertiaResponse(req, res, ctx, component, props, opts);\n } catch (err) {\n next(err);\n }\n };\n\n // res.inertiaLocation() — external redirect.\n res.inertiaLocation = (url: string): void => {\n sendInertiaLocation(req, res, url);\n };\n\n // res.inertiaErrors() — stash validation errors for the next request.\n // No-ops gracefully when no session is configured.\n res.inertiaErrors = (errors: ValidationErrors, bag?: string): void => {\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n const scoped = scopeErrors(errors, bag ?? null);\n\n if (session) {\n const existing = (session.errors as PageProps | undefined) ?? {};\n session.errors = { ...existing, ...(scoped.errors as PageProps) };\n } else {\n // Without a session, expose them on res.locals so a custom shared-prop\n // resolver can pick them up for the same response.\n res.locals.inertiaErrors = scoped.errors;\n }\n };\n\n // res.inertiaFlash() — stash flash data for the next request.\n // No-ops gracefully when no session is configured.\n res.inertiaFlash = (data: Record<string, unknown>): void => {\n const { session } = (req as unknown as { session?: Record<string, unknown> });\n\n if (session) {\n session.flash = data;\n }\n };\n\n // Promote redirects after PUT/PATCH/DELETE to 303 so the follow-up GET\n // is correctly issued by every browser.\n if (info.isInertia) {\n const originalRedirect = res.redirect.bind(res);\n // Express's `res.redirect` signature is either (url) or (status, url) —\n // handle both. The deprecated (url, status) form was removed in v5.\n res.redirect = ((arg1: number | string, arg2?: string | number) => {\n let status: number;\n let url: string;\n\n if (typeof arg1 === 'number') {\n status = arg1;\n url = String(arg2);\n } else {\n status = inertiaRedirectStatus(req.method, 302);\n url = arg1;\n }\n\n // If the user explicitly passed a 302 from a non-GET, bump to 303.\n if (status === 302 && (req.method === 'PUT' || req.method === 'PATCH' || req.method === 'DELETE')) {\n status = 303;\n }\n\n originalRedirect(status, url);\n });\n }\n\n // Make sure CDNs / shared caches don't mix Inertia JSON and HTML variants.\n const existingVary = res.getHeader('Vary');\n\n if (!existingVary) {\n res.setHeader('Vary', 'Accept, X-Inertia');\n }\n\n next();\n };\n}\n\nexport default inertia;\n","import type { SsrCacheEntry, SsrCacheStore } from '../core/index.js';\n\n/**\n * In-process LRU + TTL cache for SSR responses.\n *\n * Suitable as L1 cache in front of Redis (`@blacklizard/inertia-cache-redis`)\n * or by itself for low-traffic / single-instance deployments.\n *\n * Notes:\n * - Bounded by entry count (`max`), not bytes. Keep it conservative.\n * - TTL is enforced lazily on `get()` — expired entries are removed at\n * read time and never returned.\n * - Not safe across processes. For multi-pod web tiers, layer Redis on top.\n */\nexport interface MemoryCacheStoreOptions {\n /** Maximum number of entries before LRU eviction kicks in. Default 500. */\n max?: number;\n}\n\ninterface Slot {\n entry: SsrCacheEntry;\n expiresAt: number;\n}\n\n/**\n * Build an in-process LRU + TTL {@link SsrCacheStore}. See\n * {@link MemoryCacheStoreOptions} for the full contract.\n *\n * @param options Store configuration; defaults applied when omitted.\n */\nexport function createMemoryCacheStore(options: MemoryCacheStoreOptions = {}): SsrCacheStore {\n const max = options.max ?? 500;\n const map = new Map<string, Slot>();\n\n /**\n * Drop oldest-inserted entries until `map.size <= max`. Relies on `Map`'s\n * insertion-order iteration to identify the LRU entry.\n */\n function evict(): void {\n while (map.size > max) {\n const oldest = map.keys().next().value;\n\n if (oldest === undefined) {\n return;\n }\n\n map.delete(oldest);\n }\n }\n\n return {\n /**\n * Return the cached entry or `null` on miss / expired. Touched entries\n * are reinserted so they become the most-recently-used.\n *\n * @param key Cache key.\n */\n async get(key) {\n const slot = map.get(key);\n\n if (!slot) {\n return null;\n }\n\n if (slot.expiresAt < Date.now()) {\n map.delete(key);\n\n return null;\n }\n\n // LRU bump: re-insert to move to end of insertion order.\n map.delete(key);\n map.set(key, slot);\n\n return slot.entry;\n },\n /**\n * Write an entry with the given TTL, replacing any prior value. Runs LRU\n * eviction afterward so `max` is never exceeded.\n *\n * @param key Cache key.\n * @param entry Value to store.\n * @param ttlSeconds Time-to-live in seconds.\n */\n async set(key, entry, ttlSeconds) {\n const expiresAt = Date.now() + ttlSeconds * 1000;\n map.delete(key);\n map.set(key, { entry, expiresAt });\n evict();\n },\n /**\n * Remove an entry. Idempotent — missing keys are silently ignored.\n *\n * @param key Cache key.\n */\n async delete(key) {\n map.delete(key);\n },\n };\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\n/**\n * Inputs to {@link prerender}.\n */\nexport interface PrerenderOptions {\n /** Origin to fetch from, e.g. `http://127.0.0.1:3000`. */\n baseUrl: string;\n /** List of paths to render. Each must start with `/`. */\n routes: string[];\n /** Output mode. Default `\"warmup\"`. */\n mode?: 'static' | 'warmup' | 'both';\n /** Output directory for static HTML. Required when mode includes `\"static\"`. */\n outDir?: string;\n /** Concurrency limit. Default 4. */\n concurrency?: number;\n /** Per-request timeout, ms. Default 30000. */\n timeoutMs?: number;\n /** Extra request headers (auth, host override, A/B bucket pinning, etc.). */\n headers?: Record<string, string>;\n /** Optional fetch override (for testing). */\n fetch?: typeof fetch;\n}\n\n/**\n * Per-route outcome from a prerender run. `status` is `null` and `error` is\n * populated when the request failed before producing a response.\n */\nexport interface PrerenderRouteResult {\n route: string;\n status: number | null;\n bytes: number;\n outputPath?: string;\n error?: string;\n durationMs: number;\n}\n\n/**\n * Aggregate result returned by {@link prerender}. `ok + failed === total`;\n * a route counts as `ok` when it returned a 2xx/3xx status and no error.\n */\nexport interface PrerenderSummary {\n total: number;\n ok: number;\n failed: number;\n results: PrerenderRouteResult[];\n}\n\n/**\n * Map an HTTP route to an on-disk static-output path. `/` maps to\n * `<outDir>/index.html`; `/foo/bar` to `<outDir>/foo/bar/index.html`.\n * Query strings are stripped before computing the path — reverse proxies\n * (nginx, Caddy, CloudFront) split the URL at `?` when looking up static\n * files, so embedding the query string in a directory name produces a path\n * that can never be served.\n *\n * @param outDir Static-output root.\n * @param route HTTP path (with optional query string) being prerendered.\n */\nfunction routeToFile(outDir: string, route: string): string {\n // Extract path-only; discard query string and fragment.\n const { pathname } = new URL(route, 'http://x');\n const trimmed = pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n\n if (!trimmed) {\n return join(outDir, 'index.html');\n }\n\n return join(outDir, trimmed, 'index.html');\n}\n\n/**\n * Write the rendered HTML to disk when the mode includes static output.\n * Returns the file path written, or `undefined` for warmup-only modes.\n * Throws when static output is requested without an `outDir`.\n *\n * @param options Shared prerender options — `outDir` lives here.\n * @param route HTTP path being rendered; mapped to the on-disk path.\n * @param html Rendered response body to write.\n * @param mode Resolved output mode for this run.\n */\nasync function maybeWriteStatic(\n options: PrerenderOptions,\n route: string,\n html: string,\n mode: 'static' | 'warmup' | 'both',\n): Promise<string | undefined> {\n if (mode !== 'static' && mode !== 'both') {\n return undefined;\n }\n\n if (!options.outDir) {\n throw new Error(`outDir is required when mode is \"${mode}\"`);\n }\n\n const outputPath = routeToFile(options.outDir, route);\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, html, 'utf8');\n\n return outputPath;\n}\n\n/**\n * Fetch a single route, optionally write its body to disk, and return a\n * {@link PrerenderRouteResult}. Never throws — failures are returned with\n * `status: null` and an `error` message so the calling loop keeps going.\n *\n * @param options Shared prerender options (baseUrl, mode, outDir, etc.).\n * @param route HTTP path to render.\n */\nasync function runOne(options: PrerenderOptions, route: string): Promise<PrerenderRouteResult> {\n const fetchImpl = options.fetch ?? fetch;\n const mode = options.mode ?? 'warmup';\n const start = Date.now();\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), options.timeoutMs ?? 30000);\n\n try {\n const url = new URL(route, options.baseUrl).toString();\n const res = await fetchImpl(url, {\n method: 'GET',\n headers: { Accept: 'text/html', ...options.headers },\n signal: ctrl.signal,\n });\n const html = await res.text();\n const outputPath = await maybeWriteStatic(options, route, html, mode);\n\n return {\n route,\n status: res.status,\n bytes: Buffer.byteLength(html),\n outputPath,\n durationMs: Date.now() - start,\n };\n } catch (err) {\n return {\n route,\n status: null,\n bytes: 0,\n error: (err as Error).message,\n durationMs: Date.now() - start,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Run the prerender pipeline. Programmatic entry-point for the\n * `bin/inertia-prerender` CLI.\n *\n * Two output modes (which can be combined via `\"both\"`):\n *\n * - **`warmup`** (default) — fetches each route, discards the body. Use to\n * populate the SSR view cache after a deploy so the first real visitor\n * doesn't pay the SSR latency cost.\n * - **`static`** — fetches each route and writes the response body to\n * `<outDir>/<route>/index.html`. Serve those files directly via\n * nginx/CDN, bypassing Express entirely.\n *\n * Bounded-concurrency: `concurrency` workers consume routes from a shared\n * counter; the returned `results` preserve input order. Failures on\n * individual routes never halt the run — the per-route summary lets a CI\n * step choose to fail-loud.\n *\n * @param options Pipeline configuration — see {@link PrerenderOptions}.\n */\nexport async function prerender(options: PrerenderOptions): Promise<PrerenderSummary> {\n const concurrency = Math.max(1, options.concurrency ?? 4);\n const results: PrerenderRouteResult[] = new Array(options.routes.length);\n let next = 0;\n\n /**\n * Claim the next route index and process it, then recurse. Recursion\n * (instead of a loop) avoids both `while`-spin and `no-await-in-loop`.\n */\n async function worker(): Promise<void> {\n const i = next;\n next += 1;\n\n if (i >= options.routes.length) {\n return;\n }\n\n const route = options.routes[i] ?? '';\n results[i] = await runOne(options, route);\n await worker();\n }\n\n await Promise.all(Array.from({ length: Math.min(concurrency, options.routes.length) }, async () => worker()));\n\n const ok = results.filter((r) => r && r.status !== null && r.status < 400 && !r.error).length;\n const failed = results.length - ok;\n\n return {\n total: results.length, ok, failed, results,\n };\n}\n","import type { SsrRenderer, SsrResult } from './types.js';\nimport type { InertiaPage } from '../core/index.js';\n\n/**\n * Inputs to {@link createInertiaSsrFetcher}.\n */\nexport interface InertiaSsrFetcherOptions {\n /** SSR endpoint URL — typically your internal LB DNS, e.g. `http://ssr.internal/render`. */\n url: string;\n /** Per-attempt timeout in milliseconds. Default 5000. */\n timeoutMs?: number;\n /** Number of retry attempts after the first failure. Default 2 (so up to 3 total tries). */\n retries?: number;\n /** Initial backoff in ms; doubles per retry. Default 100. */\n retryBaseMs?: number;\n /**\n * Circuit breaker: open after this many consecutive failures.\n * Set to `0` (or `Infinity`) to disable. Default 5.\n */\n breakerThreshold?: number;\n /** How long the breaker stays open before allowing one probe. Default 30000. */\n breakerCooldownMs?: number;\n /** Failure mode. Default `\"client\"`. */\n fallback?: 'client' | 'throw';\n /** Override fetch implementation (testing). */\n fetch?: typeof fetch;\n /** Extra headers sent with each render request. */\n headers?: Record<string, string>;\n}\n\nconst EMPTY_RESULT: SsrResult = { body: '', head: '' };\n\ninterface BreakerState {\n failures: number;\n openedAt: number | null;\n}\n\n/**\n * Resolve after the given number of milliseconds.\n *\n * @param ms Delay in milliseconds.\n */\nasync function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\n/**\n * Build an {@link SsrRenderer} that POSTs the page object to a separate Node\n * SSR process (or load-balanced pool) and returns the rendered\n * `{ head, body }`.\n *\n * Matches the wire protocol used by `@inertiajs/{vue3,react,svelte}/server`\n * `createServer()`: `POST <url>` with `application/json` body containing the\n * page object, response is `{ head: string[], body: string }`.\n *\n * Adds production hardening on top of the bare protocol:\n * - Per-attempt timeout (default 5000ms) via `AbortController`.\n * - Recursive retry with exponential backoff (`retryBaseMs * 2^attempt`).\n * - Circuit breaker — opens after `breakerThreshold` consecutive failed\n * *requests* (not attempts); half-opens after `breakerCooldownMs` so a\n * probe request can re-close it on success.\n * - `fallback`: `\"client\"` returns an empty SSR result so the client\n * renders alone; `\"throw\"` rethrows so Express's error handler can react.\n *\n * @param options Fetcher configuration — see {@link InertiaSsrFetcherOptions}.\n */\nexport function createInertiaSsrFetcher(options: InertiaSsrFetcherOptions): SsrRenderer {\n const fetchImpl = options.fetch ?? fetch;\n const timeoutMs = options.timeoutMs ?? 5000;\n const retries = options.retries ?? 2;\n const retryBaseMs = options.retryBaseMs ?? 100;\n const breakerThreshold = options.breakerThreshold ?? 5;\n const breakerCooldownMs = options.breakerCooldownMs ?? 30000;\n const fallback = options.fallback ?? 'client';\n const breakerEnabled = breakerThreshold > 0 && Number.isFinite(breakerThreshold);\n\n const state: BreakerState = { failures: 0, openedAt: null };\n\n /**\n * Returns `true` while the breaker is open and within its cooldown window;\n * a return of `false` after a previous failure means we are half-open and\n * the caller may attempt a probe request.\n */\n function breakerOpen(): boolean {\n if (!breakerEnabled || state.openedAt === null) {\n return false;\n }\n\n if (Date.now() - state.openedAt >= breakerCooldownMs) {\n // Half-open: let the next request probe.\n return false;\n }\n\n return true;\n }\n\n /**\n * Reset the breaker after a successful render.\n */\n function recordSuccess(): void {\n state.failures = 0;\n state.openedAt = null;\n }\n\n /**\n * Increment the failure counter; open the breaker when the threshold is hit.\n */\n function recordFailure(): void {\n state.failures += 1;\n\n if (breakerEnabled && state.failures >= breakerThreshold) {\n state.openedAt = Date.now();\n }\n }\n\n /**\n * Fire one SSR request — the unit the retry loop wraps. Throws on\n * timeout, network error, or non-2xx response.\n *\n * @param page Page object to send to the SSR server.\n */\n async function attempt(page: InertiaPage): Promise<SsrResult> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const res = await fetchImpl(options.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n body: JSON.stringify(page),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n throw new Error(`Inertia SSR request failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as Partial<SsrResult>;\n\n return {\n body: json.body ?? '',\n head: json.head,\n bodyIsFullRoot: json.bodyIsFullRoot,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n return async ({ page }: { page: InertiaPage }): Promise<SsrResult> => {\n if (breakerOpen()) {\n if (fallback === 'throw') {\n throw new Error('Inertia SSR circuit breaker is open');\n }\n\n return EMPTY_RESULT;\n }\n\n /**\n * Run one render attempt, recursing with exponential backoff until the\n * retry budget is spent. Records breaker success on the first win.\n *\n * @param remaining Retry attempts left before the error propagates.\n */\n const attemptWithRetry = async (remaining: number): Promise<SsrResult> => {\n try {\n const result = await attempt(page);\n recordSuccess();\n\n return result;\n } catch (err) {\n if (remaining <= 0) {\n throw err;\n }\n\n await sleep(retryBaseMs * 2 ** (retries - remaining));\n\n return attemptWithRetry(remaining - 1);\n }\n };\n\n try {\n return await attemptWithRetry(retries);\n } catch (lastError) {\n recordFailure();\n\n if (fallback === 'throw') {\n throw lastError;\n }\n\n return EMPTY_RESULT;\n }\n };\n}\n","import { createHash } from 'node:crypto';\nimport { readFile, stat } from 'node:fs/promises';\n\n/**\n * Inputs to {@link viteManifestVersion}.\n */\nexport interface ViteManifestVersionOptions {\n /** Path to `manifest.json`. */\n manifestPath: string;\n /**\n * If `true` (default), the manifest is re-read on every call when its\n * mtime has advanced. Set to `false` to read once on boot — slightly\n * faster but requires a process restart to pick up new builds.\n */\n watchMtime?: boolean;\n}\n\n/**\n * Inputs to {@link viteManifestAssets}.\n */\nexport interface ViteManifestAssetsOptions {\n /** Path to `manifest.json`. */\n manifestPath: string;\n /**\n * Manifest key for the entry to resolve. Typically the source path of\n * the client entry, e.g. `src/app.ts` or `src/main.tsx`.\n */\n entry: string;\n /**\n * If `true` (default), the manifest is re-read on every call when its\n * mtime has advanced. Set to `false` to read once on boot.\n */\n watchMtime?: boolean;\n}\n\n/**\n * Resolved asset URLs for a single Vite manifest entry. URLs are web paths\n * with a leading `/`, ready to drop into the HTML shell.\n */\nexport interface ViteManifestAssets {\n /** First CSS file declared by the entry, or `null` when absent. */\n css: string | null;\n /** Compiled JS file for the entry, or `null` when absent. */\n js: string | null;\n}\n\ninterface CacheEntry {\n mtimeMs: number;\n version: string;\n}\n\ninterface AssetsCacheEntry {\n mtimeMs: number;\n assets: ViteManifestAssets;\n}\n\nconst EMPTY_ASSETS: ViteManifestAssets = { css: null, js: null };\n\n/**\n * Build a stable asset version from a Vite-generated `manifest.json`.\n *\n * Compatible with both `@inertiajs/vite-plugin` output and the standard\n * `--manifest` option from `vite build`. The returned function is suitable\n * to pass directly as the `version` option of the Inertia middleware.\n *\n * Strategy:\n * - Read the manifest file.\n * - Hash a canonicalized list of `(key -> file)` entries (only the `file`\n * field per entry, so unrelated manifest metadata never perturbs the hash).\n * - Cache the result; re-read only after the file's mtime changes (when\n * `watchMtime` is true) or never re-read (when false).\n * - Returns `null` when the manifest file is absent or unparseable.\n *\n * A new manifest (different hashed output paths) yields a new version, which\n * the middleware embeds in the SSR cache key — so a deploy atomically\n * invalidates every existing cache entry.\n *\n * @param options Path to the manifest plus the mtime-watch flag.\n */\nexport function viteManifestVersion(options: ViteManifestVersionOptions): () => Promise<string | null> {\n const watchMtime = options.watchMtime ?? true;\n let cached: CacheEntry | null = null;\n\n /**\n * Resolve to the current version string, or `null` when the manifest can't\n * be read or parsed. Hits the in-memory cache when the mtime is unchanged.\n */\n async function read(): Promise<string | null> {\n let mtimeMs: number;\n\n try {\n const s = await stat(options.manifestPath);\n mtimeMs = s.mtimeMs;\n } catch {\n return null;\n }\n\n if (cached && (!watchMtime || cached.mtimeMs === mtimeMs)) {\n return cached.version;\n }\n\n let raw: string;\n\n try {\n raw = await readFile(options.manifestPath, 'utf8');\n } catch {\n return null;\n }\n\n let parsed: Record<string, unknown>;\n\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n\n // Canonical input: keys sorted, value extracts the `file` property when\n // the entry is a Vite manifest object (so unrelated metadata doesn't\n // perturb the hash).\n const lines: string[] = Object.keys(parsed)\n .sort()\n .map((key) => {\n const entry = parsed[key];\n\n if (entry && typeof entry === 'object' && 'file' in entry) {\n return `${key}=${(entry as { file: string }).file}`;\n }\n\n return `${key}=${JSON.stringify(entry)}`;\n });\n\n const version = createHash('sha256').update(lines.join('\\n')).digest('hex').slice(0, 16);\n\n cached = { mtimeMs, version };\n\n return version;\n }\n\n return read;\n}\n\n/**\n * Web-path normalize a manifest-relative file string. Adds a leading `/`\n * and collapses any pre-existing leading slashes so the result is always\n * a single-rooted absolute web path.\n *\n * @param file Manifest-relative file string.\n */\nfunction toWebPath(file: string): string {\n return `/${file.replace(/^\\/+/, '')}`;\n}\n\n/**\n * Resolve the asset URLs (`css`, `js`) for a single Vite manifest entry.\n *\n * Reads the manifest produced by `vite build --manifest` (or\n * `@inertiajs/vite-plugin`), locates the entry by manifest key, and\n * returns its compiled JS file plus the first declared CSS file as web\n * paths suitable to drop into the HTML shell's `<link>` and `<script>`\n * tags. Caches by mtime the same way as {@link viteManifestVersion}.\n *\n * Returns `{ css: null, js: null }` when the manifest is missing,\n * unparseable, or the entry key is absent — the root view stays\n * renderable while assets are still being built.\n *\n * @param options Path to the manifest, entry key, and the mtime-watch flag.\n */\nexport function viteManifestAssets(\n options: ViteManifestAssetsOptions,\n): () => Promise<ViteManifestAssets> {\n const watchMtime = options.watchMtime ?? true;\n let cached: AssetsCacheEntry | null = null;\n\n /**\n * Resolve to the current asset URLs, or `{ css: null, js: null }` when\n * the manifest can't be read, parsed, or the entry is missing.\n */\n async function read(): Promise<ViteManifestAssets> {\n let mtimeMs: number;\n\n try {\n const s = await stat(options.manifestPath);\n mtimeMs = s.mtimeMs;\n } catch {\n return EMPTY_ASSETS;\n }\n\n if (cached && (!watchMtime || cached.mtimeMs === mtimeMs)) {\n return cached.assets;\n }\n\n let raw: string;\n\n try {\n raw = await readFile(options.manifestPath, 'utf8');\n } catch {\n return EMPTY_ASSETS;\n }\n\n let parsed: Record<string, unknown>;\n\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return EMPTY_ASSETS;\n }\n\n const entry = parsed[options.entry];\n\n if (!entry || typeof entry !== 'object') {\n return EMPTY_ASSETS;\n }\n\n const { file, css: cssList } = entry as { file?: unknown; css?: unknown };\n const firstCss = Array.isArray(cssList) && typeof cssList[0] === 'string' ? cssList[0] : null;\n\n const assets: ViteManifestAssets = {\n css: firstCss !== null ? toWebPath(firstCss) : null,\n js: typeof file === 'string' ? toWebPath(file) : null,\n };\n\n cached = { mtimeMs, assets };\n\n return assets;\n }\n\n return read;\n}\n","/**\n * Express adapter for Inertia.js v3.\n *\n * Default entry point of `@blacklizard/inertia-express`. The framework-agnostic\n * core is available at `@blacklizard/inertia-express/core`.\n */\n\nimport { inertia } from './middleware.js';\n\nexport type {\n AlwaysProp,\n ComputeCacheKeyInput,\n DeepMergeProp,\n DeferredProp,\n InertiaPage,\n InertiaRequestInfo,\n LazyProp,\n MergeProp,\n OptionalProp,\n PageProps,\n SharedPropsInput,\n SsrCacheEntry,\n SsrCacheStore,\n ValidationErrors,\n VersionResolver,\n} from '../core/index.js';\n// Re-export the most commonly used core helpers so users only need a single\n// import path for typical apps.\nexport {\n always,\n canonicalStringify,\n computeSsrCacheKey,\n deepMerge,\n defer,\n INERTIA_HEADERS,\n INERTIA_LOCATION_STATUS,\n INERTIA_REDIRECT_STATUS,\n lazy,\n merge,\n optional,\n} from '../core/index.js';\nexport type { EdgeCacheDecision, EdgeCachePolicy } from './edge-cache.js';\nexport { applyEdgeCache } from './edge-cache.js';\nexport type { MemoryCacheStoreOptions } from './memory-store.js';\nexport { createMemoryCacheStore } from './memory-store.js';\nexport { inertia };\nexport default inertia;\nexport type {\n PrerenderOptions,\n PrerenderRouteResult,\n PrerenderSummary,\n} from './prerender.js';\nexport { prerender } from './prerender.js';\nexport {\n encodePageScript,\n sendInertiaLocation,\n sendInertiaResponse,\n sendVersionMismatch,\n} from './response.js';\nexport type { InertiaSsrFetcherOptions } from './ssr-fetcher.js';\nexport { createInertiaSsrFetcher } from './ssr-fetcher.js';\nexport type {\n InertiaCacheOptions,\n InertiaMiddlewareOptions,\n InertiaResponseOptions,\n RootViewInput,\n RootViewRenderer,\n SsrRenderer,\n SsrRendererInput,\n SsrResult,\n} from './types.js';\nexport type {\n ViteManifestAssets,\n ViteManifestAssetsOptions,\n ViteManifestVersionOptions,\n} from './vite-manifest.js';\nexport { viteManifestAssets, viteManifestVersion } from './vite-manifest.js';\n"],"mappings":"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"}
|