@arponascension/express-inertia 1.0.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vite.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { V as ViteConfig } from './types-Co2XESgs.mjs';
1
+ import { V as ViteConfig } from './types-DgBPobaU.mjs';
2
2
  import 'express';
3
3
 
4
4
  /**
@@ -60,7 +60,7 @@ interface ResolvedViteConfig {
60
60
  manifestPath: string;
61
61
  base: string;
62
62
  manifest: ViteManifest | null;
63
- isDev: boolean;
63
+ isDev: boolean | undefined;
64
64
  devServerUrlOverride: string | null;
65
65
  }
66
66
  declare class ViteHelper {
@@ -80,6 +80,10 @@ declare class ViteHelper {
80
80
  * Get development server URL from hot file or config.
81
81
  */
82
82
  getDevServerUrl(): string;
83
+ /**
84
+ * Get the production asset base path (always ends with a trailing slash).
85
+ */
86
+ getBasePath(): string;
83
87
  /**
84
88
  * Check if manifest file exists.
85
89
  */
package/dist/vite.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { V as ViteConfig } from './types-Co2XESgs.js';
1
+ import { V as ViteConfig } from './types-DgBPobaU.js';
2
2
  import 'express';
3
3
 
4
4
  /**
@@ -60,7 +60,7 @@ interface ResolvedViteConfig {
60
60
  manifestPath: string;
61
61
  base: string;
62
62
  manifest: ViteManifest | null;
63
- isDev: boolean;
63
+ isDev: boolean | undefined;
64
64
  devServerUrlOverride: string | null;
65
65
  }
66
66
  declare class ViteHelper {
@@ -80,6 +80,10 @@ declare class ViteHelper {
80
80
  * Get development server URL from hot file or config.
81
81
  */
82
82
  getDevServerUrl(): string;
83
+ /**
84
+ * Get the production asset base path (always ends with a trailing slash).
85
+ */
86
+ getBasePath(): string;
83
87
  /**
84
88
  * Check if manifest file exists.
85
89
  */
package/dist/vite.js CHANGED
@@ -57,8 +57,13 @@ function createLogger(options = {}) {
57
57
  }
58
58
 
59
59
  // src/utils.ts
60
+ var cryptoModule;
61
+ async function getCrypto() {
62
+ cryptoModule ??= await import('crypto');
63
+ return cryptoModule;
64
+ }
60
65
  async function generateSriHash(content) {
61
- const crypto = await import('crypto');
66
+ const crypto = await getCrypto();
62
67
  const hash = crypto.createHash("sha384").update(content);
63
68
  return `sha384-${hash.digest("base64")}`;
64
69
  }
@@ -83,6 +88,8 @@ function resolveDevServerUrl(config, override) {
83
88
  }
84
89
  function inertiaVitePlugin(options = {}) {
85
90
  const logger = createLogger({ prefix: "express-inertia:vite" });
91
+ let cleanupRegistered = false;
92
+ let exitConfig = null;
86
93
  const write = (config, server) => {
87
94
  try {
88
95
  const hotFile = path__default.default.resolve(config.root, options.hotFile || "public/hot");
@@ -101,6 +108,11 @@ function inertiaVitePlugin(options = {}) {
101
108
  } catch {
102
109
  }
103
110
  };
111
+ const removeOnExit = () => {
112
+ if (exitConfig) {
113
+ remove(exitConfig);
114
+ }
115
+ };
104
116
  return {
105
117
  name: "express-inertia-hot-file",
106
118
  configResolved(config) {
@@ -112,9 +124,13 @@ function inertiaVitePlugin(options = {}) {
112
124
  },
113
125
  configureServer(server) {
114
126
  write(server.config, server);
127
+ exitConfig = server.config;
115
128
  server.httpServer?.once("listening", () => write(server.config, server));
116
129
  server.httpServer?.on("close", () => remove(server.config));
117
- process.once("exit", () => remove(server.config));
130
+ if (!cleanupRegistered) {
131
+ process.once("exit", removeOnExit);
132
+ cleanupRegistered = true;
133
+ }
118
134
  },
119
135
  buildStart() {
120
136
  }
@@ -137,7 +153,7 @@ var ViteHelper = class {
137
153
  ),
138
154
  base: config?.base || `/${buildDir}/`,
139
155
  manifest: config?.manifest || null,
140
- isDev: config?.isDev ?? false,
156
+ isDev: config?.isDev,
141
157
  devServerUrlOverride: config?.devServerUrlOverride || null
142
158
  };
143
159
  }
@@ -149,8 +165,8 @@ var ViteHelper = class {
149
165
  * NODE_ENV switch is required to toggle between dev and build assets.
150
166
  */
151
167
  isDev() {
152
- if (this.config.isDev === true) {
153
- return true;
168
+ if (this.config.isDev !== void 0) {
169
+ return this.config.isDev;
154
170
  }
155
171
  const candidatePaths = [
156
172
  this.config.hotFile,
@@ -184,6 +200,12 @@ var ViteHelper = class {
184
200
  }
185
201
  return this.config.devServerUrl;
186
202
  }
203
+ /**
204
+ * Get the production asset base path (always ends with a trailing slash).
205
+ */
206
+ getBasePath() {
207
+ return this.config.base.endsWith("/") ? this.config.base : `${this.config.base}/`;
208
+ }
187
209
  /**
188
210
  * Check if manifest file exists.
189
211
  */
@@ -224,7 +246,9 @@ var ViteHelper = class {
224
246
  this.manifestCache = parsed;
225
247
  return parsed;
226
248
  } catch (err) {
227
- throw new Error(`[express-inertia] Failed to parse Vite manifest at ${p}: ${err.message}`);
249
+ throw new Error(
250
+ `[express-inertia] Failed to parse Vite manifest at ${p}: ${err instanceof Error ? err.message : String(err)}`
251
+ );
228
252
  }
229
253
  }
230
254
  }
package/dist/vite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts","../src/utils.ts","../src/vite.ts"],"names":["path","fs"],"mappings":"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","file":"vite.js","sourcesContent":["export interface Logger {\n warn(message: string, meta?: Record<string, any>): void;\n error(message: string, meta?: Record<string, any>): void;\n info(message: string, meta?: Record<string, any>): void;\n debug(message: string, meta?: Record<string, any>): void;\n}\n\nexport interface LoggerOptions {\n prefix?: string;\n logger?: Logger;\n}\n\nconst DEFAULT_PREFIX = '@arponascension/express-inertia';\n\nfunction createConsoleLogger(prefix: string): Logger {\n const pad = (str: string) => str.padEnd(2, ' ');\n\n return {\n warn(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.warn(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.warn(`[${prefix}] ${message}`);\n }\n },\n\n error(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.error(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.error(`[${prefix}] ${message}`);\n }\n },\n\n info(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.info(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.info(`[${prefix}] ${message}`);\n }\n },\n\n debug(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.debug(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.debug(`[${prefix}] ${message}`);\n }\n },\n };\n}\n\nlet globalLogger: Logger = createConsoleLogger(DEFAULT_PREFIX);\n\nexport function setGlobalLogger(logger: Logger): void {\n globalLogger = logger;\n}\n\nexport function getGlobalLogger(): Logger {\n return globalLogger;\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const prefix = options.prefix || DEFAULT_PREFIX;\n if (options.logger) {\n return options.logger;\n }\n return createConsoleLogger(prefix);\n}\n","import type { Request } from 'express';\nimport type {\n PageProps,\n PropCallback,\n LazyProp,\n AlwaysProp,\n DeferredProp,\n MergeProp,\n OptionalProp,\n Page,\n SecurityOptions,\n} from './types.js';\n\n/**\n * Marks a prop as lazy. Lazy props are ONLY evaluated during partial reloads\n * when specifically requested in the `only` array by the client.\n */\nexport function lazy<T = any>(callback: PropCallback<T>): LazyProp<T> {\n return {\n __inertia_lazy: true,\n callback,\n };\n}\n\n/**\n * Marks a prop as always included. Always props are evaluated and returned\n * on every request, including partial reloads, even if not explicitly requested.\n */\nexport function always<T = any>(value: T | PropCallback<T>): AlwaysProp<T> {\n return {\n __inertia_always: true,\n value,\n };\n}\n\n/**\n * Marks a prop as deferred (Inertia v2).\n */\nexport function defer<T = any>(\n callback: PropCallback<T>,\n options?: { group?: string }\n): DeferredProp<T> {\n return {\n __inertia_deferred: true,\n callback,\n group: options?.group,\n };\n}\n\n/**\n * Marks a prop as mergeable (Inertia v2).\n */\nexport function merge<T = any>(value: T | PropCallback<T>): MergeProp<T> {\n return {\n __inertia_merge: true,\n value,\n };\n}\n\n/**\n * Marks a prop as optional.\n */\nexport function optional<T = any>(callback: PropCallback<T>): OptionalProp<T> {\n return {\n __inertia_optional: true,\n callback,\n };\n}\n\nexport function isLazy(val: any): val is LazyProp {\n return val && typeof val === 'object' && val.__inertia_lazy === true;\n}\n\nexport function isAlways(val: any): val is AlwaysProp {\n return val && typeof val === 'object' && val.__inertia_always === true;\n}\n\nexport function isDeferred(val: any): val is DeferredProp {\n return val && typeof val === 'object' && val.__inertia_deferred === true;\n}\n\nexport function isMerge(val: any): val is MergeProp {\n return val && typeof val === 'object' && val.__inertia_merge === true;\n}\n\nexport function isOptional(val: any): val is OptionalProp {\n return val && typeof val === 'object' && val.__inertia_optional === true;\n}\n\n/**\n * Evaluates and resolves all props (promises, functions, lazy, always, merge, deferred)\n * based on current Inertia request context and partial reload headers.\n */\nexport async function resolveProps(\n rawProps: PageProps,\n req: Request,\n component: string\n): Promise<{\n resolvedProps: PageProps;\n deferredProps?: Record<string, string[]>;\n mergeProps?: string[];\n}> {\n const isPartial =\n req.header('X-Inertia-Partial-Component') === component &&\n Boolean(req.header('X-Inertia-Partial-Data'));\n\n const partialKeys = isPartial\n ? (req.header('X-Inertia-Partial-Data') || '')\n .split(',')\n .map((k) => k.trim())\n .filter(Boolean)\n : [];\n\n const resolvedProps: PageProps = {};\n const deferredMap: Record<string, string[]> = {};\n const mergeKeys: string[] = [];\n\n for (const [key, rawValue] of Object.entries(rawProps)) {\n // Collect merge props\n if (isMerge(rawValue)) {\n mergeKeys.push(key);\n }\n\n // Collect deferred props\n if (isDeferred(rawValue)) {\n const group = rawValue.group || 'default';\n if (!deferredMap[group]) {\n deferredMap[group] = [];\n }\n deferredMap[group].push(key);\n }\n\n if (isPartial) {\n const isRequested = partialKeys.includes(key);\n const isAlwaysIncluded = isAlways(rawValue);\n\n // In partial reload, only include if explicitly requested or marked as always\n if (!isRequested && !isAlwaysIncluded) {\n continue;\n }\n } else {\n // In full request, lazy and deferred props are omitted.\n // Optional props are still included on initial load.\n if (isLazy(rawValue) || isDeferred(rawValue)) {\n continue;\n }\n }\n\n // Resolve prop value\n resolvedProps[key] = await unwrapValue(rawValue, req);\n }\n\n return {\n resolvedProps,\n deferredProps: Object.keys(deferredMap).length > 0 ? deferredMap : undefined,\n mergeProps: mergeKeys.length > 0 ? mergeKeys : undefined,\n };\n}\n\n/**\n * Unwraps closures, promises, and wrapper objects to get the actual value.\n */\nexport async function unwrapValue(val: any, req: Request): Promise<any> {\n if (val === null || val === undefined) {\n return val;\n }\n\n // Handle wrapper types\n if (isLazy(val)) {\n val = val.callback;\n } else if (isAlways(val)) {\n val = val.value;\n } else if (isDeferred(val)) {\n val = val.callback;\n } else if (isMerge(val)) {\n val = val.value;\n } else if (isOptional(val)) {\n val = val.callback;\n }\n\n // If function / closure, execute it\n if (typeof val === 'function') {\n val = val(req);\n }\n\n // If promise, await it\n if (val && typeof val.then === 'function') {\n val = await val;\n }\n\n return val;\n}\n\n/**\n * Escapes characters for HTML attribute insertion to prevent XSS.\n */\nexport function escapeHtmlAttr(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Serializes Page object safely for data-page HTML attribute.\n */\nexport function serializePage(page: Page): string {\n return escapeHtmlAttr(safeStringify(page));\n}\n\n/**\n * Safely stringifies an object, replacing circular references with null.\n */\nexport function safeStringify(obj: any): string {\n const seen = new WeakSet();\n return JSON.stringify(obj, (_key, value) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return null;\n }\n seen.add(value);\n }\n return value;\n });\n}\n\n/**\n * Default pattern for safe component names: alphanumeric, hyphens, and underscores,\n * optionally separated by single forward slashes. Blocks path traversal sequences\n * like `..`, leading/trailing slashes, and consecutive slashes.\n */\nexport const DEFAULT_COMPONENT_NAME_PATTERN = /^[\\w-]+(?:\\/[\\w-]+)*$/;\n\n/**\n * Validates a component name to prevent path traversal and injection attacks.\n * Throws a TypeError if the name contains suspicious characters.\n */\nexport function validateComponentName(\n component: string,\n pattern: RegExp = DEFAULT_COMPONENT_NAME_PATTERN\n): void {\n if (!pattern.test(component)) {\n throw new TypeError(\n `Invalid component name \"${component}\". Component names must match the pattern ${pattern}.`\n );\n }\n}\n\n/**\n * Recursively sanitizes viewData by stripping functions and undefined values.\n * Only plain objects and primitive values are preserved.\n */\nexport function sanitizeViewData(data: Record<string, any>): Record<string, any> {\n const seen = new WeakSet();\n\n function sanitize(value: any): any {\n if (typeof value === 'function' || value === undefined) {\n return undefined;\n }\n\n if (value === null || typeof value !== 'object' || Buffer.isBuffer(value)) {\n return value;\n }\n\n if (seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value.map((item) => sanitize(item));\n }\n\n const sanitized: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n const cleaned = sanitize(val);\n if (cleaned !== undefined) {\n sanitized[key] = cleaned;\n }\n }\n return sanitized;\n }\n\n return sanitize(data) as Record<string, any>;\n}\n\n/**\n * Generates a Subresource Integrity (SRI) hash for a given string.\n * Returns the base64-encoded SHA-384 hash prefixed with 'sha384-'.\n */\nexport async function generateSriHash(content: string | Buffer): Promise<string> {\n const crypto = await import('node:crypto');\n const hash = crypto.createHash('sha384').update(content);\n return `sha384-${hash.digest('base64')}`;\n}\n\n","import fs from 'fs';\nimport path from 'path';\nimport type { ViteConfig } from './types.js';\nimport { createLogger } from './logger.js';\nimport { generateSriHash } from './utils.js';\n\n/**\n * Options for the auto dev/build Vite plugin.\n */\nexport interface InertiaVitePluginOptions {\n /**\n * Path to the hot file. Relative paths are resolved against Vite's project root.\n * @default 'public/hot'\n */\n hotFile?: string;\n /**\n * Override the dev server URL written to the hot file.\n * Defaults to the resolved Vite dev server URL.\n */\n devServerUrl?: string;\n}\n\n/**\n * Structural subset of Vite's `Plugin` type so the core package does not need\n * a hard runtime dependency on Vite.\n */\nexport interface InertiaVitePlugin {\n name: string;\n configResolved?: (config: any) => void;\n configureServer?: (server: any) => void;\n buildStart?: () => void;\n}\n\n/**\n * Derive the dev server URL from Vite's resolved config, mirroring Laravel's\n * vite-plugin logic (honours `server.origin`, then https/host/port).\n */\nfunction resolveDevServerUrl(config: any, override?: string): string {\n if (override) return override.replace(/\\/$/, '');\n const server = config?.server || {};\n if (typeof server.origin === 'string' && server.origin) {\n return server.origin.replace(/\\/$/, '');\n }\n const scheme = server.https ? 'https' : 'http';\n let host = server.host;\n if (!host || host === '0.0.0.0' || host === '::' || host === '::0' || host === true) {\n host = 'localhost';\n }\n if (host.includes(':') && !host.startsWith('[')) {\n host = `[${host}]`;\n }\n const port = server.port ?? 5173;\n return `${scheme}://${host}:${port}`;\n}\n\n/**\n * Vite plugin that automatically toggles Express between dev and build mode.\n *\n * - `vite dev` writes a `hot` file (signalling dev mode) and removes it on shutdown.\n * - `vite build` removes any stale `hot` file, so Express falls back to the built manifest.\n *\n * Use it in your `vite.config.ts`:\n * ```ts\n * import { inertiaVitePlugin } from '@arponascension/express-inertia/vite';\n * export default defineConfig({\n * plugins: [inertiaVitePlugin()],\n * });\n * ```\n */\nexport function inertiaVitePlugin(options: InertiaVitePluginOptions = {}): InertiaVitePlugin {\n const logger = createLogger({ prefix: 'express-inertia:vite' });\n const write = (config: any, server?: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n const actual = server?.resolvedUrls?.local?.[0];\n const url = actual || resolveDevServerUrl(config, options.devServerUrl);\n fs.mkdirSync(path.dirname(hotFile), { recursive: true });\n fs.writeFileSync(hotFile, url.replace(/\\/$/, ''));\n } catch (err) {\n logger.warn('Failed to write Vite hot file', { error: (err as Error).message });\n }\n };\n\n const remove = (config: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n fs.rmSync(hotFile, { force: true });\n } catch {\n // ignore\n }\n };\n\n return {\n name: 'express-inertia-hot-file',\n\n configResolved(config) {\n if (config.command === 'build') {\n remove(config);\n } else {\n write(config);\n }\n },\n\n configureServer(server) {\n write(server.config, server);\n server.httpServer?.once('listening', () => write(server.config, server));\n server.httpServer?.on('close', () => remove(server.config));\n process.once('exit', () => remove(server.config));\n },\n\n buildStart() {\n // noop guard: build-time cleanup happens in configResolved\n },\n };\n}\n\nexport interface ViteManifestChunk {\n src?: string;\n file: string;\n css?: string[];\n assets?: string[];\n isEntry?: boolean;\n isDynamicEntry?: boolean;\n imports?: string[];\n dynamicImports?: string[];\n}\n\nexport type ViteManifest = Record<string, ViteManifestChunk>;\n\nexport interface ResolvedViteConfig {\n publicDir: string;\n buildDir: string;\n devServerUrl: string;\n hotFile: string;\n manifestPath: string;\n base: string;\n manifest: ViteManifest | null;\n isDev: boolean;\n devServerUrlOverride: string | null;\n}\n\nexport class ViteHelper {\n private config: ResolvedViteConfig;\n private manifestCache: ViteManifest | null = null;\n private logger = createLogger({ prefix: 'express-inertia:vite' });\n\n constructor(config?: ViteConfig) {\n const publicDir = config?.publicDir ? path.resolve(config.publicDir) : path.resolve('public');\n const buildDir = config?.buildDir || 'build';\n\n this.config = {\n publicDir,\n buildDir,\n devServerUrl: config?.devServerUrl || 'http://localhost:5173',\n hotFile: path.resolve(config?.hotFile || path.join(publicDir, 'hot')),\n manifestPath: path.resolve(\n config?.manifestPath || path.join(publicDir, buildDir, '.vite', 'manifest.json')\n ),\n base: config?.base || `/${buildDir}/`,\n manifest: config?.manifest || null,\n isDev: config?.isDev ?? false,\n devServerUrlOverride: config?.devServerUrlOverride || null,\n };\n }\n\n /**\n * Detect whether the Vite dev server is running.\n *\n * Mirrors Laravel: the presence of the `hot` file is the sole signal. Vite's\n * dev server writes a `hot` file on startup and removes it on shutdown, so no\n * NODE_ENV switch is required to toggle between dev and build assets.\n */\n public isDev(): boolean {\n if (this.config.isDev === true) {\n return true;\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n /**\n * Get development server URL from hot file or config.\n */\n public getDevServerUrl(): string {\n if (this.config.devServerUrlOverride) {\n return this.config.devServerUrlOverride.replace(/\\/$/, '');\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const content = fs.readFileSync(p, 'utf-8').trim();\n if (content.startsWith('http://') || content.startsWith('https://')) {\n return content;\n }\n } catch {\n // ignore\n }\n }\n }\n\n return this.config.devServerUrl;\n }\n\n /**\n * Check if manifest file exists.\n */\n public manifestExists(): boolean {\n if (this.config.manifest) {\n return true;\n }\n const candidatePaths = this.getManifestCandidatePaths();\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n private getManifestCandidatePaths(): string[] {\n const { publicDir, buildDir } = this.config;\n return [\n this.config.manifestPath,\n path.resolve(publicDir, buildDir, '.vite', 'manifest.json'),\n path.resolve(publicDir, buildDir, 'manifest.json'),\n path.resolve(buildDir, '.vite', 'manifest.json'),\n path.resolve(buildDir, 'manifest.json'),\n ];\n }\n\n /**\n * Load and cache the production manifest.\n */\n public getManifest(): ViteManifest {\n if (this.manifestCache) {\n return this.manifestCache;\n }\n\n if (this.config.manifest) {\n this.manifestCache = this.config.manifest;\n return this.config.manifest;\n }\n\n const candidatePaths = this.getManifestCandidatePaths();\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const raw = fs.readFileSync(p, 'utf-8');\n const parsed = JSON.parse(raw);\n this.manifestCache = parsed;\n return parsed;\n } catch (err: any) {\n throw new Error(`[express-inertia] Failed to parse Vite manifest at ${p}: ${err.message}`);\n }\n }\n }\n\n throw new Error(\n `[express-inertia] Vite manifest not found. Looked in:\\n${candidatePaths.join('\\n')}\\nRun your build step (e.g. vite build) to generate it.`\n );\n }\n\n /**\n * Generate HTML script & link tags for the given entrypoint(s).\n * @param entrypoints Single entry string or array of entry paths (e.g. 'src/main.ts' or ['src/main.ts', 'src/style.css'])\n */\n public renderTags(entrypoints: string | string[]): string {\n const entries = Array.isArray(entrypoints) ? entrypoints : [entrypoints];\n const tags: string[] = [];\n\n if (this.isDev()) {\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n tags.push(`<script type=\"module\" src=\"${devUrl}/@vite/client\"></script>`);\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n if (cleanEntry.endsWith('.css') || cleanEntry.endsWith('.scss') || cleanEntry.endsWith('.less')) {\n tags.push(`<link rel=\"stylesheet\" href=\"${devUrl}/${cleanEntry}\">`);\n } else {\n tags.push(`<script type=\"module\" src=\"${devUrl}/${cleanEntry}\"></script>`);\n }\n }\n\n return tags.join('\\n');\n }\n\n // Production mode\n const manifest = this.getManifest();\n const basePath = this.config.base.endsWith('/') ? this.config.base : `${this.config.base}/`;\n const renderedCss = new Set<string>();\n const renderedPreload = new Set<string>();\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n const chunk =\n manifest[cleanEntry] ||\n Object.values(manifest).find(\n (c) =>\n c.src === cleanEntry ||\n c.file === cleanEntry ||\n (c.src && (c.src.endsWith(cleanEntry) || c.src.endsWith(`/${cleanEntry}`))) ||\n (c.file && (c.file.endsWith(cleanEntry) || c.file.endsWith(`/${cleanEntry}`)))\n );\n\n if (!chunk) {\n if (!/\\.(css|scss|sass|less)$/.test(cleanEntry)) {\n this.logger.warn('Entry not found in Vite manifest', { entry, manifestPath: this.config.manifestPath });\n }\n continue;\n }\n\n // Add CSS files\n if (chunk.css) {\n for (const cssFile of chunk.css) {\n if (!renderedCss.has(cssFile)) {\n renderedCss.add(cssFile);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${cssFile}\">`);\n }\n }\n }\n\n // If entry itself is a CSS file\n if (chunk.file.endsWith('.css')) {\n if (!renderedCss.has(chunk.file)) {\n renderedCss.add(chunk.file);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${chunk.file}\">`);\n }\n } else {\n // JS entry file\n tags.push(`<script type=\"module\" src=\"${basePath}${chunk.file}\"></script>`);\n }\n\n // Add module preloads\n if (chunk.imports) {\n for (const imp of chunk.imports) {\n const impChunk = manifest[imp];\n if (impChunk && !renderedPreload.has(impChunk.file)) {\n renderedPreload.add(impChunk.file);\n tags.push(`<link rel=\"modulepreload\" href=\"${basePath}${impChunk.file}\">`);\n }\n }\n }\n }\n\n return tags.join('\\n');\n }\n\n /**\n * Generates the React Fast Refresh preamble for development.\n */\n public renderReactRefresh(): string {\n if (!this.isDev()) {\n return '';\n }\n\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n return `<script type=\"module\">\n import RefreshRuntime from \"${devUrl}/@react-refresh\";\n RefreshRuntime.injectIntoGlobalHook(window);\n window.$RefreshReg$ = () => {};\n window.$RefreshSig$ = () => (type) => type;\n window.__vite_plugin_react_preamble_installed__ = true;\n</script>`;\n }\n\n /**\n * Generates an SRI hash for the given asset file content.\n * Useful for adding integrity attributes to script/link tags.\n */\n public async generateSriHashForAsset(assetPath: string): Promise<string> {\n const fullPath = path.resolve(this.config.publicDir, assetPath);\n const content = fs.readFileSync(fullPath);\n return generateSriHash(content);\n }\n}\n\n/**\n * Creates a configured ViteHelper instance.\n */\nexport function createViteHelper(config?: ViteConfig): ViteHelper {\n return new ViteHelper(config);\n}\n\n/**\n * Default singleton instance.\n */\nexport const defaultViteHelper = new ViteHelper();\n"]}
1
+ {"version":3,"sources":["../src/logger.ts","../src/utils.ts","../src/vite.ts"],"names":["path","fs"],"mappings":"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","file":"vite.js","sourcesContent":["export interface Logger {\n warn(message: string, meta?: Record<string, any>): void;\n error(message: string, meta?: Record<string, any>): void;\n info(message: string, meta?: Record<string, any>): void;\n debug(message: string, meta?: Record<string, any>): void;\n}\n\nexport interface LoggerOptions {\n prefix?: string;\n logger?: Logger;\n}\n\nconst DEFAULT_PREFIX = '@arponascension/express-inertia';\n\nfunction createConsoleLogger(prefix: string): Logger {\n return {\n warn(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.warn(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.warn(`[${prefix}] ${message}`);\n }\n },\n\n error(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.error(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.error(`[${prefix}] ${message}`);\n }\n },\n\n info(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.info(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.info(`[${prefix}] ${message}`);\n }\n },\n\n debug(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.debug(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.debug(`[${prefix}] ${message}`);\n }\n },\n };\n}\n\nlet globalLogger: Logger = createConsoleLogger(DEFAULT_PREFIX);\n\nexport function setGlobalLogger(logger: Logger): void {\n globalLogger = logger;\n}\n\nexport function getGlobalLogger(): Logger {\n return globalLogger;\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const prefix = options.prefix || DEFAULT_PREFIX;\n if (options.logger) {\n return options.logger;\n }\n return createConsoleLogger(prefix);\n}\n","import type { Request } from 'express';\nimport type {\n PageProps,\n PropCallback,\n LazyProp,\n AlwaysProp,\n DeferredProp,\n MergeProp,\n OptionalProp,\n Page,\n SecurityOptions,\n} from './types.js';\n\n/**\n * Marks a prop as lazy. Lazy props are ONLY evaluated during partial reloads\n * when specifically requested in the `only` array by the client.\n */\nexport function lazy<T = any>(callback: PropCallback<T>): LazyProp<T> {\n return {\n __inertia_lazy: true,\n callback,\n };\n}\n\n/**\n * Marks a prop as always included. Always props are evaluated and returned\n * on every request, including partial reloads, even if not explicitly requested.\n */\nexport function always<T = any>(value: T | PropCallback<T>): AlwaysProp<T> {\n return {\n __inertia_always: true,\n value,\n };\n}\n\n/**\n * Marks a prop as deferred (Inertia v2).\n */\nexport function defer<T = any>(\n callback: PropCallback<T>,\n options?: { group?: string }\n): DeferredProp<T> {\n return {\n __inertia_deferred: true,\n callback,\n group: options?.group,\n };\n}\n\n/**\n * Marks a prop as mergeable (Inertia v2).\n */\nexport function merge<T = any>(value: T | PropCallback<T>): MergeProp<T> {\n return {\n __inertia_merge: true,\n value,\n };\n}\n\n/**\n * Marks a prop as optional.\n */\nexport function optional<T = any>(callback: PropCallback<T>): OptionalProp<T> {\n return {\n __inertia_optional: true,\n callback,\n };\n}\n\nexport function isLazy(val: any): val is LazyProp {\n return val && typeof val === 'object' && val.__inertia_lazy === true;\n}\n\nexport function isAlways(val: any): val is AlwaysProp {\n return val && typeof val === 'object' && val.__inertia_always === true;\n}\n\nexport function isDeferred(val: any): val is DeferredProp {\n return val && typeof val === 'object' && val.__inertia_deferred === true;\n}\n\nexport function isMerge(val: any): val is MergeProp {\n return val && typeof val === 'object' && val.__inertia_merge === true;\n}\n\nexport function isOptional(val: any): val is OptionalProp {\n return val && typeof val === 'object' && val.__inertia_optional === true;\n}\n\n/**\n * Evaluates and resolves all props (promises, functions, lazy, always, merge, deferred)\n * based on current Inertia request context and partial reload headers.\n */\nexport async function resolveProps(\n rawProps: PageProps,\n req: Request,\n component: string\n): Promise<{\n resolvedProps: PageProps;\n deferredProps?: Record<string, string[]>;\n mergeProps?: string[];\n}> {\n const isPartial =\n req.header('X-Inertia-Partial-Component') === component &&\n Boolean(req.header('X-Inertia-Partial-Data'));\n\n const partialKeys = isPartial\n ? (req.header('X-Inertia-Partial-Data') || '')\n .split(',')\n .map((k) => k.trim())\n .filter(Boolean)\n : [];\n\n const resolvedProps: PageProps = {};\n const deferredMap: Record<string, string[]> = {};\n const mergeKeys: string[] = [];\n\n for (const [key, rawValue] of Object.entries(rawProps)) {\n // Collect merge props\n if (isMerge(rawValue)) {\n mergeKeys.push(key);\n }\n\n // Collect deferred props\n if (isDeferred(rawValue)) {\n const group = rawValue.group || 'default';\n if (!deferredMap[group]) {\n deferredMap[group] = [];\n }\n deferredMap[group].push(key);\n }\n\n if (isPartial) {\n const isRequested = partialKeys.includes(key);\n const isAlwaysIncluded = isAlways(rawValue);\n\n // In partial reload, only include if explicitly requested or marked as always\n if (!isRequested && !isAlwaysIncluded) {\n continue;\n }\n } else {\n // In full request, lazy and deferred props are omitted.\n // Optional props are still included on initial load.\n if (isLazy(rawValue) || isDeferred(rawValue)) {\n continue;\n }\n }\n\n // Resolve prop value\n resolvedProps[key] = await unwrapValue(rawValue, req);\n }\n\n return {\n resolvedProps,\n deferredProps: Object.keys(deferredMap).length > 0 ? deferredMap : undefined,\n mergeProps: mergeKeys.length > 0 ? mergeKeys : undefined,\n };\n}\n\n/**\n * Unwraps closures, promises, and wrapper objects to get the actual value.\n */\nexport async function unwrapValue(val: any, req: Request): Promise<any> {\n if (val === null || val === undefined) {\n return val;\n }\n\n // Handle wrapper types\n if (isLazy(val)) {\n val = val.callback;\n } else if (isAlways(val)) {\n val = val.value;\n } else if (isDeferred(val)) {\n val = val.callback;\n } else if (isMerge(val)) {\n val = val.value;\n } else if (isOptional(val)) {\n val = val.callback;\n }\n\n // If function / closure, execute it\n if (typeof val === 'function') {\n val = val(req);\n }\n\n // If promise, await it\n if (val && typeof val.then === 'function') {\n val = await val;\n }\n\n return val;\n}\n\n/**\n * Escapes characters for HTML attribute insertion to prevent XSS.\n */\nexport function escapeHtmlAttr(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Serializes Page object safely for data-page HTML attribute.\n */\nexport function serializePage(page: Page): string {\n return escapeHtmlAttr(safeStringify(page));\n}\n\n/**\n * Safely stringifies an object, replacing circular references with null.\n */\nexport function safeStringify(obj: any): string {\n const seen = new WeakSet();\n return JSON.stringify(obj, (_key, value) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return null;\n }\n seen.add(value);\n }\n return value;\n });\n}\n\n/**\n * Default pattern for safe component names: alphanumeric, hyphens, and underscores,\n * optionally separated by single forward slashes. Blocks path traversal sequences\n * like `..`, leading/trailing slashes, and consecutive slashes.\n */\nexport const DEFAULT_COMPONENT_NAME_PATTERN = /^[\\w-]+(?:\\/[\\w-]+)*$/;\n\n/**\n * Default security settings. Component name validation and view data\n * sanitization are both enabled by default and can be toggled independently.\n */\nexport const DEFAULT_SECURITY_OPTIONS: SecurityOptions = {\n validateComponentNames: true,\n sanitizeViewData: true,\n};\n\n/**\n * Validates a component name to prevent path traversal and injection attacks.\n * Throws a TypeError if the name contains suspicious characters.\n */\nexport function validateComponentName(\n component: string,\n pattern: RegExp = DEFAULT_COMPONENT_NAME_PATTERN\n): void {\n if (!pattern.test(component)) {\n throw new TypeError(\n `Invalid component name \"${component}\". Component names must match the pattern ${pattern}.`\n );\n }\n}\n\n/**\n * Recursively sanitizes viewData by stripping functions and undefined values.\n * Only plain objects and primitive values are preserved.\n */\nexport function sanitizeViewData(data: Record<string, any>): Record<string, any> {\n const seen = new WeakSet();\n\n function sanitize(value: any): any {\n if (typeof value === 'function' || value === undefined) {\n return undefined;\n }\n\n if (value === null || typeof value !== 'object' || Buffer.isBuffer(value)) {\n return value;\n }\n\n if (seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value.map((item) => sanitize(item));\n }\n\n const sanitized: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n const cleaned = sanitize(val);\n if (cleaned !== undefined) {\n sanitized[key] = cleaned;\n }\n }\n return sanitized;\n }\n\n return sanitize(data) as Record<string, any>;\n}\n\nlet cryptoModule: typeof import('node:crypto') | undefined;\n\nasync function getCrypto(): Promise<typeof import('node:crypto')> {\n cryptoModule ??= await import('node:crypto');\n return cryptoModule;\n}\n\n/**\n * Generates a Subresource Integrity (SRI) hash for a given string.\n * Returns the base64-encoded SHA-384 hash prefixed with 'sha384-'.\n */\nexport async function generateSriHash(content: string | Buffer): Promise<string> {\n const crypto = await getCrypto();\n const hash = crypto.createHash('sha384').update(content);\n return `sha384-${hash.digest('base64')}`;\n}\n\n","import fs from 'fs';\nimport path from 'path';\nimport type { ViteConfig } from './types.js';\nimport { createLogger } from './logger.js';\nimport { generateSriHash } from './utils.js';\n\n/**\n * Options for the auto dev/build Vite plugin.\n */\nexport interface InertiaVitePluginOptions {\n /**\n * Path to the hot file. Relative paths are resolved against Vite's project root.\n * @default 'public/hot'\n */\n hotFile?: string;\n /**\n * Override the dev server URL written to the hot file.\n * Defaults to the resolved Vite dev server URL.\n */\n devServerUrl?: string;\n}\n\n/**\n * Structural subset of Vite's `Plugin` type so the core package does not need\n * a hard runtime dependency on Vite.\n */\nexport interface InertiaVitePlugin {\n name: string;\n configResolved?: (config: any) => void;\n configureServer?: (server: any) => void;\n buildStart?: () => void;\n}\n\n/**\n * Derive the dev server URL from Vite's resolved config, mirroring Laravel's\n * vite-plugin logic (honours `server.origin`, then https/host/port).\n */\nfunction resolveDevServerUrl(config: any, override?: string): string {\n if (override) return override.replace(/\\/$/, '');\n const server = config?.server || {};\n if (typeof server.origin === 'string' && server.origin) {\n return server.origin.replace(/\\/$/, '');\n }\n const scheme = server.https ? 'https' : 'http';\n let host = server.host;\n if (!host || host === '0.0.0.0' || host === '::' || host === '::0' || host === true) {\n host = 'localhost';\n }\n if (host.includes(':') && !host.startsWith('[')) {\n host = `[${host}]`;\n }\n const port = server.port ?? 5173;\n return `${scheme}://${host}:${port}`;\n}\n\n/**\n * Vite plugin that automatically toggles Express between dev and build mode.\n *\n * - `vite dev` writes a `hot` file (signalling dev mode) and removes it on shutdown.\n * - `vite build` removes any stale `hot` file, so Express falls back to the built manifest.\n *\n * Use it in your `vite.config.ts`:\n * ```ts\n * import { inertiaVitePlugin } from '@arponascension/express-inertia/vite';\n * export default defineConfig({\n * plugins: [inertiaVitePlugin()],\n * });\n * ```\n */\nexport function inertiaVitePlugin(options: InertiaVitePluginOptions = {}): InertiaVitePlugin {\n const logger = createLogger({ prefix: 'express-inertia:vite' });\n let cleanupRegistered = false;\n let exitConfig: any = null;\n const write = (config: any, server?: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n const actual = server?.resolvedUrls?.local?.[0];\n const url = actual || resolveDevServerUrl(config, options.devServerUrl);\n fs.mkdirSync(path.dirname(hotFile), { recursive: true });\n fs.writeFileSync(hotFile, url.replace(/\\/$/, ''));\n } catch (err) {\n logger.warn('Failed to write Vite hot file', { error: (err as Error).message });\n }\n };\n\n const remove = (config: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n fs.rmSync(hotFile, { force: true });\n } catch {\n // ignore\n }\n };\n\n const removeOnExit = () => {\n if (exitConfig) {\n remove(exitConfig);\n }\n };\n\n return {\n name: 'express-inertia-hot-file',\n\n configResolved(config) {\n if (config.command === 'build') {\n remove(config);\n } else {\n write(config);\n }\n },\n\n configureServer(server) {\n write(server.config, server);\n exitConfig = server.config;\n server.httpServer?.once('listening', () => write(server.config, server));\n server.httpServer?.on('close', () => remove(server.config));\n if (!cleanupRegistered) {\n process.once('exit', removeOnExit);\n cleanupRegistered = true;\n }\n },\n\n buildStart() {\n // noop guard: build-time cleanup happens in configResolved\n },\n };\n}\n\nexport interface ViteManifestChunk {\n src?: string;\n file: string;\n css?: string[];\n assets?: string[];\n isEntry?: boolean;\n isDynamicEntry?: boolean;\n imports?: string[];\n dynamicImports?: string[];\n}\n\nexport type ViteManifest = Record<string, ViteManifestChunk>;\n\nexport interface ResolvedViteConfig {\n publicDir: string;\n buildDir: string;\n devServerUrl: string;\n hotFile: string;\n manifestPath: string;\n base: string;\n manifest: ViteManifest | null;\n isDev: boolean | undefined;\n devServerUrlOverride: string | null;\n}\n\nexport class ViteHelper {\n private config: ResolvedViteConfig;\n private manifestCache: ViteManifest | null = null;\n private logger = createLogger({ prefix: 'express-inertia:vite' });\n\n constructor(config?: ViteConfig) {\n const publicDir = config?.publicDir ? path.resolve(config.publicDir) : path.resolve('public');\n const buildDir = config?.buildDir || 'build';\n\n this.config = {\n publicDir,\n buildDir,\n devServerUrl: config?.devServerUrl || 'http://localhost:5173',\n hotFile: path.resolve(config?.hotFile || path.join(publicDir, 'hot')),\n manifestPath: path.resolve(\n config?.manifestPath || path.join(publicDir, buildDir, '.vite', 'manifest.json')\n ),\n base: config?.base || `/${buildDir}/`,\n manifest: config?.manifest || null,\n isDev: config?.isDev,\n devServerUrlOverride: config?.devServerUrlOverride || null,\n };\n }\n\n /**\n * Detect whether the Vite dev server is running.\n *\n * Mirrors Laravel: the presence of the `hot` file is the sole signal. Vite's\n * dev server writes a `hot` file on startup and removes it on shutdown, so no\n * NODE_ENV switch is required to toggle between dev and build assets.\n */\n public isDev(): boolean {\n if (this.config.isDev !== undefined) {\n return this.config.isDev;\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n /**\n * Get development server URL from hot file or config.\n */\n public getDevServerUrl(): string {\n if (this.config.devServerUrlOverride) {\n return this.config.devServerUrlOverride.replace(/\\/$/, '');\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const content = fs.readFileSync(p, 'utf-8').trim();\n if (content.startsWith('http://') || content.startsWith('https://')) {\n return content;\n }\n } catch {\n // ignore\n }\n }\n }\n\n return this.config.devServerUrl;\n }\n\n /**\n * Get the production asset base path (always ends with a trailing slash).\n */\n public getBasePath(): string {\n return this.config.base.endsWith('/') ? this.config.base : `${this.config.base}/`;\n }\n\n /**\n * Check if manifest file exists.\n */\n public manifestExists(): boolean {\n if (this.config.manifest) {\n return true;\n }\n const candidatePaths = this.getManifestCandidatePaths();\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n private getManifestCandidatePaths(): string[] {\n const { publicDir, buildDir } = this.config;\n return [\n this.config.manifestPath,\n path.resolve(publicDir, buildDir, '.vite', 'manifest.json'),\n path.resolve(publicDir, buildDir, 'manifest.json'),\n path.resolve(buildDir, '.vite', 'manifest.json'),\n path.resolve(buildDir, 'manifest.json'),\n ];\n }\n\n /**\n * Load and cache the production manifest.\n */\n public getManifest(): ViteManifest {\n if (this.manifestCache) {\n return this.manifestCache;\n }\n\n if (this.config.manifest) {\n this.manifestCache = this.config.manifest;\n return this.config.manifest;\n }\n\n const candidatePaths = this.getManifestCandidatePaths();\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const raw = fs.readFileSync(p, 'utf-8');\n const parsed = JSON.parse(raw);\n this.manifestCache = parsed;\n return parsed;\n } catch (err: unknown) {\n throw new Error(\n `[express-inertia] Failed to parse Vite manifest at ${p}: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n }\n\n throw new Error(\n `[express-inertia] Vite manifest not found. Looked in:\\n${candidatePaths.join('\\n')}\\nRun your build step (e.g. vite build) to generate it.`\n );\n }\n\n /**\n * Generate HTML script & link tags for the given entrypoint(s).\n * @param entrypoints Single entry string or array of entry paths (e.g. 'src/main.ts' or ['src/main.ts', 'src/style.css'])\n */\n public renderTags(entrypoints: string | string[]): string {\n const entries = Array.isArray(entrypoints) ? entrypoints : [entrypoints];\n const tags: string[] = [];\n\n if (this.isDev()) {\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n tags.push(`<script type=\"module\" src=\"${devUrl}/@vite/client\"></script>`);\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n if (cleanEntry.endsWith('.css') || cleanEntry.endsWith('.scss') || cleanEntry.endsWith('.less')) {\n tags.push(`<link rel=\"stylesheet\" href=\"${devUrl}/${cleanEntry}\">`);\n } else {\n tags.push(`<script type=\"module\" src=\"${devUrl}/${cleanEntry}\"></script>`);\n }\n }\n\n return tags.join('\\n');\n }\n\n // Production mode\n const manifest = this.getManifest();\n const basePath = this.config.base.endsWith('/') ? this.config.base : `${this.config.base}/`;\n const renderedCss = new Set<string>();\n const renderedPreload = new Set<string>();\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n const chunk =\n manifest[cleanEntry] ||\n Object.values(manifest).find(\n (c) =>\n c.src === cleanEntry ||\n c.file === cleanEntry ||\n (c.src && (c.src.endsWith(cleanEntry) || c.src.endsWith(`/${cleanEntry}`))) ||\n (c.file && (c.file.endsWith(cleanEntry) || c.file.endsWith(`/${cleanEntry}`)))\n );\n\n if (!chunk) {\n if (!/\\.(css|scss|sass|less)$/.test(cleanEntry)) {\n this.logger.warn('Entry not found in Vite manifest', { entry, manifestPath: this.config.manifestPath });\n }\n continue;\n }\n\n // Add CSS files\n if (chunk.css) {\n for (const cssFile of chunk.css) {\n if (!renderedCss.has(cssFile)) {\n renderedCss.add(cssFile);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${cssFile}\">`);\n }\n }\n }\n\n // If entry itself is a CSS file\n if (chunk.file.endsWith('.css')) {\n if (!renderedCss.has(chunk.file)) {\n renderedCss.add(chunk.file);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${chunk.file}\">`);\n }\n } else {\n // JS entry file\n tags.push(`<script type=\"module\" src=\"${basePath}${chunk.file}\"></script>`);\n }\n\n // Add module preloads\n if (chunk.imports) {\n for (const imp of chunk.imports) {\n const impChunk = manifest[imp];\n if (impChunk && !renderedPreload.has(impChunk.file)) {\n renderedPreload.add(impChunk.file);\n tags.push(`<link rel=\"modulepreload\" href=\"${basePath}${impChunk.file}\">`);\n }\n }\n }\n }\n\n return tags.join('\\n');\n }\n\n /**\n * Generates the React Fast Refresh preamble for development.\n */\n public renderReactRefresh(): string {\n if (!this.isDev()) {\n return '';\n }\n\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n return `<script type=\"module\">\n import RefreshRuntime from \"${devUrl}/@react-refresh\";\n RefreshRuntime.injectIntoGlobalHook(window);\n window.$RefreshReg$ = () => {};\n window.$RefreshSig$ = () => (type) => type;\n window.__vite_plugin_react_preamble_installed__ = true;\n</script>`;\n }\n\n /**\n * Generates an SRI hash for the given asset file content.\n * Useful for adding integrity attributes to script/link tags.\n */\n public async generateSriHashForAsset(assetPath: string): Promise<string> {\n const fullPath = path.resolve(this.config.publicDir, assetPath);\n const content = fs.readFileSync(fullPath);\n return generateSriHash(content);\n }\n}\n\n/**\n * Creates a configured ViteHelper instance.\n */\nexport function createViteHelper(config?: ViteConfig): ViteHelper {\n return new ViteHelper(config);\n}\n\n/**\n * Default singleton instance.\n */\nexport const defaultViteHelper = new ViteHelper();\n"]}
package/dist/vite.mjs CHANGED
@@ -50,8 +50,13 @@ function createLogger(options = {}) {
50
50
  }
51
51
 
52
52
  // src/utils.ts
53
+ var cryptoModule;
54
+ async function getCrypto() {
55
+ cryptoModule ??= await import('crypto');
56
+ return cryptoModule;
57
+ }
53
58
  async function generateSriHash(content) {
54
- const crypto = await import('crypto');
59
+ const crypto = await getCrypto();
55
60
  const hash = crypto.createHash("sha384").update(content);
56
61
  return `sha384-${hash.digest("base64")}`;
57
62
  }
@@ -76,6 +81,8 @@ function resolveDevServerUrl(config, override) {
76
81
  }
77
82
  function inertiaVitePlugin(options = {}) {
78
83
  const logger = createLogger({ prefix: "express-inertia:vite" });
84
+ let cleanupRegistered = false;
85
+ let exitConfig = null;
79
86
  const write = (config, server) => {
80
87
  try {
81
88
  const hotFile = path.resolve(config.root, options.hotFile || "public/hot");
@@ -94,6 +101,11 @@ function inertiaVitePlugin(options = {}) {
94
101
  } catch {
95
102
  }
96
103
  };
104
+ const removeOnExit = () => {
105
+ if (exitConfig) {
106
+ remove(exitConfig);
107
+ }
108
+ };
97
109
  return {
98
110
  name: "express-inertia-hot-file",
99
111
  configResolved(config) {
@@ -105,9 +117,13 @@ function inertiaVitePlugin(options = {}) {
105
117
  },
106
118
  configureServer(server) {
107
119
  write(server.config, server);
120
+ exitConfig = server.config;
108
121
  server.httpServer?.once("listening", () => write(server.config, server));
109
122
  server.httpServer?.on("close", () => remove(server.config));
110
- process.once("exit", () => remove(server.config));
123
+ if (!cleanupRegistered) {
124
+ process.once("exit", removeOnExit);
125
+ cleanupRegistered = true;
126
+ }
111
127
  },
112
128
  buildStart() {
113
129
  }
@@ -130,7 +146,7 @@ var ViteHelper = class {
130
146
  ),
131
147
  base: config?.base || `/${buildDir}/`,
132
148
  manifest: config?.manifest || null,
133
- isDev: config?.isDev ?? false,
149
+ isDev: config?.isDev,
134
150
  devServerUrlOverride: config?.devServerUrlOverride || null
135
151
  };
136
152
  }
@@ -142,8 +158,8 @@ var ViteHelper = class {
142
158
  * NODE_ENV switch is required to toggle between dev and build assets.
143
159
  */
144
160
  isDev() {
145
- if (this.config.isDev === true) {
146
- return true;
161
+ if (this.config.isDev !== void 0) {
162
+ return this.config.isDev;
147
163
  }
148
164
  const candidatePaths = [
149
165
  this.config.hotFile,
@@ -177,6 +193,12 @@ var ViteHelper = class {
177
193
  }
178
194
  return this.config.devServerUrl;
179
195
  }
196
+ /**
197
+ * Get the production asset base path (always ends with a trailing slash).
198
+ */
199
+ getBasePath() {
200
+ return this.config.base.endsWith("/") ? this.config.base : `${this.config.base}/`;
201
+ }
180
202
  /**
181
203
  * Check if manifest file exists.
182
204
  */
@@ -217,7 +239,9 @@ var ViteHelper = class {
217
239
  this.manifestCache = parsed;
218
240
  return parsed;
219
241
  } catch (err) {
220
- throw new Error(`[express-inertia] Failed to parse Vite manifest at ${p}: ${err.message}`);
242
+ throw new Error(
243
+ `[express-inertia] Failed to parse Vite manifest at ${p}: ${err instanceof Error ? err.message : String(err)}`
244
+ );
221
245
  }
222
246
  }
223
247
  }
package/dist/vite.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts","../src/utils.ts","../src/vite.ts"],"names":[],"mappings":"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","file":"vite.mjs","sourcesContent":["export interface Logger {\n warn(message: string, meta?: Record<string, any>): void;\n error(message: string, meta?: Record<string, any>): void;\n info(message: string, meta?: Record<string, any>): void;\n debug(message: string, meta?: Record<string, any>): void;\n}\n\nexport interface LoggerOptions {\n prefix?: string;\n logger?: Logger;\n}\n\nconst DEFAULT_PREFIX = '@arponascension/express-inertia';\n\nfunction createConsoleLogger(prefix: string): Logger {\n const pad = (str: string) => str.padEnd(2, ' ');\n\n return {\n warn(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.warn(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.warn(`[${prefix}] ${message}`);\n }\n },\n\n error(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.error(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.error(`[${prefix}] ${message}`);\n }\n },\n\n info(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.info(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.info(`[${prefix}] ${message}`);\n }\n },\n\n debug(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.debug(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.debug(`[${prefix}] ${message}`);\n }\n },\n };\n}\n\nlet globalLogger: Logger = createConsoleLogger(DEFAULT_PREFIX);\n\nexport function setGlobalLogger(logger: Logger): void {\n globalLogger = logger;\n}\n\nexport function getGlobalLogger(): Logger {\n return globalLogger;\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const prefix = options.prefix || DEFAULT_PREFIX;\n if (options.logger) {\n return options.logger;\n }\n return createConsoleLogger(prefix);\n}\n","import type { Request } from 'express';\nimport type {\n PageProps,\n PropCallback,\n LazyProp,\n AlwaysProp,\n DeferredProp,\n MergeProp,\n OptionalProp,\n Page,\n SecurityOptions,\n} from './types.js';\n\n/**\n * Marks a prop as lazy. Lazy props are ONLY evaluated during partial reloads\n * when specifically requested in the `only` array by the client.\n */\nexport function lazy<T = any>(callback: PropCallback<T>): LazyProp<T> {\n return {\n __inertia_lazy: true,\n callback,\n };\n}\n\n/**\n * Marks a prop as always included. Always props are evaluated and returned\n * on every request, including partial reloads, even if not explicitly requested.\n */\nexport function always<T = any>(value: T | PropCallback<T>): AlwaysProp<T> {\n return {\n __inertia_always: true,\n value,\n };\n}\n\n/**\n * Marks a prop as deferred (Inertia v2).\n */\nexport function defer<T = any>(\n callback: PropCallback<T>,\n options?: { group?: string }\n): DeferredProp<T> {\n return {\n __inertia_deferred: true,\n callback,\n group: options?.group,\n };\n}\n\n/**\n * Marks a prop as mergeable (Inertia v2).\n */\nexport function merge<T = any>(value: T | PropCallback<T>): MergeProp<T> {\n return {\n __inertia_merge: true,\n value,\n };\n}\n\n/**\n * Marks a prop as optional.\n */\nexport function optional<T = any>(callback: PropCallback<T>): OptionalProp<T> {\n return {\n __inertia_optional: true,\n callback,\n };\n}\n\nexport function isLazy(val: any): val is LazyProp {\n return val && typeof val === 'object' && val.__inertia_lazy === true;\n}\n\nexport function isAlways(val: any): val is AlwaysProp {\n return val && typeof val === 'object' && val.__inertia_always === true;\n}\n\nexport function isDeferred(val: any): val is DeferredProp {\n return val && typeof val === 'object' && val.__inertia_deferred === true;\n}\n\nexport function isMerge(val: any): val is MergeProp {\n return val && typeof val === 'object' && val.__inertia_merge === true;\n}\n\nexport function isOptional(val: any): val is OptionalProp {\n return val && typeof val === 'object' && val.__inertia_optional === true;\n}\n\n/**\n * Evaluates and resolves all props (promises, functions, lazy, always, merge, deferred)\n * based on current Inertia request context and partial reload headers.\n */\nexport async function resolveProps(\n rawProps: PageProps,\n req: Request,\n component: string\n): Promise<{\n resolvedProps: PageProps;\n deferredProps?: Record<string, string[]>;\n mergeProps?: string[];\n}> {\n const isPartial =\n req.header('X-Inertia-Partial-Component') === component &&\n Boolean(req.header('X-Inertia-Partial-Data'));\n\n const partialKeys = isPartial\n ? (req.header('X-Inertia-Partial-Data') || '')\n .split(',')\n .map((k) => k.trim())\n .filter(Boolean)\n : [];\n\n const resolvedProps: PageProps = {};\n const deferredMap: Record<string, string[]> = {};\n const mergeKeys: string[] = [];\n\n for (const [key, rawValue] of Object.entries(rawProps)) {\n // Collect merge props\n if (isMerge(rawValue)) {\n mergeKeys.push(key);\n }\n\n // Collect deferred props\n if (isDeferred(rawValue)) {\n const group = rawValue.group || 'default';\n if (!deferredMap[group]) {\n deferredMap[group] = [];\n }\n deferredMap[group].push(key);\n }\n\n if (isPartial) {\n const isRequested = partialKeys.includes(key);\n const isAlwaysIncluded = isAlways(rawValue);\n\n // In partial reload, only include if explicitly requested or marked as always\n if (!isRequested && !isAlwaysIncluded) {\n continue;\n }\n } else {\n // In full request, lazy and deferred props are omitted.\n // Optional props are still included on initial load.\n if (isLazy(rawValue) || isDeferred(rawValue)) {\n continue;\n }\n }\n\n // Resolve prop value\n resolvedProps[key] = await unwrapValue(rawValue, req);\n }\n\n return {\n resolvedProps,\n deferredProps: Object.keys(deferredMap).length > 0 ? deferredMap : undefined,\n mergeProps: mergeKeys.length > 0 ? mergeKeys : undefined,\n };\n}\n\n/**\n * Unwraps closures, promises, and wrapper objects to get the actual value.\n */\nexport async function unwrapValue(val: any, req: Request): Promise<any> {\n if (val === null || val === undefined) {\n return val;\n }\n\n // Handle wrapper types\n if (isLazy(val)) {\n val = val.callback;\n } else if (isAlways(val)) {\n val = val.value;\n } else if (isDeferred(val)) {\n val = val.callback;\n } else if (isMerge(val)) {\n val = val.value;\n } else if (isOptional(val)) {\n val = val.callback;\n }\n\n // If function / closure, execute it\n if (typeof val === 'function') {\n val = val(req);\n }\n\n // If promise, await it\n if (val && typeof val.then === 'function') {\n val = await val;\n }\n\n return val;\n}\n\n/**\n * Escapes characters for HTML attribute insertion to prevent XSS.\n */\nexport function escapeHtmlAttr(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Serializes Page object safely for data-page HTML attribute.\n */\nexport function serializePage(page: Page): string {\n return escapeHtmlAttr(safeStringify(page));\n}\n\n/**\n * Safely stringifies an object, replacing circular references with null.\n */\nexport function safeStringify(obj: any): string {\n const seen = new WeakSet();\n return JSON.stringify(obj, (_key, value) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return null;\n }\n seen.add(value);\n }\n return value;\n });\n}\n\n/**\n * Default pattern for safe component names: alphanumeric, hyphens, and underscores,\n * optionally separated by single forward slashes. Blocks path traversal sequences\n * like `..`, leading/trailing slashes, and consecutive slashes.\n */\nexport const DEFAULT_COMPONENT_NAME_PATTERN = /^[\\w-]+(?:\\/[\\w-]+)*$/;\n\n/**\n * Validates a component name to prevent path traversal and injection attacks.\n * Throws a TypeError if the name contains suspicious characters.\n */\nexport function validateComponentName(\n component: string,\n pattern: RegExp = DEFAULT_COMPONENT_NAME_PATTERN\n): void {\n if (!pattern.test(component)) {\n throw new TypeError(\n `Invalid component name \"${component}\". Component names must match the pattern ${pattern}.`\n );\n }\n}\n\n/**\n * Recursively sanitizes viewData by stripping functions and undefined values.\n * Only plain objects and primitive values are preserved.\n */\nexport function sanitizeViewData(data: Record<string, any>): Record<string, any> {\n const seen = new WeakSet();\n\n function sanitize(value: any): any {\n if (typeof value === 'function' || value === undefined) {\n return undefined;\n }\n\n if (value === null || typeof value !== 'object' || Buffer.isBuffer(value)) {\n return value;\n }\n\n if (seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value.map((item) => sanitize(item));\n }\n\n const sanitized: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n const cleaned = sanitize(val);\n if (cleaned !== undefined) {\n sanitized[key] = cleaned;\n }\n }\n return sanitized;\n }\n\n return sanitize(data) as Record<string, any>;\n}\n\n/**\n * Generates a Subresource Integrity (SRI) hash for a given string.\n * Returns the base64-encoded SHA-384 hash prefixed with 'sha384-'.\n */\nexport async function generateSriHash(content: string | Buffer): Promise<string> {\n const crypto = await import('node:crypto');\n const hash = crypto.createHash('sha384').update(content);\n return `sha384-${hash.digest('base64')}`;\n}\n\n","import fs from 'fs';\nimport path from 'path';\nimport type { ViteConfig } from './types.js';\nimport { createLogger } from './logger.js';\nimport { generateSriHash } from './utils.js';\n\n/**\n * Options for the auto dev/build Vite plugin.\n */\nexport interface InertiaVitePluginOptions {\n /**\n * Path to the hot file. Relative paths are resolved against Vite's project root.\n * @default 'public/hot'\n */\n hotFile?: string;\n /**\n * Override the dev server URL written to the hot file.\n * Defaults to the resolved Vite dev server URL.\n */\n devServerUrl?: string;\n}\n\n/**\n * Structural subset of Vite's `Plugin` type so the core package does not need\n * a hard runtime dependency on Vite.\n */\nexport interface InertiaVitePlugin {\n name: string;\n configResolved?: (config: any) => void;\n configureServer?: (server: any) => void;\n buildStart?: () => void;\n}\n\n/**\n * Derive the dev server URL from Vite's resolved config, mirroring Laravel's\n * vite-plugin logic (honours `server.origin`, then https/host/port).\n */\nfunction resolveDevServerUrl(config: any, override?: string): string {\n if (override) return override.replace(/\\/$/, '');\n const server = config?.server || {};\n if (typeof server.origin === 'string' && server.origin) {\n return server.origin.replace(/\\/$/, '');\n }\n const scheme = server.https ? 'https' : 'http';\n let host = server.host;\n if (!host || host === '0.0.0.0' || host === '::' || host === '::0' || host === true) {\n host = 'localhost';\n }\n if (host.includes(':') && !host.startsWith('[')) {\n host = `[${host}]`;\n }\n const port = server.port ?? 5173;\n return `${scheme}://${host}:${port}`;\n}\n\n/**\n * Vite plugin that automatically toggles Express between dev and build mode.\n *\n * - `vite dev` writes a `hot` file (signalling dev mode) and removes it on shutdown.\n * - `vite build` removes any stale `hot` file, so Express falls back to the built manifest.\n *\n * Use it in your `vite.config.ts`:\n * ```ts\n * import { inertiaVitePlugin } from '@arponascension/express-inertia/vite';\n * export default defineConfig({\n * plugins: [inertiaVitePlugin()],\n * });\n * ```\n */\nexport function inertiaVitePlugin(options: InertiaVitePluginOptions = {}): InertiaVitePlugin {\n const logger = createLogger({ prefix: 'express-inertia:vite' });\n const write = (config: any, server?: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n const actual = server?.resolvedUrls?.local?.[0];\n const url = actual || resolveDevServerUrl(config, options.devServerUrl);\n fs.mkdirSync(path.dirname(hotFile), { recursive: true });\n fs.writeFileSync(hotFile, url.replace(/\\/$/, ''));\n } catch (err) {\n logger.warn('Failed to write Vite hot file', { error: (err as Error).message });\n }\n };\n\n const remove = (config: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n fs.rmSync(hotFile, { force: true });\n } catch {\n // ignore\n }\n };\n\n return {\n name: 'express-inertia-hot-file',\n\n configResolved(config) {\n if (config.command === 'build') {\n remove(config);\n } else {\n write(config);\n }\n },\n\n configureServer(server) {\n write(server.config, server);\n server.httpServer?.once('listening', () => write(server.config, server));\n server.httpServer?.on('close', () => remove(server.config));\n process.once('exit', () => remove(server.config));\n },\n\n buildStart() {\n // noop guard: build-time cleanup happens in configResolved\n },\n };\n}\n\nexport interface ViteManifestChunk {\n src?: string;\n file: string;\n css?: string[];\n assets?: string[];\n isEntry?: boolean;\n isDynamicEntry?: boolean;\n imports?: string[];\n dynamicImports?: string[];\n}\n\nexport type ViteManifest = Record<string, ViteManifestChunk>;\n\nexport interface ResolvedViteConfig {\n publicDir: string;\n buildDir: string;\n devServerUrl: string;\n hotFile: string;\n manifestPath: string;\n base: string;\n manifest: ViteManifest | null;\n isDev: boolean;\n devServerUrlOverride: string | null;\n}\n\nexport class ViteHelper {\n private config: ResolvedViteConfig;\n private manifestCache: ViteManifest | null = null;\n private logger = createLogger({ prefix: 'express-inertia:vite' });\n\n constructor(config?: ViteConfig) {\n const publicDir = config?.publicDir ? path.resolve(config.publicDir) : path.resolve('public');\n const buildDir = config?.buildDir || 'build';\n\n this.config = {\n publicDir,\n buildDir,\n devServerUrl: config?.devServerUrl || 'http://localhost:5173',\n hotFile: path.resolve(config?.hotFile || path.join(publicDir, 'hot')),\n manifestPath: path.resolve(\n config?.manifestPath || path.join(publicDir, buildDir, '.vite', 'manifest.json')\n ),\n base: config?.base || `/${buildDir}/`,\n manifest: config?.manifest || null,\n isDev: config?.isDev ?? false,\n devServerUrlOverride: config?.devServerUrlOverride || null,\n };\n }\n\n /**\n * Detect whether the Vite dev server is running.\n *\n * Mirrors Laravel: the presence of the `hot` file is the sole signal. Vite's\n * dev server writes a `hot` file on startup and removes it on shutdown, so no\n * NODE_ENV switch is required to toggle between dev and build assets.\n */\n public isDev(): boolean {\n if (this.config.isDev === true) {\n return true;\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n /**\n * Get development server URL from hot file or config.\n */\n public getDevServerUrl(): string {\n if (this.config.devServerUrlOverride) {\n return this.config.devServerUrlOverride.replace(/\\/$/, '');\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const content = fs.readFileSync(p, 'utf-8').trim();\n if (content.startsWith('http://') || content.startsWith('https://')) {\n return content;\n }\n } catch {\n // ignore\n }\n }\n }\n\n return this.config.devServerUrl;\n }\n\n /**\n * Check if manifest file exists.\n */\n public manifestExists(): boolean {\n if (this.config.manifest) {\n return true;\n }\n const candidatePaths = this.getManifestCandidatePaths();\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n private getManifestCandidatePaths(): string[] {\n const { publicDir, buildDir } = this.config;\n return [\n this.config.manifestPath,\n path.resolve(publicDir, buildDir, '.vite', 'manifest.json'),\n path.resolve(publicDir, buildDir, 'manifest.json'),\n path.resolve(buildDir, '.vite', 'manifest.json'),\n path.resolve(buildDir, 'manifest.json'),\n ];\n }\n\n /**\n * Load and cache the production manifest.\n */\n public getManifest(): ViteManifest {\n if (this.manifestCache) {\n return this.manifestCache;\n }\n\n if (this.config.manifest) {\n this.manifestCache = this.config.manifest;\n return this.config.manifest;\n }\n\n const candidatePaths = this.getManifestCandidatePaths();\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const raw = fs.readFileSync(p, 'utf-8');\n const parsed = JSON.parse(raw);\n this.manifestCache = parsed;\n return parsed;\n } catch (err: any) {\n throw new Error(`[express-inertia] Failed to parse Vite manifest at ${p}: ${err.message}`);\n }\n }\n }\n\n throw new Error(\n `[express-inertia] Vite manifest not found. Looked in:\\n${candidatePaths.join('\\n')}\\nRun your build step (e.g. vite build) to generate it.`\n );\n }\n\n /**\n * Generate HTML script & link tags for the given entrypoint(s).\n * @param entrypoints Single entry string or array of entry paths (e.g. 'src/main.ts' or ['src/main.ts', 'src/style.css'])\n */\n public renderTags(entrypoints: string | string[]): string {\n const entries = Array.isArray(entrypoints) ? entrypoints : [entrypoints];\n const tags: string[] = [];\n\n if (this.isDev()) {\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n tags.push(`<script type=\"module\" src=\"${devUrl}/@vite/client\"></script>`);\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n if (cleanEntry.endsWith('.css') || cleanEntry.endsWith('.scss') || cleanEntry.endsWith('.less')) {\n tags.push(`<link rel=\"stylesheet\" href=\"${devUrl}/${cleanEntry}\">`);\n } else {\n tags.push(`<script type=\"module\" src=\"${devUrl}/${cleanEntry}\"></script>`);\n }\n }\n\n return tags.join('\\n');\n }\n\n // Production mode\n const manifest = this.getManifest();\n const basePath = this.config.base.endsWith('/') ? this.config.base : `${this.config.base}/`;\n const renderedCss = new Set<string>();\n const renderedPreload = new Set<string>();\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n const chunk =\n manifest[cleanEntry] ||\n Object.values(manifest).find(\n (c) =>\n c.src === cleanEntry ||\n c.file === cleanEntry ||\n (c.src && (c.src.endsWith(cleanEntry) || c.src.endsWith(`/${cleanEntry}`))) ||\n (c.file && (c.file.endsWith(cleanEntry) || c.file.endsWith(`/${cleanEntry}`)))\n );\n\n if (!chunk) {\n if (!/\\.(css|scss|sass|less)$/.test(cleanEntry)) {\n this.logger.warn('Entry not found in Vite manifest', { entry, manifestPath: this.config.manifestPath });\n }\n continue;\n }\n\n // Add CSS files\n if (chunk.css) {\n for (const cssFile of chunk.css) {\n if (!renderedCss.has(cssFile)) {\n renderedCss.add(cssFile);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${cssFile}\">`);\n }\n }\n }\n\n // If entry itself is a CSS file\n if (chunk.file.endsWith('.css')) {\n if (!renderedCss.has(chunk.file)) {\n renderedCss.add(chunk.file);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${chunk.file}\">`);\n }\n } else {\n // JS entry file\n tags.push(`<script type=\"module\" src=\"${basePath}${chunk.file}\"></script>`);\n }\n\n // Add module preloads\n if (chunk.imports) {\n for (const imp of chunk.imports) {\n const impChunk = manifest[imp];\n if (impChunk && !renderedPreload.has(impChunk.file)) {\n renderedPreload.add(impChunk.file);\n tags.push(`<link rel=\"modulepreload\" href=\"${basePath}${impChunk.file}\">`);\n }\n }\n }\n }\n\n return tags.join('\\n');\n }\n\n /**\n * Generates the React Fast Refresh preamble for development.\n */\n public renderReactRefresh(): string {\n if (!this.isDev()) {\n return '';\n }\n\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n return `<script type=\"module\">\n import RefreshRuntime from \"${devUrl}/@react-refresh\";\n RefreshRuntime.injectIntoGlobalHook(window);\n window.$RefreshReg$ = () => {};\n window.$RefreshSig$ = () => (type) => type;\n window.__vite_plugin_react_preamble_installed__ = true;\n</script>`;\n }\n\n /**\n * Generates an SRI hash for the given asset file content.\n * Useful for adding integrity attributes to script/link tags.\n */\n public async generateSriHashForAsset(assetPath: string): Promise<string> {\n const fullPath = path.resolve(this.config.publicDir, assetPath);\n const content = fs.readFileSync(fullPath);\n return generateSriHash(content);\n }\n}\n\n/**\n * Creates a configured ViteHelper instance.\n */\nexport function createViteHelper(config?: ViteConfig): ViteHelper {\n return new ViteHelper(config);\n}\n\n/**\n * Default singleton instance.\n */\nexport const defaultViteHelper = new ViteHelper();\n"]}
1
+ {"version":3,"sources":["../src/logger.ts","../src/utils.ts","../src/vite.ts"],"names":[],"mappings":"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","file":"vite.mjs","sourcesContent":["export interface Logger {\n warn(message: string, meta?: Record<string, any>): void;\n error(message: string, meta?: Record<string, any>): void;\n info(message: string, meta?: Record<string, any>): void;\n debug(message: string, meta?: Record<string, any>): void;\n}\n\nexport interface LoggerOptions {\n prefix?: string;\n logger?: Logger;\n}\n\nconst DEFAULT_PREFIX = '@arponascension/express-inertia';\n\nfunction createConsoleLogger(prefix: string): Logger {\n return {\n warn(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.warn(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.warn(`[${prefix}] ${message}`);\n }\n },\n\n error(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.error(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.error(`[${prefix}] ${message}`);\n }\n },\n\n info(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.info(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.info(`[${prefix}] ${message}`);\n }\n },\n\n debug(message: string, meta?: Record<string, any>) {\n const payload = meta ? { ...meta } : undefined;\n if (payload && Object.keys(payload).length > 0) {\n console.debug(`[${prefix}] ${message}`, JSON.stringify(payload));\n } else {\n console.debug(`[${prefix}] ${message}`);\n }\n },\n };\n}\n\nlet globalLogger: Logger = createConsoleLogger(DEFAULT_PREFIX);\n\nexport function setGlobalLogger(logger: Logger): void {\n globalLogger = logger;\n}\n\nexport function getGlobalLogger(): Logger {\n return globalLogger;\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const prefix = options.prefix || DEFAULT_PREFIX;\n if (options.logger) {\n return options.logger;\n }\n return createConsoleLogger(prefix);\n}\n","import type { Request } from 'express';\nimport type {\n PageProps,\n PropCallback,\n LazyProp,\n AlwaysProp,\n DeferredProp,\n MergeProp,\n OptionalProp,\n Page,\n SecurityOptions,\n} from './types.js';\n\n/**\n * Marks a prop as lazy. Lazy props are ONLY evaluated during partial reloads\n * when specifically requested in the `only` array by the client.\n */\nexport function lazy<T = any>(callback: PropCallback<T>): LazyProp<T> {\n return {\n __inertia_lazy: true,\n callback,\n };\n}\n\n/**\n * Marks a prop as always included. Always props are evaluated and returned\n * on every request, including partial reloads, even if not explicitly requested.\n */\nexport function always<T = any>(value: T | PropCallback<T>): AlwaysProp<T> {\n return {\n __inertia_always: true,\n value,\n };\n}\n\n/**\n * Marks a prop as deferred (Inertia v2).\n */\nexport function defer<T = any>(\n callback: PropCallback<T>,\n options?: { group?: string }\n): DeferredProp<T> {\n return {\n __inertia_deferred: true,\n callback,\n group: options?.group,\n };\n}\n\n/**\n * Marks a prop as mergeable (Inertia v2).\n */\nexport function merge<T = any>(value: T | PropCallback<T>): MergeProp<T> {\n return {\n __inertia_merge: true,\n value,\n };\n}\n\n/**\n * Marks a prop as optional.\n */\nexport function optional<T = any>(callback: PropCallback<T>): OptionalProp<T> {\n return {\n __inertia_optional: true,\n callback,\n };\n}\n\nexport function isLazy(val: any): val is LazyProp {\n return val && typeof val === 'object' && val.__inertia_lazy === true;\n}\n\nexport function isAlways(val: any): val is AlwaysProp {\n return val && typeof val === 'object' && val.__inertia_always === true;\n}\n\nexport function isDeferred(val: any): val is DeferredProp {\n return val && typeof val === 'object' && val.__inertia_deferred === true;\n}\n\nexport function isMerge(val: any): val is MergeProp {\n return val && typeof val === 'object' && val.__inertia_merge === true;\n}\n\nexport function isOptional(val: any): val is OptionalProp {\n return val && typeof val === 'object' && val.__inertia_optional === true;\n}\n\n/**\n * Evaluates and resolves all props (promises, functions, lazy, always, merge, deferred)\n * based on current Inertia request context and partial reload headers.\n */\nexport async function resolveProps(\n rawProps: PageProps,\n req: Request,\n component: string\n): Promise<{\n resolvedProps: PageProps;\n deferredProps?: Record<string, string[]>;\n mergeProps?: string[];\n}> {\n const isPartial =\n req.header('X-Inertia-Partial-Component') === component &&\n Boolean(req.header('X-Inertia-Partial-Data'));\n\n const partialKeys = isPartial\n ? (req.header('X-Inertia-Partial-Data') || '')\n .split(',')\n .map((k) => k.trim())\n .filter(Boolean)\n : [];\n\n const resolvedProps: PageProps = {};\n const deferredMap: Record<string, string[]> = {};\n const mergeKeys: string[] = [];\n\n for (const [key, rawValue] of Object.entries(rawProps)) {\n // Collect merge props\n if (isMerge(rawValue)) {\n mergeKeys.push(key);\n }\n\n // Collect deferred props\n if (isDeferred(rawValue)) {\n const group = rawValue.group || 'default';\n if (!deferredMap[group]) {\n deferredMap[group] = [];\n }\n deferredMap[group].push(key);\n }\n\n if (isPartial) {\n const isRequested = partialKeys.includes(key);\n const isAlwaysIncluded = isAlways(rawValue);\n\n // In partial reload, only include if explicitly requested or marked as always\n if (!isRequested && !isAlwaysIncluded) {\n continue;\n }\n } else {\n // In full request, lazy and deferred props are omitted.\n // Optional props are still included on initial load.\n if (isLazy(rawValue) || isDeferred(rawValue)) {\n continue;\n }\n }\n\n // Resolve prop value\n resolvedProps[key] = await unwrapValue(rawValue, req);\n }\n\n return {\n resolvedProps,\n deferredProps: Object.keys(deferredMap).length > 0 ? deferredMap : undefined,\n mergeProps: mergeKeys.length > 0 ? mergeKeys : undefined,\n };\n}\n\n/**\n * Unwraps closures, promises, and wrapper objects to get the actual value.\n */\nexport async function unwrapValue(val: any, req: Request): Promise<any> {\n if (val === null || val === undefined) {\n return val;\n }\n\n // Handle wrapper types\n if (isLazy(val)) {\n val = val.callback;\n } else if (isAlways(val)) {\n val = val.value;\n } else if (isDeferred(val)) {\n val = val.callback;\n } else if (isMerge(val)) {\n val = val.value;\n } else if (isOptional(val)) {\n val = val.callback;\n }\n\n // If function / closure, execute it\n if (typeof val === 'function') {\n val = val(req);\n }\n\n // If promise, await it\n if (val && typeof val.then === 'function') {\n val = await val;\n }\n\n return val;\n}\n\n/**\n * Escapes characters for HTML attribute insertion to prevent XSS.\n */\nexport function escapeHtmlAttr(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Serializes Page object safely for data-page HTML attribute.\n */\nexport function serializePage(page: Page): string {\n return escapeHtmlAttr(safeStringify(page));\n}\n\n/**\n * Safely stringifies an object, replacing circular references with null.\n */\nexport function safeStringify(obj: any): string {\n const seen = new WeakSet();\n return JSON.stringify(obj, (_key, value) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return null;\n }\n seen.add(value);\n }\n return value;\n });\n}\n\n/**\n * Default pattern for safe component names: alphanumeric, hyphens, and underscores,\n * optionally separated by single forward slashes. Blocks path traversal sequences\n * like `..`, leading/trailing slashes, and consecutive slashes.\n */\nexport const DEFAULT_COMPONENT_NAME_PATTERN = /^[\\w-]+(?:\\/[\\w-]+)*$/;\n\n/**\n * Default security settings. Component name validation and view data\n * sanitization are both enabled by default and can be toggled independently.\n */\nexport const DEFAULT_SECURITY_OPTIONS: SecurityOptions = {\n validateComponentNames: true,\n sanitizeViewData: true,\n};\n\n/**\n * Validates a component name to prevent path traversal and injection attacks.\n * Throws a TypeError if the name contains suspicious characters.\n */\nexport function validateComponentName(\n component: string,\n pattern: RegExp = DEFAULT_COMPONENT_NAME_PATTERN\n): void {\n if (!pattern.test(component)) {\n throw new TypeError(\n `Invalid component name \"${component}\". Component names must match the pattern ${pattern}.`\n );\n }\n}\n\n/**\n * Recursively sanitizes viewData by stripping functions and undefined values.\n * Only plain objects and primitive values are preserved.\n */\nexport function sanitizeViewData(data: Record<string, any>): Record<string, any> {\n const seen = new WeakSet();\n\n function sanitize(value: any): any {\n if (typeof value === 'function' || value === undefined) {\n return undefined;\n }\n\n if (value === null || typeof value !== 'object' || Buffer.isBuffer(value)) {\n return value;\n }\n\n if (seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n return value.map((item) => sanitize(item));\n }\n\n const sanitized: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n const cleaned = sanitize(val);\n if (cleaned !== undefined) {\n sanitized[key] = cleaned;\n }\n }\n return sanitized;\n }\n\n return sanitize(data) as Record<string, any>;\n}\n\nlet cryptoModule: typeof import('node:crypto') | undefined;\n\nasync function getCrypto(): Promise<typeof import('node:crypto')> {\n cryptoModule ??= await import('node:crypto');\n return cryptoModule;\n}\n\n/**\n * Generates a Subresource Integrity (SRI) hash for a given string.\n * Returns the base64-encoded SHA-384 hash prefixed with 'sha384-'.\n */\nexport async function generateSriHash(content: string | Buffer): Promise<string> {\n const crypto = await getCrypto();\n const hash = crypto.createHash('sha384').update(content);\n return `sha384-${hash.digest('base64')}`;\n}\n\n","import fs from 'fs';\nimport path from 'path';\nimport type { ViteConfig } from './types.js';\nimport { createLogger } from './logger.js';\nimport { generateSriHash } from './utils.js';\n\n/**\n * Options for the auto dev/build Vite plugin.\n */\nexport interface InertiaVitePluginOptions {\n /**\n * Path to the hot file. Relative paths are resolved against Vite's project root.\n * @default 'public/hot'\n */\n hotFile?: string;\n /**\n * Override the dev server URL written to the hot file.\n * Defaults to the resolved Vite dev server URL.\n */\n devServerUrl?: string;\n}\n\n/**\n * Structural subset of Vite's `Plugin` type so the core package does not need\n * a hard runtime dependency on Vite.\n */\nexport interface InertiaVitePlugin {\n name: string;\n configResolved?: (config: any) => void;\n configureServer?: (server: any) => void;\n buildStart?: () => void;\n}\n\n/**\n * Derive the dev server URL from Vite's resolved config, mirroring Laravel's\n * vite-plugin logic (honours `server.origin`, then https/host/port).\n */\nfunction resolveDevServerUrl(config: any, override?: string): string {\n if (override) return override.replace(/\\/$/, '');\n const server = config?.server || {};\n if (typeof server.origin === 'string' && server.origin) {\n return server.origin.replace(/\\/$/, '');\n }\n const scheme = server.https ? 'https' : 'http';\n let host = server.host;\n if (!host || host === '0.0.0.0' || host === '::' || host === '::0' || host === true) {\n host = 'localhost';\n }\n if (host.includes(':') && !host.startsWith('[')) {\n host = `[${host}]`;\n }\n const port = server.port ?? 5173;\n return `${scheme}://${host}:${port}`;\n}\n\n/**\n * Vite plugin that automatically toggles Express between dev and build mode.\n *\n * - `vite dev` writes a `hot` file (signalling dev mode) and removes it on shutdown.\n * - `vite build` removes any stale `hot` file, so Express falls back to the built manifest.\n *\n * Use it in your `vite.config.ts`:\n * ```ts\n * import { inertiaVitePlugin } from '@arponascension/express-inertia/vite';\n * export default defineConfig({\n * plugins: [inertiaVitePlugin()],\n * });\n * ```\n */\nexport function inertiaVitePlugin(options: InertiaVitePluginOptions = {}): InertiaVitePlugin {\n const logger = createLogger({ prefix: 'express-inertia:vite' });\n let cleanupRegistered = false;\n let exitConfig: any = null;\n const write = (config: any, server?: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n const actual = server?.resolvedUrls?.local?.[0];\n const url = actual || resolveDevServerUrl(config, options.devServerUrl);\n fs.mkdirSync(path.dirname(hotFile), { recursive: true });\n fs.writeFileSync(hotFile, url.replace(/\\/$/, ''));\n } catch (err) {\n logger.warn('Failed to write Vite hot file', { error: (err as Error).message });\n }\n };\n\n const remove = (config: any) => {\n try {\n const hotFile = path.resolve(config.root, options.hotFile || 'public/hot');\n fs.rmSync(hotFile, { force: true });\n } catch {\n // ignore\n }\n };\n\n const removeOnExit = () => {\n if (exitConfig) {\n remove(exitConfig);\n }\n };\n\n return {\n name: 'express-inertia-hot-file',\n\n configResolved(config) {\n if (config.command === 'build') {\n remove(config);\n } else {\n write(config);\n }\n },\n\n configureServer(server) {\n write(server.config, server);\n exitConfig = server.config;\n server.httpServer?.once('listening', () => write(server.config, server));\n server.httpServer?.on('close', () => remove(server.config));\n if (!cleanupRegistered) {\n process.once('exit', removeOnExit);\n cleanupRegistered = true;\n }\n },\n\n buildStart() {\n // noop guard: build-time cleanup happens in configResolved\n },\n };\n}\n\nexport interface ViteManifestChunk {\n src?: string;\n file: string;\n css?: string[];\n assets?: string[];\n isEntry?: boolean;\n isDynamicEntry?: boolean;\n imports?: string[];\n dynamicImports?: string[];\n}\n\nexport type ViteManifest = Record<string, ViteManifestChunk>;\n\nexport interface ResolvedViteConfig {\n publicDir: string;\n buildDir: string;\n devServerUrl: string;\n hotFile: string;\n manifestPath: string;\n base: string;\n manifest: ViteManifest | null;\n isDev: boolean | undefined;\n devServerUrlOverride: string | null;\n}\n\nexport class ViteHelper {\n private config: ResolvedViteConfig;\n private manifestCache: ViteManifest | null = null;\n private logger = createLogger({ prefix: 'express-inertia:vite' });\n\n constructor(config?: ViteConfig) {\n const publicDir = config?.publicDir ? path.resolve(config.publicDir) : path.resolve('public');\n const buildDir = config?.buildDir || 'build';\n\n this.config = {\n publicDir,\n buildDir,\n devServerUrl: config?.devServerUrl || 'http://localhost:5173',\n hotFile: path.resolve(config?.hotFile || path.join(publicDir, 'hot')),\n manifestPath: path.resolve(\n config?.manifestPath || path.join(publicDir, buildDir, '.vite', 'manifest.json')\n ),\n base: config?.base || `/${buildDir}/`,\n manifest: config?.manifest || null,\n isDev: config?.isDev,\n devServerUrlOverride: config?.devServerUrlOverride || null,\n };\n }\n\n /**\n * Detect whether the Vite dev server is running.\n *\n * Mirrors Laravel: the presence of the `hot` file is the sole signal. Vite's\n * dev server writes a `hot` file on startup and removes it on shutdown, so no\n * NODE_ENV switch is required to toggle between dev and build assets.\n */\n public isDev(): boolean {\n if (this.config.isDev !== undefined) {\n return this.config.isDev;\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n /**\n * Get development server URL from hot file or config.\n */\n public getDevServerUrl(): string {\n if (this.config.devServerUrlOverride) {\n return this.config.devServerUrlOverride.replace(/\\/$/, '');\n }\n\n const candidatePaths = [\n this.config.hotFile,\n path.resolve('hot'),\n path.join(this.config.publicDir, 'hot'),\n ];\n\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const content = fs.readFileSync(p, 'utf-8').trim();\n if (content.startsWith('http://') || content.startsWith('https://')) {\n return content;\n }\n } catch {\n // ignore\n }\n }\n }\n\n return this.config.devServerUrl;\n }\n\n /**\n * Get the production asset base path (always ends with a trailing slash).\n */\n public getBasePath(): string {\n return this.config.base.endsWith('/') ? this.config.base : `${this.config.base}/`;\n }\n\n /**\n * Check if manifest file exists.\n */\n public manifestExists(): boolean {\n if (this.config.manifest) {\n return true;\n }\n const candidatePaths = this.getManifestCandidatePaths();\n return candidatePaths.some((p) => fs.existsSync(p));\n }\n\n private getManifestCandidatePaths(): string[] {\n const { publicDir, buildDir } = this.config;\n return [\n this.config.manifestPath,\n path.resolve(publicDir, buildDir, '.vite', 'manifest.json'),\n path.resolve(publicDir, buildDir, 'manifest.json'),\n path.resolve(buildDir, '.vite', 'manifest.json'),\n path.resolve(buildDir, 'manifest.json'),\n ];\n }\n\n /**\n * Load and cache the production manifest.\n */\n public getManifest(): ViteManifest {\n if (this.manifestCache) {\n return this.manifestCache;\n }\n\n if (this.config.manifest) {\n this.manifestCache = this.config.manifest;\n return this.config.manifest;\n }\n\n const candidatePaths = this.getManifestCandidatePaths();\n for (const p of candidatePaths) {\n if (fs.existsSync(p)) {\n try {\n const raw = fs.readFileSync(p, 'utf-8');\n const parsed = JSON.parse(raw);\n this.manifestCache = parsed;\n return parsed;\n } catch (err: unknown) {\n throw new Error(\n `[express-inertia] Failed to parse Vite manifest at ${p}: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n }\n\n throw new Error(\n `[express-inertia] Vite manifest not found. Looked in:\\n${candidatePaths.join('\\n')}\\nRun your build step (e.g. vite build) to generate it.`\n );\n }\n\n /**\n * Generate HTML script & link tags for the given entrypoint(s).\n * @param entrypoints Single entry string or array of entry paths (e.g. 'src/main.ts' or ['src/main.ts', 'src/style.css'])\n */\n public renderTags(entrypoints: string | string[]): string {\n const entries = Array.isArray(entrypoints) ? entrypoints : [entrypoints];\n const tags: string[] = [];\n\n if (this.isDev()) {\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n tags.push(`<script type=\"module\" src=\"${devUrl}/@vite/client\"></script>`);\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n if (cleanEntry.endsWith('.css') || cleanEntry.endsWith('.scss') || cleanEntry.endsWith('.less')) {\n tags.push(`<link rel=\"stylesheet\" href=\"${devUrl}/${cleanEntry}\">`);\n } else {\n tags.push(`<script type=\"module\" src=\"${devUrl}/${cleanEntry}\"></script>`);\n }\n }\n\n return tags.join('\\n');\n }\n\n // Production mode\n const manifest = this.getManifest();\n const basePath = this.config.base.endsWith('/') ? this.config.base : `${this.config.base}/`;\n const renderedCss = new Set<string>();\n const renderedPreload = new Set<string>();\n\n for (const entry of entries) {\n const cleanEntry = entry.replace(/^\\//, '');\n const chunk =\n manifest[cleanEntry] ||\n Object.values(manifest).find(\n (c) =>\n c.src === cleanEntry ||\n c.file === cleanEntry ||\n (c.src && (c.src.endsWith(cleanEntry) || c.src.endsWith(`/${cleanEntry}`))) ||\n (c.file && (c.file.endsWith(cleanEntry) || c.file.endsWith(`/${cleanEntry}`)))\n );\n\n if (!chunk) {\n if (!/\\.(css|scss|sass|less)$/.test(cleanEntry)) {\n this.logger.warn('Entry not found in Vite manifest', { entry, manifestPath: this.config.manifestPath });\n }\n continue;\n }\n\n // Add CSS files\n if (chunk.css) {\n for (const cssFile of chunk.css) {\n if (!renderedCss.has(cssFile)) {\n renderedCss.add(cssFile);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${cssFile}\">`);\n }\n }\n }\n\n // If entry itself is a CSS file\n if (chunk.file.endsWith('.css')) {\n if (!renderedCss.has(chunk.file)) {\n renderedCss.add(chunk.file);\n tags.push(`<link rel=\"stylesheet\" href=\"${basePath}${chunk.file}\">`);\n }\n } else {\n // JS entry file\n tags.push(`<script type=\"module\" src=\"${basePath}${chunk.file}\"></script>`);\n }\n\n // Add module preloads\n if (chunk.imports) {\n for (const imp of chunk.imports) {\n const impChunk = manifest[imp];\n if (impChunk && !renderedPreload.has(impChunk.file)) {\n renderedPreload.add(impChunk.file);\n tags.push(`<link rel=\"modulepreload\" href=\"${basePath}${impChunk.file}\">`);\n }\n }\n }\n }\n\n return tags.join('\\n');\n }\n\n /**\n * Generates the React Fast Refresh preamble for development.\n */\n public renderReactRefresh(): string {\n if (!this.isDev()) {\n return '';\n }\n\n const devUrl = this.getDevServerUrl().replace(/\\/$/, '');\n return `<script type=\"module\">\n import RefreshRuntime from \"${devUrl}/@react-refresh\";\n RefreshRuntime.injectIntoGlobalHook(window);\n window.$RefreshReg$ = () => {};\n window.$RefreshSig$ = () => (type) => type;\n window.__vite_plugin_react_preamble_installed__ = true;\n</script>`;\n }\n\n /**\n * Generates an SRI hash for the given asset file content.\n * Useful for adding integrity attributes to script/link tags.\n */\n public async generateSriHashForAsset(assetPath: string): Promise<string> {\n const fullPath = path.resolve(this.config.publicDir, assetPath);\n const content = fs.readFileSync(fullPath);\n return generateSriHash(content);\n }\n}\n\n/**\n * Creates a configured ViteHelper instance.\n */\nexport function createViteHelper(config?: ViteConfig): ViteHelper {\n return new ViteHelper(config);\n}\n\n/**\n * Default singleton instance.\n */\nexport const defaultViteHelper = new ViteHelper();\n"]}