@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.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _nestjs_common from '@nestjs/common';
|
|
2
2
|
import { DynamicModule, OnApplicationBootstrap, OnModuleDestroy, ExecutionContext } from '@nestjs/common';
|
|
3
|
-
import { U as UserConfig } from '../index-
|
|
3
|
+
import { U as UserConfig } from '../index-Dc4s883u.cjs';
|
|
4
4
|
import 'ts-morph';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/nest/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _nestjs_common from '@nestjs/common';
|
|
2
2
|
import { DynamicModule, OnApplicationBootstrap, OnModuleDestroy, ExecutionContext } from '@nestjs/common';
|
|
3
|
-
import { U as UserConfig } from '../index-
|
|
3
|
+
import { U as UserConfig } from '../index-Dc4s883u.js';
|
|
4
4
|
import 'ts-morph';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/nest/index.js
CHANGED
|
@@ -70,11 +70,32 @@ function validateUserConfig(userConfig) {
|
|
|
70
70
|
"validation adapter is required \u2014 install @dudousxd/nestjs-codegen-zod and pass zodAdapter, or use @dudousxd/nestjs-codegen-valibot / -arktype"
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
|
-
if (userConfig.pages &&
|
|
73
|
+
if (userConfig.pages && !isGlobInput(userConfig.pages.glob)) {
|
|
74
74
|
throw new ConfigError(
|
|
75
|
-
"Config validation failed: `pages.glob` must be a string when `pages` is set"
|
|
75
|
+
"Config validation failed: `pages.glob` must be a string or a non-empty array of strings when `pages` is set"
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
|
+
for (const [scope, scopeConfig] of Object.entries(userConfig.pages?.scopes ?? {})) {
|
|
79
|
+
if (scope === "default") {
|
|
80
|
+
throw new ConfigError(
|
|
81
|
+
'Config validation failed: `pages.scopes` cannot declare "default" \u2014 the default app is `pages.glob` (InertiaModule.forRoot).'
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if (!isGlobInput(scopeConfig?.glob)) {
|
|
85
|
+
throw new ConfigError(
|
|
86
|
+
`Config validation failed: \`pages.scopes.${scope}.glob\` must be a string or a non-empty array of strings`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (userConfig.scopes && Object.keys(userConfig.scopes).length > 0) {
|
|
91
|
+
console.warn(
|
|
92
|
+
"[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)."
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function isGlobInput(value) {
|
|
97
|
+
if (typeof value === "string") return true;
|
|
98
|
+
return Array.isArray(value) && value.length > 0 && value.every((glob) => typeof glob === "string");
|
|
78
99
|
}
|
|
79
100
|
function applyDefaults(userConfig, cwd) {
|
|
80
101
|
validateUserConfig(userConfig);
|
|
@@ -102,7 +123,17 @@ function applyDefaults(userConfig, cwd) {
|
|
|
102
123
|
pages: userConfig.pages ? {
|
|
103
124
|
glob: userConfig.pages.glob,
|
|
104
125
|
propsExport: userConfig.pages.propsExport ?? "ComponentProps",
|
|
105
|
-
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext"
|
|
126
|
+
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext",
|
|
127
|
+
scopes: Object.fromEntries(
|
|
128
|
+
Object.entries(userConfig.pages.scopes ?? {}).map(([scope, scopeConfig]) => [
|
|
129
|
+
scope,
|
|
130
|
+
{
|
|
131
|
+
glob: scopeConfig.glob,
|
|
132
|
+
prefix: scopeConfig.prefix ?? `${scope}/`,
|
|
133
|
+
componentNameStrategy: scopeConfig.componentNameStrategy ?? userConfig.pages?.componentNameStrategy ?? "relative-no-ext"
|
|
134
|
+
}
|
|
135
|
+
])
|
|
136
|
+
)
|
|
106
137
|
} : null,
|
|
107
138
|
contracts: {
|
|
108
139
|
glob: userConfig.contracts?.glob ?? "src/**/*.controller.ts",
|
|
@@ -255,10 +286,11 @@ function resolveModuleSpecifier(moduleSpecifier, sourceFile, project) {
|
|
|
255
286
|
}
|
|
256
287
|
return [];
|
|
257
288
|
}
|
|
258
|
-
function resolveImportedType(name, sourceFile, project) {
|
|
289
|
+
function resolveImportedType(name, sourceFile, project, seen = /* @__PURE__ */ new Set()) {
|
|
259
290
|
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
260
|
-
const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);
|
|
291
|
+
const namedImport = importDecl.getNamedImports().find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name);
|
|
261
292
|
if (!namedImport) continue;
|
|
293
|
+
const sourceName = namedImport.getName();
|
|
262
294
|
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
263
295
|
const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);
|
|
264
296
|
for (const candidate of candidates) {
|
|
@@ -270,17 +302,17 @@ function resolveImportedType(name, sourceFile, project) {
|
|
|
270
302
|
continue;
|
|
271
303
|
}
|
|
272
304
|
}
|
|
273
|
-
const result = findTypeInFile(
|
|
305
|
+
const result = findTypeInFile(sourceName, importedFile);
|
|
274
306
|
if (result) return result;
|
|
275
|
-
const viaReExport = resolveReExportedType(
|
|
307
|
+
const viaReExport = resolveReExportedType(sourceName, importedFile, project, /* @__PURE__ */ new Set());
|
|
276
308
|
if (viaReExport) return viaReExport;
|
|
277
309
|
}
|
|
278
310
|
if (candidates.length === 0) {
|
|
279
|
-
const viaCompiler = resolveBareSpecifierType(
|
|
311
|
+
const viaCompiler = resolveBareSpecifierType(sourceName, importDecl, project);
|
|
280
312
|
if (viaCompiler) return viaCompiler;
|
|
281
313
|
}
|
|
282
314
|
}
|
|
283
|
-
return resolveReExportedType(name, sourceFile, project,
|
|
315
|
+
return resolveReExportedType(name, sourceFile, project, seen);
|
|
284
316
|
}
|
|
285
317
|
function resolveBareSpecifierType(name, importDecl, project) {
|
|
286
318
|
let target;
|
|
@@ -295,9 +327,9 @@ function resolveBareSpecifierType(name, importDecl, project) {
|
|
|
295
327
|
return resolveReExportedType(name, target, project, /* @__PURE__ */ new Set());
|
|
296
328
|
}
|
|
297
329
|
function resolveReExportedType(name, file, project, seen) {
|
|
298
|
-
const
|
|
299
|
-
if (seen.has(
|
|
300
|
-
seen.add(
|
|
330
|
+
const visit = `${file.getFilePath()}#${name}`;
|
|
331
|
+
if (seen.has(visit)) return null;
|
|
332
|
+
seen.add(visit);
|
|
301
333
|
for (const exportDecl of file.getExportDeclarations()) {
|
|
302
334
|
const moduleSpecifier = exportDecl.getModuleSpecifierValue();
|
|
303
335
|
const namedExports = exportDecl.getNamedExports();
|
|
@@ -319,7 +351,7 @@ function resolveReExportedType(name, file, project, seen) {
|
|
|
319
351
|
const sourceName = namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ?? name;
|
|
320
352
|
const local = findTypeInFile(sourceName, file);
|
|
321
353
|
if (local) return local;
|
|
322
|
-
const imported = resolveImportedType(sourceName, file, project);
|
|
354
|
+
const imported = resolveImportedType(sourceName, file, project, seen);
|
|
323
355
|
if (imported) return imported;
|
|
324
356
|
}
|
|
325
357
|
return null;
|
|
@@ -3344,32 +3376,86 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
3344
3376
|
return routes;
|
|
3345
3377
|
}
|
|
3346
3378
|
|
|
3347
|
-
// src/generate.ts
|
|
3348
|
-
import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
|
|
3349
|
-
import { dirname as dirname4, join as join13 } from "path";
|
|
3350
|
-
|
|
3351
3379
|
// src/discovery/pages.ts
|
|
3352
3380
|
import { readFile } from "fs/promises";
|
|
3353
|
-
import { join as join3, relative as relative2 } from "path";
|
|
3381
|
+
import { join as join3, relative as relative2, sep as sep2 } from "path";
|
|
3354
3382
|
import fg2 from "fast-glob";
|
|
3355
3383
|
var NON_PAGE_FILE_RE = /\.(?:test|spec|stories|story)\.(?:tsx?|jsx?|vue|svelte)$/i;
|
|
3384
|
+
var MAGIC_SEGMENT_RE = /[*?{}[\]()!]/;
|
|
3385
|
+
function globStaticBase(glob) {
|
|
3386
|
+
const segments = glob.split("/");
|
|
3387
|
+
const staticSegments = [];
|
|
3388
|
+
for (const segment of segments.slice(0, -1)) {
|
|
3389
|
+
if (MAGIC_SEGMENT_RE.test(segment)) break;
|
|
3390
|
+
staticSegments.push(segment);
|
|
3391
|
+
}
|
|
3392
|
+
return staticSegments.join("/");
|
|
3393
|
+
}
|
|
3356
3394
|
async function discoverPages(opts) {
|
|
3357
|
-
const
|
|
3358
|
-
const
|
|
3359
|
-
|
|
3360
|
-
const
|
|
3361
|
-
const pagesBase = join3(opts.cwd, globStatic);
|
|
3395
|
+
const globs = typeof opts.glob === "string" ? [opts.glob] : opts.glob;
|
|
3396
|
+
const prefix = opts.prefix ?? "";
|
|
3397
|
+
const scope = opts.scope ?? "default";
|
|
3398
|
+
const seenFiles = /* @__PURE__ */ new Set();
|
|
3362
3399
|
const out = [];
|
|
3363
|
-
for (const
|
|
3364
|
-
const
|
|
3365
|
-
const
|
|
3366
|
-
const
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3400
|
+
for (const glob of globs) {
|
|
3401
|
+
const files = (await fg2(glob, { cwd: opts.cwd, absolute: true })).filter((f) => !NON_PAGE_FILE_RE.test(f) && !seenFiles.has(f)).sort();
|
|
3402
|
+
const pagesBase = join3(opts.cwd, globStaticBase(glob));
|
|
3403
|
+
for (const file of files) {
|
|
3404
|
+
seenFiles.add(file);
|
|
3405
|
+
const rel = relative2(opts.cwd, file);
|
|
3406
|
+
const nameRel = relative2(pagesBase, file).split(sep2).join("/");
|
|
3407
|
+
const name = `${prefix}${computeName(nameRel, opts.componentNameStrategy)}`;
|
|
3408
|
+
const source = await readFile(file, "utf8");
|
|
3409
|
+
const propsSource = extractPropsSource(source, opts.propsExport);
|
|
3410
|
+
out.push({ name, absolutePath: file, relativePath: rel, propsSource, scope });
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
assertUniqueNames(out);
|
|
3414
|
+
return out;
|
|
3415
|
+
}
|
|
3416
|
+
async function discoverPageScopes(config) {
|
|
3417
|
+
const pages = config.pages;
|
|
3418
|
+
if (!pages) return [];
|
|
3419
|
+
const common = { cwd: config.codegen.cwd, propsExport: pages.propsExport };
|
|
3420
|
+
const out = await discoverPages({
|
|
3421
|
+
...common,
|
|
3422
|
+
glob: pages.glob,
|
|
3423
|
+
componentNameStrategy: pages.componentNameStrategy
|
|
3424
|
+
});
|
|
3425
|
+
for (const [scope, scopeConfig] of Object.entries(pages.scopes ?? {})) {
|
|
3426
|
+
out.push(
|
|
3427
|
+
...await discoverPages({
|
|
3428
|
+
...common,
|
|
3429
|
+
glob: scopeConfig.glob,
|
|
3430
|
+
componentNameStrategy: scopeConfig.componentNameStrategy,
|
|
3431
|
+
prefix: scopeConfig.prefix,
|
|
3432
|
+
scope
|
|
3433
|
+
})
|
|
3434
|
+
);
|
|
3370
3435
|
}
|
|
3436
|
+
assertUniqueNames(out);
|
|
3371
3437
|
return out;
|
|
3372
3438
|
}
|
|
3439
|
+
function allPageGlobs(config) {
|
|
3440
|
+
if (!config.pages) return [];
|
|
3441
|
+
const asList = (glob) => typeof glob === "string" ? [glob] : glob;
|
|
3442
|
+
return [
|
|
3443
|
+
...asList(config.pages.glob),
|
|
3444
|
+
...Object.values(config.pages.scopes ?? {}).flatMap((scope) => asList(scope.glob))
|
|
3445
|
+
];
|
|
3446
|
+
}
|
|
3447
|
+
function assertUniqueNames(pages) {
|
|
3448
|
+
const byName = /* @__PURE__ */ new Map();
|
|
3449
|
+
for (const page of pages) {
|
|
3450
|
+
const previous = byName.get(page.name);
|
|
3451
|
+
if (previous) {
|
|
3452
|
+
throw new Error(
|
|
3453
|
+
`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.`
|
|
3454
|
+
);
|
|
3455
|
+
}
|
|
3456
|
+
byName.set(page.name, page);
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3373
3459
|
function computeName(rel, strat) {
|
|
3374
3460
|
if (typeof strat === "function") return strat(rel);
|
|
3375
3461
|
const noExt = rel.replace(/\.(tsx?|vue|svelte)$/, "");
|
|
@@ -3400,6 +3486,10 @@ function extractPropsSource(source, exportName) {
|
|
|
3400
3486
|
return source.slice(start);
|
|
3401
3487
|
}
|
|
3402
3488
|
|
|
3489
|
+
// src/generate.ts
|
|
3490
|
+
import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
|
|
3491
|
+
import { dirname as dirname4, join as join13 } from "path";
|
|
3492
|
+
|
|
3403
3493
|
// src/discovery/shared-props.ts
|
|
3404
3494
|
import { join as join4 } from "path";
|
|
3405
3495
|
import { Node as Node11, Project as Project4, SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -4034,28 +4124,28 @@ function renderFetcherRequest(req, binaryResponse) {
|
|
|
4034
4124
|
}
|
|
4035
4125
|
function emitReqHelper() {
|
|
4036
4126
|
return [
|
|
4037
|
-
"/**
|
|
4038
|
-
"type
|
|
4039
|
-
"
|
|
4127
|
+
"/** An awaitable request handle: a lazy, memoized `Promise` that also carries `fetch()` and the members extensions add. */",
|
|
4128
|
+
"export type RequestHandle<R, M = {}> = Promise<R> & { fetch(): Promise<R> } & M;",
|
|
4129
|
+
"class __Request<R> extends Promise<R> {",
|
|
4130
|
+
" static override get [Symbol.species](): PromiseConstructor {",
|
|
4131
|
+
" return Promise;",
|
|
4132
|
+
" }",
|
|
4133
|
+
" private __run: () => Promise<R>;",
|
|
4134
|
+
" private __p: Promise<R> | undefined;",
|
|
4135
|
+
" constructor(run: () => Promise<R>) {",
|
|
4136
|
+
" super(() => {});",
|
|
4137
|
+
" this.__run = run;",
|
|
4138
|
+
" }",
|
|
4139
|
+
" override then<T1 = R, T2 = never>(",
|
|
4040
4140
|
" onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,",
|
|
4041
4141
|
" onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,",
|
|
4042
|
-
" ): Promise<T1 | T2
|
|
4043
|
-
"
|
|
4044
|
-
"
|
|
4045
|
-
"
|
|
4046
|
-
"}
|
|
4047
|
-
"function __req<R>(run: () => Promise<R
|
|
4048
|
-
"
|
|
4049
|
-
" const __promise = () => {",
|
|
4050
|
-
" __p ??= run();",
|
|
4051
|
-
" return __p;",
|
|
4052
|
-
" };",
|
|
4053
|
-
" return {",
|
|
4054
|
-
" then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),",
|
|
4055
|
-
" catch: (onrejected) => __promise().catch(onrejected),",
|
|
4056
|
-
" finally: (onfinally) => __promise().finally(onfinally),",
|
|
4057
|
-
" fetch: run,",
|
|
4058
|
-
" };",
|
|
4142
|
+
" ): Promise<T1 | T2> {",
|
|
4143
|
+
" this.__p ??= this.__run();",
|
|
4144
|
+
" return this.__p.then(onfulfilled, onrejected);",
|
|
4145
|
+
" }",
|
|
4146
|
+
"}",
|
|
4147
|
+
"function __req<R, M extends object = {}>(run: () => Promise<R>, members?: M): RequestHandle<R, M> {",
|
|
4148
|
+
" return Object.assign(new __Request<R>(run), { fetch: run }, members) as RequestHandle<R, M>;",
|
|
4059
4149
|
"}",
|
|
4060
4150
|
""
|
|
4061
4151
|
];
|
|
@@ -4073,18 +4163,26 @@ function emitFilterFieldGuard() {
|
|
|
4073
4163
|
];
|
|
4074
4164
|
}
|
|
4075
4165
|
function renderLeaf(pad, objKey, req, requestExpr, members, streamExpr) {
|
|
4076
|
-
const
|
|
4077
|
-
lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4166
|
+
const memberLines = [];
|
|
4078
4167
|
if (req.filterFieldsExpr) {
|
|
4079
|
-
|
|
4168
|
+
memberLines.push(`${pad} filterFields: ${req.filterFieldsExpr},`);
|
|
4080
4169
|
}
|
|
4081
4170
|
if (streamExpr) {
|
|
4082
|
-
|
|
4171
|
+
memberLines.push(`${pad} stream: () => ${streamExpr},`);
|
|
4083
4172
|
}
|
|
4084
4173
|
for (const [name, value] of Object.entries(members)) {
|
|
4085
|
-
|
|
4086
|
-
}
|
|
4087
|
-
|
|
4174
|
+
memberLines.push(`${pad} ${name}: ${value},`);
|
|
4175
|
+
}
|
|
4176
|
+
const body = [requestExpr, ...memberLines].join("\n");
|
|
4177
|
+
const param = /\binput\b/.test(body) ? `input?: ${req.inputType}` : "";
|
|
4178
|
+
const lines = [`${pad}${objKey}: (${param}) =>`];
|
|
4179
|
+
if (memberLines.length === 0) {
|
|
4180
|
+
lines.push(`${pad} __req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4181
|
+
return lines;
|
|
4182
|
+
}
|
|
4183
|
+
lines.push(`${pad} __req(() => ${requestExpr}, {`);
|
|
4184
|
+
lines.push(...memberLines);
|
|
4185
|
+
lines.push(`${pad} }),`);
|
|
4088
4186
|
return lines;
|
|
4089
4187
|
}
|
|
4090
4188
|
function renderStreamExpr(req) {
|
|
@@ -4218,6 +4316,23 @@ var EMPTY_PATH_NAMESPACE = [
|
|
|
4218
4316
|
function isClientCallable(route) {
|
|
4219
4317
|
return route.method.toUpperCase() !== "ALL";
|
|
4220
4318
|
}
|
|
4319
|
+
var ROUTES_IMPORT_PLACEHOLDER = "/* @@routes-import@@ */";
|
|
4320
|
+
var ROUTES_EXPORTS = [
|
|
4321
|
+
// Called, never mentioned in prose: match the call so a comment saying "route" doesn't count.
|
|
4322
|
+
{ name: "route", typeOnly: false },
|
|
4323
|
+
{ name: "ROUTES", typeOnly: false },
|
|
4324
|
+
{ name: "RouteName", typeOnly: true },
|
|
4325
|
+
{ name: "ExtractParams", typeOnly: true },
|
|
4326
|
+
{ name: "RouteParams", typeOnly: true }
|
|
4327
|
+
];
|
|
4328
|
+
function finishRoutesImport(lines) {
|
|
4329
|
+
const body = lines.filter((l) => l !== ROUTES_IMPORT_PLACEHOLDER).join("\n");
|
|
4330
|
+
const used = ROUTES_EXPORTS.filter(
|
|
4331
|
+
({ name }) => new RegExp(name === "route" ? "\\broute\\(" : `\\b${name}\\b`).test(body)
|
|
4332
|
+
).map(({ name, typeOnly }) => typeOnly ? `type ${name}` : name);
|
|
4333
|
+
const importLine = used.length ? `import { ${used.join(", ")} } from './routes.js';` : null;
|
|
4334
|
+
return lines.flatMap((l) => l === ROUTES_IMPORT_PLACEHOLDER ? importLine ? [importLine] : [] : [l]).join("\n");
|
|
4335
|
+
}
|
|
4221
4336
|
function buildApiFile(routes, outDir, opts = {}) {
|
|
4222
4337
|
const fetcherImportPath = opts.fetcherImportPath;
|
|
4223
4338
|
const serialization = opts.serialization ?? "json";
|
|
@@ -4277,9 +4392,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4277
4392
|
for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);
|
|
4278
4393
|
}
|
|
4279
4394
|
lines.push(...extImports);
|
|
4280
|
-
lines.push(
|
|
4281
|
-
"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';"
|
|
4282
|
-
);
|
|
4395
|
+
lines.push(ROUTES_IMPORT_PLACEHOLDER);
|
|
4283
4396
|
const runtimeImport = fetcherImportPath ?? "@dudousxd/nestjs-client";
|
|
4284
4397
|
lines.push(`import type { Fetcher } from '${runtimeImport}';`);
|
|
4285
4398
|
if (serialization === "json" && contracted.length > 0) {
|
|
@@ -4330,7 +4443,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4330
4443
|
lines.push(...statements, "");
|
|
4331
4444
|
}
|
|
4332
4445
|
}
|
|
4333
|
-
return lines
|
|
4446
|
+
return finishRoutesImport(lines);
|
|
4334
4447
|
}
|
|
4335
4448
|
const tree = /* @__PURE__ */ new Map();
|
|
4336
4449
|
for (const r of contracted) {
|
|
@@ -4383,7 +4496,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4383
4496
|
lines.push(...statements, "");
|
|
4384
4497
|
}
|
|
4385
4498
|
}
|
|
4386
|
-
return lines
|
|
4499
|
+
return finishRoutesImport(lines);
|
|
4387
4500
|
}
|
|
4388
4501
|
|
|
4389
4502
|
// src/emit/emit-cache.ts
|
|
@@ -4396,6 +4509,7 @@ async function emitCache(pages, outDir) {
|
|
|
4396
4509
|
const s = await stat(p.absolutePath);
|
|
4397
4510
|
return {
|
|
4398
4511
|
name: p.name,
|
|
4512
|
+
scope: p.scope ?? "default",
|
|
4399
4513
|
relativePath: p.relativePath,
|
|
4400
4514
|
mtime: s.mtime.toISOString()
|
|
4401
4515
|
};
|
|
@@ -5187,10 +5301,11 @@ async function emitPages(pages, outDir, _options = {}) {
|
|
|
5187
5301
|
}).join("\n");
|
|
5188
5302
|
const propsHelper = "\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\n";
|
|
5189
5303
|
const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);
|
|
5304
|
+
const scopesBlock = buildScopesBlock(pages);
|
|
5190
5305
|
const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.
|
|
5191
5306
|
|
|
5192
5307
|
export type InertiaPageName = ${pageNameUnion};
|
|
5193
|
-
${propsHelper}
|
|
5308
|
+
${propsHelper}${scopesBlock}
|
|
5194
5309
|
declare module '@dudousxd/nestjs-inertia' {
|
|
5195
5310
|
interface InertiaPages {
|
|
5196
5311
|
${augBody}
|
|
@@ -5199,6 +5314,31 @@ ${sharedPropsBlock}}
|
|
|
5199
5314
|
`;
|
|
5200
5315
|
await writeFile7(join11(outDir, "pages.d.ts"), content, "utf8");
|
|
5201
5316
|
}
|
|
5317
|
+
function buildScopesBlock(pages) {
|
|
5318
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
5319
|
+
for (const page of pages) {
|
|
5320
|
+
const scope = page.scope ?? "default";
|
|
5321
|
+
const names = byScope.get(scope) ?? [];
|
|
5322
|
+
names.push(JSON.stringify(page.name));
|
|
5323
|
+
byScope.set(scope, names);
|
|
5324
|
+
}
|
|
5325
|
+
if (![...byScope.keys()].some((scope) => scope !== "default")) return "";
|
|
5326
|
+
if (!byScope.has("default")) byScope.set("default", []);
|
|
5327
|
+
const scopes = ["default", ...[...byScope.keys()].filter((s) => s !== "default")];
|
|
5328
|
+
const body = scopes.map((scope) => {
|
|
5329
|
+
const key = needsQuotes(scope) ? JSON.stringify(scope) : scope;
|
|
5330
|
+
const names = byScope.get(scope) ?? [];
|
|
5331
|
+
return ` ${key}: ${names.length ? names.join(" | ") : "never"};`;
|
|
5332
|
+
}).join("\n");
|
|
5333
|
+
return `
|
|
5334
|
+
/** The page names of each Inertia app: \`default\` (forRoot) and every \`pages.scopes\` entry. */
|
|
5335
|
+
export interface InertiaScopePages {
|
|
5336
|
+
${body}
|
|
5337
|
+
}
|
|
5338
|
+
|
|
5339
|
+
export type InertiaScopePageName<S extends keyof InertiaScopePages> = InertiaScopePages[S];
|
|
5340
|
+
`;
|
|
5341
|
+
}
|
|
5202
5342
|
function buildSharedPropsBlock(sharedProps) {
|
|
5203
5343
|
if (!sharedProps) return "";
|
|
5204
5344
|
if (sharedProps.isImportRef) {
|
|
@@ -5380,12 +5520,7 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
|
|
|
5380
5520
|
}
|
|
5381
5521
|
if (config.pages) {
|
|
5382
5522
|
const pagesConfig = config.pages;
|
|
5383
|
-
const pages = await
|
|
5384
|
-
glob: pagesConfig.glob,
|
|
5385
|
-
cwd: config.codegen.cwd,
|
|
5386
|
-
propsExport: pagesConfig.propsExport,
|
|
5387
|
-
componentNameStrategy: pagesConfig.componentNameStrategy
|
|
5388
|
-
});
|
|
5523
|
+
const pages = await discoverPageScopes(config);
|
|
5389
5524
|
const sharedProps = discoverSharedPropsFromConfig(config);
|
|
5390
5525
|
await emitPages(pages, config.codegen.outDir, {
|
|
5391
5526
|
propsExport: pagesConfig.propsExport,
|
|
@@ -5560,12 +5695,17 @@ async function watch(config, onChange, options = {}) {
|
|
|
5560
5695
|
await runInitialPass();
|
|
5561
5696
|
}
|
|
5562
5697
|
let pagesDebounceTimer;
|
|
5563
|
-
const
|
|
5564
|
-
const pagesWatcher = chokidar.watch(
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5698
|
+
const pageGlobs = allPageGlobs(config);
|
|
5699
|
+
const pagesWatcher = chokidar.watch(
|
|
5700
|
+
(pageGlobs.length ? pageGlobs : [".nestjs-codegen-no-pages"]).map(
|
|
5701
|
+
(glob) => join15(config.codegen.cwd, glob)
|
|
5702
|
+
),
|
|
5703
|
+
{
|
|
5704
|
+
ignoreInitial: true,
|
|
5705
|
+
persistent: true,
|
|
5706
|
+
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
5707
|
+
}
|
|
5708
|
+
);
|
|
5569
5709
|
function schedulePagesRegenerate() {
|
|
5570
5710
|
if (pagesDebounceTimer !== void 0) {
|
|
5571
5711
|
clearTimeout(pagesDebounceTimer);
|
|
@@ -5645,7 +5785,7 @@ async function watch(config, onChange, options = {}) {
|
|
|
5645
5785
|
}
|
|
5646
5786
|
|
|
5647
5787
|
// src/index.ts
|
|
5648
|
-
var VERSION = "0.
|
|
5788
|
+
var VERSION = "0.27.1";
|
|
5649
5789
|
|
|
5650
5790
|
// src/generate-manifest.ts
|
|
5651
5791
|
var MANIFEST_FILE = ".codegen-manifest.json";
|
|
@@ -5705,8 +5845,7 @@ function diffConfigKeyHashes(previous, current) {
|
|
|
5705
5845
|
return [...keys].filter((key) => previous[key] !== current[key]).sort();
|
|
5706
5846
|
}
|
|
5707
5847
|
async function discoverInputFiles(config) {
|
|
5708
|
-
const globs = [config.contracts.glob, config.forms.watch];
|
|
5709
|
-
if (config.pages) globs.push(config.pages.glob);
|
|
5848
|
+
const globs = [config.contracts.glob, config.forms.watch, ...allPageGlobs(config)];
|
|
5710
5849
|
const cwd = config.codegen.cwd;
|
|
5711
5850
|
const matched = await fg3(globs, { cwd, absolute: true, onlyFiles: true });
|
|
5712
5851
|
return [...new Set(matched)].sort();
|