@dudousxd/nestjs-inertia 1.0.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/CHANGELOG.md +139 -0
- package/LICENSE +21 -0
- package/README.md +317 -0
- package/dist/index.cjs +2314 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +461 -0
- package/dist/index.js +2265 -0
- package/dist/index.js.map +1 -0
- package/package.json +120 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2265 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/errors/exceptions.ts
|
|
13
|
+
import { ForbiddenException } from "@nestjs/common";
|
|
14
|
+
var InvalidInertiaConfigException, InertiaServiceNotAvailableException, UnsupportedRootViewExtensionException, MissingTemplateEngineDepException, MissingCookieDepException, InvalidCsrfTokenException;
|
|
15
|
+
var init_exceptions = __esm({
|
|
16
|
+
"src/errors/exceptions.ts"() {
|
|
17
|
+
"use strict";
|
|
18
|
+
InvalidInertiaConfigException = class extends Error {
|
|
19
|
+
static {
|
|
20
|
+
__name(this, "InvalidInertiaConfigException");
|
|
21
|
+
}
|
|
22
|
+
constructor(message) {
|
|
23
|
+
super(`[nestjs-inertia] Invalid config: ${message}`);
|
|
24
|
+
this.name = "InvalidInertiaConfigException";
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
InertiaServiceNotAvailableException = class extends Error {
|
|
28
|
+
static {
|
|
29
|
+
__name(this, "InertiaServiceNotAvailableException");
|
|
30
|
+
}
|
|
31
|
+
constructor() {
|
|
32
|
+
super("[nestjs-inertia] req.inertia is not defined \u2014 middleware did not run. Ensure InertiaModule is imported and the middleware applies to this route.");
|
|
33
|
+
this.name = "InertiaServiceNotAvailableException";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
UnsupportedRootViewExtensionException = class extends Error {
|
|
37
|
+
static {
|
|
38
|
+
__name(this, "UnsupportedRootViewExtensionException");
|
|
39
|
+
}
|
|
40
|
+
constructor(extension) {
|
|
41
|
+
super(`[nestjs-inertia] rootView extension "${extension}" is not supported. Supported extensions: .html, .htm, .hbs, .handlebars, .ejs, .pug, .liquid, .liquidjs. Or pass a (ctx) => string function for full control.`);
|
|
42
|
+
this.name = "UnsupportedRootViewExtensionException";
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
MissingTemplateEngineDepException = class extends Error {
|
|
46
|
+
static {
|
|
47
|
+
__name(this, "MissingTemplateEngineDepException");
|
|
48
|
+
}
|
|
49
|
+
constructor(engine, packageName) {
|
|
50
|
+
super(`[nestjs-inertia] Template engine "${engine}" requires "${packageName}" as a peer dependency. Install with: pnpm add ${packageName}`);
|
|
51
|
+
this.name = "MissingTemplateEngineDepException";
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
MissingCookieDepException = class extends Error {
|
|
55
|
+
static {
|
|
56
|
+
__name(this, "MissingCookieDepException");
|
|
57
|
+
}
|
|
58
|
+
constructor(platform) {
|
|
59
|
+
const dep = platform === "express" ? "cookie-parser" : "@fastify/cookie";
|
|
60
|
+
super(`[nestjs-inertia] CSRF requires "${dep}" as a peer dependency for ${platform}. Install with: pnpm add ${dep}`);
|
|
61
|
+
this.name = "MissingCookieDepException";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
InvalidCsrfTokenException = class extends ForbiddenException {
|
|
65
|
+
static {
|
|
66
|
+
__name(this, "InvalidCsrfTokenException");
|
|
67
|
+
}
|
|
68
|
+
constructor() {
|
|
69
|
+
super("[nestjs-inertia] CSRF token is missing or invalid.");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// src/shell/handlebars.adapter.ts
|
|
76
|
+
var handlebars_adapter_exports = {};
|
|
77
|
+
__export(handlebars_adapter_exports, {
|
|
78
|
+
handlebarsAdapter: () => handlebarsAdapter
|
|
79
|
+
});
|
|
80
|
+
import { createRequire } from "module";
|
|
81
|
+
function loadHandlebars() {
|
|
82
|
+
try {
|
|
83
|
+
return require2("handlebars");
|
|
84
|
+
} catch {
|
|
85
|
+
throw new MissingTemplateEngineDepException("Handlebars", "handlebars");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
var require2, handlebarsAdapter;
|
|
89
|
+
var init_handlebars_adapter = __esm({
|
|
90
|
+
"src/shell/handlebars.adapter.ts"() {
|
|
91
|
+
"use strict";
|
|
92
|
+
init_exceptions();
|
|
93
|
+
require2 = createRequire(import.meta.url);
|
|
94
|
+
__name(loadHandlebars, "loadHandlebars");
|
|
95
|
+
handlebarsAdapter = {
|
|
96
|
+
extension: ".hbs",
|
|
97
|
+
packageName: "handlebars",
|
|
98
|
+
compile(templateSource) {
|
|
99
|
+
const hbs = loadHandlebars();
|
|
100
|
+
const compiled = hbs.compile(templateSource);
|
|
101
|
+
return (locals) => compiled(locals);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// src/shell/ejs.adapter.ts
|
|
108
|
+
var ejs_adapter_exports = {};
|
|
109
|
+
__export(ejs_adapter_exports, {
|
|
110
|
+
ejsAdapter: () => ejsAdapter
|
|
111
|
+
});
|
|
112
|
+
import { createRequire as createRequire2 } from "module";
|
|
113
|
+
function loadEjs() {
|
|
114
|
+
try {
|
|
115
|
+
return require3("ejs");
|
|
116
|
+
} catch {
|
|
117
|
+
throw new MissingTemplateEngineDepException("EJS", "ejs");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
var require3, ejsAdapter;
|
|
121
|
+
var init_ejs_adapter = __esm({
|
|
122
|
+
"src/shell/ejs.adapter.ts"() {
|
|
123
|
+
"use strict";
|
|
124
|
+
init_exceptions();
|
|
125
|
+
require3 = createRequire2(import.meta.url);
|
|
126
|
+
__name(loadEjs, "loadEjs");
|
|
127
|
+
ejsAdapter = {
|
|
128
|
+
extension: ".ejs",
|
|
129
|
+
packageName: "ejs",
|
|
130
|
+
compile(templateSource, absPath) {
|
|
131
|
+
const ejs = loadEjs();
|
|
132
|
+
const compiled = ejs.compile(templateSource, {
|
|
133
|
+
filename: absPath,
|
|
134
|
+
async: false
|
|
135
|
+
});
|
|
136
|
+
return (locals) => compiled(locals);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// src/shell/pug.adapter.ts
|
|
143
|
+
var pug_adapter_exports = {};
|
|
144
|
+
__export(pug_adapter_exports, {
|
|
145
|
+
pugAdapter: () => pugAdapter
|
|
146
|
+
});
|
|
147
|
+
import { createRequire as createRequire3 } from "module";
|
|
148
|
+
function loadPug() {
|
|
149
|
+
try {
|
|
150
|
+
return require4("pug");
|
|
151
|
+
} catch {
|
|
152
|
+
throw new MissingTemplateEngineDepException("Pug", "pug");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
var require4, pugAdapter;
|
|
156
|
+
var init_pug_adapter = __esm({
|
|
157
|
+
"src/shell/pug.adapter.ts"() {
|
|
158
|
+
"use strict";
|
|
159
|
+
init_exceptions();
|
|
160
|
+
require4 = createRequire3(import.meta.url);
|
|
161
|
+
__name(loadPug, "loadPug");
|
|
162
|
+
pugAdapter = {
|
|
163
|
+
extension: ".pug",
|
|
164
|
+
packageName: "pug",
|
|
165
|
+
compile(templateSource, absPath) {
|
|
166
|
+
const pug = loadPug();
|
|
167
|
+
const compiled = pug.compile(templateSource, {
|
|
168
|
+
filename: absPath
|
|
169
|
+
});
|
|
170
|
+
return (locals) => compiled(locals);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// src/shell/liquid.adapter.ts
|
|
177
|
+
var liquid_adapter_exports = {};
|
|
178
|
+
__export(liquid_adapter_exports, {
|
|
179
|
+
liquidAdapter: () => liquidAdapter
|
|
180
|
+
});
|
|
181
|
+
import { createRequire as createRequire4 } from "module";
|
|
182
|
+
function loadLiquid() {
|
|
183
|
+
try {
|
|
184
|
+
const mod = require5("liquidjs");
|
|
185
|
+
return mod.Liquid;
|
|
186
|
+
} catch {
|
|
187
|
+
throw new MissingTemplateEngineDepException("Liquid", "liquidjs");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
var require5, liquidAdapter;
|
|
191
|
+
var init_liquid_adapter = __esm({
|
|
192
|
+
"src/shell/liquid.adapter.ts"() {
|
|
193
|
+
"use strict";
|
|
194
|
+
init_exceptions();
|
|
195
|
+
require5 = createRequire4(import.meta.url);
|
|
196
|
+
__name(loadLiquid, "loadLiquid");
|
|
197
|
+
liquidAdapter = {
|
|
198
|
+
extension: ".liquid",
|
|
199
|
+
packageName: "liquidjs",
|
|
200
|
+
compile(templateSource) {
|
|
201
|
+
const Liquid = loadLiquid();
|
|
202
|
+
const engine = new Liquid({
|
|
203
|
+
outputEscape: "escape"
|
|
204
|
+
});
|
|
205
|
+
return async (locals) => engine.parseAndRender(templateSource, locals);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// src/middleware/fastify-method-spoof.middleware.ts
|
|
212
|
+
var fastify_method_spoof_middleware_exports = {};
|
|
213
|
+
__export(fastify_method_spoof_middleware_exports, {
|
|
214
|
+
registerFastifyMethodSpoof: () => registerFastifyMethodSpoof
|
|
215
|
+
});
|
|
216
|
+
function registerFastifyMethodSpoof(app, options) {
|
|
217
|
+
if (options.methodSpoofing !== true) return;
|
|
218
|
+
app.addHook("preHandler", async (req) => {
|
|
219
|
+
const r = req;
|
|
220
|
+
if (r.method !== "POST") return;
|
|
221
|
+
const contentType = (r.headers["content-type"] ?? "").toString().toLowerCase();
|
|
222
|
+
if (!contentType.startsWith("multipart/")) return;
|
|
223
|
+
const spoofed = String(r.body?._method ?? "").toUpperCase();
|
|
224
|
+
if (ALLOWED2.has(spoofed)) {
|
|
225
|
+
r.method = spoofed;
|
|
226
|
+
if (r.body && typeof r.body === "object") {
|
|
227
|
+
r.body._method = void 0;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
var ALLOWED2;
|
|
233
|
+
var init_fastify_method_spoof_middleware = __esm({
|
|
234
|
+
"src/middleware/fastify-method-spoof.middleware.ts"() {
|
|
235
|
+
"use strict";
|
|
236
|
+
ALLOWED2 = /* @__PURE__ */ new Set([
|
|
237
|
+
"PUT",
|
|
238
|
+
"PATCH",
|
|
239
|
+
"DELETE"
|
|
240
|
+
]);
|
|
241
|
+
__name(registerFastifyMethodSpoof, "registerFastifyMethodSpoof");
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// src/interceptor/error-bag.interceptor.ts
|
|
246
|
+
import { Injectable } from "@nestjs/common";
|
|
247
|
+
import { map } from "rxjs/operators";
|
|
248
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
249
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
250
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
251
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
252
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
253
|
+
}
|
|
254
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
255
|
+
var ErrorBagInterceptor = class {
|
|
256
|
+
static {
|
|
257
|
+
__name(this, "ErrorBagInterceptor");
|
|
258
|
+
}
|
|
259
|
+
intercept(context, next) {
|
|
260
|
+
const req = context.switchToHttp().getRequest();
|
|
261
|
+
const bag = req.header("X-Inertia-Error-Bag");
|
|
262
|
+
if (!bag) return next.handle();
|
|
263
|
+
return next.handle().pipe(map((value) => {
|
|
264
|
+
if (typeof value !== "object" || value === null) return value;
|
|
265
|
+
const v = value;
|
|
266
|
+
if (v.errors === void 0) return value;
|
|
267
|
+
return {
|
|
268
|
+
...v,
|
|
269
|
+
errors: {
|
|
270
|
+
[bag]: v.errors
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
ErrorBagInterceptor = _ts_decorate([
|
|
277
|
+
Injectable()
|
|
278
|
+
], ErrorBagInterceptor);
|
|
279
|
+
|
|
280
|
+
// src/interceptor/redirect.interceptor.ts
|
|
281
|
+
import { Inject, Injectable as Injectable2 } from "@nestjs/common";
|
|
282
|
+
import { tap } from "rxjs/operators";
|
|
283
|
+
|
|
284
|
+
// src/tokens.ts
|
|
285
|
+
var INERTIA_MODULE_OPTIONS = /* @__PURE__ */ Symbol("INERTIA_MODULE_OPTIONS");
|
|
286
|
+
var INERTIA_FEATURE_OPTIONS = /* @__PURE__ */ Symbol("INERTIA_FEATURE_OPTIONS");
|
|
287
|
+
var INERTIA_MANIFEST = /* @__PURE__ */ Symbol("INERTIA_MANIFEST");
|
|
288
|
+
var INERTIA_ASSET_VERSION = /* @__PURE__ */ Symbol("INERTIA_ASSET_VERSION");
|
|
289
|
+
var INERTIA_DEFAULT_SCOPE = "default";
|
|
290
|
+
var RESERVED_SCOPES = /* @__PURE__ */ new Set([
|
|
291
|
+
"default"
|
|
292
|
+
]);
|
|
293
|
+
var _featureTokenCache = /* @__PURE__ */ new Map();
|
|
294
|
+
function featureToken(kind, scope, rootId) {
|
|
295
|
+
const key = rootId ? `${kind}:${scope}:${rootId}` : `${kind}:${scope}`;
|
|
296
|
+
const cached = _featureTokenCache.get(key);
|
|
297
|
+
if (cached) return cached;
|
|
298
|
+
const sym = /* @__PURE__ */ Symbol(`INERTIA_FEATURE_${kind}:${scope}${rootId ? `:${rootId}` : ""}`);
|
|
299
|
+
_featureTokenCache.set(key, sym);
|
|
300
|
+
return sym;
|
|
301
|
+
}
|
|
302
|
+
__name(featureToken, "featureToken");
|
|
303
|
+
function assertScopeNotReserved(scope) {
|
|
304
|
+
if (RESERVED_SCOPES.has(scope)) {
|
|
305
|
+
throw new Error(`[nestjs-inertia] Scope "${scope}" is reserved. Use forRoot() for the default scope.`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
__name(assertScopeNotReserved, "assertScopeNotReserved");
|
|
309
|
+
|
|
310
|
+
// src/interceptor/redirect.interceptor.ts
|
|
311
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
312
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
313
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
314
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
315
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
316
|
+
}
|
|
317
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
318
|
+
function _ts_metadata(k, v) {
|
|
319
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
320
|
+
}
|
|
321
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
322
|
+
function _ts_param(paramIndex, decorator) {
|
|
323
|
+
return function(target, key) {
|
|
324
|
+
decorator(target, key, paramIndex);
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
__name(_ts_param, "_ts_param");
|
|
328
|
+
var SAFE_METHODS = /* @__PURE__ */ new Set([
|
|
329
|
+
"PUT",
|
|
330
|
+
"PATCH",
|
|
331
|
+
"DELETE"
|
|
332
|
+
]);
|
|
333
|
+
function getHeader(req, name) {
|
|
334
|
+
const r = req;
|
|
335
|
+
if (typeof r.header === "function") return r.header(name);
|
|
336
|
+
const v = r.headers?.[name.toLowerCase()];
|
|
337
|
+
return Array.isArray(v) ? v[0] : v;
|
|
338
|
+
}
|
|
339
|
+
__name(getHeader, "getHeader");
|
|
340
|
+
var RedirectInterceptor = class {
|
|
341
|
+
static {
|
|
342
|
+
__name(this, "RedirectInterceptor");
|
|
343
|
+
}
|
|
344
|
+
options;
|
|
345
|
+
constructor(options) {
|
|
346
|
+
this.options = options;
|
|
347
|
+
}
|
|
348
|
+
intercept(context, next) {
|
|
349
|
+
if (this.options.autoUpgrade303 === false) return next.handle();
|
|
350
|
+
const req = context.switchToHttp().getRequest();
|
|
351
|
+
const res = context.switchToHttp().getResponse();
|
|
352
|
+
const method = req.method;
|
|
353
|
+
if (SAFE_METHODS.has(method) && getHeader(req, "X-Inertia")) {
|
|
354
|
+
if (typeof res.redirect === "function") {
|
|
355
|
+
const originalRedirect = res.redirect.bind(res);
|
|
356
|
+
res.redirect = /* @__PURE__ */ __name(function patchedRedirect(statusOrUrl, url) {
|
|
357
|
+
if (typeof statusOrUrl === "number" && statusOrUrl === 302) {
|
|
358
|
+
originalRedirect(303, url);
|
|
359
|
+
} else if (typeof statusOrUrl === "string") {
|
|
360
|
+
originalRedirect(303, statusOrUrl);
|
|
361
|
+
} else {
|
|
362
|
+
originalRedirect(statusOrUrl, url);
|
|
363
|
+
}
|
|
364
|
+
}, "patchedRedirect");
|
|
365
|
+
}
|
|
366
|
+
const resAny = res;
|
|
367
|
+
if (typeof resAny.code === "function") {
|
|
368
|
+
const originalCode = resAny.code.bind(res);
|
|
369
|
+
resAny.code = /* @__PURE__ */ __name(function patchedCode(n) {
|
|
370
|
+
return originalCode(n === 302 ? 303 : n);
|
|
371
|
+
}, "patchedCode");
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return next.handle().pipe(tap(() => {
|
|
375
|
+
if (res.statusCode === 302 && SAFE_METHODS.has(method) && getHeader(req, "X-Inertia")) {
|
|
376
|
+
res.statusCode = 303;
|
|
377
|
+
}
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
RedirectInterceptor = _ts_decorate2([
|
|
382
|
+
Injectable2(),
|
|
383
|
+
_ts_param(0, Inject(INERTIA_MODULE_OPTIONS)),
|
|
384
|
+
_ts_metadata("design:type", Function),
|
|
385
|
+
_ts_metadata("design:paramtypes", [
|
|
386
|
+
typeof InertiaModuleOptions === "undefined" ? Object : InertiaModuleOptions
|
|
387
|
+
])
|
|
388
|
+
], RedirectInterceptor);
|
|
389
|
+
|
|
390
|
+
// src/middleware/method-spoof.middleware.ts
|
|
391
|
+
import { Inject as Inject2, Injectable as Injectable3 } from "@nestjs/common";
|
|
392
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
393
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
394
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
395
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
396
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
397
|
+
}
|
|
398
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
399
|
+
function _ts_metadata2(k, v) {
|
|
400
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
401
|
+
}
|
|
402
|
+
__name(_ts_metadata2, "_ts_metadata");
|
|
403
|
+
function _ts_param2(paramIndex, decorator) {
|
|
404
|
+
return function(target, key) {
|
|
405
|
+
decorator(target, key, paramIndex);
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
__name(_ts_param2, "_ts_param");
|
|
409
|
+
var ALLOWED = /* @__PURE__ */ new Set([
|
|
410
|
+
"PUT",
|
|
411
|
+
"PATCH",
|
|
412
|
+
"DELETE"
|
|
413
|
+
]);
|
|
414
|
+
var MethodSpoofMiddleware = class {
|
|
415
|
+
static {
|
|
416
|
+
__name(this, "MethodSpoofMiddleware");
|
|
417
|
+
}
|
|
418
|
+
options;
|
|
419
|
+
constructor(options) {
|
|
420
|
+
this.options = options;
|
|
421
|
+
}
|
|
422
|
+
use(req, _res, next) {
|
|
423
|
+
if (this.options.methodSpoofing !== true) return next();
|
|
424
|
+
if (req.method !== "POST") return next();
|
|
425
|
+
const contentType = (req.headers["content-type"] ?? "").toString().toLowerCase();
|
|
426
|
+
if (!contentType.startsWith("multipart/")) return next();
|
|
427
|
+
const spoofed = String(req.body?._method ?? "").toUpperCase();
|
|
428
|
+
if (ALLOWED.has(spoofed)) {
|
|
429
|
+
req.method = spoofed;
|
|
430
|
+
if (req.body && typeof req.body === "object") {
|
|
431
|
+
req.body._method = void 0;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
next();
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
MethodSpoofMiddleware = _ts_decorate3([
|
|
438
|
+
Injectable3(),
|
|
439
|
+
_ts_param2(0, Inject2(INERTIA_MODULE_OPTIONS)),
|
|
440
|
+
_ts_metadata2("design:type", Function),
|
|
441
|
+
_ts_metadata2("design:paramtypes", [
|
|
442
|
+
typeof InertiaModuleOptions === "undefined" ? Object : InertiaModuleOptions
|
|
443
|
+
])
|
|
444
|
+
], MethodSpoofMiddleware);
|
|
445
|
+
|
|
446
|
+
// src/index.ts
|
|
447
|
+
init_exceptions();
|
|
448
|
+
|
|
449
|
+
// src/decorator/inertia.decorator.ts
|
|
450
|
+
import { SetMetadata } from "@nestjs/common";
|
|
451
|
+
var INERTIA_RENDER_COMPONENT = /* @__PURE__ */ Symbol("INERTIA_RENDER_COMPONENT");
|
|
452
|
+
function createInertiaDecorator(component) {
|
|
453
|
+
return SetMetadata(INERTIA_RENDER_COMPONENT, component);
|
|
454
|
+
}
|
|
455
|
+
__name(createInertiaDecorator, "createInertiaDecorator");
|
|
456
|
+
|
|
457
|
+
// src/markers.ts
|
|
458
|
+
var MARKER = /* @__PURE__ */ Symbol("inertia.marker");
|
|
459
|
+
function make(kind, value, meta = {}) {
|
|
460
|
+
return {
|
|
461
|
+
[MARKER]: true,
|
|
462
|
+
kind,
|
|
463
|
+
value,
|
|
464
|
+
meta
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
__name(make, "make");
|
|
468
|
+
function inertiaDecorator(component) {
|
|
469
|
+
return createInertiaDecorator(component);
|
|
470
|
+
}
|
|
471
|
+
__name(inertiaDecorator, "inertiaDecorator");
|
|
472
|
+
function always(fn) {
|
|
473
|
+
return make("always", fn);
|
|
474
|
+
}
|
|
475
|
+
__name(always, "always");
|
|
476
|
+
function optional(fn) {
|
|
477
|
+
return make("optional", fn);
|
|
478
|
+
}
|
|
479
|
+
__name(optional, "optional");
|
|
480
|
+
var _lazyWarned = false;
|
|
481
|
+
function lazy(fn) {
|
|
482
|
+
if (!_lazyWarned) {
|
|
483
|
+
_lazyWarned = true;
|
|
484
|
+
console.warn("[nestjs-inertia] Inertia.lazy() is deprecated and will be removed in a future version. Use Inertia.optional() instead (Inertia v3).");
|
|
485
|
+
}
|
|
486
|
+
return optional(fn);
|
|
487
|
+
}
|
|
488
|
+
__name(lazy, "lazy");
|
|
489
|
+
function defer(fn, group = "default") {
|
|
490
|
+
return make("defer", fn, {
|
|
491
|
+
group
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
__name(defer, "defer");
|
|
495
|
+
function once(fn) {
|
|
496
|
+
return make("once", fn);
|
|
497
|
+
}
|
|
498
|
+
__name(once, "once");
|
|
499
|
+
function merge(fn, opts) {
|
|
500
|
+
const meta = {
|
|
501
|
+
deep: opts?.deep ?? false
|
|
502
|
+
};
|
|
503
|
+
if (opts?.matchOn !== void 0) meta.matchOn = opts.matchOn;
|
|
504
|
+
return make("merge", fn, meta);
|
|
505
|
+
}
|
|
506
|
+
__name(merge, "merge");
|
|
507
|
+
var Inertia = Object.assign(inertiaDecorator, {
|
|
508
|
+
always,
|
|
509
|
+
optional,
|
|
510
|
+
lazy,
|
|
511
|
+
defer,
|
|
512
|
+
once,
|
|
513
|
+
merge
|
|
514
|
+
});
|
|
515
|
+
function isMarker(value) {
|
|
516
|
+
return typeof value === "object" && value !== null && value[MARKER] === true;
|
|
517
|
+
}
|
|
518
|
+
__name(isMarker, "isMarker");
|
|
519
|
+
function getMarkerKind(marker) {
|
|
520
|
+
return marker.kind;
|
|
521
|
+
}
|
|
522
|
+
__name(getMarkerKind, "getMarkerKind");
|
|
523
|
+
function getMarkerValue(marker) {
|
|
524
|
+
return marker.value;
|
|
525
|
+
}
|
|
526
|
+
__name(getMarkerValue, "getMarkerValue");
|
|
527
|
+
function getMarkerMeta(marker) {
|
|
528
|
+
return marker.meta;
|
|
529
|
+
}
|
|
530
|
+
__name(getMarkerMeta, "getMarkerMeta");
|
|
531
|
+
|
|
532
|
+
// src/decorator/use-inertia.decorator.ts
|
|
533
|
+
import { SetMetadata as SetMetadata2 } from "@nestjs/common";
|
|
534
|
+
var INERTIA_USE_SCOPE = "INERTIA_USE_SCOPE";
|
|
535
|
+
function UseInertia(scope) {
|
|
536
|
+
return SetMetadata2(INERTIA_USE_SCOPE, scope);
|
|
537
|
+
}
|
|
538
|
+
__name(UseInertia, "UseInertia");
|
|
539
|
+
|
|
540
|
+
// src/interceptor/render.interceptor.ts
|
|
541
|
+
import { Inject as Inject3, Injectable as Injectable4 } from "@nestjs/common";
|
|
542
|
+
import { Reflector } from "@nestjs/core";
|
|
543
|
+
import { from, of } from "rxjs";
|
|
544
|
+
import { switchMap } from "rxjs/operators";
|
|
545
|
+
init_exceptions();
|
|
546
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
547
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
548
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
549
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
550
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
551
|
+
}
|
|
552
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
553
|
+
function _ts_metadata3(k, v) {
|
|
554
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
555
|
+
}
|
|
556
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
557
|
+
function _ts_param3(paramIndex, decorator) {
|
|
558
|
+
return function(target, key) {
|
|
559
|
+
decorator(target, key, paramIndex);
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
__name(_ts_param3, "_ts_param");
|
|
563
|
+
var InertiaRenderInterceptor = class {
|
|
564
|
+
static {
|
|
565
|
+
__name(this, "InertiaRenderInterceptor");
|
|
566
|
+
}
|
|
567
|
+
reflector;
|
|
568
|
+
constructor(reflector) {
|
|
569
|
+
this.reflector = reflector;
|
|
570
|
+
}
|
|
571
|
+
intercept(context, next) {
|
|
572
|
+
const component = this.reflector.get(INERTIA_RENDER_COMPONENT, context.getHandler());
|
|
573
|
+
if (!component) {
|
|
574
|
+
return next.handle();
|
|
575
|
+
}
|
|
576
|
+
const req = context.switchToHttp().getRequest();
|
|
577
|
+
const res = context.switchToHttp().getResponse();
|
|
578
|
+
return next.handle().pipe(switchMap((returnValue) => {
|
|
579
|
+
if (res.headersSent) {
|
|
580
|
+
return of(void 0);
|
|
581
|
+
}
|
|
582
|
+
if (!req.inertia) {
|
|
583
|
+
throw new InertiaServiceNotAvailableException();
|
|
584
|
+
}
|
|
585
|
+
const props = returnValue ?? {};
|
|
586
|
+
return from(req.inertia.render(component, props)).pipe(switchMap(() => of(void 0)));
|
|
587
|
+
}));
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
InertiaRenderInterceptor = _ts_decorate4([
|
|
591
|
+
Injectable4(),
|
|
592
|
+
_ts_param3(0, Inject3(Reflector)),
|
|
593
|
+
_ts_metadata3("design:type", Function),
|
|
594
|
+
_ts_metadata3("design:paramtypes", [
|
|
595
|
+
typeof Reflector === "undefined" ? Object : Reflector
|
|
596
|
+
])
|
|
597
|
+
], InertiaRenderInterceptor);
|
|
598
|
+
|
|
599
|
+
// src/service.ts
|
|
600
|
+
import { Logger } from "@nestjs/common";
|
|
601
|
+
|
|
602
|
+
// src/helpers/nullify-undefined.ts
|
|
603
|
+
function nullifyUndefined(props) {
|
|
604
|
+
const out = {};
|
|
605
|
+
for (const [k, v] of Object.entries(props)) {
|
|
606
|
+
out[k] = v === void 0 ? null : v;
|
|
607
|
+
}
|
|
608
|
+
return out;
|
|
609
|
+
}
|
|
610
|
+
__name(nullifyUndefined, "nullifyUndefined");
|
|
611
|
+
|
|
612
|
+
// src/helpers/set-nested.ts
|
|
613
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
614
|
+
"__proto__",
|
|
615
|
+
"prototype",
|
|
616
|
+
"constructor"
|
|
617
|
+
]);
|
|
618
|
+
function assertSafeKey(key) {
|
|
619
|
+
if (FORBIDDEN_KEYS.has(key)) {
|
|
620
|
+
throw new Error(`[nestjs-inertia] Disallowed property key in nested path: "${key}"`);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
__name(assertSafeKey, "assertSafeKey");
|
|
624
|
+
function setNested(target, path, value) {
|
|
625
|
+
if (path.length === 0) return;
|
|
626
|
+
let cur = target;
|
|
627
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
628
|
+
const key = path[i];
|
|
629
|
+
assertSafeKey(key);
|
|
630
|
+
const existing = cur[key];
|
|
631
|
+
if (existing === void 0) {
|
|
632
|
+
cur[key] = {};
|
|
633
|
+
} else if (typeof existing !== "object" || existing === null || Array.isArray(existing)) {
|
|
634
|
+
throw new Error(`[nestjs-inertia] dot-notation conflict at key "${path.slice(0, i + 1).join(".")}": expected object, got ${Array.isArray(existing) ? "array" : typeof existing}`);
|
|
635
|
+
}
|
|
636
|
+
cur = cur[key];
|
|
637
|
+
}
|
|
638
|
+
const finalKey = path[path.length - 1];
|
|
639
|
+
assertSafeKey(finalKey);
|
|
640
|
+
cur[finalKey] = value;
|
|
641
|
+
}
|
|
642
|
+
__name(setNested, "setNested");
|
|
643
|
+
function unpackDotKeys(props) {
|
|
644
|
+
const out = {};
|
|
645
|
+
const dotKeysParents = /* @__PURE__ */ new Set();
|
|
646
|
+
for (const key of Object.keys(props)) {
|
|
647
|
+
if (key.includes(".")) {
|
|
648
|
+
dotKeysParents.add(key.split(".")[0]);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
for (const parent of dotKeysParents) {
|
|
652
|
+
if (props[parent] !== void 0 && (typeof props[parent] !== "object" || props[parent] === null || Array.isArray(props[parent]))) {
|
|
653
|
+
throw new Error(`[nestjs-inertia] dot-notation conflict at key "${parent}": exists as scalar AND as parent of a dot key`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
for (const [key, value] of Object.entries(props)) {
|
|
657
|
+
if (key.includes(".")) {
|
|
658
|
+
setNested(out, key.split("."), value);
|
|
659
|
+
} else {
|
|
660
|
+
out[key] = value;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return out;
|
|
664
|
+
}
|
|
665
|
+
__name(unpackDotKeys, "unpackDotKeys");
|
|
666
|
+
|
|
667
|
+
// src/service.ts
|
|
668
|
+
function validateLocationUrl(url) {
|
|
669
|
+
if (url.startsWith("/")) return url;
|
|
670
|
+
try {
|
|
671
|
+
const parsed = new URL(url);
|
|
672
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
673
|
+
throw new Error(`[nestjs-inertia] location() rejected unsafe URL scheme: ${url}`);
|
|
674
|
+
}
|
|
675
|
+
throw new Error(`[nestjs-inertia] location() rejected absolute URL to external host: ${url}. Use a relative path (e.g. "/dashboard") instead.`);
|
|
676
|
+
} catch (err) {
|
|
677
|
+
if (err instanceof TypeError) {
|
|
678
|
+
return url;
|
|
679
|
+
}
|
|
680
|
+
throw err;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
__name(validateLocationUrl, "validateLocationUrl");
|
|
684
|
+
var OMIT = /* @__PURE__ */ Symbol("inertia.omit");
|
|
685
|
+
function containsAlwaysMarker(value) {
|
|
686
|
+
if (isMarker(value)) {
|
|
687
|
+
return getMarkerKind(value) === "always";
|
|
688
|
+
}
|
|
689
|
+
if (Array.isArray(value)) {
|
|
690
|
+
return value.some(containsAlwaysMarker);
|
|
691
|
+
}
|
|
692
|
+
if (typeof value === "object" && value !== null) {
|
|
693
|
+
return Object.values(value).some(containsAlwaysMarker);
|
|
694
|
+
}
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
__name(containsAlwaysMarker, "containsAlwaysMarker");
|
|
698
|
+
async function resolveNestedObjectValue(obj, topKey, subKeep, deferredProps) {
|
|
699
|
+
const out = {};
|
|
700
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
701
|
+
const resolved = await resolveNestedValueInner(v, k, topKey, subKeep, deferredProps);
|
|
702
|
+
if (resolved !== OMIT) out[k] = resolved;
|
|
703
|
+
}
|
|
704
|
+
return out;
|
|
705
|
+
}
|
|
706
|
+
__name(resolveNestedObjectValue, "resolveNestedObjectValue");
|
|
707
|
+
async function resolveNestedValueInner(value, relPath, topKey, subKeep, deferredProps) {
|
|
708
|
+
if (isMarker(value)) {
|
|
709
|
+
return resolveMarker(value, relPath, topKey, subKeep, deferredProps);
|
|
710
|
+
}
|
|
711
|
+
if (Array.isArray(value)) {
|
|
712
|
+
const out = [];
|
|
713
|
+
for (const item of value) {
|
|
714
|
+
const resolved = await resolveNestedValueInner(item, relPath, topKey, subKeep, deferredProps);
|
|
715
|
+
if (resolved !== OMIT) out.push(resolved);
|
|
716
|
+
}
|
|
717
|
+
return out;
|
|
718
|
+
}
|
|
719
|
+
if (typeof value === "object" && value !== null) {
|
|
720
|
+
const obj = value;
|
|
721
|
+
const out = {};
|
|
722
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
723
|
+
const childPath = `${relPath}.${k}`;
|
|
724
|
+
const resolved = await resolveNestedValueInner(v, childPath, topKey, subKeep, deferredProps);
|
|
725
|
+
if (resolved !== OMIT) out[k] = resolved;
|
|
726
|
+
}
|
|
727
|
+
return out;
|
|
728
|
+
}
|
|
729
|
+
if (subKeep !== null) {
|
|
730
|
+
const included = subKeep.some((k) => k === relPath || k.startsWith(`${relPath}.`));
|
|
731
|
+
if (!included) return OMIT;
|
|
732
|
+
}
|
|
733
|
+
return value;
|
|
734
|
+
}
|
|
735
|
+
__name(resolveNestedValueInner, "resolveNestedValueInner");
|
|
736
|
+
async function resolveMarker(marker, relPath, topKey, subKeep, deferredProps) {
|
|
737
|
+
const kind = getMarkerKind(marker);
|
|
738
|
+
const fullPath = `${topKey}.${relPath}`;
|
|
739
|
+
if (kind === "always") {
|
|
740
|
+
return getMarkerValue(marker)();
|
|
741
|
+
}
|
|
742
|
+
if (kind === "optional") {
|
|
743
|
+
if (subKeep?.includes(relPath)) {
|
|
744
|
+
return getMarkerValue(marker)();
|
|
745
|
+
}
|
|
746
|
+
return OMIT;
|
|
747
|
+
}
|
|
748
|
+
if (kind === "once") {
|
|
749
|
+
if (subKeep === null) {
|
|
750
|
+
return getMarkerValue(marker)();
|
|
751
|
+
}
|
|
752
|
+
return OMIT;
|
|
753
|
+
}
|
|
754
|
+
if (kind === "defer") {
|
|
755
|
+
if (subKeep !== null) {
|
|
756
|
+
if (subKeep.includes(relPath)) return getMarkerValue(marker)();
|
|
757
|
+
return OMIT;
|
|
758
|
+
}
|
|
759
|
+
const meta = getMarkerMeta(marker);
|
|
760
|
+
const group = meta.group;
|
|
761
|
+
const existing = deferredProps[group];
|
|
762
|
+
if (existing) existing.push(fullPath);
|
|
763
|
+
else deferredProps[group] = [
|
|
764
|
+
fullPath
|
|
765
|
+
];
|
|
766
|
+
return OMIT;
|
|
767
|
+
}
|
|
768
|
+
if (kind === "merge") {
|
|
769
|
+
if (subKeep !== null && !subKeep.includes(relPath)) return OMIT;
|
|
770
|
+
return getMarkerValue(marker)();
|
|
771
|
+
}
|
|
772
|
+
return OMIT;
|
|
773
|
+
}
|
|
774
|
+
__name(resolveMarker, "resolveMarker");
|
|
775
|
+
var InertiaService = class _InertiaService {
|
|
776
|
+
static {
|
|
777
|
+
__name(this, "InertiaService");
|
|
778
|
+
}
|
|
779
|
+
req;
|
|
780
|
+
res;
|
|
781
|
+
deps;
|
|
782
|
+
logger = new Logger(_InertiaService.name);
|
|
783
|
+
shared = [];
|
|
784
|
+
encryptHistoryFlag;
|
|
785
|
+
clearHistoryFlag = false;
|
|
786
|
+
constructor(req, res, deps) {
|
|
787
|
+
this.req = req;
|
|
788
|
+
this.res = res;
|
|
789
|
+
this.deps = deps;
|
|
790
|
+
}
|
|
791
|
+
share(input) {
|
|
792
|
+
this.shared.push(input);
|
|
793
|
+
return this;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Perform an Inertia redirect. For Inertia XHR requests, issues a 409 with
|
|
797
|
+
* `X-Inertia-Location`; for plain browser visits, issues a 302 redirect.
|
|
798
|
+
*
|
|
799
|
+
* Only relative URLs (starting with `/`) or same-origin absolute URLs are
|
|
800
|
+
* accepted. Absolute URLs pointing to a different host are rejected to prevent
|
|
801
|
+
* open-redirect vulnerabilities.
|
|
802
|
+
*
|
|
803
|
+
* @param url Relative path (e.g. `/dashboard`) or same-origin absolute URL.
|
|
804
|
+
* @throws Error when `url` is an absolute URL pointing to a different origin.
|
|
805
|
+
*/
|
|
806
|
+
location(url) {
|
|
807
|
+
const safeUrl = validateLocationUrl(url);
|
|
808
|
+
if (this.req.header("X-Inertia")) {
|
|
809
|
+
this.res.status(409).setHeader("X-Inertia-Location", safeUrl).end();
|
|
810
|
+
} else {
|
|
811
|
+
this.res.status(302).setHeader("Location", safeUrl).end();
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
encryptHistory(value = true) {
|
|
815
|
+
this.encryptHistoryFlag = value;
|
|
816
|
+
return this;
|
|
817
|
+
}
|
|
818
|
+
clearHistory() {
|
|
819
|
+
this.clearHistoryFlag = true;
|
|
820
|
+
return this;
|
|
821
|
+
}
|
|
822
|
+
async resolveShared() {
|
|
823
|
+
const sources = [];
|
|
824
|
+
if (this.deps.moduleShare !== void 0) sources.push(this.deps.moduleShare);
|
|
825
|
+
if (this.deps.featureShare !== void 0) sources.push(this.deps.featureShare);
|
|
826
|
+
sources.push(...this.shared);
|
|
827
|
+
const out = {};
|
|
828
|
+
for (const s of sources) {
|
|
829
|
+
const resolved = typeof s === "function" ? await s(this.req) : s;
|
|
830
|
+
Object.assign(out, resolved);
|
|
831
|
+
}
|
|
832
|
+
return out;
|
|
833
|
+
}
|
|
834
|
+
async render(component, props = {}) {
|
|
835
|
+
const clientVersion = this.req.header("X-Inertia-Version");
|
|
836
|
+
if (this.req.method === "GET" && this.req.header("X-Inertia") && clientVersion !== void 0 && clientVersion !== this.deps.assetVersion) {
|
|
837
|
+
this.res.status(409).setHeader("X-Inertia-Location", this.req.originalUrl).end();
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
if (this.deps.flashStore && props.errors === void 0) {
|
|
841
|
+
try {
|
|
842
|
+
const flashed = await this.deps.flashStore.read(this.req.raw);
|
|
843
|
+
if (flashed && Object.keys(flashed).length > 0) {
|
|
844
|
+
this.share({
|
|
845
|
+
errors: flashed
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
} catch (err) {
|
|
849
|
+
this.logger.warn(`FlashStore.read() threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
const sharedProps = await this.resolveShared();
|
|
853
|
+
const rawProps = {
|
|
854
|
+
...sharedProps,
|
|
855
|
+
...props
|
|
856
|
+
};
|
|
857
|
+
if (rawProps.errors === void 0) rawProps.errors = {};
|
|
858
|
+
const partialComponent = this.req.header("X-Inertia-Partial-Component");
|
|
859
|
+
const isPartial = partialComponent === component;
|
|
860
|
+
const partialDataHeader = this.req.header("X-Inertia-Partial-Data");
|
|
861
|
+
const keepList = isPartial && partialDataHeader ? partialDataHeader.split(",").filter(Boolean) : null;
|
|
862
|
+
const keep = keepList && keepList.length > 0 ? keepList : null;
|
|
863
|
+
const resetHeader = this.req.header("X-Inertia-Reset");
|
|
864
|
+
const resetKeys = (resetHeader ?? "").split(",").filter(Boolean);
|
|
865
|
+
const resetOnceHeader = this.req.header("X-Inertia-Reset-Once");
|
|
866
|
+
const resetOnceKeys = (resetOnceHeader ?? "").split(",").filter(Boolean);
|
|
867
|
+
const exceptHeader = this.req.header("X-Inertia-Partial-Except");
|
|
868
|
+
const exceptKeys = isPartial ? (exceptHeader ?? "").split(",").filter(Boolean) : [];
|
|
869
|
+
const finalProps = {};
|
|
870
|
+
const deferredProps = {};
|
|
871
|
+
const mergeProps = [];
|
|
872
|
+
const deepMergeProps = [];
|
|
873
|
+
const matchPropsOn = {};
|
|
874
|
+
for (const [key, value] of Object.entries(rawProps)) {
|
|
875
|
+
if (exceptKeys.includes(key) && key !== "errors") continue;
|
|
876
|
+
if (isMarker(value)) {
|
|
877
|
+
const kind = getMarkerKind(value);
|
|
878
|
+
if (kind === "always") {
|
|
879
|
+
finalProps[key] = await getMarkerValue(value)();
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
if (kind === "optional") {
|
|
883
|
+
if (keep?.includes(key)) {
|
|
884
|
+
finalProps[key] = await getMarkerValue(value)();
|
|
885
|
+
}
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
if (kind === "once") {
|
|
889
|
+
if (!keep || resetOnceKeys.includes(key)) {
|
|
890
|
+
finalProps[key] = await getMarkerValue(value)();
|
|
891
|
+
}
|
|
892
|
+
continue;
|
|
893
|
+
}
|
|
894
|
+
if (kind === "defer") {
|
|
895
|
+
if (keep) {
|
|
896
|
+
if (keep.includes(key)) finalProps[key] = await getMarkerValue(value)();
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
const meta = getMarkerMeta(value);
|
|
900
|
+
const group = meta.group;
|
|
901
|
+
const existing = deferredProps[group];
|
|
902
|
+
if (existing) existing.push(key);
|
|
903
|
+
else deferredProps[group] = [
|
|
904
|
+
key
|
|
905
|
+
];
|
|
906
|
+
continue;
|
|
907
|
+
}
|
|
908
|
+
if (kind === "merge") {
|
|
909
|
+
const meta = getMarkerMeta(value);
|
|
910
|
+
if (keep && !keep.includes(key) && key !== "errors") continue;
|
|
911
|
+
const resolved2 = await getMarkerValue(value)();
|
|
912
|
+
finalProps[key] = resolved2;
|
|
913
|
+
if (!resetKeys.includes(key)) {
|
|
914
|
+
if (meta.deep) deepMergeProps.push(key);
|
|
915
|
+
else mergeProps.push(key);
|
|
916
|
+
}
|
|
917
|
+
if (meta.matchOn !== void 0) matchPropsOn[key] = meta.matchOn;
|
|
918
|
+
continue;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
const hasNestedKeepPath = keep?.some((k) => k.startsWith(`${key}.`)) ?? false;
|
|
922
|
+
const hasNestedAlways = keep ? containsAlwaysMarker(value) : false;
|
|
923
|
+
if (keep && !keep.includes(key) && key !== "errors" && !hasNestedKeepPath && !hasNestedAlways) continue;
|
|
924
|
+
let resolved = value;
|
|
925
|
+
if (typeof value === "function") {
|
|
926
|
+
resolved = await value();
|
|
927
|
+
}
|
|
928
|
+
let nestedKeep = null;
|
|
929
|
+
if (keep !== null) {
|
|
930
|
+
if (keep.includes(key)) {
|
|
931
|
+
nestedKeep = null;
|
|
932
|
+
} else {
|
|
933
|
+
nestedKeep = keep.filter((k) => k.startsWith(`${key}.`)).map((k) => k.slice(key.length + 1));
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
if (typeof resolved === "object" && resolved !== null && !Array.isArray(resolved)) {
|
|
937
|
+
resolved = await resolveNestedObjectValue(resolved, key, nestedKeep, deferredProps);
|
|
938
|
+
}
|
|
939
|
+
finalProps[key] = resolved;
|
|
940
|
+
}
|
|
941
|
+
const unpackedProps = unpackDotKeys(finalProps);
|
|
942
|
+
const wireProps = nullifyUndefined(unpackedProps);
|
|
943
|
+
const page = {
|
|
944
|
+
component,
|
|
945
|
+
props: wireProps,
|
|
946
|
+
url: this.req.originalUrl,
|
|
947
|
+
version: this.deps.assetVersion
|
|
948
|
+
};
|
|
949
|
+
if (Object.keys(deferredProps).length > 0) page.deferredProps = deferredProps;
|
|
950
|
+
if (mergeProps.length > 0) page.mergeProps = mergeProps;
|
|
951
|
+
if (deepMergeProps.length > 0) page.deepMergeProps = deepMergeProps;
|
|
952
|
+
if (Object.keys(matchPropsOn).length > 0) page.matchPropsOn = matchPropsOn;
|
|
953
|
+
const encryptHistory = this.encryptHistoryFlag !== void 0 ? this.encryptHistoryFlag : this.deps.historyEncryptionDefault ?? false;
|
|
954
|
+
if (encryptHistory) page.encryptHistory = true;
|
|
955
|
+
if (this.clearHistoryFlag) page.clearHistory = true;
|
|
956
|
+
if (this.req.header("X-Inertia")) {
|
|
957
|
+
this.res.setHeader("X-Inertia", "true").setHeader("Vary", "X-Inertia").json(page);
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
const ssrModule = await this.deps.ssrLoader.load();
|
|
961
|
+
const ssr = ssrModule ? await ssrModule.render(page) : null;
|
|
962
|
+
const html = await this.deps.rootViewRender({
|
|
963
|
+
page,
|
|
964
|
+
ssr,
|
|
965
|
+
manifest: this.deps.manifest,
|
|
966
|
+
assetVersion: this.deps.assetVersion,
|
|
967
|
+
ctx: {
|
|
968
|
+
req: this.req.raw,
|
|
969
|
+
res: this.res.raw
|
|
970
|
+
}
|
|
971
|
+
});
|
|
972
|
+
this.res.setHeader("Vary", "X-Inertia").html(html);
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
// src/module.ts
|
|
977
|
+
import { Inject as Inject7, Logger as Logger3, Module, RequestMethod } from "@nestjs/common";
|
|
978
|
+
import { APP_INTERCEPTOR, HttpAdapterHost as HttpAdapterHost2 } from "@nestjs/core";
|
|
979
|
+
|
|
980
|
+
// src/asset/version.provider.ts
|
|
981
|
+
import { createHash, randomUUID } from "crypto";
|
|
982
|
+
import { readFileSync } from "fs";
|
|
983
|
+
import { isAbsolute, resolve } from "path";
|
|
984
|
+
var DEFAULT_MANIFEST_PATH = "dist/inertia/client/.vite/manifest.json";
|
|
985
|
+
function assertManifestShape(parsed, path) {
|
|
986
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
987
|
+
throw new Error(`Vite manifest at ${path} has unexpected shape: expected a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}`);
|
|
988
|
+
}
|
|
989
|
+
for (const [key, entry] of Object.entries(parsed)) {
|
|
990
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
991
|
+
throw new Error(`Vite manifest at ${path} has unexpected shape: entry "${key}" is not an object`);
|
|
992
|
+
}
|
|
993
|
+
const e = entry;
|
|
994
|
+
if (typeof e.file !== "string") {
|
|
995
|
+
throw new Error(`Vite manifest at ${path} has unexpected shape: entry "${key}" is missing required string field "file"`);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return parsed;
|
|
999
|
+
}
|
|
1000
|
+
__name(assertManifestShape, "assertManifestShape");
|
|
1001
|
+
function loadManifest(path) {
|
|
1002
|
+
try {
|
|
1003
|
+
const abs = isAbsolute(path) ? path : resolve(process.cwd(), path);
|
|
1004
|
+
const raw = readFileSync(abs, "utf8");
|
|
1005
|
+
const parsed = JSON.parse(raw);
|
|
1006
|
+
return assertManifestShape(parsed, abs);
|
|
1007
|
+
} catch (err) {
|
|
1008
|
+
if (err instanceof Error && err.message.includes("Vite manifest at")) {
|
|
1009
|
+
throw err;
|
|
1010
|
+
}
|
|
1011
|
+
return null;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
__name(loadManifest, "loadManifest");
|
|
1015
|
+
function computeAssetVersion(manifest) {
|
|
1016
|
+
if (manifest) {
|
|
1017
|
+
return createHash("sha1").update(JSON.stringify(manifest)).digest("hex").slice(0, 32);
|
|
1018
|
+
}
|
|
1019
|
+
return randomUUID().replace(/-/g, "");
|
|
1020
|
+
}
|
|
1021
|
+
__name(computeAssetVersion, "computeAssetVersion");
|
|
1022
|
+
var manifestProvider = {
|
|
1023
|
+
provide: INERTIA_MANIFEST,
|
|
1024
|
+
inject: [
|
|
1025
|
+
INERTIA_MODULE_OPTIONS
|
|
1026
|
+
],
|
|
1027
|
+
useFactory: /* @__PURE__ */ __name((opts) => {
|
|
1028
|
+
if (process.env.NODE_ENV !== "production") return null;
|
|
1029
|
+
const path = opts.vite?.manifestPath ?? DEFAULT_MANIFEST_PATH;
|
|
1030
|
+
return loadManifest(path);
|
|
1031
|
+
}, "useFactory")
|
|
1032
|
+
};
|
|
1033
|
+
var assetVersionProvider = {
|
|
1034
|
+
provide: INERTIA_ASSET_VERSION,
|
|
1035
|
+
inject: [
|
|
1036
|
+
INERTIA_MANIFEST,
|
|
1037
|
+
INERTIA_MODULE_OPTIONS
|
|
1038
|
+
],
|
|
1039
|
+
useFactory: /* @__PURE__ */ __name(async (manifest, opts) => {
|
|
1040
|
+
if (opts.version !== void 0) {
|
|
1041
|
+
return typeof opts.version === "function" ? await opts.version() : opts.version;
|
|
1042
|
+
}
|
|
1043
|
+
return computeAssetVersion(manifest);
|
|
1044
|
+
}, "useFactory")
|
|
1045
|
+
};
|
|
1046
|
+
|
|
1047
|
+
// src/module.ts
|
|
1048
|
+
init_exceptions();
|
|
1049
|
+
|
|
1050
|
+
// src/interceptor/scope-switcher.interceptor.ts
|
|
1051
|
+
import { Inject as Inject4, Injectable as Injectable5 } from "@nestjs/common";
|
|
1052
|
+
import { HttpAdapterHost, ModuleRef, Reflector as Reflector2 } from "@nestjs/core";
|
|
1053
|
+
|
|
1054
|
+
// src/adapter/express.ts
|
|
1055
|
+
var expressAdapter = {
|
|
1056
|
+
adaptRequest(raw) {
|
|
1057
|
+
const r = raw;
|
|
1058
|
+
const req = {
|
|
1059
|
+
method: r.method,
|
|
1060
|
+
originalUrl: r.originalUrl,
|
|
1061
|
+
url: r.url,
|
|
1062
|
+
header(name) {
|
|
1063
|
+
if (typeof r.header === "function") return r.header(name);
|
|
1064
|
+
const v = r.headers[name.toLowerCase()];
|
|
1065
|
+
return Array.isArray(v) ? v[0] : v;
|
|
1066
|
+
},
|
|
1067
|
+
raw
|
|
1068
|
+
};
|
|
1069
|
+
if (r.body !== void 0) req.body = r.body;
|
|
1070
|
+
if (r.query !== void 0) req.query = r.query;
|
|
1071
|
+
return req;
|
|
1072
|
+
},
|
|
1073
|
+
adaptResponse(raw) {
|
|
1074
|
+
const r = raw;
|
|
1075
|
+
const wrapper = {
|
|
1076
|
+
get statusCode() {
|
|
1077
|
+
return r.statusCode;
|
|
1078
|
+
},
|
|
1079
|
+
get headersSent() {
|
|
1080
|
+
return r.headersSent;
|
|
1081
|
+
},
|
|
1082
|
+
status(code) {
|
|
1083
|
+
r.status(code);
|
|
1084
|
+
return wrapper;
|
|
1085
|
+
},
|
|
1086
|
+
setHeader(name, value) {
|
|
1087
|
+
r.setHeader(name, value);
|
|
1088
|
+
return wrapper;
|
|
1089
|
+
},
|
|
1090
|
+
getHeader(name) {
|
|
1091
|
+
return r.getHeader(name);
|
|
1092
|
+
},
|
|
1093
|
+
json(body) {
|
|
1094
|
+
r.json(body);
|
|
1095
|
+
},
|
|
1096
|
+
html(body) {
|
|
1097
|
+
r.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
1098
|
+
r.send(body);
|
|
1099
|
+
},
|
|
1100
|
+
end() {
|
|
1101
|
+
r.end();
|
|
1102
|
+
},
|
|
1103
|
+
raw
|
|
1104
|
+
};
|
|
1105
|
+
return wrapper;
|
|
1106
|
+
}
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1109
|
+
// src/adapter/fastify.ts
|
|
1110
|
+
var fastifyAdapter = {
|
|
1111
|
+
adaptRequest(raw) {
|
|
1112
|
+
const r = raw;
|
|
1113
|
+
const req = {
|
|
1114
|
+
method: r.method,
|
|
1115
|
+
originalUrl: r.raw?.originalUrl ?? r.url,
|
|
1116
|
+
url: r.url,
|
|
1117
|
+
header(name) {
|
|
1118
|
+
const v = r.headers[name.toLowerCase()];
|
|
1119
|
+
return Array.isArray(v) ? v[0] : v;
|
|
1120
|
+
},
|
|
1121
|
+
raw
|
|
1122
|
+
};
|
|
1123
|
+
if (r.body !== void 0) req.body = r.body;
|
|
1124
|
+
if (r.query !== void 0) req.query = r.query;
|
|
1125
|
+
return req;
|
|
1126
|
+
},
|
|
1127
|
+
adaptResponse(raw) {
|
|
1128
|
+
const r = raw;
|
|
1129
|
+
const wrapper = {
|
|
1130
|
+
get statusCode() {
|
|
1131
|
+
return r.statusCode;
|
|
1132
|
+
},
|
|
1133
|
+
get headersSent() {
|
|
1134
|
+
return r.sent;
|
|
1135
|
+
},
|
|
1136
|
+
status(code) {
|
|
1137
|
+
r.code(code);
|
|
1138
|
+
return wrapper;
|
|
1139
|
+
},
|
|
1140
|
+
setHeader(name, value) {
|
|
1141
|
+
r.header(name, value);
|
|
1142
|
+
return wrapper;
|
|
1143
|
+
},
|
|
1144
|
+
getHeader(name) {
|
|
1145
|
+
return r.getHeader(name);
|
|
1146
|
+
},
|
|
1147
|
+
json(body) {
|
|
1148
|
+
r.send(body);
|
|
1149
|
+
},
|
|
1150
|
+
html(body) {
|
|
1151
|
+
r.header("Content-Type", "text/html; charset=utf-8");
|
|
1152
|
+
r.send(body);
|
|
1153
|
+
},
|
|
1154
|
+
end() {
|
|
1155
|
+
r.send("");
|
|
1156
|
+
},
|
|
1157
|
+
raw
|
|
1158
|
+
};
|
|
1159
|
+
return wrapper;
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
|
|
1163
|
+
// src/interceptor/scope-switcher.interceptor.ts
|
|
1164
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
1165
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1166
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1167
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1168
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1169
|
+
}
|
|
1170
|
+
__name(_ts_decorate5, "_ts_decorate");
|
|
1171
|
+
function _ts_metadata4(k, v) {
|
|
1172
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1173
|
+
}
|
|
1174
|
+
__name(_ts_metadata4, "_ts_metadata");
|
|
1175
|
+
function _ts_param4(paramIndex, decorator) {
|
|
1176
|
+
return function(target, key) {
|
|
1177
|
+
decorator(target, key, paramIndex);
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
__name(_ts_param4, "_ts_param");
|
|
1181
|
+
var InertiaScopeSwitcherInterceptor = class {
|
|
1182
|
+
static {
|
|
1183
|
+
__name(this, "InertiaScopeSwitcherInterceptor");
|
|
1184
|
+
}
|
|
1185
|
+
reflector;
|
|
1186
|
+
moduleRef;
|
|
1187
|
+
httpAdapterHost;
|
|
1188
|
+
constructor(reflector, moduleRef, httpAdapterHost) {
|
|
1189
|
+
this.reflector = reflector;
|
|
1190
|
+
this.moduleRef = moduleRef;
|
|
1191
|
+
this.httpAdapterHost = httpAdapterHost;
|
|
1192
|
+
}
|
|
1193
|
+
intercept(ctx, next) {
|
|
1194
|
+
const scope = this.reflector.getAllAndOverride(INERTIA_USE_SCOPE, [
|
|
1195
|
+
ctx.getHandler(),
|
|
1196
|
+
ctx.getClass()
|
|
1197
|
+
]);
|
|
1198
|
+
if (scope && scope !== "default") {
|
|
1199
|
+
const opts = this.moduleRef.get(featureToken("OPTIONS", scope), {
|
|
1200
|
+
strict: false
|
|
1201
|
+
});
|
|
1202
|
+
const manifest = this.moduleRef.get(featureToken("MANIFEST", scope), {
|
|
1203
|
+
strict: false
|
|
1204
|
+
});
|
|
1205
|
+
const assetVersion = this.moduleRef.get(featureToken("ASSET_VERSION", scope), {
|
|
1206
|
+
strict: false
|
|
1207
|
+
});
|
|
1208
|
+
const shellRenderer = this.moduleRef.get(featureToken("SHELL_RENDERER", scope), {
|
|
1209
|
+
strict: false
|
|
1210
|
+
});
|
|
1211
|
+
const ssrLoader = this.moduleRef.get(featureToken("SSR_LOADER", scope), {
|
|
1212
|
+
strict: false
|
|
1213
|
+
});
|
|
1214
|
+
const req = ctx.switchToHttp().getRequest();
|
|
1215
|
+
const res = ctx.switchToHttp().getResponse();
|
|
1216
|
+
const deps = {
|
|
1217
|
+
assetVersion,
|
|
1218
|
+
manifest,
|
|
1219
|
+
ssrLoader,
|
|
1220
|
+
rootViewRender: /* @__PURE__ */ __name((c) => shellRenderer.render(c), "rootViewRender"),
|
|
1221
|
+
moduleShare: opts.share,
|
|
1222
|
+
featureShare: void 0,
|
|
1223
|
+
historyEncryptionDefault: opts.historyEncryption?.default ?? false,
|
|
1224
|
+
flashStore: opts.flashStore
|
|
1225
|
+
};
|
|
1226
|
+
const platform = this.httpAdapterHost.httpAdapter?.getType();
|
|
1227
|
+
const adapter = platform === "fastify" ? fastifyAdapter : expressAdapter;
|
|
1228
|
+
req.inertia = new InertiaService(adapter.adaptRequest(req), adapter.adaptResponse(res), deps);
|
|
1229
|
+
}
|
|
1230
|
+
return next.handle();
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
InertiaScopeSwitcherInterceptor = _ts_decorate5([
|
|
1234
|
+
Injectable5(),
|
|
1235
|
+
_ts_param4(0, Inject4(Reflector2)),
|
|
1236
|
+
_ts_param4(1, Inject4(ModuleRef)),
|
|
1237
|
+
_ts_param4(2, Inject4(HttpAdapterHost)),
|
|
1238
|
+
_ts_metadata4("design:type", Function),
|
|
1239
|
+
_ts_metadata4("design:paramtypes", [
|
|
1240
|
+
typeof Reflector2 === "undefined" ? Object : Reflector2,
|
|
1241
|
+
typeof ModuleRef === "undefined" ? Object : ModuleRef,
|
|
1242
|
+
typeof HttpAdapterHost === "undefined" ? Object : HttpAdapterHost
|
|
1243
|
+
])
|
|
1244
|
+
], InertiaScopeSwitcherInterceptor);
|
|
1245
|
+
|
|
1246
|
+
// src/middleware/express.middleware.ts
|
|
1247
|
+
import { Inject as Inject5, Injectable as Injectable6 } from "@nestjs/common";
|
|
1248
|
+
|
|
1249
|
+
// src/helpers/suppress-post-send-writes.ts
|
|
1250
|
+
var KEYS = [
|
|
1251
|
+
"status",
|
|
1252
|
+
"json",
|
|
1253
|
+
"send",
|
|
1254
|
+
"header",
|
|
1255
|
+
"setHeader",
|
|
1256
|
+
"end"
|
|
1257
|
+
];
|
|
1258
|
+
function suppressPostSendWrites(res) {
|
|
1259
|
+
for (const key of KEYS) {
|
|
1260
|
+
const original = res[key].bind(res);
|
|
1261
|
+
res[key] = (...args) => res.headersSent ? res : original(...args);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
__name(suppressPostSendWrites, "suppressPostSendWrites");
|
|
1265
|
+
|
|
1266
|
+
// src/middleware/express.middleware.ts
|
|
1267
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
1268
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1269
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1270
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1271
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1272
|
+
}
|
|
1273
|
+
__name(_ts_decorate6, "_ts_decorate");
|
|
1274
|
+
function _ts_metadata5(k, v) {
|
|
1275
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1276
|
+
}
|
|
1277
|
+
__name(_ts_metadata5, "_ts_metadata");
|
|
1278
|
+
function _ts_param5(paramIndex, decorator) {
|
|
1279
|
+
return function(target, key) {
|
|
1280
|
+
decorator(target, key, paramIndex);
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
__name(_ts_param5, "_ts_param");
|
|
1284
|
+
var InertiaMiddleware = class {
|
|
1285
|
+
static {
|
|
1286
|
+
__name(this, "InertiaMiddleware");
|
|
1287
|
+
}
|
|
1288
|
+
assetVersion;
|
|
1289
|
+
manifest;
|
|
1290
|
+
options;
|
|
1291
|
+
shellRenderer;
|
|
1292
|
+
ssrLoader;
|
|
1293
|
+
constructor(assetVersion, manifest, options, shellRenderer, ssrLoader) {
|
|
1294
|
+
this.assetVersion = assetVersion;
|
|
1295
|
+
this.manifest = manifest;
|
|
1296
|
+
this.options = options;
|
|
1297
|
+
this.shellRenderer = shellRenderer;
|
|
1298
|
+
this.ssrLoader = ssrLoader;
|
|
1299
|
+
}
|
|
1300
|
+
use(req, res, next) {
|
|
1301
|
+
const adaptedReq = expressAdapter.adaptRequest(req);
|
|
1302
|
+
const adaptedRes = expressAdapter.adaptResponse(res);
|
|
1303
|
+
req.inertia = new InertiaService(adaptedReq, adaptedRes, {
|
|
1304
|
+
assetVersion: this.assetVersion,
|
|
1305
|
+
manifest: this.manifest,
|
|
1306
|
+
ssrLoader: this.ssrLoader,
|
|
1307
|
+
rootViewRender: /* @__PURE__ */ __name((ctx) => this.shellRenderer.render(ctx), "rootViewRender"),
|
|
1308
|
+
moduleShare: this.options.share,
|
|
1309
|
+
featureShare: void 0,
|
|
1310
|
+
historyEncryptionDefault: this.options.historyEncryption?.default ?? false,
|
|
1311
|
+
flashStore: this.options.flashStore
|
|
1312
|
+
});
|
|
1313
|
+
suppressPostSendWrites(res);
|
|
1314
|
+
next();
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
InertiaMiddleware = _ts_decorate6([
|
|
1318
|
+
Injectable6(),
|
|
1319
|
+
_ts_param5(0, Inject5(INERTIA_ASSET_VERSION)),
|
|
1320
|
+
_ts_param5(1, Inject5(INERTIA_MANIFEST)),
|
|
1321
|
+
_ts_param5(2, Inject5(INERTIA_MODULE_OPTIONS)),
|
|
1322
|
+
_ts_param5(3, Inject5("INERTIA_SHELL_RENDERER")),
|
|
1323
|
+
_ts_param5(4, Inject5("INERTIA_SSR_LOADER")),
|
|
1324
|
+
_ts_metadata5("design:type", Function),
|
|
1325
|
+
_ts_metadata5("design:paramtypes", [
|
|
1326
|
+
String,
|
|
1327
|
+
Object,
|
|
1328
|
+
typeof InertiaModuleOptions === "undefined" ? Object : InertiaModuleOptions,
|
|
1329
|
+
typeof ShellRenderer === "undefined" ? Object : ShellRenderer,
|
|
1330
|
+
typeof SsrLoader === "undefined" ? Object : SsrLoader
|
|
1331
|
+
])
|
|
1332
|
+
], InertiaMiddleware);
|
|
1333
|
+
|
|
1334
|
+
// src/middleware/fastify.middleware.ts
|
|
1335
|
+
function registerFastifyInertia(app, depsFactory) {
|
|
1336
|
+
const appAsAny = app;
|
|
1337
|
+
if (appAsAny._inertiaRegistered) return;
|
|
1338
|
+
appAsAny._inertiaRegistered = true;
|
|
1339
|
+
app.decorateRequest("inertia", null);
|
|
1340
|
+
app.addHook("onRequest", async (req, reply) => {
|
|
1341
|
+
const adaptedReq = fastifyAdapter.adaptRequest(req);
|
|
1342
|
+
const adaptedRes = fastifyAdapter.adaptResponse(reply);
|
|
1343
|
+
req.inertia = new InertiaService(adaptedReq, adaptedRes, depsFactory());
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
__name(registerFastifyInertia, "registerFastifyInertia");
|
|
1347
|
+
|
|
1348
|
+
// src/shell/file-shell.renderer.ts
|
|
1349
|
+
init_exceptions();
|
|
1350
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
1351
|
+
import { extname, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
1352
|
+
|
|
1353
|
+
// src/shell/directives.ts
|
|
1354
|
+
var VITE_REFRESH_PREAMBLE = `<script type="module">
|
|
1355
|
+
import RefreshRuntime from "/@react-refresh"
|
|
1356
|
+
RefreshRuntime.injectIntoGlobalHook(window)
|
|
1357
|
+
window.$RefreshReg$ = () => {}
|
|
1358
|
+
window.$RefreshSig$ = () => (type) => type
|
|
1359
|
+
window.__vite_plugin_react_preamble_installed__ = true
|
|
1360
|
+
</script>`;
|
|
1361
|
+
function processDirectives(template, ctx) {
|
|
1362
|
+
let out = template;
|
|
1363
|
+
out = out.replace(/@inertiaHead\b/g, () => ctx.ssrHead);
|
|
1364
|
+
out = out.replace(/@inertia(?![a-zA-Z(])/g, () => {
|
|
1365
|
+
if (ctx.ssrBody) return ctx.ssrBody;
|
|
1366
|
+
return `<div id="app"></div>
|
|
1367
|
+
<script id="inertia-page" type="application/json">${ctx.pageJson}</script>`;
|
|
1368
|
+
});
|
|
1369
|
+
out = out.replace(/@viteRefresh\b/g, () => ctx.isDev ? VITE_REFRESH_PREAMBLE : "");
|
|
1370
|
+
out = out.replace(/@vite\(\s*['"]([^'"]+)['"]\s*\)/g, (_full, entry) => {
|
|
1371
|
+
if (ctx.isDev) {
|
|
1372
|
+
return `<script type="module" src="/@vite/client"></script>
|
|
1373
|
+
<script type="module" src="/${entry}"></script>`;
|
|
1374
|
+
}
|
|
1375
|
+
const entryRecord = ctx.manifest?.[entry];
|
|
1376
|
+
if (!entryRecord) {
|
|
1377
|
+
throw new Error(`[nestjs-inertia] manifest entry not found for "${entry}"`);
|
|
1378
|
+
}
|
|
1379
|
+
const scriptTag = `<script type="module" src="/${entryRecord.file}"></script>`;
|
|
1380
|
+
const cssTags = (entryRecord.css ?? []).map((href) => `<link rel="stylesheet" href="/${href}" />`).join("\n");
|
|
1381
|
+
return [
|
|
1382
|
+
scriptTag,
|
|
1383
|
+
cssTags
|
|
1384
|
+
].filter(Boolean).join("\n");
|
|
1385
|
+
});
|
|
1386
|
+
out = out.replace(/@asset\(\s*['"]([^'"]+)['"]\s*\)/g, (_full, path) => {
|
|
1387
|
+
if (ctx.isDev) return `/${path}`;
|
|
1388
|
+
const entry = ctx.manifest?.[path];
|
|
1389
|
+
return entry ? `/${entry.file}` : `/${path}`;
|
|
1390
|
+
});
|
|
1391
|
+
return out;
|
|
1392
|
+
}
|
|
1393
|
+
__name(processDirectives, "processDirectives");
|
|
1394
|
+
|
|
1395
|
+
// src/shell/serialize-page.ts
|
|
1396
|
+
var LS = "\u2028";
|
|
1397
|
+
var PS = "\u2029";
|
|
1398
|
+
var UNSAFE_CHARS = new RegExp(`[<>&${LS}${PS}]`, "g");
|
|
1399
|
+
function serializePageData(page) {
|
|
1400
|
+
return JSON.stringify(page).replace(UNSAFE_CHARS, (c) => {
|
|
1401
|
+
switch (c) {
|
|
1402
|
+
case "<":
|
|
1403
|
+
return "\\u003c";
|
|
1404
|
+
case ">":
|
|
1405
|
+
return "\\u003e";
|
|
1406
|
+
case "&":
|
|
1407
|
+
return "\\u0026";
|
|
1408
|
+
case LS:
|
|
1409
|
+
return "\\u2028";
|
|
1410
|
+
case PS:
|
|
1411
|
+
return "\\u2029";
|
|
1412
|
+
default:
|
|
1413
|
+
return c;
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
__name(serializePageData, "serializePageData");
|
|
1418
|
+
|
|
1419
|
+
// src/shell/template-engine.registry.ts
|
|
1420
|
+
init_exceptions();
|
|
1421
|
+
var registry = {
|
|
1422
|
+
".hbs": /* @__PURE__ */ __name(() => Promise.resolve().then(() => (init_handlebars_adapter(), handlebars_adapter_exports)).then((m) => m.handlebarsAdapter), ".hbs"),
|
|
1423
|
+
".handlebars": /* @__PURE__ */ __name(() => Promise.resolve().then(() => (init_handlebars_adapter(), handlebars_adapter_exports)).then((m) => m.handlebarsAdapter), ".handlebars"),
|
|
1424
|
+
".ejs": /* @__PURE__ */ __name(() => Promise.resolve().then(() => (init_ejs_adapter(), ejs_adapter_exports)).then((m) => m.ejsAdapter), ".ejs"),
|
|
1425
|
+
".pug": /* @__PURE__ */ __name(() => Promise.resolve().then(() => (init_pug_adapter(), pug_adapter_exports)).then((m) => m.pugAdapter), ".pug"),
|
|
1426
|
+
".liquid": /* @__PURE__ */ __name(() => Promise.resolve().then(() => (init_liquid_adapter(), liquid_adapter_exports)).then((m) => m.liquidAdapter), ".liquid"),
|
|
1427
|
+
".liquidjs": /* @__PURE__ */ __name(() => Promise.resolve().then(() => (init_liquid_adapter(), liquid_adapter_exports)).then((m) => m.liquidAdapter), ".liquidjs")
|
|
1428
|
+
};
|
|
1429
|
+
async function resolveTemplateEngine(extension) {
|
|
1430
|
+
const loader = registry[extension.toLowerCase()];
|
|
1431
|
+
if (!loader) {
|
|
1432
|
+
throw new UnsupportedRootViewExtensionException(extension);
|
|
1433
|
+
}
|
|
1434
|
+
return loader();
|
|
1435
|
+
}
|
|
1436
|
+
__name(resolveTemplateEngine, "resolveTemplateEngine");
|
|
1437
|
+
|
|
1438
|
+
// src/shell/file-shell.renderer.ts
|
|
1439
|
+
var PLAIN_HTML = /* @__PURE__ */ new Set([
|
|
1440
|
+
".html",
|
|
1441
|
+
".htm"
|
|
1442
|
+
]);
|
|
1443
|
+
var TEMPLATE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
1444
|
+
".hbs",
|
|
1445
|
+
".handlebars",
|
|
1446
|
+
".ejs",
|
|
1447
|
+
".pug",
|
|
1448
|
+
".liquid",
|
|
1449
|
+
".liquidjs"
|
|
1450
|
+
]);
|
|
1451
|
+
var FileBasedShellRenderer = class {
|
|
1452
|
+
static {
|
|
1453
|
+
__name(this, "FileBasedShellRenderer");
|
|
1454
|
+
}
|
|
1455
|
+
cachedTemplate = null;
|
|
1456
|
+
engineRenderer = null;
|
|
1457
|
+
adapterPromise = null;
|
|
1458
|
+
absPath;
|
|
1459
|
+
ext;
|
|
1460
|
+
constructor(rootViewPath) {
|
|
1461
|
+
const ext = extname(rootViewPath).toLowerCase();
|
|
1462
|
+
if (!PLAIN_HTML.has(ext) && !TEMPLATE_EXTENSIONS.has(ext)) {
|
|
1463
|
+
throw new UnsupportedRootViewExtensionException(ext);
|
|
1464
|
+
}
|
|
1465
|
+
this.ext = ext;
|
|
1466
|
+
this.absPath = isAbsolute2(rootViewPath) ? rootViewPath : resolve2(process.cwd(), rootViewPath);
|
|
1467
|
+
}
|
|
1468
|
+
async render(ctx) {
|
|
1469
|
+
if (this.cachedTemplate === null) {
|
|
1470
|
+
this.cachedTemplate = readFileSync2(this.absPath, "utf8");
|
|
1471
|
+
}
|
|
1472
|
+
const pageJson = serializePageData(ctx.page);
|
|
1473
|
+
const ssrHead = ctx.ssr?.head.join("\n") ?? "";
|
|
1474
|
+
const ssrBody = ctx.ssr?.body ?? null;
|
|
1475
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
1476
|
+
const manifest = ctx.manifest;
|
|
1477
|
+
if (PLAIN_HTML.has(this.ext)) {
|
|
1478
|
+
return processDirectives(this.cachedTemplate, {
|
|
1479
|
+
pageJson,
|
|
1480
|
+
ssrHead,
|
|
1481
|
+
ssrBody,
|
|
1482
|
+
manifest,
|
|
1483
|
+
isDev
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
if (this.adapterPromise === null) {
|
|
1487
|
+
this.adapterPromise = resolveTemplateEngine(this.ext);
|
|
1488
|
+
}
|
|
1489
|
+
if (this.engineRenderer === null) {
|
|
1490
|
+
const adapter = await this.adapterPromise;
|
|
1491
|
+
this.engineRenderer = adapter.compile(this.cachedTemplate, this.absPath);
|
|
1492
|
+
}
|
|
1493
|
+
const inertiaHtml = ssrBody ?? `<div id="app"></div>
|
|
1494
|
+
<script id="inertia-page" type="application/json">${pageJson}</script>`;
|
|
1495
|
+
const directiveCtx = {
|
|
1496
|
+
pageJson,
|
|
1497
|
+
ssrHead,
|
|
1498
|
+
ssrBody,
|
|
1499
|
+
manifest,
|
|
1500
|
+
isDev
|
|
1501
|
+
};
|
|
1502
|
+
const locals = {
|
|
1503
|
+
page: ctx.page,
|
|
1504
|
+
inertia: inertiaHtml,
|
|
1505
|
+
inertiaHead: ssrHead,
|
|
1506
|
+
vite: /* @__PURE__ */ __name((entry) => processDirectives(`@vite('${entry}')`, directiveCtx), "vite"),
|
|
1507
|
+
viteRefresh: processDirectives("@viteRefresh", directiveCtx),
|
|
1508
|
+
asset: /* @__PURE__ */ __name((p) => processDirectives(`@asset('${p}')`, directiveCtx), "asset")
|
|
1509
|
+
};
|
|
1510
|
+
let output = await this.engineRenderer(locals);
|
|
1511
|
+
output = processDirectives(output, directiveCtx);
|
|
1512
|
+
return output;
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1515
|
+
|
|
1516
|
+
// src/shell/shell.ts
|
|
1517
|
+
var DefaultShellRenderer = class {
|
|
1518
|
+
static {
|
|
1519
|
+
__name(this, "DefaultShellRenderer");
|
|
1520
|
+
}
|
|
1521
|
+
async render(ctx) {
|
|
1522
|
+
const pageJson = serializePageData(ctx.page);
|
|
1523
|
+
return `<!doctype html>
|
|
1524
|
+
<html lang="en">
|
|
1525
|
+
<head>
|
|
1526
|
+
<meta charset="utf-8" />
|
|
1527
|
+
<title>Inertia</title>
|
|
1528
|
+
</head>
|
|
1529
|
+
<body>
|
|
1530
|
+
<div id="app"></div>
|
|
1531
|
+
<script id="inertia-page" type="application/json">${pageJson}</script>
|
|
1532
|
+
</body>
|
|
1533
|
+
</html>`;
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
|
|
1537
|
+
// src/ssr/ssr-loader.service.ts
|
|
1538
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
1539
|
+
import { resolve as resolve3 } from "path";
|
|
1540
|
+
import { pathToFileURL } from "url";
|
|
1541
|
+
import { Inject as Inject6, Injectable as Injectable7, Logger as Logger2 } from "@nestjs/common";
|
|
1542
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
1543
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1544
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1545
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1546
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1547
|
+
}
|
|
1548
|
+
__name(_ts_decorate7, "_ts_decorate");
|
|
1549
|
+
function _ts_metadata6(k, v) {
|
|
1550
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1551
|
+
}
|
|
1552
|
+
__name(_ts_metadata6, "_ts_metadata");
|
|
1553
|
+
function _ts_param6(paramIndex, decorator) {
|
|
1554
|
+
return function(target, key) {
|
|
1555
|
+
decorator(target, key, paramIndex);
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
__name(_ts_param6, "_ts_param");
|
|
1559
|
+
function isVitest() {
|
|
1560
|
+
return process.env.VITEST === "true" || process.env.NODE_ENV === "test";
|
|
1561
|
+
}
|
|
1562
|
+
__name(isVitest, "isVitest");
|
|
1563
|
+
var SsrLoaderService = class _SsrLoaderService {
|
|
1564
|
+
static {
|
|
1565
|
+
__name(this, "SsrLoaderService");
|
|
1566
|
+
}
|
|
1567
|
+
opts;
|
|
1568
|
+
logger = new Logger2(_SsrLoaderService.name);
|
|
1569
|
+
cached = null;
|
|
1570
|
+
failed = false;
|
|
1571
|
+
constructor(opts) {
|
|
1572
|
+
this.opts = opts;
|
|
1573
|
+
}
|
|
1574
|
+
async load() {
|
|
1575
|
+
if (!this.opts.ssr?.enabled) return null;
|
|
1576
|
+
if (this.cached) return this.cached;
|
|
1577
|
+
if (this.failed) return null;
|
|
1578
|
+
try {
|
|
1579
|
+
const bundlePath = resolve3(process.cwd(), this.opts.ssr.bundlePath ?? "dist/inertia/ssr/ssr.mjs");
|
|
1580
|
+
let mod;
|
|
1581
|
+
if (isVitest()) {
|
|
1582
|
+
const code = readFileSync3(bundlePath, "utf8");
|
|
1583
|
+
const dataUrl = `data:text/javascript;base64,${Buffer.from(code, "utf8").toString("base64")}`;
|
|
1584
|
+
mod = await import(
|
|
1585
|
+
/* @vite-ignore */
|
|
1586
|
+
dataUrl
|
|
1587
|
+
);
|
|
1588
|
+
} else {
|
|
1589
|
+
const fileUrl = pathToFileURL(bundlePath).href;
|
|
1590
|
+
mod = await import(
|
|
1591
|
+
/* @vite-ignore */
|
|
1592
|
+
fileUrl
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1595
|
+
if (mod.default && typeof mod.default.render === "function") {
|
|
1596
|
+
this.cached = mod.default;
|
|
1597
|
+
} else if (typeof mod.render === "function") {
|
|
1598
|
+
this.cached = {
|
|
1599
|
+
render: mod.render
|
|
1600
|
+
};
|
|
1601
|
+
} else {
|
|
1602
|
+
if (this.opts.ssr.throwOnError) throw new Error("SSR bundle exports neither default nor render()");
|
|
1603
|
+
this.failed = true;
|
|
1604
|
+
this.logger.warn("SSR bundle missing required exports; falling back to CSR.");
|
|
1605
|
+
return null;
|
|
1606
|
+
}
|
|
1607
|
+
return this.cached;
|
|
1608
|
+
} catch (err) {
|
|
1609
|
+
this.failed = true;
|
|
1610
|
+
if (this.opts.ssr.throwOnError) throw err;
|
|
1611
|
+
this.logger.warn(`SSR bundle not loaded, falling back to CSR: ${err.message}`);
|
|
1612
|
+
return null;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
SsrLoaderService = _ts_decorate7([
|
|
1617
|
+
Injectable7(),
|
|
1618
|
+
_ts_param6(0, Inject6(INERTIA_MODULE_OPTIONS)),
|
|
1619
|
+
_ts_metadata6("design:type", Function),
|
|
1620
|
+
_ts_metadata6("design:paramtypes", [
|
|
1621
|
+
typeof InertiaModuleOptions === "undefined" ? Object : InertiaModuleOptions
|
|
1622
|
+
])
|
|
1623
|
+
], SsrLoaderService);
|
|
1624
|
+
|
|
1625
|
+
// src/module.ts
|
|
1626
|
+
function _ts_decorate8(decorators, target, key, desc) {
|
|
1627
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1628
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1629
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1630
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1631
|
+
}
|
|
1632
|
+
__name(_ts_decorate8, "_ts_decorate");
|
|
1633
|
+
function _ts_metadata7(k, v) {
|
|
1634
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1635
|
+
}
|
|
1636
|
+
__name(_ts_metadata7, "_ts_metadata");
|
|
1637
|
+
function _ts_param7(paramIndex, decorator) {
|
|
1638
|
+
return function(target, key) {
|
|
1639
|
+
decorator(target, key, paramIndex);
|
|
1640
|
+
};
|
|
1641
|
+
}
|
|
1642
|
+
__name(_ts_param7, "_ts_param");
|
|
1643
|
+
var InertiaModule = class _InertiaModule {
|
|
1644
|
+
static {
|
|
1645
|
+
__name(this, "InertiaModule");
|
|
1646
|
+
}
|
|
1647
|
+
httpAdapterHost;
|
|
1648
|
+
options;
|
|
1649
|
+
assetVersion;
|
|
1650
|
+
manifest;
|
|
1651
|
+
shellRenderer;
|
|
1652
|
+
ssrLoader;
|
|
1653
|
+
/**
|
|
1654
|
+
* Shared provider set for both `forRoot` and `forRootAsync`.
|
|
1655
|
+
* Does NOT include the options provider(s) — callers prepend those themselves.
|
|
1656
|
+
*/
|
|
1657
|
+
static buildModuleProviders() {
|
|
1658
|
+
const shellProvider = {
|
|
1659
|
+
provide: "INERTIA_SHELL_RENDERER",
|
|
1660
|
+
inject: [
|
|
1661
|
+
INERTIA_MODULE_OPTIONS
|
|
1662
|
+
],
|
|
1663
|
+
useFactory: /* @__PURE__ */ __name((opts) => {
|
|
1664
|
+
const rv = opts.rootView;
|
|
1665
|
+
if (typeof rv === "function") {
|
|
1666
|
+
const fn = rv;
|
|
1667
|
+
return {
|
|
1668
|
+
render: /* @__PURE__ */ __name(async (ctx) => fn(ctx), "render")
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
if (typeof rv === "string") {
|
|
1672
|
+
return new FileBasedShellRenderer(rv);
|
|
1673
|
+
}
|
|
1674
|
+
return new DefaultShellRenderer();
|
|
1675
|
+
}, "useFactory")
|
|
1676
|
+
};
|
|
1677
|
+
const ssrProvider = {
|
|
1678
|
+
provide: "INERTIA_SSR_LOADER",
|
|
1679
|
+
useClass: SsrLoaderService
|
|
1680
|
+
};
|
|
1681
|
+
return [
|
|
1682
|
+
manifestProvider,
|
|
1683
|
+
assetVersionProvider,
|
|
1684
|
+
shellProvider,
|
|
1685
|
+
ssrProvider,
|
|
1686
|
+
InertiaMiddleware,
|
|
1687
|
+
MethodSpoofMiddleware,
|
|
1688
|
+
{
|
|
1689
|
+
provide: APP_INTERCEPTOR,
|
|
1690
|
+
useClass: InertiaScopeSwitcherInterceptor
|
|
1691
|
+
},
|
|
1692
|
+
{
|
|
1693
|
+
provide: APP_INTERCEPTOR,
|
|
1694
|
+
useClass: InertiaRenderInterceptor
|
|
1695
|
+
},
|
|
1696
|
+
{
|
|
1697
|
+
provide: APP_INTERCEPTOR,
|
|
1698
|
+
useClass: RedirectInterceptor
|
|
1699
|
+
}
|
|
1700
|
+
];
|
|
1701
|
+
}
|
|
1702
|
+
static moduleExports = [
|
|
1703
|
+
INERTIA_MODULE_OPTIONS,
|
|
1704
|
+
INERTIA_MANIFEST,
|
|
1705
|
+
INERTIA_ASSET_VERSION,
|
|
1706
|
+
"INERTIA_SHELL_RENDERER",
|
|
1707
|
+
"INERTIA_SSR_LOADER",
|
|
1708
|
+
InertiaMiddleware
|
|
1709
|
+
];
|
|
1710
|
+
static forRoot(options = {}) {
|
|
1711
|
+
const optionsProvider = {
|
|
1712
|
+
provide: INERTIA_MODULE_OPTIONS,
|
|
1713
|
+
useValue: options
|
|
1714
|
+
};
|
|
1715
|
+
return {
|
|
1716
|
+
module: _InertiaModule,
|
|
1717
|
+
global: true,
|
|
1718
|
+
providers: [
|
|
1719
|
+
optionsProvider,
|
|
1720
|
+
..._InertiaModule.buildModuleProviders()
|
|
1721
|
+
],
|
|
1722
|
+
exports: [
|
|
1723
|
+
..._InertiaModule.moduleExports
|
|
1724
|
+
]
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
static forRootAsync(asyncOptions) {
|
|
1728
|
+
_InertiaModule.validateAsyncOptions(asyncOptions);
|
|
1729
|
+
const optionsProviders = _InertiaModule.createAsyncOptionsProviders(asyncOptions);
|
|
1730
|
+
const injectProviders = (asyncOptions.inject ?? []).filter((token) => typeof token === "function").map((token) => token);
|
|
1731
|
+
return {
|
|
1732
|
+
module: _InertiaModule,
|
|
1733
|
+
global: true,
|
|
1734
|
+
imports: asyncOptions.imports ?? [],
|
|
1735
|
+
providers: [
|
|
1736
|
+
...injectProviders,
|
|
1737
|
+
...optionsProviders,
|
|
1738
|
+
..._InertiaModule.buildModuleProviders()
|
|
1739
|
+
],
|
|
1740
|
+
exports: [
|
|
1741
|
+
..._InertiaModule.moduleExports
|
|
1742
|
+
]
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
static forFeature(options) {
|
|
1746
|
+
assertScopeNotReserved(options.scope);
|
|
1747
|
+
const optionsProvider = {
|
|
1748
|
+
provide: featureToken("OPTIONS", options.scope),
|
|
1749
|
+
useValue: options
|
|
1750
|
+
};
|
|
1751
|
+
return {
|
|
1752
|
+
module: _InertiaModule,
|
|
1753
|
+
global: true,
|
|
1754
|
+
providers: [
|
|
1755
|
+
optionsProvider,
|
|
1756
|
+
..._InertiaModule.createFeatureProviders(options.scope)
|
|
1757
|
+
],
|
|
1758
|
+
exports: [
|
|
1759
|
+
featureToken("OPTIONS", options.scope),
|
|
1760
|
+
featureToken("MANIFEST", options.scope),
|
|
1761
|
+
featureToken("ASSET_VERSION", options.scope),
|
|
1762
|
+
featureToken("SHELL_RENDERER", options.scope),
|
|
1763
|
+
featureToken("SSR_LOADER", options.scope)
|
|
1764
|
+
]
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
static forFeatureAsync(asyncOptions) {
|
|
1768
|
+
assertScopeNotReserved(asyncOptions.scope);
|
|
1769
|
+
const has = /* @__PURE__ */ __name((k) => asyncOptions[k] !== void 0, "has");
|
|
1770
|
+
const declared = [
|
|
1771
|
+
has("useFactory"),
|
|
1772
|
+
has("useClass"),
|
|
1773
|
+
has("useExisting")
|
|
1774
|
+
].filter(Boolean).length;
|
|
1775
|
+
if (declared === 0) {
|
|
1776
|
+
throw new InvalidInertiaConfigException("forFeatureAsync requires one of: useFactory, useClass, useExisting");
|
|
1777
|
+
}
|
|
1778
|
+
if (declared > 1) {
|
|
1779
|
+
throw new InvalidInertiaConfigException("forFeatureAsync accepts exactly one of: useFactory, useClass, useExisting (got multiple)");
|
|
1780
|
+
}
|
|
1781
|
+
const scope = asyncOptions.scope;
|
|
1782
|
+
const optionsToken = featureToken("OPTIONS", scope);
|
|
1783
|
+
const injectProviders = (asyncOptions.inject ?? []).filter((token) => typeof token === "function").map((token) => token);
|
|
1784
|
+
let optionsProviders;
|
|
1785
|
+
if (asyncOptions.useFactory) {
|
|
1786
|
+
optionsProviders = [
|
|
1787
|
+
{
|
|
1788
|
+
provide: optionsToken,
|
|
1789
|
+
useFactory: /* @__PURE__ */ __name(async (...args) => {
|
|
1790
|
+
const opts = await asyncOptions.useFactory(...args);
|
|
1791
|
+
return {
|
|
1792
|
+
...opts,
|
|
1793
|
+
scope
|
|
1794
|
+
};
|
|
1795
|
+
}, "useFactory"),
|
|
1796
|
+
inject: asyncOptions.inject ?? []
|
|
1797
|
+
}
|
|
1798
|
+
];
|
|
1799
|
+
} else if (asyncOptions.useClass) {
|
|
1800
|
+
optionsProviders = [
|
|
1801
|
+
asyncOptions.useClass,
|
|
1802
|
+
{
|
|
1803
|
+
provide: optionsToken,
|
|
1804
|
+
useFactory: /* @__PURE__ */ __name(async (factory) => ({
|
|
1805
|
+
...await factory.createInertiaOptions(),
|
|
1806
|
+
scope
|
|
1807
|
+
}), "useFactory"),
|
|
1808
|
+
inject: [
|
|
1809
|
+
asyncOptions.useClass
|
|
1810
|
+
]
|
|
1811
|
+
}
|
|
1812
|
+
];
|
|
1813
|
+
} else if (asyncOptions.useExisting) {
|
|
1814
|
+
optionsProviders = [
|
|
1815
|
+
{
|
|
1816
|
+
provide: optionsToken,
|
|
1817
|
+
useFactory: /* @__PURE__ */ __name(async (factory) => ({
|
|
1818
|
+
...await factory.createInertiaOptions(),
|
|
1819
|
+
scope
|
|
1820
|
+
}), "useFactory"),
|
|
1821
|
+
inject: [
|
|
1822
|
+
asyncOptions.useExisting
|
|
1823
|
+
]
|
|
1824
|
+
}
|
|
1825
|
+
];
|
|
1826
|
+
} else {
|
|
1827
|
+
optionsProviders = [];
|
|
1828
|
+
}
|
|
1829
|
+
return {
|
|
1830
|
+
module: _InertiaModule,
|
|
1831
|
+
global: true,
|
|
1832
|
+
imports: asyncOptions.imports ?? [],
|
|
1833
|
+
providers: [
|
|
1834
|
+
...injectProviders,
|
|
1835
|
+
...optionsProviders,
|
|
1836
|
+
..._InertiaModule.createFeatureProviders(scope)
|
|
1837
|
+
],
|
|
1838
|
+
exports: [
|
|
1839
|
+
optionsToken,
|
|
1840
|
+
featureToken("MANIFEST", scope),
|
|
1841
|
+
featureToken("ASSET_VERSION", scope),
|
|
1842
|
+
featureToken("SHELL_RENDERER", scope),
|
|
1843
|
+
featureToken("SSR_LOADER", scope)
|
|
1844
|
+
]
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
static createFeatureProviders(scope) {
|
|
1848
|
+
return [
|
|
1849
|
+
{
|
|
1850
|
+
provide: featureToken("MANIFEST", scope),
|
|
1851
|
+
inject: [
|
|
1852
|
+
featureToken("OPTIONS", scope)
|
|
1853
|
+
],
|
|
1854
|
+
useFactory: /* @__PURE__ */ __name((opts) => {
|
|
1855
|
+
if (process.env.NODE_ENV !== "production") return null;
|
|
1856
|
+
return loadManifest(opts.vite?.manifestPath ?? "dist/inertia/client/.vite/manifest.json");
|
|
1857
|
+
}, "useFactory")
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
provide: featureToken("ASSET_VERSION", scope),
|
|
1861
|
+
inject: [
|
|
1862
|
+
featureToken("MANIFEST", scope),
|
|
1863
|
+
featureToken("OPTIONS", scope)
|
|
1864
|
+
],
|
|
1865
|
+
useFactory: /* @__PURE__ */ __name(async (manifest, opts) => {
|
|
1866
|
+
if (opts.version !== void 0) {
|
|
1867
|
+
return typeof opts.version === "function" ? await opts.version() : opts.version;
|
|
1868
|
+
}
|
|
1869
|
+
return computeAssetVersion(manifest);
|
|
1870
|
+
}, "useFactory")
|
|
1871
|
+
},
|
|
1872
|
+
{
|
|
1873
|
+
provide: featureToken("SHELL_RENDERER", scope),
|
|
1874
|
+
inject: [
|
|
1875
|
+
featureToken("OPTIONS", scope)
|
|
1876
|
+
],
|
|
1877
|
+
useFactory: /* @__PURE__ */ __name((opts) => {
|
|
1878
|
+
const rv = opts.rootView;
|
|
1879
|
+
if (typeof rv === "function") {
|
|
1880
|
+
const fn = rv;
|
|
1881
|
+
return {
|
|
1882
|
+
render: /* @__PURE__ */ __name(async (ctx) => fn(ctx), "render")
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
if (typeof rv === "string") {
|
|
1886
|
+
return new FileBasedShellRenderer(rv);
|
|
1887
|
+
}
|
|
1888
|
+
return new DefaultShellRenderer();
|
|
1889
|
+
}, "useFactory")
|
|
1890
|
+
},
|
|
1891
|
+
{
|
|
1892
|
+
provide: featureToken("SSR_LOADER", scope),
|
|
1893
|
+
inject: [
|
|
1894
|
+
featureToken("OPTIONS", scope)
|
|
1895
|
+
],
|
|
1896
|
+
useFactory: /* @__PURE__ */ __name((opts) => new SsrLoaderService(opts), "useFactory")
|
|
1897
|
+
}
|
|
1898
|
+
];
|
|
1899
|
+
}
|
|
1900
|
+
static validateAsyncOptions(asyncOptions) {
|
|
1901
|
+
const has = /* @__PURE__ */ __name((k) => asyncOptions[k] !== void 0, "has");
|
|
1902
|
+
const declared = [
|
|
1903
|
+
has("useFactory"),
|
|
1904
|
+
has("useClass"),
|
|
1905
|
+
has("useExisting")
|
|
1906
|
+
].filter(Boolean).length;
|
|
1907
|
+
if (declared === 0) {
|
|
1908
|
+
throw new InvalidInertiaConfigException("forRootAsync requires one of: useFactory, useClass, useExisting");
|
|
1909
|
+
}
|
|
1910
|
+
if (declared > 1) {
|
|
1911
|
+
throw new InvalidInertiaConfigException("forRootAsync accepts exactly one of: useFactory, useClass, useExisting (got multiple)");
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
static createAsyncOptionsProviders(asyncOptions) {
|
|
1915
|
+
if (asyncOptions.useFactory) {
|
|
1916
|
+
return [
|
|
1917
|
+
{
|
|
1918
|
+
provide: INERTIA_MODULE_OPTIONS,
|
|
1919
|
+
useFactory: asyncOptions.useFactory,
|
|
1920
|
+
inject: asyncOptions.inject ?? []
|
|
1921
|
+
}
|
|
1922
|
+
];
|
|
1923
|
+
}
|
|
1924
|
+
if (asyncOptions.useClass) {
|
|
1925
|
+
return [
|
|
1926
|
+
asyncOptions.useClass,
|
|
1927
|
+
{
|
|
1928
|
+
provide: INERTIA_MODULE_OPTIONS,
|
|
1929
|
+
useFactory: /* @__PURE__ */ __name(async (factory) => factory.createInertiaOptions(), "useFactory"),
|
|
1930
|
+
inject: [
|
|
1931
|
+
asyncOptions.useClass
|
|
1932
|
+
]
|
|
1933
|
+
}
|
|
1934
|
+
];
|
|
1935
|
+
}
|
|
1936
|
+
return [
|
|
1937
|
+
asyncOptions.useExisting,
|
|
1938
|
+
{
|
|
1939
|
+
provide: INERTIA_MODULE_OPTIONS,
|
|
1940
|
+
useFactory: /* @__PURE__ */ __name(async (factory) => factory.createInertiaOptions(), "useFactory"),
|
|
1941
|
+
inject: [
|
|
1942
|
+
asyncOptions.useExisting
|
|
1943
|
+
]
|
|
1944
|
+
}
|
|
1945
|
+
];
|
|
1946
|
+
}
|
|
1947
|
+
logger = new Logger3(_InertiaModule.name);
|
|
1948
|
+
codegenWatcher = null;
|
|
1949
|
+
constructor(httpAdapterHost, options, assetVersion, manifest, shellRenderer, ssrLoader) {
|
|
1950
|
+
this.httpAdapterHost = httpAdapterHost;
|
|
1951
|
+
this.options = options;
|
|
1952
|
+
this.assetVersion = assetVersion;
|
|
1953
|
+
this.manifest = manifest;
|
|
1954
|
+
this.shellRenderer = shellRenderer;
|
|
1955
|
+
this.ssrLoader = ssrLoader;
|
|
1956
|
+
}
|
|
1957
|
+
/**
|
|
1958
|
+
* Test seam: override in a subclass or via `Object.defineProperty` to inject a stub
|
|
1959
|
+
* codegen module without touching NestJS DI. Production callers never touch this.
|
|
1960
|
+
*
|
|
1961
|
+
* @internal
|
|
1962
|
+
*/
|
|
1963
|
+
_resolveCodegenModule() {
|
|
1964
|
+
const dynamicImport = new Function("s", "return import(s)");
|
|
1965
|
+
return dynamicImport("@dudousxd/nestjs-inertia-codegen");
|
|
1966
|
+
}
|
|
1967
|
+
async onApplicationBootstrap() {
|
|
1968
|
+
const adapter = this.httpAdapterHost.httpAdapter;
|
|
1969
|
+
if (adapter) {
|
|
1970
|
+
const platform = adapter.getType();
|
|
1971
|
+
if (platform === "fastify") {
|
|
1972
|
+
const fastifyApp = adapter.getInstance();
|
|
1973
|
+
registerFastifyInertia(fastifyApp, () => ({
|
|
1974
|
+
assetVersion: this.assetVersion,
|
|
1975
|
+
manifest: this.manifest,
|
|
1976
|
+
ssrLoader: this.ssrLoader,
|
|
1977
|
+
rootViewRender: /* @__PURE__ */ __name((ctx) => this.shellRenderer.render(ctx), "rootViewRender"),
|
|
1978
|
+
moduleShare: this.options.share,
|
|
1979
|
+
featureShare: void 0,
|
|
1980
|
+
historyEncryptionDefault: this.options.historyEncryption?.default ?? false,
|
|
1981
|
+
flashStore: this.options.flashStore
|
|
1982
|
+
}));
|
|
1983
|
+
const { registerFastifyMethodSpoof: registerFastifyMethodSpoof2 } = await Promise.resolve().then(() => (init_fastify_method_spoof_middleware(), fastify_method_spoof_middleware_exports));
|
|
1984
|
+
registerFastifyMethodSpoof2(fastifyApp, this.options);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
await this._startCodegenWatcher();
|
|
1988
|
+
}
|
|
1989
|
+
/**
|
|
1990
|
+
* Auto-starts the codegen file watcher in dev mode.
|
|
1991
|
+
*
|
|
1992
|
+
* Rules (all must pass for the watcher to start):
|
|
1993
|
+
* 1. `process.env.NODE_ENV !== 'production'`
|
|
1994
|
+
* 2. `options.codegen?.enabled !== false`
|
|
1995
|
+
* 3. `@dudousxd/nestjs-inertia-codegen` is resolvable (peer-optional)
|
|
1996
|
+
* 4. A `nestjs-inertia.config.ts` (or equivalent) is present in `process.cwd()`
|
|
1997
|
+
*
|
|
1998
|
+
* If the CLI watcher already holds the lock file, the codegen package returns a
|
|
1999
|
+
* no-op watcher — no conflict occurs.
|
|
2000
|
+
*
|
|
2001
|
+
* This method NEVER throws; any unexpected error is logged as a warning.
|
|
2002
|
+
*/
|
|
2003
|
+
async _startCodegenWatcher() {
|
|
2004
|
+
try {
|
|
2005
|
+
if (process.env.NODE_ENV === "production") return;
|
|
2006
|
+
if (process.env.NESTJS_INERTIA_DISABLE_AUTO_CODEGEN === "1") return;
|
|
2007
|
+
if (this.options.codegen?.enabled === false) return;
|
|
2008
|
+
let codegen;
|
|
2009
|
+
try {
|
|
2010
|
+
codegen = await this._resolveCodegenModule();
|
|
2011
|
+
} catch (err) {
|
|
2012
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2013
|
+
this.logger.warn(`Codegen auto-watch: failed to import @dudousxd/nestjs-inertia-codegen: ${message}`);
|
|
2014
|
+
return;
|
|
2015
|
+
}
|
|
2016
|
+
let config;
|
|
2017
|
+
try {
|
|
2018
|
+
config = await codegen.loadConfig(process.cwd());
|
|
2019
|
+
} catch (err) {
|
|
2020
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2021
|
+
this.logger.warn(`Codegen auto-watch: failed to load config: ${message}`);
|
|
2022
|
+
return;
|
|
2023
|
+
}
|
|
2024
|
+
this.codegenWatcher = await codegen.watch(config);
|
|
2025
|
+
this.logger.log("Codegen auto-watch started (dev mode).");
|
|
2026
|
+
} catch (err) {
|
|
2027
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2028
|
+
this.logger.warn(`Codegen auto-watch failed to start: ${message}. Install @dudousxd/nestjs-inertia-codegen and add nestjs-inertia.config.ts to enable auto-watch, or set codegen: { enabled: false } to suppress this warning.`);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
async onApplicationShutdown() {
|
|
2032
|
+
await this.codegenWatcher?.close();
|
|
2033
|
+
this.codegenWatcher = null;
|
|
2034
|
+
}
|
|
2035
|
+
configure(consumer) {
|
|
2036
|
+
const adapter = this.httpAdapterHost.httpAdapter;
|
|
2037
|
+
if (!adapter || adapter.getType() === "express") {
|
|
2038
|
+
consumer.apply(MethodSpoofMiddleware).forRoutes({
|
|
2039
|
+
path: "{*path}",
|
|
2040
|
+
method: RequestMethod.ALL
|
|
2041
|
+
});
|
|
2042
|
+
consumer.apply(InertiaMiddleware).forRoutes({
|
|
2043
|
+
path: "{*path}",
|
|
2044
|
+
method: RequestMethod.ALL
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
InertiaModule = _ts_decorate8([
|
|
2050
|
+
Module({}),
|
|
2051
|
+
_ts_param7(0, Inject7(HttpAdapterHost2)),
|
|
2052
|
+
_ts_param7(1, Inject7(INERTIA_MODULE_OPTIONS)),
|
|
2053
|
+
_ts_param7(2, Inject7(INERTIA_ASSET_VERSION)),
|
|
2054
|
+
_ts_param7(3, Inject7(INERTIA_MANIFEST)),
|
|
2055
|
+
_ts_param7(4, Inject7("INERTIA_SHELL_RENDERER")),
|
|
2056
|
+
_ts_param7(5, Inject7("INERTIA_SSR_LOADER")),
|
|
2057
|
+
_ts_metadata7("design:type", Function),
|
|
2058
|
+
_ts_metadata7("design:paramtypes", [
|
|
2059
|
+
typeof HttpAdapterHost2 === "undefined" ? Object : HttpAdapterHost2,
|
|
2060
|
+
typeof InertiaModuleOptions === "undefined" ? Object : InertiaModuleOptions,
|
|
2061
|
+
String,
|
|
2062
|
+
Object,
|
|
2063
|
+
typeof ShellRenderer === "undefined" ? Object : ShellRenderer,
|
|
2064
|
+
Object
|
|
2065
|
+
])
|
|
2066
|
+
], InertiaModule);
|
|
2067
|
+
|
|
2068
|
+
// src/csrf/csrf-cookie.interceptor.ts
|
|
2069
|
+
import { Injectable as Injectable8 } from "@nestjs/common";
|
|
2070
|
+
|
|
2071
|
+
// src/csrf/csrf-token.ts
|
|
2072
|
+
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
2073
|
+
function generateCsrfToken(secret, context) {
|
|
2074
|
+
const raw = randomBytes(32).toString("base64url");
|
|
2075
|
+
if (context !== void 0 && context !== "") {
|
|
2076
|
+
const ctx = Buffer.from(context).toString("hex");
|
|
2077
|
+
const sig2 = createHmac("sha256", secret).update(`${raw}:${context}`).digest("base64url");
|
|
2078
|
+
return `${raw}.${ctx}.${sig2}`;
|
|
2079
|
+
}
|
|
2080
|
+
const sig = createHmac("sha256", secret).update(raw).digest("base64url");
|
|
2081
|
+
return `${raw}.${sig}`;
|
|
2082
|
+
}
|
|
2083
|
+
__name(generateCsrfToken, "generateCsrfToken");
|
|
2084
|
+
function timingSafeEqualSafe(a, b) {
|
|
2085
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
2086
|
+
return timingSafeEqual(a, b);
|
|
2087
|
+
}
|
|
2088
|
+
__name(timingSafeEqualSafe, "timingSafeEqualSafe");
|
|
2089
|
+
function verifyCsrfToken(token, secret, context) {
|
|
2090
|
+
if (typeof token !== "string") return false;
|
|
2091
|
+
const parts = token.split(".");
|
|
2092
|
+
if (parts.length === 3) {
|
|
2093
|
+
const [raw, ctxHex, sig] = parts;
|
|
2094
|
+
if (!raw || !ctxHex || !sig) return false;
|
|
2095
|
+
let storedContext;
|
|
2096
|
+
try {
|
|
2097
|
+
storedContext = Buffer.from(ctxHex, "hex").toString();
|
|
2098
|
+
} catch {
|
|
2099
|
+
return false;
|
|
2100
|
+
}
|
|
2101
|
+
if (context !== void 0 && context !== "" && storedContext !== context) return false;
|
|
2102
|
+
const expectedContext = context !== void 0 && context !== "" ? context : storedContext;
|
|
2103
|
+
const expected = createHmac("sha256", secret).update(`${raw}:${expectedContext}`).digest("base64url");
|
|
2104
|
+
return timingSafeEqualSafe(Buffer.from(sig), Buffer.from(expected));
|
|
2105
|
+
}
|
|
2106
|
+
if (parts.length === 2) {
|
|
2107
|
+
const [raw, sig] = parts;
|
|
2108
|
+
if (!raw || !sig) return false;
|
|
2109
|
+
if (context !== void 0 && context !== "") return false;
|
|
2110
|
+
const expected = createHmac("sha256", secret).update(raw).digest("base64url");
|
|
2111
|
+
return timingSafeEqualSafe(Buffer.from(sig), Buffer.from(expected));
|
|
2112
|
+
}
|
|
2113
|
+
return false;
|
|
2114
|
+
}
|
|
2115
|
+
__name(verifyCsrfToken, "verifyCsrfToken");
|
|
2116
|
+
|
|
2117
|
+
// src/csrf/csrf-cookie.interceptor.ts
|
|
2118
|
+
function _ts_decorate9(decorators, target, key, desc) {
|
|
2119
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2120
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2121
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2122
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2123
|
+
}
|
|
2124
|
+
__name(_ts_decorate9, "_ts_decorate");
|
|
2125
|
+
function _ts_metadata8(k, v) {
|
|
2126
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2127
|
+
}
|
|
2128
|
+
__name(_ts_metadata8, "_ts_metadata");
|
|
2129
|
+
function writeCsrfCookie(res, cookieName, token, cookieOpts) {
|
|
2130
|
+
if (typeof res.cookie === "function") {
|
|
2131
|
+
res.cookie(cookieName, token, cookieOpts);
|
|
2132
|
+
} else if (typeof res.setCookie === "function") {
|
|
2133
|
+
res.setCookie(cookieName, token, cookieOpts);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
__name(writeCsrfCookie, "writeCsrfCookie");
|
|
2137
|
+
function rotateCsrfToken(res, options, context) {
|
|
2138
|
+
const cookieName = options.cookieName ?? "XSRF-TOKEN";
|
|
2139
|
+
const token = generateCsrfToken(options.secret, context);
|
|
2140
|
+
const cookieOpts = {
|
|
2141
|
+
httpOnly: options.httpOnly ?? false,
|
|
2142
|
+
sameSite: options.sameSite ?? "lax",
|
|
2143
|
+
secure: options.secure ?? process.env.NODE_ENV === "production",
|
|
2144
|
+
path: "/"
|
|
2145
|
+
};
|
|
2146
|
+
writeCsrfCookie(res, cookieName, token, cookieOpts);
|
|
2147
|
+
}
|
|
2148
|
+
__name(rotateCsrfToken, "rotateCsrfToken");
|
|
2149
|
+
var CsrfCookieInterceptor = class {
|
|
2150
|
+
static {
|
|
2151
|
+
__name(this, "CsrfCookieInterceptor");
|
|
2152
|
+
}
|
|
2153
|
+
options;
|
|
2154
|
+
cookieName;
|
|
2155
|
+
constructor(options) {
|
|
2156
|
+
this.options = options;
|
|
2157
|
+
this.cookieName = options.cookieName ?? "XSRF-TOKEN";
|
|
2158
|
+
}
|
|
2159
|
+
intercept(context, next) {
|
|
2160
|
+
const req = context.switchToHttp().getRequest();
|
|
2161
|
+
const res = context.switchToHttp().getResponse();
|
|
2162
|
+
const ctx = this.options.tokenContext ? this.options.tokenContext(req) : void 0;
|
|
2163
|
+
const existing = req.cookies?.[this.cookieName];
|
|
2164
|
+
if (!existing || !verifyCsrfToken(existing, this.options.secret, ctx)) {
|
|
2165
|
+
rotateCsrfToken(res, this.options, ctx);
|
|
2166
|
+
}
|
|
2167
|
+
return next.handle();
|
|
2168
|
+
}
|
|
2169
|
+
};
|
|
2170
|
+
CsrfCookieInterceptor = _ts_decorate9([
|
|
2171
|
+
Injectable8(),
|
|
2172
|
+
_ts_metadata8("design:type", Function),
|
|
2173
|
+
_ts_metadata8("design:paramtypes", [
|
|
2174
|
+
typeof CsrfCookieOptions === "undefined" ? Object : CsrfCookieOptions
|
|
2175
|
+
])
|
|
2176
|
+
], CsrfCookieInterceptor);
|
|
2177
|
+
|
|
2178
|
+
// src/csrf/csrf.guard.ts
|
|
2179
|
+
init_exceptions();
|
|
2180
|
+
import { Injectable as Injectable9 } from "@nestjs/common";
|
|
2181
|
+
function _ts_decorate10(decorators, target, key, desc) {
|
|
2182
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2183
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2184
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2185
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2186
|
+
}
|
|
2187
|
+
__name(_ts_decorate10, "_ts_decorate");
|
|
2188
|
+
function _ts_metadata9(k, v) {
|
|
2189
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2190
|
+
}
|
|
2191
|
+
__name(_ts_metadata9, "_ts_metadata");
|
|
2192
|
+
var SAFE = /* @__PURE__ */ new Set([
|
|
2193
|
+
"GET",
|
|
2194
|
+
"HEAD",
|
|
2195
|
+
"OPTIONS"
|
|
2196
|
+
]);
|
|
2197
|
+
var CsrfGuard = class {
|
|
2198
|
+
static {
|
|
2199
|
+
__name(this, "CsrfGuard");
|
|
2200
|
+
}
|
|
2201
|
+
options;
|
|
2202
|
+
cookieName;
|
|
2203
|
+
headerName;
|
|
2204
|
+
constructor(options) {
|
|
2205
|
+
this.options = options;
|
|
2206
|
+
this.cookieName = options.cookieName ?? "XSRF-TOKEN";
|
|
2207
|
+
this.headerName = (options.headerName ?? "X-XSRF-TOKEN").toLowerCase();
|
|
2208
|
+
}
|
|
2209
|
+
canActivate(ctx) {
|
|
2210
|
+
const req = ctx.switchToHttp().getRequest();
|
|
2211
|
+
if (SAFE.has(req.method)) return true;
|
|
2212
|
+
const cookieToken = req.cookies?.[this.cookieName];
|
|
2213
|
+
const headerRaw = req.headers[this.headerName];
|
|
2214
|
+
const headerToken = Array.isArray(headerRaw) ? headerRaw[0] : headerRaw;
|
|
2215
|
+
if (!cookieToken || !headerToken) throw new InvalidCsrfTokenException();
|
|
2216
|
+
if (!timingSafeEqualSafe(Buffer.from(cookieToken), Buffer.from(headerToken))) {
|
|
2217
|
+
throw new InvalidCsrfTokenException();
|
|
2218
|
+
}
|
|
2219
|
+
const context = this.options.tokenContext ? this.options.tokenContext(req) : void 0;
|
|
2220
|
+
if (!verifyCsrfToken(cookieToken, this.options.secret, context)) throw new InvalidCsrfTokenException();
|
|
2221
|
+
return true;
|
|
2222
|
+
}
|
|
2223
|
+
};
|
|
2224
|
+
CsrfGuard = _ts_decorate10([
|
|
2225
|
+
Injectable9(),
|
|
2226
|
+
_ts_metadata9("design:type", Function),
|
|
2227
|
+
_ts_metadata9("design:paramtypes", [
|
|
2228
|
+
typeof CsrfGuardOptions === "undefined" ? Object : CsrfGuardOptions
|
|
2229
|
+
])
|
|
2230
|
+
], CsrfGuard);
|
|
2231
|
+
|
|
2232
|
+
// src/index.ts
|
|
2233
|
+
var VERSION = "1.0.0";
|
|
2234
|
+
export {
|
|
2235
|
+
CsrfCookieInterceptor,
|
|
2236
|
+
CsrfGuard,
|
|
2237
|
+
ErrorBagInterceptor,
|
|
2238
|
+
INERTIA_ASSET_VERSION,
|
|
2239
|
+
INERTIA_DEFAULT_SCOPE,
|
|
2240
|
+
INERTIA_FEATURE_OPTIONS,
|
|
2241
|
+
INERTIA_MANIFEST,
|
|
2242
|
+
INERTIA_MODULE_OPTIONS,
|
|
2243
|
+
INERTIA_RENDER_COMPONENT,
|
|
2244
|
+
INERTIA_USE_SCOPE,
|
|
2245
|
+
Inertia,
|
|
2246
|
+
InertiaModule,
|
|
2247
|
+
InertiaRenderInterceptor,
|
|
2248
|
+
InertiaService,
|
|
2249
|
+
InertiaServiceNotAvailableException,
|
|
2250
|
+
InvalidCsrfTokenException,
|
|
2251
|
+
InvalidInertiaConfigException,
|
|
2252
|
+
MethodSpoofMiddleware,
|
|
2253
|
+
MissingCookieDepException,
|
|
2254
|
+
MissingTemplateEngineDepException,
|
|
2255
|
+
RedirectInterceptor,
|
|
2256
|
+
UnsupportedRootViewExtensionException,
|
|
2257
|
+
UseInertia,
|
|
2258
|
+
VERSION,
|
|
2259
|
+
featureToken,
|
|
2260
|
+
generateCsrfToken,
|
|
2261
|
+
rotateCsrfToken,
|
|
2262
|
+
timingSafeEqualSafe,
|
|
2263
|
+
verifyCsrfToken
|
|
2264
|
+
};
|
|
2265
|
+
//# sourceMappingURL=index.js.map
|