@dudousxd/nestjs-codegen 0.26.0 → 0.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +2 -2
- package/dist/cli/main.cjs +212 -73
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +213 -74
- package/dist/cli/main.js.map +1 -1
- package/dist/extension/index.d.cts +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/{index-Bbw73Kkb.d.cts → index-Dc4s883u.d.cts} +41 -4
- package/dist/{index-Bbw73Kkb.d.ts → index-Dc4s883u.d.ts} +41 -4
- package/dist/index.cjs +212 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +213 -74
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +216 -77
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +217 -78
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
package/dist/nest/index.cjs
CHANGED
|
@@ -109,11 +109,32 @@ function validateUserConfig(userConfig) {
|
|
|
109
109
|
"validation adapter is required \u2014 install @dudousxd/nestjs-codegen-zod and pass zodAdapter, or use @dudousxd/nestjs-codegen-valibot / -arktype"
|
|
110
110
|
);
|
|
111
111
|
}
|
|
112
|
-
if (userConfig.pages &&
|
|
112
|
+
if (userConfig.pages && !isGlobInput(userConfig.pages.glob)) {
|
|
113
113
|
throw new ConfigError(
|
|
114
|
-
"Config validation failed: `pages.glob` must be a string when `pages` is set"
|
|
114
|
+
"Config validation failed: `pages.glob` must be a string or a non-empty array of strings when `pages` is set"
|
|
115
115
|
);
|
|
116
116
|
}
|
|
117
|
+
for (const [scope, scopeConfig] of Object.entries(userConfig.pages?.scopes ?? {})) {
|
|
118
|
+
if (scope === "default") {
|
|
119
|
+
throw new ConfigError(
|
|
120
|
+
'Config validation failed: `pages.scopes` cannot declare "default" \u2014 the default app is `pages.glob` (InertiaModule.forRoot).'
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
if (!isGlobInput(scopeConfig?.glob)) {
|
|
124
|
+
throw new ConfigError(
|
|
125
|
+
`Config validation failed: \`pages.scopes.${scope}.glob\` must be a string or a non-empty array of strings`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (userConfig.scopes && Object.keys(userConfig.scopes).length > 0) {
|
|
130
|
+
console.warn(
|
|
131
|
+
"[nestjs-codegen] The top-level `scopes` option has no effect and is deprecated. For several Inertia apps use `pages.scopes` (one entry per InertiaModule.forFeature scope); for several controller sets use one `contracts.glob` (e.g. a brace glob)."
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function isGlobInput(value) {
|
|
136
|
+
if (typeof value === "string") return true;
|
|
137
|
+
return Array.isArray(value) && value.length > 0 && value.every((glob) => typeof glob === "string");
|
|
117
138
|
}
|
|
118
139
|
function applyDefaults(userConfig, cwd) {
|
|
119
140
|
validateUserConfig(userConfig);
|
|
@@ -141,7 +162,17 @@ function applyDefaults(userConfig, cwd) {
|
|
|
141
162
|
pages: userConfig.pages ? {
|
|
142
163
|
glob: userConfig.pages.glob,
|
|
143
164
|
propsExport: userConfig.pages.propsExport ?? "ComponentProps",
|
|
144
|
-
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext"
|
|
165
|
+
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext",
|
|
166
|
+
scopes: Object.fromEntries(
|
|
167
|
+
Object.entries(userConfig.pages.scopes ?? {}).map(([scope, scopeConfig]) => [
|
|
168
|
+
scope,
|
|
169
|
+
{
|
|
170
|
+
glob: scopeConfig.glob,
|
|
171
|
+
prefix: scopeConfig.prefix ?? `${scope}/`,
|
|
172
|
+
componentNameStrategy: scopeConfig.componentNameStrategy ?? userConfig.pages?.componentNameStrategy ?? "relative-no-ext"
|
|
173
|
+
}
|
|
174
|
+
])
|
|
175
|
+
)
|
|
145
176
|
} : null,
|
|
146
177
|
contracts: {
|
|
147
178
|
glob: userConfig.contracts?.glob ?? "src/**/*.controller.ts",
|
|
@@ -283,10 +314,11 @@ function resolveModuleSpecifier(moduleSpecifier, sourceFile, project) {
|
|
|
283
314
|
}
|
|
284
315
|
return [];
|
|
285
316
|
}
|
|
286
|
-
function resolveImportedType(name, sourceFile, project) {
|
|
317
|
+
function resolveImportedType(name, sourceFile, project, seen = /* @__PURE__ */ new Set()) {
|
|
287
318
|
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
288
|
-
const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);
|
|
319
|
+
const namedImport = importDecl.getNamedImports().find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name);
|
|
289
320
|
if (!namedImport) continue;
|
|
321
|
+
const sourceName = namedImport.getName();
|
|
290
322
|
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
291
323
|
const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);
|
|
292
324
|
for (const candidate of candidates) {
|
|
@@ -298,17 +330,17 @@ function resolveImportedType(name, sourceFile, project) {
|
|
|
298
330
|
continue;
|
|
299
331
|
}
|
|
300
332
|
}
|
|
301
|
-
const result = findTypeInFile(
|
|
333
|
+
const result = findTypeInFile(sourceName, importedFile);
|
|
302
334
|
if (result) return result;
|
|
303
|
-
const viaReExport = resolveReExportedType(
|
|
335
|
+
const viaReExport = resolveReExportedType(sourceName, importedFile, project, /* @__PURE__ */ new Set());
|
|
304
336
|
if (viaReExport) return viaReExport;
|
|
305
337
|
}
|
|
306
338
|
if (candidates.length === 0) {
|
|
307
|
-
const viaCompiler = resolveBareSpecifierType(
|
|
339
|
+
const viaCompiler = resolveBareSpecifierType(sourceName, importDecl, project);
|
|
308
340
|
if (viaCompiler) return viaCompiler;
|
|
309
341
|
}
|
|
310
342
|
}
|
|
311
|
-
return resolveReExportedType(name, sourceFile, project,
|
|
343
|
+
return resolveReExportedType(name, sourceFile, project, seen);
|
|
312
344
|
}
|
|
313
345
|
function resolveBareSpecifierType(name, importDecl, project) {
|
|
314
346
|
let target;
|
|
@@ -323,9 +355,9 @@ function resolveBareSpecifierType(name, importDecl, project) {
|
|
|
323
355
|
return resolveReExportedType(name, target, project, /* @__PURE__ */ new Set());
|
|
324
356
|
}
|
|
325
357
|
function resolveReExportedType(name, file, project, seen) {
|
|
326
|
-
const
|
|
327
|
-
if (seen.has(
|
|
328
|
-
seen.add(
|
|
358
|
+
const visit = `${file.getFilePath()}#${name}`;
|
|
359
|
+
if (seen.has(visit)) return null;
|
|
360
|
+
seen.add(visit);
|
|
329
361
|
for (const exportDecl of file.getExportDeclarations()) {
|
|
330
362
|
const moduleSpecifier = exportDecl.getModuleSpecifierValue();
|
|
331
363
|
const namedExports = exportDecl.getNamedExports();
|
|
@@ -347,7 +379,7 @@ function resolveReExportedType(name, file, project, seen) {
|
|
|
347
379
|
const sourceName = namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ?? name;
|
|
348
380
|
const local = findTypeInFile(sourceName, file);
|
|
349
381
|
if (local) return local;
|
|
350
|
-
const imported = resolveImportedType(sourceName, file, project);
|
|
382
|
+
const imported = resolveImportedType(sourceName, file, project, seen);
|
|
351
383
|
if (imported) return imported;
|
|
352
384
|
}
|
|
353
385
|
return null;
|
|
@@ -3365,32 +3397,86 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
3365
3397
|
return routes;
|
|
3366
3398
|
}
|
|
3367
3399
|
|
|
3368
|
-
// src/generate.ts
|
|
3369
|
-
var import_promises11 = require("fs/promises");
|
|
3370
|
-
var import_node_path15 = require("path");
|
|
3371
|
-
|
|
3372
3400
|
// src/discovery/pages.ts
|
|
3373
3401
|
var import_promises2 = require("fs/promises");
|
|
3374
3402
|
var import_node_path4 = require("path");
|
|
3375
3403
|
var import_fast_glob2 = __toESM(require("fast-glob"), 1);
|
|
3376
3404
|
var NON_PAGE_FILE_RE = /\.(?:test|spec|stories|story)\.(?:tsx?|jsx?|vue|svelte)$/i;
|
|
3405
|
+
var MAGIC_SEGMENT_RE = /[*?{}[\]()!]/;
|
|
3406
|
+
function globStaticBase(glob) {
|
|
3407
|
+
const segments = glob.split("/");
|
|
3408
|
+
const staticSegments = [];
|
|
3409
|
+
for (const segment of segments.slice(0, -1)) {
|
|
3410
|
+
if (MAGIC_SEGMENT_RE.test(segment)) break;
|
|
3411
|
+
staticSegments.push(segment);
|
|
3412
|
+
}
|
|
3413
|
+
return staticSegments.join("/");
|
|
3414
|
+
}
|
|
3377
3415
|
async function discoverPages(opts) {
|
|
3378
|
-
const
|
|
3379
|
-
const
|
|
3380
|
-
|
|
3381
|
-
const
|
|
3382
|
-
const pagesBase = (0, import_node_path4.join)(opts.cwd, globStatic);
|
|
3416
|
+
const globs = typeof opts.glob === "string" ? [opts.glob] : opts.glob;
|
|
3417
|
+
const prefix = opts.prefix ?? "";
|
|
3418
|
+
const scope = opts.scope ?? "default";
|
|
3419
|
+
const seenFiles = /* @__PURE__ */ new Set();
|
|
3383
3420
|
const out = [];
|
|
3384
|
-
for (const
|
|
3385
|
-
const
|
|
3386
|
-
const
|
|
3387
|
-
const
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3421
|
+
for (const glob of globs) {
|
|
3422
|
+
const files = (await (0, import_fast_glob2.default)(glob, { cwd: opts.cwd, absolute: true })).filter((f) => !NON_PAGE_FILE_RE.test(f) && !seenFiles.has(f)).sort();
|
|
3423
|
+
const pagesBase = (0, import_node_path4.join)(opts.cwd, globStaticBase(glob));
|
|
3424
|
+
for (const file of files) {
|
|
3425
|
+
seenFiles.add(file);
|
|
3426
|
+
const rel = (0, import_node_path4.relative)(opts.cwd, file);
|
|
3427
|
+
const nameRel = (0, import_node_path4.relative)(pagesBase, file).split(import_node_path4.sep).join("/");
|
|
3428
|
+
const name = `${prefix}${computeName(nameRel, opts.componentNameStrategy)}`;
|
|
3429
|
+
const source = await (0, import_promises2.readFile)(file, "utf8");
|
|
3430
|
+
const propsSource = extractPropsSource(source, opts.propsExport);
|
|
3431
|
+
out.push({ name, absolutePath: file, relativePath: rel, propsSource, scope });
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
assertUniqueNames(out);
|
|
3435
|
+
return out;
|
|
3436
|
+
}
|
|
3437
|
+
async function discoverPageScopes(config) {
|
|
3438
|
+
const pages = config.pages;
|
|
3439
|
+
if (!pages) return [];
|
|
3440
|
+
const common = { cwd: config.codegen.cwd, propsExport: pages.propsExport };
|
|
3441
|
+
const out = await discoverPages({
|
|
3442
|
+
...common,
|
|
3443
|
+
glob: pages.glob,
|
|
3444
|
+
componentNameStrategy: pages.componentNameStrategy
|
|
3445
|
+
});
|
|
3446
|
+
for (const [scope, scopeConfig] of Object.entries(pages.scopes ?? {})) {
|
|
3447
|
+
out.push(
|
|
3448
|
+
...await discoverPages({
|
|
3449
|
+
...common,
|
|
3450
|
+
glob: scopeConfig.glob,
|
|
3451
|
+
componentNameStrategy: scopeConfig.componentNameStrategy,
|
|
3452
|
+
prefix: scopeConfig.prefix,
|
|
3453
|
+
scope
|
|
3454
|
+
})
|
|
3455
|
+
);
|
|
3391
3456
|
}
|
|
3457
|
+
assertUniqueNames(out);
|
|
3392
3458
|
return out;
|
|
3393
3459
|
}
|
|
3460
|
+
function allPageGlobs(config) {
|
|
3461
|
+
if (!config.pages) return [];
|
|
3462
|
+
const asList = (glob) => typeof glob === "string" ? [glob] : glob;
|
|
3463
|
+
return [
|
|
3464
|
+
...asList(config.pages.glob),
|
|
3465
|
+
...Object.values(config.pages.scopes ?? {}).flatMap((scope) => asList(scope.glob))
|
|
3466
|
+
];
|
|
3467
|
+
}
|
|
3468
|
+
function assertUniqueNames(pages) {
|
|
3469
|
+
const byName = /* @__PURE__ */ new Map();
|
|
3470
|
+
for (const page of pages) {
|
|
3471
|
+
const previous = byName.get(page.name);
|
|
3472
|
+
if (previous) {
|
|
3473
|
+
throw new Error(
|
|
3474
|
+
`Two Inertia pages resolve to the component name "${page.name}": ${previous.relativePath} (scope "${previous.scope}") and ${page.relativePath} (scope "${page.scope}"). Give one of them another name, directory or scope prefix.`
|
|
3475
|
+
);
|
|
3476
|
+
}
|
|
3477
|
+
byName.set(page.name, page);
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3394
3480
|
function computeName(rel, strat) {
|
|
3395
3481
|
if (typeof strat === "function") return strat(rel);
|
|
3396
3482
|
const noExt = rel.replace(/\.(tsx?|vue|svelte)$/, "");
|
|
@@ -3421,6 +3507,10 @@ function extractPropsSource(source, exportName) {
|
|
|
3421
3507
|
return source.slice(start);
|
|
3422
3508
|
}
|
|
3423
3509
|
|
|
3510
|
+
// src/generate.ts
|
|
3511
|
+
var import_promises11 = require("fs/promises");
|
|
3512
|
+
var import_node_path15 = require("path");
|
|
3513
|
+
|
|
3424
3514
|
// src/discovery/shared-props.ts
|
|
3425
3515
|
var import_node_path5 = require("path");
|
|
3426
3516
|
var import_ts_morph12 = require("ts-morph");
|
|
@@ -4055,28 +4145,28 @@ function renderFetcherRequest(req, binaryResponse) {
|
|
|
4055
4145
|
}
|
|
4056
4146
|
function emitReqHelper() {
|
|
4057
4147
|
return [
|
|
4058
|
-
"/**
|
|
4059
|
-
"type
|
|
4060
|
-
"
|
|
4148
|
+
"/** An awaitable request handle: a lazy, memoized `Promise` that also carries `fetch()` and the members extensions add. */",
|
|
4149
|
+
"export type RequestHandle<R, M = {}> = Promise<R> & { fetch(): Promise<R> } & M;",
|
|
4150
|
+
"class __Request<R> extends Promise<R> {",
|
|
4151
|
+
" static override get [Symbol.species](): PromiseConstructor {",
|
|
4152
|
+
" return Promise;",
|
|
4153
|
+
" }",
|
|
4154
|
+
" private __run: () => Promise<R>;",
|
|
4155
|
+
" private __p: Promise<R> | undefined;",
|
|
4156
|
+
" constructor(run: () => Promise<R>) {",
|
|
4157
|
+
" super(() => {});",
|
|
4158
|
+
" this.__run = run;",
|
|
4159
|
+
" }",
|
|
4160
|
+
" override then<T1 = R, T2 = never>(",
|
|
4061
4161
|
" onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,",
|
|
4062
4162
|
" onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,",
|
|
4063
|
-
" ): Promise<T1 | T2
|
|
4064
|
-
"
|
|
4065
|
-
"
|
|
4066
|
-
"
|
|
4067
|
-
"}
|
|
4068
|
-
"function __req<R>(run: () => Promise<R
|
|
4069
|
-
"
|
|
4070
|
-
" const __promise = () => {",
|
|
4071
|
-
" __p ??= run();",
|
|
4072
|
-
" return __p;",
|
|
4073
|
-
" };",
|
|
4074
|
-
" return {",
|
|
4075
|
-
" then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),",
|
|
4076
|
-
" catch: (onrejected) => __promise().catch(onrejected),",
|
|
4077
|
-
" finally: (onfinally) => __promise().finally(onfinally),",
|
|
4078
|
-
" fetch: run,",
|
|
4079
|
-
" };",
|
|
4163
|
+
" ): Promise<T1 | T2> {",
|
|
4164
|
+
" this.__p ??= this.__run();",
|
|
4165
|
+
" return this.__p.then(onfulfilled, onrejected);",
|
|
4166
|
+
" }",
|
|
4167
|
+
"}",
|
|
4168
|
+
"function __req<R, M extends object = {}>(run: () => Promise<R>, members?: M): RequestHandle<R, M> {",
|
|
4169
|
+
" return Object.assign(new __Request<R>(run), { fetch: run }, members) as RequestHandle<R, M>;",
|
|
4080
4170
|
"}",
|
|
4081
4171
|
""
|
|
4082
4172
|
];
|
|
@@ -4094,18 +4184,26 @@ function emitFilterFieldGuard() {
|
|
|
4094
4184
|
];
|
|
4095
4185
|
}
|
|
4096
4186
|
function renderLeaf(pad, objKey, req, requestExpr, members, streamExpr) {
|
|
4097
|
-
const
|
|
4098
|
-
lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4187
|
+
const memberLines = [];
|
|
4099
4188
|
if (req.filterFieldsExpr) {
|
|
4100
|
-
|
|
4189
|
+
memberLines.push(`${pad} filterFields: ${req.filterFieldsExpr},`);
|
|
4101
4190
|
}
|
|
4102
4191
|
if (streamExpr) {
|
|
4103
|
-
|
|
4192
|
+
memberLines.push(`${pad} stream: () => ${streamExpr},`);
|
|
4104
4193
|
}
|
|
4105
4194
|
for (const [name, value] of Object.entries(members)) {
|
|
4106
|
-
|
|
4107
|
-
}
|
|
4108
|
-
|
|
4195
|
+
memberLines.push(`${pad} ${name}: ${value},`);
|
|
4196
|
+
}
|
|
4197
|
+
const body = [requestExpr, ...memberLines].join("\n");
|
|
4198
|
+
const param = /\binput\b/.test(body) ? `input?: ${req.inputType}` : "";
|
|
4199
|
+
const lines = [`${pad}${objKey}: (${param}) =>`];
|
|
4200
|
+
if (memberLines.length === 0) {
|
|
4201
|
+
lines.push(`${pad} __req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4202
|
+
return lines;
|
|
4203
|
+
}
|
|
4204
|
+
lines.push(`${pad} __req(() => ${requestExpr}, {`);
|
|
4205
|
+
lines.push(...memberLines);
|
|
4206
|
+
lines.push(`${pad} }),`);
|
|
4109
4207
|
return lines;
|
|
4110
4208
|
}
|
|
4111
4209
|
function renderStreamExpr(req) {
|
|
@@ -4239,6 +4337,23 @@ var EMPTY_PATH_NAMESPACE = [
|
|
|
4239
4337
|
function isClientCallable(route) {
|
|
4240
4338
|
return route.method.toUpperCase() !== "ALL";
|
|
4241
4339
|
}
|
|
4340
|
+
var ROUTES_IMPORT_PLACEHOLDER = "/* @@routes-import@@ */";
|
|
4341
|
+
var ROUTES_EXPORTS = [
|
|
4342
|
+
// Called, never mentioned in prose: match the call so a comment saying "route" doesn't count.
|
|
4343
|
+
{ name: "route", typeOnly: false },
|
|
4344
|
+
{ name: "ROUTES", typeOnly: false },
|
|
4345
|
+
{ name: "RouteName", typeOnly: true },
|
|
4346
|
+
{ name: "ExtractParams", typeOnly: true },
|
|
4347
|
+
{ name: "RouteParams", typeOnly: true }
|
|
4348
|
+
];
|
|
4349
|
+
function finishRoutesImport(lines) {
|
|
4350
|
+
const body = lines.filter((l) => l !== ROUTES_IMPORT_PLACEHOLDER).join("\n");
|
|
4351
|
+
const used = ROUTES_EXPORTS.filter(
|
|
4352
|
+
({ name }) => new RegExp(name === "route" ? "\\broute\\(" : `\\b${name}\\b`).test(body)
|
|
4353
|
+
).map(({ name, typeOnly }) => typeOnly ? `type ${name}` : name);
|
|
4354
|
+
const importLine = used.length ? `import { ${used.join(", ")} } from './routes.js';` : null;
|
|
4355
|
+
return lines.flatMap((l) => l === ROUTES_IMPORT_PLACEHOLDER ? importLine ? [importLine] : [] : [l]).join("\n");
|
|
4356
|
+
}
|
|
4242
4357
|
function buildApiFile(routes, outDir, opts = {}) {
|
|
4243
4358
|
const fetcherImportPath = opts.fetcherImportPath;
|
|
4244
4359
|
const serialization = opts.serialization ?? "json";
|
|
@@ -4298,9 +4413,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4298
4413
|
for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);
|
|
4299
4414
|
}
|
|
4300
4415
|
lines.push(...extImports);
|
|
4301
|
-
lines.push(
|
|
4302
|
-
"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';"
|
|
4303
|
-
);
|
|
4416
|
+
lines.push(ROUTES_IMPORT_PLACEHOLDER);
|
|
4304
4417
|
const runtimeImport = fetcherImportPath ?? "@dudousxd/nestjs-client";
|
|
4305
4418
|
lines.push(`import type { Fetcher } from '${runtimeImport}';`);
|
|
4306
4419
|
if (serialization === "json" && contracted.length > 0) {
|
|
@@ -4351,7 +4464,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4351
4464
|
lines.push(...statements, "");
|
|
4352
4465
|
}
|
|
4353
4466
|
}
|
|
4354
|
-
return lines
|
|
4467
|
+
return finishRoutesImport(lines);
|
|
4355
4468
|
}
|
|
4356
4469
|
const tree = /* @__PURE__ */ new Map();
|
|
4357
4470
|
for (const r of contracted) {
|
|
@@ -4404,7 +4517,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4404
4517
|
lines.push(...statements, "");
|
|
4405
4518
|
}
|
|
4406
4519
|
}
|
|
4407
|
-
return lines
|
|
4520
|
+
return finishRoutesImport(lines);
|
|
4408
4521
|
}
|
|
4409
4522
|
|
|
4410
4523
|
// src/emit/emit-cache.ts
|
|
@@ -4417,6 +4530,7 @@ async function emitCache(pages, outDir) {
|
|
|
4417
4530
|
const s = await (0, import_promises4.stat)(p.absolutePath);
|
|
4418
4531
|
return {
|
|
4419
4532
|
name: p.name,
|
|
4533
|
+
scope: p.scope ?? "default",
|
|
4420
4534
|
relativePath: p.relativePath,
|
|
4421
4535
|
mtime: s.mtime.toISOString()
|
|
4422
4536
|
};
|
|
@@ -5208,10 +5322,11 @@ async function emitPages(pages, outDir, _options = {}) {
|
|
|
5208
5322
|
}).join("\n");
|
|
5209
5323
|
const propsHelper = "\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\n";
|
|
5210
5324
|
const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);
|
|
5325
|
+
const scopesBlock = buildScopesBlock(pages);
|
|
5211
5326
|
const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.
|
|
5212
5327
|
|
|
5213
5328
|
export type InertiaPageName = ${pageNameUnion};
|
|
5214
|
-
${propsHelper}
|
|
5329
|
+
${propsHelper}${scopesBlock}
|
|
5215
5330
|
declare module '@dudousxd/nestjs-inertia' {
|
|
5216
5331
|
interface InertiaPages {
|
|
5217
5332
|
${augBody}
|
|
@@ -5220,6 +5335,31 @@ ${sharedPropsBlock}}
|
|
|
5220
5335
|
`;
|
|
5221
5336
|
await (0, import_promises9.writeFile)((0, import_node_path13.join)(outDir, "pages.d.ts"), content, "utf8");
|
|
5222
5337
|
}
|
|
5338
|
+
function buildScopesBlock(pages) {
|
|
5339
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
5340
|
+
for (const page of pages) {
|
|
5341
|
+
const scope = page.scope ?? "default";
|
|
5342
|
+
const names = byScope.get(scope) ?? [];
|
|
5343
|
+
names.push(JSON.stringify(page.name));
|
|
5344
|
+
byScope.set(scope, names);
|
|
5345
|
+
}
|
|
5346
|
+
if (![...byScope.keys()].some((scope) => scope !== "default")) return "";
|
|
5347
|
+
if (!byScope.has("default")) byScope.set("default", []);
|
|
5348
|
+
const scopes = ["default", ...[...byScope.keys()].filter((s) => s !== "default")];
|
|
5349
|
+
const body = scopes.map((scope) => {
|
|
5350
|
+
const key = needsQuotes(scope) ? JSON.stringify(scope) : scope;
|
|
5351
|
+
const names = byScope.get(scope) ?? [];
|
|
5352
|
+
return ` ${key}: ${names.length ? names.join(" | ") : "never"};`;
|
|
5353
|
+
}).join("\n");
|
|
5354
|
+
return `
|
|
5355
|
+
/** The page names of each Inertia app: \`default\` (forRoot) and every \`pages.scopes\` entry. */
|
|
5356
|
+
export interface InertiaScopePages {
|
|
5357
|
+
${body}
|
|
5358
|
+
}
|
|
5359
|
+
|
|
5360
|
+
export type InertiaScopePageName<S extends keyof InertiaScopePages> = InertiaScopePages[S];
|
|
5361
|
+
`;
|
|
5362
|
+
}
|
|
5223
5363
|
function buildSharedPropsBlock(sharedProps) {
|
|
5224
5364
|
if (!sharedProps) return "";
|
|
5225
5365
|
if (sharedProps.isImportRef) {
|
|
@@ -5401,12 +5541,7 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
|
|
|
5401
5541
|
}
|
|
5402
5542
|
if (config.pages) {
|
|
5403
5543
|
const pagesConfig = config.pages;
|
|
5404
|
-
const pages = await
|
|
5405
|
-
glob: pagesConfig.glob,
|
|
5406
|
-
cwd: config.codegen.cwd,
|
|
5407
|
-
propsExport: pagesConfig.propsExport,
|
|
5408
|
-
componentNameStrategy: pagesConfig.componentNameStrategy
|
|
5409
|
-
});
|
|
5544
|
+
const pages = await discoverPageScopes(config);
|
|
5410
5545
|
const sharedProps = discoverSharedPropsFromConfig(config);
|
|
5411
5546
|
await emitPages(pages, config.codegen.outDir, {
|
|
5412
5547
|
propsExport: pagesConfig.propsExport,
|
|
@@ -5581,12 +5716,17 @@ async function watch(config, onChange, options = {}) {
|
|
|
5581
5716
|
await runInitialPass();
|
|
5582
5717
|
}
|
|
5583
5718
|
let pagesDebounceTimer;
|
|
5584
|
-
const
|
|
5585
|
-
const pagesWatcher = import_chokidar.default.watch(
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5719
|
+
const pageGlobs = allPageGlobs(config);
|
|
5720
|
+
const pagesWatcher = import_chokidar.default.watch(
|
|
5721
|
+
(pageGlobs.length ? pageGlobs : [".nestjs-codegen-no-pages"]).map(
|
|
5722
|
+
(glob) => (0, import_node_path17.join)(config.codegen.cwd, glob)
|
|
5723
|
+
),
|
|
5724
|
+
{
|
|
5725
|
+
ignoreInitial: true,
|
|
5726
|
+
persistent: true,
|
|
5727
|
+
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
5728
|
+
}
|
|
5729
|
+
);
|
|
5590
5730
|
function schedulePagesRegenerate() {
|
|
5591
5731
|
if (pagesDebounceTimer !== void 0) {
|
|
5592
5732
|
clearTimeout(pagesDebounceTimer);
|
|
@@ -5666,7 +5806,7 @@ async function watch(config, onChange, options = {}) {
|
|
|
5666
5806
|
}
|
|
5667
5807
|
|
|
5668
5808
|
// src/index.ts
|
|
5669
|
-
var VERSION = "0.
|
|
5809
|
+
var VERSION = "0.27.1";
|
|
5670
5810
|
|
|
5671
5811
|
// src/generate-manifest.ts
|
|
5672
5812
|
var MANIFEST_FILE = ".codegen-manifest.json";
|
|
@@ -5726,8 +5866,7 @@ function diffConfigKeyHashes(previous, current) {
|
|
|
5726
5866
|
return [...keys].filter((key) => previous[key] !== current[key]).sort();
|
|
5727
5867
|
}
|
|
5728
5868
|
async function discoverInputFiles(config) {
|
|
5729
|
-
const globs = [config.contracts.glob, config.forms.watch];
|
|
5730
|
-
if (config.pages) globs.push(config.pages.glob);
|
|
5869
|
+
const globs = [config.contracts.glob, config.forms.watch, ...allPageGlobs(config)];
|
|
5731
5870
|
const cwd = config.codegen.cwd;
|
|
5732
5871
|
const matched = await (0, import_fast_glob3.default)(globs, { cwd, absolute: true, onlyFiles: true });
|
|
5733
5872
|
return [...new Set(matched)].sort();
|