@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/README.md +301 -137
- package/dist/engine.d.mts +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.js +54 -15
- package/dist/engine.js.map +1 -1
- package/dist/engine.mjs +54 -15
- package/dist/engine.mjs.map +1 -1
- package/dist/index.d.mts +13 -3
- package/dist/index.d.ts +13 -3
- package/dist/index.js +145 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +144 -57
- package/dist/index.mjs.map +1 -1
- package/dist/{types-Co2XESgs.d.mts → types-DgBPobaU.d.mts} +11 -1
- package/dist/{types-Co2XESgs.d.ts → types-DgBPobaU.d.ts} +11 -1
- package/dist/vite.d.mts +6 -2
- package/dist/vite.d.ts +6 -2
- package/dist/vite.js +30 -6
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +30 -6
- package/dist/vite.mjs.map +1 -1
- package/package.json +22 -4
package/dist/engine.js
CHANGED
|
@@ -15,7 +15,7 @@ var path__default = /*#__PURE__*/_interopDefault(path);
|
|
|
15
15
|
// src/directives.ts
|
|
16
16
|
var customDirectives = {};
|
|
17
17
|
function escapeJsString(str) {
|
|
18
|
-
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
18
|
+
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
19
19
|
}
|
|
20
20
|
function compileBladeDirectives(templateSource, localDirectives) {
|
|
21
21
|
let compiled = templateSource;
|
|
@@ -157,8 +157,13 @@ function safeStringify(obj) {
|
|
|
157
157
|
return value;
|
|
158
158
|
});
|
|
159
159
|
}
|
|
160
|
+
var cryptoModule;
|
|
161
|
+
async function getCrypto() {
|
|
162
|
+
cryptoModule ??= await import('crypto');
|
|
163
|
+
return cryptoModule;
|
|
164
|
+
}
|
|
160
165
|
async function generateSriHash(content) {
|
|
161
|
-
const crypto = await
|
|
166
|
+
const crypto = await getCrypto();
|
|
162
167
|
const hash = crypto.createHash("sha384").update(content);
|
|
163
168
|
return `sha384-${hash.digest("base64")}`;
|
|
164
169
|
}
|
|
@@ -181,7 +186,7 @@ var ViteHelper = class {
|
|
|
181
186
|
),
|
|
182
187
|
base: config?.base || `/${buildDir}/`,
|
|
183
188
|
manifest: config?.manifest || null,
|
|
184
|
-
isDev: config?.isDev
|
|
189
|
+
isDev: config?.isDev,
|
|
185
190
|
devServerUrlOverride: config?.devServerUrlOverride || null
|
|
186
191
|
};
|
|
187
192
|
}
|
|
@@ -193,8 +198,8 @@ var ViteHelper = class {
|
|
|
193
198
|
* NODE_ENV switch is required to toggle between dev and build assets.
|
|
194
199
|
*/
|
|
195
200
|
isDev() {
|
|
196
|
-
if (this.config.isDev
|
|
197
|
-
return
|
|
201
|
+
if (this.config.isDev !== void 0) {
|
|
202
|
+
return this.config.isDev;
|
|
198
203
|
}
|
|
199
204
|
const candidatePaths = [
|
|
200
205
|
this.config.hotFile,
|
|
@@ -228,6 +233,12 @@ var ViteHelper = class {
|
|
|
228
233
|
}
|
|
229
234
|
return this.config.devServerUrl;
|
|
230
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Get the production asset base path (always ends with a trailing slash).
|
|
238
|
+
*/
|
|
239
|
+
getBasePath() {
|
|
240
|
+
return this.config.base.endsWith("/") ? this.config.base : `${this.config.base}/`;
|
|
241
|
+
}
|
|
231
242
|
/**
|
|
232
243
|
* Check if manifest file exists.
|
|
233
244
|
*/
|
|
@@ -268,7 +279,9 @@ var ViteHelper = class {
|
|
|
268
279
|
this.manifestCache = parsed;
|
|
269
280
|
return parsed;
|
|
270
281
|
} catch (err) {
|
|
271
|
-
throw new Error(
|
|
282
|
+
throw new Error(
|
|
283
|
+
`[express-inertia] Failed to parse Vite manifest at ${p}: ${err instanceof Error ? err.message : String(err)}`
|
|
284
|
+
);
|
|
272
285
|
}
|
|
273
286
|
}
|
|
274
287
|
}
|
|
@@ -374,26 +387,49 @@ new ViteHelper();
|
|
|
374
387
|
|
|
375
388
|
// src/engine.ts
|
|
376
389
|
var engineCaches = /* @__PURE__ */ new Set();
|
|
390
|
+
var engineTimestamps = /* @__PURE__ */ new Set();
|
|
391
|
+
var TEMPLATE_SOURCE_KEY = "__express_inertia_template_source__";
|
|
377
392
|
function createInertiaEngine(options) {
|
|
378
393
|
const viteHelper = options?.vite ? createViteHelper(options.vite) : createViteHelper();
|
|
379
394
|
const shouldCache = options?.cache ?? !viteHelper.isDev();
|
|
380
395
|
const inertiaVersion = options?.inertiaVersion ?? 2;
|
|
381
396
|
const defaultRootElement = options?.rootElement ?? true;
|
|
382
397
|
const templateCache = /* @__PURE__ */ new Map();
|
|
398
|
+
const templateTimestamps = /* @__PURE__ */ new Map();
|
|
383
399
|
engineCaches.add(templateCache);
|
|
400
|
+
engineTimestamps.add(templateTimestamps);
|
|
384
401
|
return function inertiaBladeEngine(filePath, rawOptions, callback) {
|
|
385
402
|
try {
|
|
386
|
-
|
|
403
|
+
const template = options?.templateSource;
|
|
404
|
+
const hasTemplateSource = template !== void 0;
|
|
405
|
+
const cacheKey = hasTemplateSource ? TEMPLATE_SOURCE_KEY : filePath;
|
|
406
|
+
let compiledTemplate;
|
|
407
|
+
let templateMtimeMs = -1;
|
|
408
|
+
if (hasTemplateSource) {
|
|
409
|
+
compiledTemplate = templateCache.get(cacheKey);
|
|
410
|
+
} else if (shouldCache) {
|
|
411
|
+
compiledTemplate = templateCache.get(cacheKey);
|
|
412
|
+
} else {
|
|
413
|
+
try {
|
|
414
|
+
templateMtimeMs = fs__default.default.statSync(filePath).mtimeMs;
|
|
415
|
+
} catch {
|
|
416
|
+
templateMtimeMs = 0;
|
|
417
|
+
}
|
|
418
|
+
if (templateTimestamps.get(cacheKey) === templateMtimeMs) {
|
|
419
|
+
compiledTemplate = templateCache.get(cacheKey);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
387
422
|
if (!compiledTemplate) {
|
|
388
|
-
const templateSource =
|
|
423
|
+
const templateSource = template !== void 0 ? template : fs__default.default.readFileSync(filePath, "utf-8");
|
|
389
424
|
const compiledSource = options?.compileTemplate ? options.compileTemplate(templateSource) : compileBladeDirectives(templateSource, options?.directives);
|
|
390
425
|
compiledTemplate = ejs__default.default.compile(compiledSource, {
|
|
391
426
|
filename: filePath,
|
|
392
|
-
cache:
|
|
427
|
+
cache: false,
|
|
393
428
|
async: false
|
|
394
429
|
});
|
|
395
|
-
|
|
396
|
-
|
|
430
|
+
templateCache.set(cacheKey, compiledTemplate);
|
|
431
|
+
if (!hasTemplateSource) {
|
|
432
|
+
templateTimestamps.set(cacheKey, templateMtimeMs);
|
|
397
433
|
}
|
|
398
434
|
}
|
|
399
435
|
const locals = { ...rawOptions };
|
|
@@ -445,15 +481,15 @@ ${scriptTag}`;
|
|
|
445
481
|
};
|
|
446
482
|
locals.csrf = () => {
|
|
447
483
|
const token = locals._csrf || locals.csrfToken || (typeof locals.req?.csrfToken === "function" ? locals.req.csrfToken() : "") || "";
|
|
448
|
-
return token ? `<input type="hidden" name="_token" value="${token}">` : "";
|
|
484
|
+
return token ? `<input type="hidden" name="_token" value="${escapeHtmlAttr(token)}">` : "";
|
|
449
485
|
};
|
|
450
486
|
locals.json = (value) => {
|
|
451
487
|
return JSON.stringify(value);
|
|
452
488
|
};
|
|
453
489
|
if (!locals.routes) {
|
|
454
|
-
locals.routes = (
|
|
490
|
+
locals.routes = (_group) => {
|
|
455
491
|
if (locals.routeConfig || locals.ziggy) {
|
|
456
|
-
const routesData = JSON.stringify(locals.routeConfig || locals.ziggy);
|
|
492
|
+
const routesData = JSON.stringify(locals.routeConfig || locals.ziggy).replace(/</g, "\\u003c");
|
|
457
493
|
return `<script>const Ziggy = ${routesData};</script>`;
|
|
458
494
|
}
|
|
459
495
|
return "";
|
|
@@ -462,7 +498,7 @@ ${scriptTag}`;
|
|
|
462
498
|
const html = compiledTemplate(locals);
|
|
463
499
|
callback(null, html);
|
|
464
500
|
} catch (err) {
|
|
465
|
-
callback(err);
|
|
501
|
+
callback(err instanceof Error ? err : new Error(String(err)));
|
|
466
502
|
}
|
|
467
503
|
};
|
|
468
504
|
}
|
|
@@ -471,6 +507,9 @@ function clearEngineCache() {
|
|
|
471
507
|
for (const cache of engineCaches) {
|
|
472
508
|
cache.clear();
|
|
473
509
|
}
|
|
510
|
+
for (const timestamps of engineTimestamps) {
|
|
511
|
+
timestamps.clear();
|
|
512
|
+
}
|
|
474
513
|
}
|
|
475
514
|
|
|
476
515
|
exports.clearEngineCache = clearEngineCache;
|
package/dist/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/directives.ts","../src/logger.ts","../src/utils.ts","../src/vite.ts","../src/engine.ts"],"names":["path","fs","ejs"],"mappings":";;;;;;;;;;;;;;;AAEA,IAAM,mBAAqD,EAAC;AAK5D,SAAS,eAAe,GAAA,EAAqB;AAC3C,EAAA,OAAO,IAAI,OAAA,CAAQ,KAAA,EAAO,MAAM,CAAA,CAAE,OAAA,CAAQ,MAAM,KAAK,CAAA;AACvD;AAcO,SAAS,sBAAA,CACd,gBACA,eAAA,EACQ;AACR,EAAA,IAAI,QAAA,GAAW,cAAA;AAGf,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA;AAAA,IAClB,8CAAA;AAAA,IACA,CAAC,QAAQ,KAAA,KAAU;AACjB,MAAA,MAAM,OAAA,GAAU,KAAA,EAAO,KAAA,CAAM,4BAA4B,CAAA;AACzD,MAAA,MAAM,KAAK,OAAA,GAAW,OAAA,CAAQ,CAAC,CAAA,IAAK,OAAA,CAAQ,CAAC,CAAA,GAAK,MAAA;AAClD,MAAA,OAAO,EAAA,GAAK,CAAA,aAAA,EAAgB,cAAA,CAAe,EAAE,CAAC,CAAA,KAAA,CAAA,GAAU,CAAA,gBAAA,CAAA;AAAA,IAC1D;AAAA,GACF;AAGA,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA;AAAA,IAClB,8EAAA;AAAA,IACA,CAAC,QAAQ,KAAA,KAAU;AACjB,MAAA,MAAM,OAAA,GAAU,KAAA,EAAO,KAAA,CAAM,4BAA4B,CAAA;AACzD,MAAA,MAAM,KAAK,OAAA,GAAW,OAAA,CAAQ,CAAC,CAAA,IAAK,OAAA,CAAQ,CAAC,CAAA,GAAK,MAAA;AAClD,MAAA,OAAO,EAAA,GAAK,CAAA,mBAAA,EAAsB,cAAA,CAAe,EAAE,CAAC,CAAA,KAAA,CAAA,GAAU,CAAA,sBAAA,CAAA;AAAA,IAChE;AAAA,GACF;AAGA,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA;AAAA,IAClB,6FAAA;AAAA,IACA;AAAA,GACF;AAGA,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA;AAAA,IAClB,2CAAA;AAAA,IACA,CAAC,QAAQ,KAAA,KAAU;AACjB,MAAA,MAAM,QAAA,GAAW,KAAA,EAAO,KAAA,CAAM,yCAAyC,CAAA;AACvE,MAAA,MAAM,MAAM,QAAA,GAAY,QAAA,CAAS,CAAC,CAAA,IAAK,QAAA,CAAS,CAAC,CAAA,GAAK,EAAA;AACtD,MAAA,IAAI,IAAI,UAAA,CAAW,GAAG,KAAK,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5C,QAAA,OAAO,YAAY,GAAG,CAAA,IAAA,CAAA;AAAA,MACxB;AACA,MAAA,OAAO,CAAA,UAAA,EAAa,cAAA,CAAe,GAAG,CAAC,CAAA,KAAA,CAAA;AAAA,IACzC;AAAA,GACF;AAGA,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA;AAAA,IAClB,mHAAA;AAAA,IACA;AAAA,GACF;AAGA,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,iCAAA,EAAmC,eAAe,CAAA;AAG9E,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA;AAAA,IAClB,+CAAA;AAAA,IACA,CAAC,QAAQ,KAAA,KAAU;AACjB,MAAA,MAAM,UAAA,GAAa,KAAA,EAAO,KAAA,CAAM,+BAA+B,CAAA;AAC/D,MAAA,MAAM,QAAQ,UAAA,GAAc,UAAA,CAAW,CAAC,CAAA,IAAK,UAAA,CAAW,CAAC,CAAA,GAAK,MAAA;AAC9D,MAAA,OAAO,KAAA,GAAQ,CAAA,YAAA,EAAe,cAAA,CAAe,KAAK,CAAC,CAAA,KAAA,CAAA,GAAU,CAAA,eAAA,CAAA;AAAA,IAC/D;AAAA,GACF;AAIA,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,iBAAA,EAAmB,sBAAsB,CAAA;AAGrE,EAAA,QAAA,GAAW,SAAS,OAAA,CAAQ,iDAAA,EAAmD,CAAC,MAAA,EAAQ,IAAI,IAAA,KAAS;AACnG,IAAA,OAAO,IAAA,GAAO,CAAA,iBAAA,EAAoB,IAAI,CAAA,GAAA,CAAA,GAAQ,CAAA,sBAAA,CAAA;AAAA,EAChD,CAAC,CAAA;AAGD,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,6BAAA,EAA+B,CAAC,QAAQ,IAAA,KAAS;AAC3E,IAAA,OAAO,IAAA,GAAO,CAAA,WAAA,EAAc,IAAI,CAAA,GAAA,CAAA,GAAQ,CAAA,gBAAA,CAAA;AAAA,EAC1C,CAAC,CAAA;AAGD,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,sBAAA,EAAwB,2BAA2B,CAAA;AAG/E,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,sCAAA,EAAwC,CAAC,QAAQ,IAAA,KAAS;AACpF,IAAA,OAAO,CAAA,SAAA,EAAY,IAAA,CAAK,IAAA,EAAM,CAAA,IAAA,CAAA;AAAA,EAChC,CAAC,CAAA;AAGD,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,UAAA,EAAY,eAAe,CAAA;AAGvD,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,4BAAA,EAA8B,CAAC,QAAQ,IAAA,KAAS;AAC1E,IAAA,OAAO,IAAA,GAAO,CAAA,UAAA,EAAa,IAAI,CAAA,GAAA,CAAA,GAAQ,CAAA,eAAA,CAAA;AAAA,EACzC,CAAC,CAAA;AAGD,EAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,sCAAA,EAAwC,CAAC,QAAQ,IAAA,KAAS;AACpF,IAAA,OAAO,CAAA,SAAA,EAAY,IAAA,CAAK,IAAA,EAAM,CAAA,IAAA,CAAA;AAAA,EAChC,CAAC,CAAA;AAGD,EAAA,MAAM,gBAAgB,EAAE,GAAG,kBAAkB,GAAI,eAAA,IAAmB,EAAC,EAAG;AACxE,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAA,EAAG;AAC3D,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB,MAAM,CAAA;AAC9D,IAAA,MAAM,UAAU,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,WAAW,8CAA8C,GAAG,CAAA;AAC3F,IAAA,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,OAAA,EAAS,CAAC,QAAQ,IAAA,KAAS;AACrD,MAAA,OAAO,OAAA,CAAQ,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,IAAA,EAAK,GAAI,EAAA,EAAI,EAAE,CAAA;AAAA,IACzD,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,QAAA;AACT;;;ACzHA,IAAM,cAAA,GAAiB,iCAAA;AAEvB,SAAS,oBAAoB,MAAA,EAAwB;AAGnD,EAAA,OAAO;AAAA,IACL,IAAA,CAAK,SAAiB,IAAA,EAA4B;AAChD,MAAA,MAAM,OAAA,GAAU,IAAA,GAAO,EAAE,GAAG,MAAK,GAAI,MAAA;AACrC,MAAA,IAAI,WAAW,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,SAAS,CAAA,EAAG;AAC9C,QAAA,OAAA,CAAQ,IAAA,CAAK,IAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,MAChE,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,EAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,MACvC;AAAA,IACF,CAAA;AAAA,IAEA,KAAA,CAAM,SAAiB,IAAA,EAA4B;AACjD,MAAA,MAAM,OAAA,GAAU,IAAA,GAAO,EAAE,GAAG,MAAK,GAAI,MAAA;AACrC,MAAA,IAAI,WAAW,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,SAAS,CAAA,EAAG;AAC9C,QAAA,OAAA,CAAQ,KAAA,CAAM,IAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,MACjE,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,CAAA,EAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,MACxC;AAAA,IACF,CAAA;AAAA,IAEA,IAAA,CAAK,SAAiB,IAAA,EAA4B;AAChD,MAAA,MAAM,OAAA,GAAU,IAAA,GAAO,EAAE,GAAG,MAAK,GAAI,MAAA;AACrC,MAAA,IAAI,WAAW,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,SAAS,CAAA,EAAG;AAC9C,QAAA,OAAA,CAAQ,IAAA,CAAK,IAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,MAChE,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,EAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,MACvC;AAAA,IACF,CAAA;AAAA,IAEA,KAAA,CAAM,SAAiB,IAAA,EAA4B;AACjD,MAAA,MAAM,OAAA,GAAU,IAAA,GAAO,EAAE,GAAG,MAAK,GAAI,MAAA;AACrC,MAAA,IAAI,WAAW,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,SAAS,CAAA,EAAG;AAC9C,QAAA,OAAA,CAAQ,KAAA,CAAM,IAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,MACjE,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,CAAA,EAAI,MAAM,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,MACxC;AAAA,IACF;AAAA,GACF;AACF;AAYO,SAAS,YAAA,CAAa,OAAA,GAAyB,EAAC,EAAW;AAChE,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,cAAA;AACjC,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,EACjB;AACA,EAAA,OAAO,oBAAoB,MAAM,CAAA;AACnC;;;AC4HO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,OAAO,IACJ,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA,CACrB,OAAA,CAAQ,MAAM,QAAQ,CAAA,CACtB,QAAQ,IAAA,EAAM,OAAO,EACrB,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,OAAA,CAAQ,MAAM,MAAM,CAAA;AACzB;AAKO,SAAS,cAAc,IAAA,EAAoB;AAChD,EAAA,OAAO,cAAA,CAAe,aAAA,CAAc,IAAI,CAAC,CAAA;AAC3C;AAKO,SAAS,cAAc,GAAA,EAAkB;AAC9C,EAAA,MAAM,IAAA,uBAAW,OAAA,EAAQ;AACzB,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,CAAC,MAAM,KAAA,KAAU;AAC1C,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,EAAM;AAC/C,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,EAAG;AACnB,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,IAChB;AACA,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH;AAkEA,eAAsB,gBAAgB,OAAA,EAA2C;AAC/E,EAAA,MAAM,MAAA,GAAS,MAAM,OAAO,QAAa,CAAA;AACzC,EAAA,MAAM,OAAO,MAAA,CAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,OAAO,OAAO,CAAA;AACvD,EAAA,OAAO,CAAA,OAAA,EAAU,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAA;AACxC;;;AC3JO,IAAM,aAAN,MAAiB;AAAA,EACd,MAAA;AAAA,EACA,aAAA,GAAqC,IAAA;AAAA,EACrC,MAAA,GAAS,YAAA,CAAa,EAAE,MAAA,EAAQ,wBAAwB,CAAA;AAAA,EAEhE,YAAY,MAAA,EAAqB;AAC/B,IAAA,MAAM,SAAA,GAAY,MAAA,EAAQ,SAAA,GAAYA,qBAAA,CAAK,OAAA,CAAQ,OAAO,SAAS,CAAA,GAAIA,qBAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA;AAC5F,IAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,OAAA;AAErC,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,SAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA,EAAc,QAAQ,YAAA,IAAgB,uBAAA;AAAA,MACtC,OAAA,EAASA,sBAAK,OAAA,CAAQ,MAAA,EAAQ,WAAWA,qBAAA,CAAK,IAAA,CAAK,SAAA,EAAW,KAAK,CAAC,CAAA;AAAA,MACpE,cAAcA,qBAAA,CAAK,OAAA;AAAA,QACjB,QAAQ,YAAA,IAAgBA,qBAAA,CAAK,KAAK,SAAA,EAAW,QAAA,EAAU,SAAS,eAAe;AAAA,OACjF;AAAA,MACA,IAAA,EAAM,MAAA,EAAQ,IAAA,IAAQ,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,CAAA;AAAA,MAClC,QAAA,EAAU,QAAQ,QAAA,IAAY,IAAA;AAAA,MAC9B,KAAA,EAAO,QAAQ,KAAA,IAAS,KAAA;AAAA,MACxB,oBAAA,EAAsB,QAAQ,oBAAA,IAAwB;AAAA,KACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,KAAA,GAAiB;AACtB,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,KAAU,IAAA,EAAM;AAC9B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,cAAA,GAAiB;AAAA,MACrB,KAAK,MAAA,CAAO,OAAA;AAAA,MACZA,qBAAA,CAAK,QAAQ,KAAK,CAAA;AAAA,MAClBA,qBAAA,CAAK,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,WAAW,KAAK;AAAA,KACxC;AAEA,IAAA,OAAO,eAAe,IAAA,CAAK,CAAC,MAAMC,mBAAA,CAAG,UAAA,CAAW,CAAC,CAAC,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKO,eAAA,GAA0B;AAC/B,IAAA,IAAI,IAAA,CAAK,OAAO,oBAAA,EAAsB;AACpC,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,oBAAA,CAAqB,OAAA,CAAQ,OAAO,EAAE,CAAA;AAAA,IAC3D;AAEA,IAAA,MAAM,cAAA,GAAiB;AAAA,MACrB,KAAK,MAAA,CAAO,OAAA;AAAA,MACZD,qBAAA,CAAK,QAAQ,KAAK,CAAA;AAAA,MAClBA,qBAAA,CAAK,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,WAAW,KAAK;AAAA,KACxC;AAEA,IAAA,KAAA,MAAW,KAAK,cAAA,EAAgB;AAC9B,MAAA,IAAIC,mBAAA,CAAG,UAAA,CAAW,CAAC,CAAA,EAAG;AACpB,QAAA,IAAI;AACF,UAAA,MAAM,UAAUA,mBAAA,CAAG,YAAA,CAAa,CAAA,EAAG,OAAO,EAAE,IAAA,EAAK;AACjD,UAAA,IAAI,QAAQ,UAAA,CAAW,SAAS,KAAK,OAAA,CAAQ,UAAA,CAAW,UAAU,CAAA,EAAG;AACnE,YAAA,OAAO,OAAA;AAAA,UACT;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,KAAK,MAAA,CAAO,YAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKO,cAAA,GAA0B;AAC/B,IAAA,IAAI,IAAA,CAAK,OAAO,QAAA,EAAU;AACxB,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,cAAA,GAAiB,KAAK,yBAAA,EAA0B;AACtD,IAAA,OAAO,eAAe,IAAA,CAAK,CAAC,MAAMA,mBAAA,CAAG,UAAA,CAAW,CAAC,CAAC,CAAA;AAAA,EACpD;AAAA,EAEQ,yBAAA,GAAsC;AAC5C,IAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAS,GAAI,IAAA,CAAK,MAAA;AACrC,IAAA,OAAO;AAAA,MACL,KAAK,MAAA,CAAO,YAAA;AAAA,MACZD,qBAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,QAAA,EAAU,SAAS,eAAe,CAAA;AAAA,MAC1DA,qBAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,QAAA,EAAU,eAAe,CAAA;AAAA,MACjDA,qBAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,OAAA,EAAS,eAAe,CAAA;AAAA,MAC/CA,qBAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,eAAe;AAAA,KACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,WAAA,GAA4B;AACjC,IAAA,IAAI,KAAK,aAAA,EAAe;AACtB,MAAA,OAAO,IAAA,CAAK,aAAA;AAAA,IACd;AAEA,IAAA,IAAI,IAAA,CAAK,OAAO,QAAA,EAAU;AACxB,MAAA,IAAA,CAAK,aAAA,GAAgB,KAAK,MAAA,CAAO,QAAA;AACjC,MAAA,OAAO,KAAK,MAAA,CAAO,QAAA;AAAA,IACrB;AAEA,IAAA,MAAM,cAAA,GAAiB,KAAK,yBAAA,EAA0B;AACtD,IAAA,KAAA,MAAW,KAAK,cAAA,EAAgB;AAC9B,MAAA,IAAIC,mBAAA,CAAG,UAAA,CAAW,CAAC,CAAA,EAAG;AACpB,QAAA,IAAI;AACF,UAAA,MAAM,GAAA,GAAMA,mBAAA,CAAG,YAAA,CAAa,CAAA,EAAG,OAAO,CAAA;AACtC,UAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,UAAA,IAAA,CAAK,aAAA,GAAgB,MAAA;AACrB,UAAA,OAAO,MAAA;AAAA,QACT,SAAS,GAAA,EAAU;AACjB,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mDAAA,EAAsD,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,QAC3F;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA;AAAA,EAA0D,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC;AAAA,qDAAA;AAAA,KACrF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,WAAW,WAAA,EAAwC;AACxD,IAAA,MAAM,UAAU,KAAA,CAAM,OAAA,CAAQ,WAAW,CAAA,GAAI,WAAA,GAAc,CAAC,WAAW,CAAA;AACvE,IAAA,MAAM,OAAiB,EAAC;AAExB,IAAA,IAAI,IAAA,CAAK,OAAM,EAAG;AAChB,MAAA,MAAM,SAAS,IAAA,CAAK,eAAA,EAAgB,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACvD,MAAA,IAAA,CAAK,IAAA,CAAK,CAAA,2BAAA,EAA8B,MAAM,CAAA,wBAAA,CAA0B,CAAA;AAExE,MAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,QAAA,MAAM,UAAA,GAAa,KAAA,CAAM,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAC1C,QAAA,IAAI,UAAA,CAAW,QAAA,CAAS,MAAM,CAAA,IAAK,UAAA,CAAW,QAAA,CAAS,OAAO,CAAA,IAAK,UAAA,CAAW,QAAA,CAAS,OAAO,CAAA,EAAG;AAC/F,UAAA,IAAA,CAAK,IAAA,CAAK,CAAA,6BAAA,EAAgC,MAAM,CAAA,CAAA,EAAI,UAAU,CAAA,EAAA,CAAI,CAAA;AAAA,QACpE,CAAA,MAAO;AACL,UAAA,IAAA,CAAK,IAAA,CAAK,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAA,EAAI,UAAU,CAAA,WAAA,CAAa,CAAA;AAAA,QAC3E;AAAA,MACF;AAEA,MAAA,OAAO,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,IACvB;AAGA,IAAA,MAAM,QAAA,GAAW,KAAK,WAAA,EAAY;AAClC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,IAAA,GAAO,CAAA,EAAG,IAAA,CAAK,OAAO,IAAI,CAAA,CAAA,CAAA;AACxF,IAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AACpC,IAAA,MAAM,eAAA,uBAAsB,GAAA,EAAY;AAExC,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,MAAM,UAAA,GAAa,KAAA,CAAM,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAC1C,MAAA,MAAM,QACJ,QAAA,CAAS,UAAU,KACnB,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA,CAAE,IAAA;AAAA,QACtB,CAAC,CAAA,KACC,CAAA,CAAE,GAAA,KAAQ,cACV,CAAA,CAAE,IAAA,KAAS,UAAA,IACV,CAAA,CAAE,QAAQ,CAAA,CAAE,GAAA,CAAI,QAAA,CAAS,UAAU,KAAK,CAAA,CAAE,GAAA,CAAI,QAAA,CAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAE,CAAA,CAAA,IACvE,CAAA,CAAE,SAAS,CAAA,CAAE,IAAA,CAAK,QAAA,CAAS,UAAU,KAAK,CAAA,CAAE,IAAA,CAAK,QAAA,CAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAE,CAAA;AAAA,OAC/E;AAEA,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,IAAI,CAAC,yBAAA,CAA0B,IAAA,CAAK,UAAU,CAAA,EAAG;AAC/C,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,kCAAA,EAAoC,EAAE,OAAO,YAAA,EAAc,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc,CAAA;AAAA,QACxG;AACA,QAAA;AAAA,MACF;AAGF,MAAA,IAAI,MAAM,GAAA,EAAK;AACb,QAAA,KAAA,MAAW,OAAA,IAAW,MAAM,GAAA,EAAK;AAC/B,UAAA,IAAI,CAAC,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA,EAAG;AAC7B,YAAA,WAAA,CAAY,IAAI,OAAO,CAAA;AACvB,YAAA,IAAA,CAAK,IAAA,CAAK,CAAA,6BAAA,EAAgC,QAAQ,CAAA,EAAG,OAAO,CAAA,EAAA,CAAI,CAAA;AAAA,UAClE;AAAA,QACF;AAAA,MACF;AAGA,MAAA,IAAI,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC/B,QAAA,IAAI,CAAC,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AAChC,UAAA,WAAA,CAAY,GAAA,CAAI,MAAM,IAAI,CAAA;AAC1B,UAAA,IAAA,CAAK,KAAK,CAAA,6BAAA,EAAgC,QAAQ,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,EAAA,CAAI,CAAA;AAAA,QACrE;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,IAAA,CAAK,KAAK,CAAA,2BAAA,EAA8B,QAAQ,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,WAAA,CAAa,CAAA;AAAA,MAC5E;AAGA,MAAA,IAAI,MAAM,OAAA,EAAS;AACjB,QAAA,KAAA,MAAW,GAAA,IAAO,MAAM,OAAA,EAAS;AAC/B,UAAA,MAAM,QAAA,GAAW,SAAS,GAAG,CAAA;AAC7B,UAAA,IAAI,YAAY,CAAC,eAAA,CAAgB,GAAA,CAAI,QAAA,CAAS,IAAI,CAAA,EAAG;AACnD,YAAA,eAAA,CAAgB,GAAA,CAAI,SAAS,IAAI,CAAA;AACjC,YAAA,IAAA,CAAK,KAAK,CAAA,gCAAA,EAAmC,QAAQ,CAAA,EAAG,QAAA,CAAS,IAAI,CAAA,EAAA,CAAI,CAAA;AAAA,UAC3E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKO,kBAAA,GAA6B;AAClC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAM,EAAG;AACjB,MAAA,OAAO,EAAA;AAAA,IACT;AAEA,IAAA,MAAM,SAAS,IAAA,CAAK,eAAA,EAAgB,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACvD,IAAA,OAAO,CAAA;AAAA,8BAAA,EACqB,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AAAA,EAMpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,wBAAwB,SAAA,EAAoC;AACvE,IAAA,MAAM,WAAWD,qBAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,WAAW,SAAS,CAAA;AAC9D,IAAA,MAAM,OAAA,GAAUC,mBAAA,CAAG,YAAA,CAAa,QAAQ,CAAA;AACxC,IAAA,OAAO,gBAAgB,OAAO,CAAA;AAAA,EAChC;AACF,CAAA;AAKO,SAAS,iBAAiB,MAAA,EAAiC;AAChE,EAAA,OAAO,IAAI,WAAW,MAAM,CAAA;AAC9B;AAKiC,IAAI,UAAA;;;ACvXrC,IAAM,YAAA,uBAA2D,GAAA,EAAI;AAK9D,SAAS,oBAAoB,OAAA,EAA8B;AAChE,EAAA,MAAM,aAAyB,OAAA,EAAS,IAAA,GAAO,iBAAiB,OAAA,CAAQ,IAAI,IAAI,gBAAA,EAAiB;AACjG,EAAA,MAAM,WAAA,GAAc,OAAA,EAAS,KAAA,IAAS,CAAC,WAAW,KAAA,EAAM;AAExD,EAAA,MAAM,cAAA,GAAiB,SAAS,cAAA,IAAkB,CAAA;AAClD,EAAA,MAAM,kBAAA,GAAqB,SAAS,WAAA,IAAe,IAAA;AAEnD,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAkC;AAC5D,EAAA,YAAA,CAAa,IAAI,aAAa,CAAA;AAE9B,EAAA,OAAO,SAAS,kBAAA,CACd,QAAA,EACA,UAAA,EACA,QAAA,EACA;AACA,IAAA,IAAI;AACF,MAAA,IAAI,gBAAA,GAAmB,WAAA,GAAc,aAAA,CAAc,GAAA,CAAI,QAAQ,CAAA,GAAI,KAAA,CAAA;AAEnE,MAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,QAAA,MAAM,iBAAiB,OAAA,EAAS,cAAA,IAAkBA,mBAAAA,CAAG,YAAA,CAAa,UAAU,OAAO,CAAA;AACnF,QAAA,MAAM,cAAA,GAAiB,OAAA,EAAS,eAAA,GAC5B,OAAA,CAAQ,eAAA,CAAgB,cAAc,CAAA,GACtC,sBAAA,CAAuB,cAAA,EAAgB,OAAA,EAAS,UAAU,CAAA;AAE9D,QAAA,gBAAA,GAAmBC,oBAAA,CAAI,QAAQ,cAAA,EAAgB;AAAA,UAC7C,QAAA,EAAU,QAAA;AAAA,UACV,KAAA,EAAO,WAAA;AAAA,UACP,KAAA,EAAO;AAAA,SACR,CAAA;AAED,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,aAAA,CAAc,GAAA,CAAI,UAAU,gBAAgB,CAAA;AAAA,QAC9C;AAAA,MACF;AAEA,MAAA,MAAM,MAAA,GAAyB,EAAE,GAAG,UAAA,EAAW;AAC/C,MAAA,MAAM,OAAyB,MAAA,CAAO,IAAA;AACtC,MAAA,MAAM,MAAoC,MAAA,CAAO,GAAA;AACjD,MAAA,MAAM,gBAAA,GAAmB,OAAO,cAAA,IAAkB,cAAA;AAClD,MAAA,MAAM,uBAAA,GAA0B,OAAO,WAAA,IAAe,kBAAA;AAGtD,MAAA,MAAA,CAAO,aAAA,GAAgB,CAAC,EAAA,GAAa,KAAA,KAAU;AAC7C,QAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,QAAA,MAAM,WAAW,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,CAAE,OAAA,CAAQ,MAAM,SAAS,CAAA;AAC7D,QAAA,OAAO,CAAA,mBAAA,EAAsB,EAAE,CAAA,0BAAA,EAA6B,QAAQ,CAAA,SAAA,CAAA;AAAA,MACtE,CAAA;AAEA,MAAA,MAAA,CAAO,cAAc,MAAA,CAAO,aAAA;AAE5B,MAAA,MAAA,CAAO,OAAA,GAAU,CAAC,WAAA,GAAgC,KAAA,EAAO,OAAA,KAAoB;AAC3E,QAAA,MAAM,EAAA,GAAK,OAAO,WAAA,KAAgB,QAAA,GAAW,WAAA,GAAc,KAAA;AAC3D,QAAA,MAAM,aAAA,GAAgB,OAAO,WAAA,KAAgB,SAAA,GAAY,cAAe,uBAAA,KAA4B,KAAA;AACpG,QAAA,MAAM,MAAM,OAAA,IAAW,gBAAA;AAEvB,QAAA,IAAI,CAAC,IAAA,EAAM;AACT,UAAA,OAAO,aAAA,GAAgB,CAAA,SAAA,EAAY,EAAE,CAAA,QAAA,CAAA,GAAa,EAAA;AAAA,QACpD;AAEA,QAAA,MAAM,OAAA,GAAU,GAAA,IAAO,GAAA,CAAI,IAAA,GAAO,IAAI,IAAA,GAAO,EAAA;AAK7C,QAAA,MAAM,WAAA,GAAc,+BAAA,CAAgC,IAAA,CAAK,OAAO,CAAA;AAGhE,QAAA,IAAI,QAAQ,CAAA,EAAG;AACb,UAAA,MAAM,QAAA,GAAW,cAAc,IAAI,CAAA;AACnC,UAAA,OAAO,gBAAgB,CAAA,SAAA,EAAY,EAAE,gBAAgB,QAAQ,CAAA,EAAA,EAAK,OAAO,CAAA,MAAA,CAAA,GAAW,EAAA;AAAA,QACtF;AAGA,QAAA,MAAM,WAAW,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,CAAE,OAAA,CAAQ,MAAM,SAAS,CAAA;AAC7D,QAAA,MAAM,SAAA,GAAY,CAAA,mBAAA,EAAsB,EAAE,CAAA,0BAAA,EAA6B,QAAQ,CAAA,SAAA,CAAA;AAE/E,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,OAAO,OAAA;AAAA,QACT;AAEA,QAAA,IAAI,CAAC,aAAA,EAAe;AAClB,UAAA,OAAO,SAAA;AAAA,QACT;AAEA,QAAA,OAAO,CAAA,SAAA,EAAY,EAAE,CAAA,EAAA,EAAK,OAAO,CAAA;AAAA,EAAW,SAAS,CAAA,CAAA;AAAA,MACvD,CAAA;AAEA,MAAA,MAAA,CAAO,cAAc,MAAM;AACzB,QAAA,IAAI,GAAA,IAAO,MAAM,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,IAAK,GAAA,CAAI,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG;AACzD,UAAA,OAAO,GAAA,CAAI,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAAA,QAC3B;AACA,QAAA,OAAO,EAAA;AAAA,MACT,CAAA;AAEA,MAAA,MAAA,CAAO,IAAA,GAAO,CAAC,WAAA,KAAmC;AAChD,QAAA,OAAO,UAAA,CAAW,WAAW,WAAW,CAAA;AAAA,MAC1C,CAAA;AAEA,MAAA,MAAA,CAAO,mBAAmB,MAAM;AAC9B,QAAA,OAAO,WAAW,kBAAA,EAAmB;AAAA,MACvC,CAAA;AAEA,MAAA,MAAA,CAAO,OAAO,MAAM;AAClB,QAAA,MAAM,KAAA,GACJ,MAAA,CAAO,KAAA,IACP,MAAA,CAAO,cACN,OAAO,MAAA,CAAO,GAAA,EAAK,SAAA,KAAc,UAAA,GAAa,MAAA,CAAO,GAAA,CAAI,SAAA,KAAc,EAAA,CAAA,IACxE,EAAA;AACF,QAAA,OAAO,KAAA,GAAQ,CAAA,0CAAA,EAA6C,KAAK,CAAA,EAAA,CAAA,GAAO,EAAA;AAAA,MAC1E,CAAA;AAEA,MAAA,MAAA,CAAO,IAAA,GAAO,CAAC,KAAA,KAAe;AAC5B,QAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,MAC7B,CAAA;AAEA,MAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,QAAA,MAAA,CAAO,MAAA,GAAS,CAAC,KAAA,KAAmB;AAClC,UAAA,IAAI,MAAA,CAAO,WAAA,IAAe,MAAA,CAAO,KAAA,EAAO;AACtC,YAAA,MAAM,aAAa,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,WAAA,IAAe,OAAO,KAAK,CAAA;AACpE,YAAA,OAAO,yBAAyB,UAAU,CAAA,UAAA,CAAA;AAAA,UAC5C;AACA,UAAA,OAAO,EAAA;AAAA,QACT,CAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,iBAAiB,MAAM,CAAA;AACpC,MAAA,QAAA,CAAS,MAAM,IAAI,CAAA;AAAA,IACrB,SAAS,GAAA,EAAU;AACjB,MAAA,QAAA,CAAS,GAAG,CAAA;AAAA,IACd;AAAA,EACF,CAAA;AACF;AAKO,IAAM,gBAAgB,mBAAA;AAKtB,SAAS,gBAAA,GAAyB;AACvC,EAAA,KAAA,MAAW,SAAS,YAAA,EAAc;AAChC,IAAA,KAAA,CAAM,KAAA,EAAM;AAAA,EACd;AACF","file":"engine.js","sourcesContent":["import type { DirectiveHandler } from './types.js';\n\nconst customDirectives: Record<string, DirectiveHandler> = {};\n\n/**\n * Escape a string for safe interpolation inside a single-quoted JS string literal.\n */\nfunction escapeJsString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Register a global custom Blade directive.\n * @param name Directive name without the @ (e.g. 'datetime' for @datetime($date))\n * @param handler Function returning the compiled EJS string or HTML\n */\nexport function registerDirective(name: string, handler: DirectiveHandler): void {\n customDirectives[name] = handler;\n}\n\n/**\n * Compiles Blade-style directives and Blade-style component tags into valid EJS syntax.\n */\nexport function compileBladeDirectives(\n templateSource: string,\n localDirectives?: Record<string, DirectiveHandler>\n): string {\n let compiled = templateSource;\n\n // <x-inertia ... /> or <x-inertia ...></x-inertia>\n compiled = compiled.replace(\n /<x-inertia(\\s[^>]*)?\\s*(\\/|><\\/x-inertia>)/gi,\n (_match, attrs) => {\n const idMatch = attrs?.match(/id=(?:\"([^\"]*)\"|'([^']*)')/);\n const id = idMatch ? (idMatch[1] || idMatch[2]) : undefined;\n return id ? `<%- inertia('${escapeJsString(id)}') %>` : `<%- inertia() %>`;\n }\n );\n\n // <x-inertia-script ... /> or <x-inertia-data ... />\n compiled = compiled.replace(\n /<x-inertia-(?:script|data)(\\s[^>]*)?\\s*(\\/|><\\/x-inertia-(?:script|data)>)/gi,\n (_match, attrs) => {\n const idMatch = attrs?.match(/id=(?:\"([^\"]*)\"|'([^']*)')/);\n const id = idMatch ? (idMatch[1] || idMatch[2]) : undefined;\n return id ? `<%- inertiaScript('${escapeJsString(id)}') %>` : `<%- inertiaScript() %>`;\n }\n );\n\n // <x-inertia-head /> or <x-inertiaHead />\n compiled = compiled.replace(\n /<x-inertia-head\\s*(?:\\/>|><\\/x-inertia-head>)|<x-inertiaHead\\s*(?:\\/>|><\\/x-inertiaHead>)/gi,\n '<%- inertiaHead() %>'\n );\n\n // <x-vite src=\"...\" /> or <x-vite entries=\"...\" />\n compiled = compiled.replace(\n /<x-vite(\\s[^>]*)?\\s*(?:\\/>|><\\/x-vite>)/gi,\n (_match, attrs) => {\n const srcMatch = attrs?.match(/(?:src|entries)=(?:\"([^\"]*)\"|'([^']*)')/);\n const val = srcMatch ? (srcMatch[1] || srcMatch[2]) : '';\n if (val.startsWith('[') && val.endsWith(']')) {\n return `<%- vite(${val}) %>`;\n }\n return `<%- vite('${escapeJsString(val)}') %>`;\n }\n );\n\n // <x-vite-react-refresh /> or <x-viteReactRefresh />\n compiled = compiled.replace(\n /<x-vite-react-refresh\\s*(?:\\/>|><\\/x-vite-react-refresh>)|<x-viteReactRefresh\\s*(?:\\/>|><\\/x-viteReactRefresh>)/gi,\n '<%- viteReactRefresh() %>'\n );\n\n // <x-csrf />\n compiled = compiled.replace(/<x-csrf\\s*(?:\\/>|><\\/x-csrf>)/gi, '<%- csrf() %>');\n\n // <x-routes ... />\n compiled = compiled.replace(\n /<x-routes(\\s[^>]*)?\\s*(?:\\/>|><\\/x-routes>)/gi,\n (_match, attrs) => {\n const groupMatch = attrs?.match(/group=(?:\"([^\"]*)\"|'([^']*)')/);\n const group = groupMatch ? (groupMatch[1] || groupMatch[2]) : undefined;\n return group ? `<%- routes('${escapeJsString(group)}') %>` : `<%- routes() %>`;\n }\n );\n\n // 2. Built-in Blade Directives\n // @inertiaHead (must match before @inertia)\n compiled = compiled.replace(/@inertiaHead\\b/g, '<%- inertiaHead() %>');\n\n // @inertiaScript or @inertiaData\n compiled = compiled.replace(/@(inertiaScript|inertiaData)(\\([^)]*\\))?(?!\\w)/g, (_match, _d, args) => {\n return args ? `<%- inertiaScript${args} %>` : `<%- inertiaScript() %>`;\n });\n\n // @inertia or @inertia(...)\n compiled = compiled.replace(/@inertia(\\([^)]*\\))?(?!\\w)/g, (_match, args) => {\n return args ? `<%- inertia${args} %>` : `<%- inertia() %>`;\n });\n\n // @viteReactRefresh (must match before @vite)\n compiled = compiled.replace(/@viteReactRefresh\\b/g, '<%- viteReactRefresh() %>');\n\n // @vite(...)\n compiled = compiled.replace(/@vite\\(([^)]*(?:\\([^)]*\\)[^)]*)*)\\)/g, (_match, args) => {\n return `<%- vite(${args.trim()}) %>`;\n });\n\n // @csrf\n compiled = compiled.replace(/@csrf\\b/g, '<%- csrf() %>');\n\n // @routes or @routes(...)\n compiled = compiled.replace(/@routes(\\([^)]*\\))?(?!\\w)/g, (_match, args) => {\n return args ? `<%- routes${args} %>` : `<%- routes() %>`;\n });\n\n // @json(...)\n compiled = compiled.replace(/@json\\(([^)]*(?:\\([^)]*\\)[^)]*)*)\\)/g, (_match, args) => {\n return `<%- json(${args.trim()}) %>`;\n });\n\n // 3. User Registered Custom Directives\n const allDirectives = { ...customDirectives, ...(localDirectives || {}) };\n for (const [name, handler] of Object.entries(allDirectives)) {\n const escapedName = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`@${escapedName}(\\\\([^)]*(?:\\\\([^)]*\\\\)[^)]*)*\\\\))?(?!\\\\w)`, 'g');\n compiled = compiled.replace(pattern, (_match, args) => {\n return handler(args ? args.slice(1, -1).trim() : '', {});\n });\n }\n\n return compiled;\n}\n","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, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\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","import fs from 'fs';\nimport path from 'path';\nimport ejs from 'ejs';\nimport type { BladeEngineOptions, Page, SSRResult } from './types.js';\nimport { compileBladeDirectives } from './directives.js';\nimport { createViteHelper, ViteHelper } from './vite.js';\nimport { serializePage } from './utils.js';\n\nexport interface TemplateLocals extends Record<string, any> {\n page?: Page;\n ssr?: SSRResult | null;\n _csrf?: string;\n csrfToken?: string;\n routes?: any;\n}\n\n/**\n * Registry of all engine instance caches for bulk clearing.\n */\nconst engineCaches: Set<Map<string, ejs.TemplateFunction>> = new Set();\n\n/**\n * Creates an Express view engine with Blade directive support and built-in Inertia/Vite helpers.\n */\nexport function createInertiaEngine(options?: BladeEngineOptions) {\n const viteHelper: ViteHelper = options?.vite ? createViteHelper(options.vite) : createViteHelper();\n const shouldCache = options?.cache ?? !viteHelper.isDev();\n\n const inertiaVersion = options?.inertiaVersion ?? 2;\n const defaultRootElement = options?.rootElement ?? true;\n\n const templateCache = new Map<string, ejs.TemplateFunction>();\n engineCaches.add(templateCache);\n\n return function inertiaBladeEngine(\n filePath: string,\n rawOptions: Record<string, any>,\n callback: (err: Error | null, html?: string) => void\n ) {\n try {\n let compiledTemplate = shouldCache ? templateCache.get(filePath) : undefined;\n\n if (!compiledTemplate) {\n const templateSource = options?.templateSource || fs.readFileSync(filePath, 'utf-8');\n const compiledSource = options?.compileTemplate\n ? options.compileTemplate(templateSource)\n : compileBladeDirectives(templateSource, options?.directives);\n\n compiledTemplate = ejs.compile(compiledSource, {\n filename: filePath,\n cache: shouldCache,\n async: false,\n });\n\n if (shouldCache) {\n templateCache.set(filePath, compiledTemplate);\n }\n }\n\n const locals: TemplateLocals = { ...rawOptions };\n const page: Page | undefined = locals.page;\n const ssr: SSRResult | null | undefined = locals.ssr;\n const effectiveVersion = locals.inertiaVersion ?? inertiaVersion;\n const shouldRenderRootElement = locals.rootElement ?? defaultRootElement;\n\n // Provide standard Inertia and Blade helpers\n locals.inertiaScript = (id: string = 'app') => {\n if (!page) return '';\n const jsonSafe = JSON.stringify(page).replace(/</g, '\\\\u003c');\n return `<script data-page=\"${id}\" type=\"application/json\">${jsonSafe}</script>`;\n };\n\n locals.inertiaData = locals.inertiaScript;\n\n locals.inertia = (idOrOptions: string | boolean = 'app', version?: 1 | 2) => {\n const id = typeof idOrOptions === 'string' ? idOrOptions : 'app';\n const renderElement = typeof idOrOptions === 'boolean' ? idOrOptions : (shouldRenderRootElement !== false);\n const ver = version ?? effectiveVersion;\n\n if (!page) {\n return renderElement ? `<div id=\"${id}\"></div>` : '';\n }\n\n const ssrBody = ssr && ssr.body ? ssr.body : '';\n\n // Official @inertiajs SSR servers return a fully-wrapped payload\n // (`<script data-page=\"...\">` + `<div data-server-rendered id=\"app\">`) that\n // already includes the page data and root element, so pass it through untouched.\n const ssrFullBody = /<div[^>]*data-server-rendered/.test(ssrBody);\n\n // Inertia v1: data-page attribute on root div\n if (ver === 1) {\n const pageData = serializePage(page);\n return renderElement ? `<div id=\"${id}\" data-page=\"${pageData}\">${ssrBody}</div>` : '';\n }\n\n // Inertia v2:\n const jsonSafe = JSON.stringify(page).replace(/</g, '\\\\u003c');\n const scriptTag = `<script data-page=\"${id}\" type=\"application/json\">${jsonSafe}</script>`;\n\n if (ssrFullBody) {\n return ssrBody;\n }\n\n if (!renderElement) {\n return scriptTag;\n }\n\n return `<div id=\"${id}\">${ssrBody}</div>\\n${scriptTag}`;\n };\n\n locals.inertiaHead = () => {\n if (ssr && Array.isArray(ssr.head) && ssr.head.length > 0) {\n return ssr.head.join('\\n');\n }\n return '';\n };\n\n locals.vite = (entrypoints: string | string[]) => {\n return viteHelper.renderTags(entrypoints);\n };\n\n locals.viteReactRefresh = () => {\n return viteHelper.renderReactRefresh();\n };\n\n locals.csrf = () => {\n const token =\n locals._csrf ||\n locals.csrfToken ||\n (typeof locals.req?.csrfToken === 'function' ? locals.req.csrfToken() : '') ||\n '';\n return token ? `<input type=\"hidden\" name=\"_token\" value=\"${token}\">` : '';\n };\n\n locals.json = (value: any) => {\n return JSON.stringify(value);\n };\n\n if (!locals.routes) {\n locals.routes = (group?: string) => {\n if (locals.routeConfig || locals.ziggy) {\n const routesData = JSON.stringify(locals.routeConfig || locals.ziggy);\n return `<script>const Ziggy = ${routesData};</script>`;\n }\n return '';\n };\n }\n\n const html = compiledTemplate(locals);\n callback(null, html);\n } catch (err: any) {\n callback(err);\n }\n };\n}\n\n/**\n * Default Inertia Blade EJS engine instance.\n */\nexport const inertiaEngine = createInertiaEngine();\n\n/**\n * Clear all template engine caches (useful during testing or hot reloading).\n */\nexport function clearEngineCache(): void {\n for (const cache of engineCaches) {\n cache.clear();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/directives.ts","../src/logger.ts","../src/utils.ts","../src/vite.ts","../src/engine.ts"],"names":["path","fs","ejs"],"mappings":"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","file":"engine.js","sourcesContent":["import type { DirectiveHandler } from './types.js';\n\nconst customDirectives: Record<string, DirectiveHandler> = {};\n\n/**\n * Escape a string for safe interpolation inside a single-quoted JS string literal.\n */\nfunction escapeJsString(str: string): string {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\n/**\n * Register a global custom Blade directive.\n * @param name Directive name without the @ (e.g. 'datetime' for @datetime($date))\n * @param handler Function returning the compiled EJS string or HTML\n */\nexport function registerDirective(name: string, handler: DirectiveHandler): void {\n customDirectives[name] = handler;\n}\n\n/**\n * Remove all globally registered custom directives.\n * Useful for tests and hot-reload scenarios that need an isolated registry.\n */\nexport function clearCustomDirectives(): void {\n for (const name of Object.keys(customDirectives)) {\n delete customDirectives[name];\n }\n}\n\n/**\n * Compiles Blade-style directives and Blade-style component tags into valid EJS syntax.\n */\nexport function compileBladeDirectives(\n templateSource: string,\n localDirectives?: Record<string, DirectiveHandler>\n): string {\n let compiled = templateSource;\n\n // <x-inertia ... /> or <x-inertia ...></x-inertia>\n compiled = compiled.replace(\n /<x-inertia(\\s[^>]*)?\\s*(\\/|><\\/x-inertia>)/gi,\n (_match, attrs) => {\n const idMatch = attrs?.match(/id=(?:\"([^\"]*)\"|'([^']*)')/);\n const id = idMatch ? (idMatch[1] || idMatch[2]) : undefined;\n return id ? `<%- inertia('${escapeJsString(id)}') %>` : `<%- inertia() %>`;\n }\n );\n\n // <x-inertia-script ... /> or <x-inertia-data ... />\n compiled = compiled.replace(\n /<x-inertia-(?:script|data)(\\s[^>]*)?\\s*(\\/|><\\/x-inertia-(?:script|data)>)/gi,\n (_match, attrs) => {\n const idMatch = attrs?.match(/id=(?:\"([^\"]*)\"|'([^']*)')/);\n const id = idMatch ? (idMatch[1] || idMatch[2]) : undefined;\n return id ? `<%- inertiaScript('${escapeJsString(id)}') %>` : `<%- inertiaScript() %>`;\n }\n );\n\n // <x-inertia-head /> or <x-inertiaHead />\n compiled = compiled.replace(\n /<x-inertia-head\\s*(?:\\/>|><\\/x-inertia-head>)|<x-inertiaHead\\s*(?:\\/>|><\\/x-inertiaHead>)/gi,\n '<%- inertiaHead() %>'\n );\n\n // <x-vite src=\"...\" /> or <x-vite entries=\"...\" />\n compiled = compiled.replace(\n /<x-vite(\\s[^>]*)?\\s*(?:\\/>|><\\/x-vite>)/gi,\n (_match, attrs) => {\n const srcMatch = attrs?.match(/(?:src|entries)=(?:\"([^\"]*)\"|'([^']*)')/);\n const val = srcMatch ? (srcMatch[1] || srcMatch[2]) : '';\n if (val.startsWith('[') && val.endsWith(']')) {\n return `<%- vite(${val}) %>`;\n }\n return `<%- vite('${escapeJsString(val)}') %>`;\n }\n );\n\n // <x-vite-react-refresh /> or <x-viteReactRefresh />\n compiled = compiled.replace(\n /<x-vite-react-refresh\\s*(?:\\/>|><\\/x-vite-react-refresh>)|<x-viteReactRefresh\\s*(?:\\/>|><\\/x-viteReactRefresh>)/gi,\n '<%- viteReactRefresh() %>'\n );\n\n // <x-csrf />\n compiled = compiled.replace(/<x-csrf\\s*(?:\\/>|><\\/x-csrf>)/gi, '<%- csrf() %>');\n\n // <x-routes ... />\n compiled = compiled.replace(\n /<x-routes(\\s[^>]*)?\\s*(?:\\/>|><\\/x-routes>)/gi,\n (_match, attrs) => {\n const groupMatch = attrs?.match(/group=(?:\"([^\"]*)\"|'([^']*)')/);\n const group = groupMatch ? (groupMatch[1] || groupMatch[2]) : undefined;\n return group ? `<%- routes('${escapeJsString(group)}') %>` : `<%- routes() %>`;\n }\n );\n\n // 2. Built-in Blade Directives\n // @inertiaHead (must match before @inertia)\n compiled = compiled.replace(/@inertiaHead\\b/g, '<%- inertiaHead() %>');\n\n // @inertiaScript or @inertiaData\n compiled = compiled.replace(/@(inertiaScript|inertiaData)(\\([^)]*\\))?(?!\\w)/g, (_match, _d, args) => {\n return args ? `<%- inertiaScript${args} %>` : `<%- inertiaScript() %>`;\n });\n\n // @inertia or @inertia(...)\n compiled = compiled.replace(/@inertia(\\([^)]*\\))?(?!\\w)/g, (_match, args) => {\n return args ? `<%- inertia${args} %>` : `<%- inertia() %>`;\n });\n\n // @viteReactRefresh (must match before @vite)\n compiled = compiled.replace(/@viteReactRefresh\\b/g, '<%- viteReactRefresh() %>');\n\n // @vite(...)\n compiled = compiled.replace(/@vite\\(([^)]*(?:\\([^)]*\\)[^)]*)*)\\)/g, (_match, args) => {\n return `<%- vite(${args.trim()}) %>`;\n });\n\n // @csrf\n compiled = compiled.replace(/@csrf\\b/g, '<%- csrf() %>');\n\n // @routes or @routes(...)\n compiled = compiled.replace(/@routes(\\([^)]*\\))?(?!\\w)/g, (_match, args) => {\n return args ? `<%- routes${args} %>` : `<%- routes() %>`;\n });\n\n // @json(...)\n compiled = compiled.replace(/@json\\(([^)]*(?:\\([^)]*\\)[^)]*)*)\\)/g, (_match, args) => {\n return `<%- json(${args.trim()}) %>`;\n });\n\n // 3. User Registered Custom Directives\n const allDirectives = { ...customDirectives, ...(localDirectives || {}) };\n for (const [name, handler] of Object.entries(allDirectives)) {\n const escapedName = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`@${escapedName}(\\\\([^)]*(?:\\\\([^)]*\\\\)[^)]*)*\\\\))?(?!\\\\w)`, 'g');\n compiled = compiled.replace(pattern, (_match, args) => {\n return handler(args ? args.slice(1, -1).trim() : '', {});\n });\n }\n\n return compiled;\n}\n","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, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\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","import fs from 'fs';\nimport ejs from 'ejs';\nimport type { BladeEngineOptions, Page, SSRResult } from './types.js';\nimport { compileBladeDirectives } from './directives.js';\nimport { createViteHelper, ViteHelper } from './vite.js';\nimport { serializePage, escapeHtmlAttr } from './utils.js';\n\nexport interface TemplateLocals extends Record<string, any> {\n page?: Page;\n ssr?: SSRResult | null;\n _csrf?: string;\n csrfToken?: string;\n routes?: any;\n}\n\n/**\n * Registry of all engine instance caches for bulk clearing.\n */\nconst engineCaches: Set<Map<string, ejs.TemplateFunction>> = new Set();\nconst engineTimestamps: Set<Map<string, number>> = new Set();\n\nconst TEMPLATE_SOURCE_KEY = '__express_inertia_template_source__';\n\n/**\n * Creates an Express view engine with Blade directive support and built-in Inertia/Vite helpers.\n */\nexport function createInertiaEngine(options?: BladeEngineOptions) {\n const viteHelper: ViteHelper = options?.vite ? createViteHelper(options.vite) : createViteHelper();\n const shouldCache = options?.cache ?? !viteHelper.isDev();\n\n const inertiaVersion = options?.inertiaVersion ?? 2;\n const defaultRootElement = options?.rootElement ?? true;\n\n const templateCache = new Map<string, ejs.TemplateFunction>();\n const templateTimestamps = new Map<string, number>();\n engineCaches.add(templateCache);\n engineTimestamps.add(templateTimestamps);\n\n return function inertiaBladeEngine(\n filePath: string,\n rawOptions: Record<string, any>,\n callback: (err: Error | null, html?: string) => void\n ) {\n try {\n const template = options?.templateSource;\n const hasTemplateSource = template !== undefined;\n const cacheKey = hasTemplateSource ? TEMPLATE_SOURCE_KEY : filePath;\n\n let compiledTemplate: ejs.TemplateFunction | undefined;\n let templateMtimeMs = -1;\n\n if (hasTemplateSource) {\n compiledTemplate = templateCache.get(cacheKey);\n } else if (shouldCache) {\n compiledTemplate = templateCache.get(cacheKey);\n } else {\n try {\n templateMtimeMs = fs.statSync(filePath).mtimeMs;\n } catch {\n templateMtimeMs = 0;\n }\n if (templateTimestamps.get(cacheKey) === templateMtimeMs) {\n compiledTemplate = templateCache.get(cacheKey);\n }\n }\n\n if (!compiledTemplate) {\n const templateSource = template !== undefined ? template : fs.readFileSync(filePath, 'utf-8');\n const compiledSource = options?.compileTemplate\n ? options.compileTemplate(templateSource)\n : compileBladeDirectives(templateSource, options?.directives);\n\n compiledTemplate = ejs.compile(compiledSource, {\n filename: filePath,\n cache: false,\n async: false,\n });\n\n templateCache.set(cacheKey, compiledTemplate);\n if (!hasTemplateSource) {\n templateTimestamps.set(cacheKey, templateMtimeMs);\n }\n }\n\n const locals: TemplateLocals = { ...rawOptions };\n const page: Page | undefined = locals.page;\n const ssr: SSRResult | null | undefined = locals.ssr;\n const effectiveVersion = locals.inertiaVersion ?? inertiaVersion;\n const shouldRenderRootElement = locals.rootElement ?? defaultRootElement;\n\n // Provide standard Inertia and Blade helpers\n locals.inertiaScript = (id: string = 'app') => {\n if (!page) return '';\n const jsonSafe = JSON.stringify(page).replace(/</g, '\\\\u003c');\n return `<script data-page=\"${id}\" type=\"application/json\">${jsonSafe}</script>`;\n };\n\n locals.inertiaData = locals.inertiaScript;\n\n locals.inertia = (idOrOptions: string | boolean = 'app', version?: 1 | 2) => {\n const id = typeof idOrOptions === 'string' ? idOrOptions : 'app';\n const renderElement = typeof idOrOptions === 'boolean' ? idOrOptions : (shouldRenderRootElement !== false);\n const ver = version ?? effectiveVersion;\n\n if (!page) {\n return renderElement ? `<div id=\"${id}\"></div>` : '';\n }\n\n const ssrBody = ssr && ssr.body ? ssr.body : '';\n\n // Official @inertiajs SSR servers return a fully-wrapped payload\n // (`<script data-page=\"...\">` + `<div data-server-rendered id=\"app\">`) that\n // already includes the page data and root element, so pass it through untouched.\n const ssrFullBody = /<div[^>]*data-server-rendered/.test(ssrBody);\n\n // Inertia v1: data-page attribute on root div\n if (ver === 1) {\n const pageData = serializePage(page);\n return renderElement ? `<div id=\"${id}\" data-page=\"${pageData}\">${ssrBody}</div>` : '';\n }\n\n // Inertia v2:\n const jsonSafe = JSON.stringify(page).replace(/</g, '\\\\u003c');\n const scriptTag = `<script data-page=\"${id}\" type=\"application/json\">${jsonSafe}</script>`;\n\n if (ssrFullBody) {\n return ssrBody;\n }\n\n if (!renderElement) {\n return scriptTag;\n }\n\n return `<div id=\"${id}\">${ssrBody}</div>\\n${scriptTag}`;\n };\n\n locals.inertiaHead = () => {\n if (ssr && Array.isArray(ssr.head) && ssr.head.length > 0) {\n return ssr.head.join('\\n');\n }\n return '';\n };\n\n locals.vite = (entrypoints: string | string[]) => {\n return viteHelper.renderTags(entrypoints);\n };\n\n locals.viteReactRefresh = () => {\n return viteHelper.renderReactRefresh();\n };\n\n locals.csrf = () => {\n const token =\n locals._csrf ||\n locals.csrfToken ||\n (typeof locals.req?.csrfToken === 'function' ? locals.req.csrfToken() : '') ||\n '';\n return token ? `<input type=\"hidden\" name=\"_token\" value=\"${escapeHtmlAttr(token)}\">` : '';\n };\n\n locals.json = (value: any) => {\n return JSON.stringify(value);\n };\n\n if (!locals.routes) {\n locals.routes = (_group?: string) => {\n if (locals.routeConfig || locals.ziggy) {\n const routesData = JSON.stringify(locals.routeConfig || locals.ziggy).replace(/</g, '\\\\u003c');\n return `<script>const Ziggy = ${routesData};</script>`;\n }\n return '';\n };\n }\n\n const html = compiledTemplate(locals);\n callback(null, html);\n } catch (err: unknown) {\n callback(err instanceof Error ? err : new Error(String(err)));\n }\n };\n}\n\n/**\n * Default Inertia Blade EJS engine instance.\n */\nexport const inertiaEngine = createInertiaEngine();\n\n/**\n * Clear all template engine caches (useful during testing or hot reloading).\n */\nexport function clearEngineCache(): void {\n for (const cache of engineCaches) {\n cache.clear();\n }\n for (const timestamps of engineTimestamps) {\n timestamps.clear();\n }\n}\n"]}
|
package/dist/engine.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import path from 'path';
|
|
|
7
7
|
// src/directives.ts
|
|
8
8
|
var customDirectives = {};
|
|
9
9
|
function escapeJsString(str) {
|
|
10
|
-
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
10
|
+
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
11
11
|
}
|
|
12
12
|
function compileBladeDirectives(templateSource, localDirectives) {
|
|
13
13
|
let compiled = templateSource;
|
|
@@ -149,8 +149,13 @@ function safeStringify(obj) {
|
|
|
149
149
|
return value;
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
|
+
var cryptoModule;
|
|
153
|
+
async function getCrypto() {
|
|
154
|
+
cryptoModule ??= await import('crypto');
|
|
155
|
+
return cryptoModule;
|
|
156
|
+
}
|
|
152
157
|
async function generateSriHash(content) {
|
|
153
|
-
const crypto = await
|
|
158
|
+
const crypto = await getCrypto();
|
|
154
159
|
const hash = crypto.createHash("sha384").update(content);
|
|
155
160
|
return `sha384-${hash.digest("base64")}`;
|
|
156
161
|
}
|
|
@@ -173,7 +178,7 @@ var ViteHelper = class {
|
|
|
173
178
|
),
|
|
174
179
|
base: config?.base || `/${buildDir}/`,
|
|
175
180
|
manifest: config?.manifest || null,
|
|
176
|
-
isDev: config?.isDev
|
|
181
|
+
isDev: config?.isDev,
|
|
177
182
|
devServerUrlOverride: config?.devServerUrlOverride || null
|
|
178
183
|
};
|
|
179
184
|
}
|
|
@@ -185,8 +190,8 @@ var ViteHelper = class {
|
|
|
185
190
|
* NODE_ENV switch is required to toggle between dev and build assets.
|
|
186
191
|
*/
|
|
187
192
|
isDev() {
|
|
188
|
-
if (this.config.isDev
|
|
189
|
-
return
|
|
193
|
+
if (this.config.isDev !== void 0) {
|
|
194
|
+
return this.config.isDev;
|
|
190
195
|
}
|
|
191
196
|
const candidatePaths = [
|
|
192
197
|
this.config.hotFile,
|
|
@@ -220,6 +225,12 @@ var ViteHelper = class {
|
|
|
220
225
|
}
|
|
221
226
|
return this.config.devServerUrl;
|
|
222
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Get the production asset base path (always ends with a trailing slash).
|
|
230
|
+
*/
|
|
231
|
+
getBasePath() {
|
|
232
|
+
return this.config.base.endsWith("/") ? this.config.base : `${this.config.base}/`;
|
|
233
|
+
}
|
|
223
234
|
/**
|
|
224
235
|
* Check if manifest file exists.
|
|
225
236
|
*/
|
|
@@ -260,7 +271,9 @@ var ViteHelper = class {
|
|
|
260
271
|
this.manifestCache = parsed;
|
|
261
272
|
return parsed;
|
|
262
273
|
} catch (err) {
|
|
263
|
-
throw new Error(
|
|
274
|
+
throw new Error(
|
|
275
|
+
`[express-inertia] Failed to parse Vite manifest at ${p}: ${err instanceof Error ? err.message : String(err)}`
|
|
276
|
+
);
|
|
264
277
|
}
|
|
265
278
|
}
|
|
266
279
|
}
|
|
@@ -366,26 +379,49 @@ new ViteHelper();
|
|
|
366
379
|
|
|
367
380
|
// src/engine.ts
|
|
368
381
|
var engineCaches = /* @__PURE__ */ new Set();
|
|
382
|
+
var engineTimestamps = /* @__PURE__ */ new Set();
|
|
383
|
+
var TEMPLATE_SOURCE_KEY = "__express_inertia_template_source__";
|
|
369
384
|
function createInertiaEngine(options) {
|
|
370
385
|
const viteHelper = options?.vite ? createViteHelper(options.vite) : createViteHelper();
|
|
371
386
|
const shouldCache = options?.cache ?? !viteHelper.isDev();
|
|
372
387
|
const inertiaVersion = options?.inertiaVersion ?? 2;
|
|
373
388
|
const defaultRootElement = options?.rootElement ?? true;
|
|
374
389
|
const templateCache = /* @__PURE__ */ new Map();
|
|
390
|
+
const templateTimestamps = /* @__PURE__ */ new Map();
|
|
375
391
|
engineCaches.add(templateCache);
|
|
392
|
+
engineTimestamps.add(templateTimestamps);
|
|
376
393
|
return function inertiaBladeEngine(filePath, rawOptions, callback) {
|
|
377
394
|
try {
|
|
378
|
-
|
|
395
|
+
const template = options?.templateSource;
|
|
396
|
+
const hasTemplateSource = template !== void 0;
|
|
397
|
+
const cacheKey = hasTemplateSource ? TEMPLATE_SOURCE_KEY : filePath;
|
|
398
|
+
let compiledTemplate;
|
|
399
|
+
let templateMtimeMs = -1;
|
|
400
|
+
if (hasTemplateSource) {
|
|
401
|
+
compiledTemplate = templateCache.get(cacheKey);
|
|
402
|
+
} else if (shouldCache) {
|
|
403
|
+
compiledTemplate = templateCache.get(cacheKey);
|
|
404
|
+
} else {
|
|
405
|
+
try {
|
|
406
|
+
templateMtimeMs = fs.statSync(filePath).mtimeMs;
|
|
407
|
+
} catch {
|
|
408
|
+
templateMtimeMs = 0;
|
|
409
|
+
}
|
|
410
|
+
if (templateTimestamps.get(cacheKey) === templateMtimeMs) {
|
|
411
|
+
compiledTemplate = templateCache.get(cacheKey);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
379
414
|
if (!compiledTemplate) {
|
|
380
|
-
const templateSource =
|
|
415
|
+
const templateSource = template !== void 0 ? template : fs.readFileSync(filePath, "utf-8");
|
|
381
416
|
const compiledSource = options?.compileTemplate ? options.compileTemplate(templateSource) : compileBladeDirectives(templateSource, options?.directives);
|
|
382
417
|
compiledTemplate = ejs.compile(compiledSource, {
|
|
383
418
|
filename: filePath,
|
|
384
|
-
cache:
|
|
419
|
+
cache: false,
|
|
385
420
|
async: false
|
|
386
421
|
});
|
|
387
|
-
|
|
388
|
-
|
|
422
|
+
templateCache.set(cacheKey, compiledTemplate);
|
|
423
|
+
if (!hasTemplateSource) {
|
|
424
|
+
templateTimestamps.set(cacheKey, templateMtimeMs);
|
|
389
425
|
}
|
|
390
426
|
}
|
|
391
427
|
const locals = { ...rawOptions };
|
|
@@ -437,15 +473,15 @@ ${scriptTag}`;
|
|
|
437
473
|
};
|
|
438
474
|
locals.csrf = () => {
|
|
439
475
|
const token = locals._csrf || locals.csrfToken || (typeof locals.req?.csrfToken === "function" ? locals.req.csrfToken() : "") || "";
|
|
440
|
-
return token ? `<input type="hidden" name="_token" value="${token}">` : "";
|
|
476
|
+
return token ? `<input type="hidden" name="_token" value="${escapeHtmlAttr(token)}">` : "";
|
|
441
477
|
};
|
|
442
478
|
locals.json = (value) => {
|
|
443
479
|
return JSON.stringify(value);
|
|
444
480
|
};
|
|
445
481
|
if (!locals.routes) {
|
|
446
|
-
locals.routes = (
|
|
482
|
+
locals.routes = (_group) => {
|
|
447
483
|
if (locals.routeConfig || locals.ziggy) {
|
|
448
|
-
const routesData = JSON.stringify(locals.routeConfig || locals.ziggy);
|
|
484
|
+
const routesData = JSON.stringify(locals.routeConfig || locals.ziggy).replace(/</g, "\\u003c");
|
|
449
485
|
return `<script>const Ziggy = ${routesData};</script>`;
|
|
450
486
|
}
|
|
451
487
|
return "";
|
|
@@ -454,7 +490,7 @@ ${scriptTag}`;
|
|
|
454
490
|
const html = compiledTemplate(locals);
|
|
455
491
|
callback(null, html);
|
|
456
492
|
} catch (err) {
|
|
457
|
-
callback(err);
|
|
493
|
+
callback(err instanceof Error ? err : new Error(String(err)));
|
|
458
494
|
}
|
|
459
495
|
};
|
|
460
496
|
}
|
|
@@ -463,6 +499,9 @@ function clearEngineCache() {
|
|
|
463
499
|
for (const cache of engineCaches) {
|
|
464
500
|
cache.clear();
|
|
465
501
|
}
|
|
502
|
+
for (const timestamps of engineTimestamps) {
|
|
503
|
+
timestamps.clear();
|
|
504
|
+
}
|
|
466
505
|
}
|
|
467
506
|
|
|
468
507
|
export { clearEngineCache, createInertiaEngine, inertiaEngine };
|