@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/cli/main.js
CHANGED
|
@@ -83,12 +83,33 @@ function validateUserConfig(userConfig) {
|
|
|
83
83
|
"validation adapter is required \u2014 install @dudousxd/nestjs-codegen-zod and pass zodAdapter, or use @dudousxd/nestjs-codegen-valibot / -arktype"
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
|
-
if (userConfig.pages &&
|
|
86
|
+
if (userConfig.pages && !isGlobInput(userConfig.pages.glob)) {
|
|
87
87
|
throw new ConfigError(
|
|
88
|
-
"Config validation failed: `pages.glob` must be a string when `pages` is set"
|
|
88
|
+
"Config validation failed: `pages.glob` must be a string or a non-empty array of strings when `pages` is set"
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
for (const [scope, scopeConfig] of Object.entries(userConfig.pages?.scopes ?? {})) {
|
|
92
|
+
if (scope === "default") {
|
|
93
|
+
throw new ConfigError(
|
|
94
|
+
'Config validation failed: `pages.scopes` cannot declare "default" \u2014 the default app is `pages.glob` (InertiaModule.forRoot).'
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (!isGlobInput(scopeConfig?.glob)) {
|
|
98
|
+
throw new ConfigError(
|
|
99
|
+
`Config validation failed: \`pages.scopes.${scope}.glob\` must be a string or a non-empty array of strings`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (userConfig.scopes && Object.keys(userConfig.scopes).length > 0) {
|
|
104
|
+
console.warn(
|
|
105
|
+
"[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)."
|
|
89
106
|
);
|
|
90
107
|
}
|
|
91
108
|
}
|
|
109
|
+
function isGlobInput(value) {
|
|
110
|
+
if (typeof value === "string") return true;
|
|
111
|
+
return Array.isArray(value) && value.length > 0 && value.every((glob) => typeof glob === "string");
|
|
112
|
+
}
|
|
92
113
|
function applyDefaults(userConfig, cwd) {
|
|
93
114
|
validateUserConfig(userConfig);
|
|
94
115
|
const outDir = userConfig.codegen?.outDir ? resolveAbsolute(cwd, userConfig.codegen.outDir) : join(cwd, ".nestjs-codegen");
|
|
@@ -115,7 +136,17 @@ function applyDefaults(userConfig, cwd) {
|
|
|
115
136
|
pages: userConfig.pages ? {
|
|
116
137
|
glob: userConfig.pages.glob,
|
|
117
138
|
propsExport: userConfig.pages.propsExport ?? "ComponentProps",
|
|
118
|
-
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext"
|
|
139
|
+
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext",
|
|
140
|
+
scopes: Object.fromEntries(
|
|
141
|
+
Object.entries(userConfig.pages.scopes ?? {}).map(([scope, scopeConfig]) => [
|
|
142
|
+
scope,
|
|
143
|
+
{
|
|
144
|
+
glob: scopeConfig.glob,
|
|
145
|
+
prefix: scopeConfig.prefix ?? `${scope}/`,
|
|
146
|
+
componentNameStrategy: scopeConfig.componentNameStrategy ?? userConfig.pages?.componentNameStrategy ?? "relative-no-ext"
|
|
147
|
+
}
|
|
148
|
+
])
|
|
149
|
+
)
|
|
119
150
|
} : null,
|
|
120
151
|
contracts: {
|
|
121
152
|
glob: userConfig.contracts?.glob ?? "src/**/*.controller.ts",
|
|
@@ -189,26 +220,84 @@ import { dirname as dirname4, join as join14 } from "path";
|
|
|
189
220
|
|
|
190
221
|
// src/discovery/pages.ts
|
|
191
222
|
import { readFile } from "fs/promises";
|
|
192
|
-
import { join as join2, relative as relative2 } from "path";
|
|
223
|
+
import { join as join2, relative as relative2, sep as sep2 } from "path";
|
|
193
224
|
import fg from "fast-glob";
|
|
194
225
|
var NON_PAGE_FILE_RE = /\.(?:test|spec|stories|story)\.(?:tsx?|jsx?|vue|svelte)$/i;
|
|
226
|
+
var MAGIC_SEGMENT_RE = /[*?{}[\]()!]/;
|
|
227
|
+
function globStaticBase(glob) {
|
|
228
|
+
const segments = glob.split("/");
|
|
229
|
+
const staticSegments = [];
|
|
230
|
+
for (const segment of segments.slice(0, -1)) {
|
|
231
|
+
if (MAGIC_SEGMENT_RE.test(segment)) break;
|
|
232
|
+
staticSegments.push(segment);
|
|
233
|
+
}
|
|
234
|
+
return staticSegments.join("/");
|
|
235
|
+
}
|
|
195
236
|
async function discoverPages(opts) {
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
const pagesBase = join2(opts.cwd, globStatic);
|
|
237
|
+
const globs = typeof opts.glob === "string" ? [opts.glob] : opts.glob;
|
|
238
|
+
const prefix = opts.prefix ?? "";
|
|
239
|
+
const scope = opts.scope ?? "default";
|
|
240
|
+
const seenFiles = /* @__PURE__ */ new Set();
|
|
201
241
|
const out = [];
|
|
202
|
-
for (const
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
242
|
+
for (const glob of globs) {
|
|
243
|
+
const files = (await fg(glob, { cwd: opts.cwd, absolute: true })).filter((f) => !NON_PAGE_FILE_RE.test(f) && !seenFiles.has(f)).sort();
|
|
244
|
+
const pagesBase = join2(opts.cwd, globStaticBase(glob));
|
|
245
|
+
for (const file of files) {
|
|
246
|
+
seenFiles.add(file);
|
|
247
|
+
const rel = relative2(opts.cwd, file);
|
|
248
|
+
const nameRel = relative2(pagesBase, file).split(sep2).join("/");
|
|
249
|
+
const name = `${prefix}${computeName(nameRel, opts.componentNameStrategy)}`;
|
|
250
|
+
const source = await readFile(file, "utf8");
|
|
251
|
+
const propsSource = extractPropsSource(source, opts.propsExport);
|
|
252
|
+
out.push({ name, absolutePath: file, relativePath: rel, propsSource, scope });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
assertUniqueNames(out);
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
258
|
+
async function discoverPageScopes(config) {
|
|
259
|
+
const pages = config.pages;
|
|
260
|
+
if (!pages) return [];
|
|
261
|
+
const common = { cwd: config.codegen.cwd, propsExport: pages.propsExport };
|
|
262
|
+
const out = await discoverPages({
|
|
263
|
+
...common,
|
|
264
|
+
glob: pages.glob,
|
|
265
|
+
componentNameStrategy: pages.componentNameStrategy
|
|
266
|
+
});
|
|
267
|
+
for (const [scope, scopeConfig] of Object.entries(pages.scopes ?? {})) {
|
|
268
|
+
out.push(
|
|
269
|
+
...await discoverPages({
|
|
270
|
+
...common,
|
|
271
|
+
glob: scopeConfig.glob,
|
|
272
|
+
componentNameStrategy: scopeConfig.componentNameStrategy,
|
|
273
|
+
prefix: scopeConfig.prefix,
|
|
274
|
+
scope
|
|
275
|
+
})
|
|
276
|
+
);
|
|
209
277
|
}
|
|
278
|
+
assertUniqueNames(out);
|
|
210
279
|
return out;
|
|
211
280
|
}
|
|
281
|
+
function allPageGlobs(config) {
|
|
282
|
+
if (!config.pages) return [];
|
|
283
|
+
const asList = (glob) => typeof glob === "string" ? [glob] : glob;
|
|
284
|
+
return [
|
|
285
|
+
...asList(config.pages.glob),
|
|
286
|
+
...Object.values(config.pages.scopes ?? {}).flatMap((scope) => asList(scope.glob))
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
function assertUniqueNames(pages) {
|
|
290
|
+
const byName = /* @__PURE__ */ new Map();
|
|
291
|
+
for (const page of pages) {
|
|
292
|
+
const previous = byName.get(page.name);
|
|
293
|
+
if (previous) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
`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.`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
byName.set(page.name, page);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
212
301
|
function computeName(rel, strat) {
|
|
213
302
|
if (typeof strat === "function") return strat(rel);
|
|
214
303
|
const noExt = rel.replace(/\.(tsx?|vue|svelte)$/, "");
|
|
@@ -631,10 +720,11 @@ function resolveModuleSpecifier(moduleSpecifier, sourceFile, project) {
|
|
|
631
720
|
}
|
|
632
721
|
return [];
|
|
633
722
|
}
|
|
634
|
-
function resolveImportedType(name, sourceFile, project) {
|
|
723
|
+
function resolveImportedType(name, sourceFile, project, seen = /* @__PURE__ */ new Set()) {
|
|
635
724
|
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
636
|
-
const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);
|
|
725
|
+
const namedImport = importDecl.getNamedImports().find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name);
|
|
637
726
|
if (!namedImport) continue;
|
|
727
|
+
const sourceName = namedImport.getName();
|
|
638
728
|
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
639
729
|
const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);
|
|
640
730
|
for (const candidate of candidates) {
|
|
@@ -646,17 +736,17 @@ function resolveImportedType(name, sourceFile, project) {
|
|
|
646
736
|
continue;
|
|
647
737
|
}
|
|
648
738
|
}
|
|
649
|
-
const result = findTypeInFile(
|
|
739
|
+
const result = findTypeInFile(sourceName, importedFile);
|
|
650
740
|
if (result) return result;
|
|
651
|
-
const viaReExport = resolveReExportedType(
|
|
741
|
+
const viaReExport = resolveReExportedType(sourceName, importedFile, project, /* @__PURE__ */ new Set());
|
|
652
742
|
if (viaReExport) return viaReExport;
|
|
653
743
|
}
|
|
654
744
|
if (candidates.length === 0) {
|
|
655
|
-
const viaCompiler = resolveBareSpecifierType(
|
|
745
|
+
const viaCompiler = resolveBareSpecifierType(sourceName, importDecl, project);
|
|
656
746
|
if (viaCompiler) return viaCompiler;
|
|
657
747
|
}
|
|
658
748
|
}
|
|
659
|
-
return resolveReExportedType(name, sourceFile, project,
|
|
749
|
+
return resolveReExportedType(name, sourceFile, project, seen);
|
|
660
750
|
}
|
|
661
751
|
function resolveBareSpecifierType(name, importDecl, project) {
|
|
662
752
|
let target;
|
|
@@ -671,9 +761,9 @@ function resolveBareSpecifierType(name, importDecl, project) {
|
|
|
671
761
|
return resolveReExportedType(name, target, project, /* @__PURE__ */ new Set());
|
|
672
762
|
}
|
|
673
763
|
function resolveReExportedType(name, file, project, seen) {
|
|
674
|
-
const
|
|
675
|
-
if (seen.has(
|
|
676
|
-
seen.add(
|
|
764
|
+
const visit = `${file.getFilePath()}#${name}`;
|
|
765
|
+
if (seen.has(visit)) return null;
|
|
766
|
+
seen.add(visit);
|
|
677
767
|
for (const exportDecl of file.getExportDeclarations()) {
|
|
678
768
|
const moduleSpecifier = exportDecl.getModuleSpecifierValue();
|
|
679
769
|
const namedExports = exportDecl.getNamedExports();
|
|
@@ -695,7 +785,7 @@ function resolveReExportedType(name, file, project, seen) {
|
|
|
695
785
|
const sourceName = namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ?? name;
|
|
696
786
|
const local = findTypeInFile(sourceName, file);
|
|
697
787
|
if (local) return local;
|
|
698
|
-
const imported = resolveImportedType(sourceName, file, project);
|
|
788
|
+
const imported = resolveImportedType(sourceName, file, project, seen);
|
|
699
789
|
if (imported) return imported;
|
|
700
790
|
}
|
|
701
791
|
return null;
|
|
@@ -4097,28 +4187,28 @@ function renderFetcherRequest(req, binaryResponse) {
|
|
|
4097
4187
|
}
|
|
4098
4188
|
function emitReqHelper() {
|
|
4099
4189
|
return [
|
|
4100
|
-
"/**
|
|
4101
|
-
"type
|
|
4102
|
-
"
|
|
4190
|
+
"/** An awaitable request handle: a lazy, memoized `Promise` that also carries `fetch()` and the members extensions add. */",
|
|
4191
|
+
"export type RequestHandle<R, M = {}> = Promise<R> & { fetch(): Promise<R> } & M;",
|
|
4192
|
+
"class __Request<R> extends Promise<R> {",
|
|
4193
|
+
" static override get [Symbol.species](): PromiseConstructor {",
|
|
4194
|
+
" return Promise;",
|
|
4195
|
+
" }",
|
|
4196
|
+
" private __run: () => Promise<R>;",
|
|
4197
|
+
" private __p: Promise<R> | undefined;",
|
|
4198
|
+
" constructor(run: () => Promise<R>) {",
|
|
4199
|
+
" super(() => {});",
|
|
4200
|
+
" this.__run = run;",
|
|
4201
|
+
" }",
|
|
4202
|
+
" override then<T1 = R, T2 = never>(",
|
|
4103
4203
|
" onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,",
|
|
4104
4204
|
" onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,",
|
|
4105
|
-
" ): Promise<T1 | T2
|
|
4106
|
-
"
|
|
4107
|
-
"
|
|
4108
|
-
"
|
|
4109
|
-
"}
|
|
4110
|
-
"function __req<R>(run: () => Promise<R
|
|
4111
|
-
"
|
|
4112
|
-
" const __promise = () => {",
|
|
4113
|
-
" __p ??= run();",
|
|
4114
|
-
" return __p;",
|
|
4115
|
-
" };",
|
|
4116
|
-
" return {",
|
|
4117
|
-
" then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),",
|
|
4118
|
-
" catch: (onrejected) => __promise().catch(onrejected),",
|
|
4119
|
-
" finally: (onfinally) => __promise().finally(onfinally),",
|
|
4120
|
-
" fetch: run,",
|
|
4121
|
-
" };",
|
|
4205
|
+
" ): Promise<T1 | T2> {",
|
|
4206
|
+
" this.__p ??= this.__run();",
|
|
4207
|
+
" return this.__p.then(onfulfilled, onrejected);",
|
|
4208
|
+
" }",
|
|
4209
|
+
"}",
|
|
4210
|
+
"function __req<R, M extends object = {}>(run: () => Promise<R>, members?: M): RequestHandle<R, M> {",
|
|
4211
|
+
" return Object.assign(new __Request<R>(run), { fetch: run }, members) as RequestHandle<R, M>;",
|
|
4122
4212
|
"}",
|
|
4123
4213
|
""
|
|
4124
4214
|
];
|
|
@@ -4136,18 +4226,26 @@ function emitFilterFieldGuard() {
|
|
|
4136
4226
|
];
|
|
4137
4227
|
}
|
|
4138
4228
|
function renderLeaf(pad, objKey, req, requestExpr, members, streamExpr) {
|
|
4139
|
-
const
|
|
4140
|
-
lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4229
|
+
const memberLines = [];
|
|
4141
4230
|
if (req.filterFieldsExpr) {
|
|
4142
|
-
|
|
4231
|
+
memberLines.push(`${pad} filterFields: ${req.filterFieldsExpr},`);
|
|
4143
4232
|
}
|
|
4144
4233
|
if (streamExpr) {
|
|
4145
|
-
|
|
4234
|
+
memberLines.push(`${pad} stream: () => ${streamExpr},`);
|
|
4146
4235
|
}
|
|
4147
4236
|
for (const [name, value] of Object.entries(members)) {
|
|
4148
|
-
|
|
4149
|
-
}
|
|
4150
|
-
|
|
4237
|
+
memberLines.push(`${pad} ${name}: ${value},`);
|
|
4238
|
+
}
|
|
4239
|
+
const body = [requestExpr, ...memberLines].join("\n");
|
|
4240
|
+
const param = /\binput\b/.test(body) ? `input?: ${req.inputType}` : "";
|
|
4241
|
+
const lines = [`${pad}${objKey}: (${param}) =>`];
|
|
4242
|
+
if (memberLines.length === 0) {
|
|
4243
|
+
lines.push(`${pad} __req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4244
|
+
return lines;
|
|
4245
|
+
}
|
|
4246
|
+
lines.push(`${pad} __req(() => ${requestExpr}, {`);
|
|
4247
|
+
lines.push(...memberLines);
|
|
4248
|
+
lines.push(`${pad} }),`);
|
|
4151
4249
|
return lines;
|
|
4152
4250
|
}
|
|
4153
4251
|
function renderStreamExpr(req) {
|
|
@@ -4281,6 +4379,23 @@ var EMPTY_PATH_NAMESPACE = [
|
|
|
4281
4379
|
function isClientCallable(route) {
|
|
4282
4380
|
return route.method.toUpperCase() !== "ALL";
|
|
4283
4381
|
}
|
|
4382
|
+
var ROUTES_IMPORT_PLACEHOLDER = "/* @@routes-import@@ */";
|
|
4383
|
+
var ROUTES_EXPORTS = [
|
|
4384
|
+
// Called, never mentioned in prose: match the call so a comment saying "route" doesn't count.
|
|
4385
|
+
{ name: "route", typeOnly: false },
|
|
4386
|
+
{ name: "ROUTES", typeOnly: false },
|
|
4387
|
+
{ name: "RouteName", typeOnly: true },
|
|
4388
|
+
{ name: "ExtractParams", typeOnly: true },
|
|
4389
|
+
{ name: "RouteParams", typeOnly: true }
|
|
4390
|
+
];
|
|
4391
|
+
function finishRoutesImport(lines) {
|
|
4392
|
+
const body = lines.filter((l) => l !== ROUTES_IMPORT_PLACEHOLDER).join("\n");
|
|
4393
|
+
const used = ROUTES_EXPORTS.filter(
|
|
4394
|
+
({ name }) => new RegExp(name === "route" ? "\\broute\\(" : `\\b${name}\\b`).test(body)
|
|
4395
|
+
).map(({ name, typeOnly }) => typeOnly ? `type ${name}` : name);
|
|
4396
|
+
const importLine = used.length ? `import { ${used.join(", ")} } from './routes.js';` : null;
|
|
4397
|
+
return lines.flatMap((l) => l === ROUTES_IMPORT_PLACEHOLDER ? importLine ? [importLine] : [] : [l]).join("\n");
|
|
4398
|
+
}
|
|
4284
4399
|
function buildApiFile(routes, outDir, opts = {}) {
|
|
4285
4400
|
const fetcherImportPath = opts.fetcherImportPath;
|
|
4286
4401
|
const serialization = opts.serialization ?? "json";
|
|
@@ -4340,9 +4455,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4340
4455
|
for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);
|
|
4341
4456
|
}
|
|
4342
4457
|
lines.push(...extImports);
|
|
4343
|
-
lines.push(
|
|
4344
|
-
"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';"
|
|
4345
|
-
);
|
|
4458
|
+
lines.push(ROUTES_IMPORT_PLACEHOLDER);
|
|
4346
4459
|
const runtimeImport = fetcherImportPath ?? "@dudousxd/nestjs-client";
|
|
4347
4460
|
lines.push(`import type { Fetcher } from '${runtimeImport}';`);
|
|
4348
4461
|
if (serialization === "json" && contracted.length > 0) {
|
|
@@ -4393,7 +4506,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4393
4506
|
lines.push(...statements, "");
|
|
4394
4507
|
}
|
|
4395
4508
|
}
|
|
4396
|
-
return lines
|
|
4509
|
+
return finishRoutesImport(lines);
|
|
4397
4510
|
}
|
|
4398
4511
|
const tree = /* @__PURE__ */ new Map();
|
|
4399
4512
|
for (const r of contracted) {
|
|
@@ -4446,7 +4559,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4446
4559
|
lines.push(...statements, "");
|
|
4447
4560
|
}
|
|
4448
4561
|
}
|
|
4449
|
-
return lines
|
|
4562
|
+
return finishRoutesImport(lines);
|
|
4450
4563
|
}
|
|
4451
4564
|
|
|
4452
4565
|
// src/emit/emit-cache.ts
|
|
@@ -4459,6 +4572,7 @@ async function emitCache(pages, outDir) {
|
|
|
4459
4572
|
const s = await stat(p.absolutePath);
|
|
4460
4573
|
return {
|
|
4461
4574
|
name: p.name,
|
|
4575
|
+
scope: p.scope ?? "default",
|
|
4462
4576
|
relativePath: p.relativePath,
|
|
4463
4577
|
mtime: s.mtime.toISOString()
|
|
4464
4578
|
};
|
|
@@ -5250,10 +5364,11 @@ async function emitPages(pages, outDir, _options = {}) {
|
|
|
5250
5364
|
}).join("\n");
|
|
5251
5365
|
const propsHelper = "\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\n";
|
|
5252
5366
|
const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);
|
|
5367
|
+
const scopesBlock = buildScopesBlock(pages);
|
|
5253
5368
|
const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.
|
|
5254
5369
|
|
|
5255
5370
|
export type InertiaPageName = ${pageNameUnion};
|
|
5256
|
-
${propsHelper}
|
|
5371
|
+
${propsHelper}${scopesBlock}
|
|
5257
5372
|
declare module '@dudousxd/nestjs-inertia' {
|
|
5258
5373
|
interface InertiaPages {
|
|
5259
5374
|
${augBody}
|
|
@@ -5262,6 +5377,31 @@ ${sharedPropsBlock}}
|
|
|
5262
5377
|
`;
|
|
5263
5378
|
await writeFile7(join11(outDir, "pages.d.ts"), content, "utf8");
|
|
5264
5379
|
}
|
|
5380
|
+
function buildScopesBlock(pages) {
|
|
5381
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
5382
|
+
for (const page of pages) {
|
|
5383
|
+
const scope = page.scope ?? "default";
|
|
5384
|
+
const names = byScope.get(scope) ?? [];
|
|
5385
|
+
names.push(JSON.stringify(page.name));
|
|
5386
|
+
byScope.set(scope, names);
|
|
5387
|
+
}
|
|
5388
|
+
if (![...byScope.keys()].some((scope) => scope !== "default")) return "";
|
|
5389
|
+
if (!byScope.has("default")) byScope.set("default", []);
|
|
5390
|
+
const scopes = ["default", ...[...byScope.keys()].filter((s) => s !== "default")];
|
|
5391
|
+
const body = scopes.map((scope) => {
|
|
5392
|
+
const key = needsQuotes(scope) ? JSON.stringify(scope) : scope;
|
|
5393
|
+
const names = byScope.get(scope) ?? [];
|
|
5394
|
+
return ` ${key}: ${names.length ? names.join(" | ") : "never"};`;
|
|
5395
|
+
}).join("\n");
|
|
5396
|
+
return `
|
|
5397
|
+
/** The page names of each Inertia app: \`default\` (forRoot) and every \`pages.scopes\` entry. */
|
|
5398
|
+
export interface InertiaScopePages {
|
|
5399
|
+
${body}
|
|
5400
|
+
}
|
|
5401
|
+
|
|
5402
|
+
export type InertiaScopePageName<S extends keyof InertiaScopePages> = InertiaScopePages[S];
|
|
5403
|
+
`;
|
|
5404
|
+
}
|
|
5265
5405
|
function buildSharedPropsBlock(sharedProps) {
|
|
5266
5406
|
if (!sharedProps) return "";
|
|
5267
5407
|
if (sharedProps.isImportRef) {
|
|
@@ -5469,8 +5609,7 @@ function diffConfigKeyHashes(previous, current) {
|
|
|
5469
5609
|
return [...keys].filter((key) => previous[key] !== current[key]).sort();
|
|
5470
5610
|
}
|
|
5471
5611
|
async function discoverInputFiles(config) {
|
|
5472
|
-
const globs = [config.contracts.glob, config.forms.watch];
|
|
5473
|
-
if (config.pages) globs.push(config.pages.glob);
|
|
5612
|
+
const globs = [config.contracts.glob, config.forms.watch, ...allPageGlobs(config)];
|
|
5474
5613
|
const cwd = config.codegen.cwd;
|
|
5475
5614
|
const matched = await fg3(globs, { cwd, absolute: true, onlyFiles: true });
|
|
5476
5615
|
return [...new Set(matched)].sort();
|
|
@@ -5601,12 +5740,7 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
|
|
|
5601
5740
|
}
|
|
5602
5741
|
if (config.pages) {
|
|
5603
5742
|
const pagesConfig = config.pages;
|
|
5604
|
-
const pages = await
|
|
5605
|
-
glob: pagesConfig.glob,
|
|
5606
|
-
cwd: config.codegen.cwd,
|
|
5607
|
-
propsExport: pagesConfig.propsExport,
|
|
5608
|
-
componentNameStrategy: pagesConfig.componentNameStrategy
|
|
5609
|
-
});
|
|
5743
|
+
const pages = await discoverPageScopes(config);
|
|
5610
5744
|
const sharedProps = discoverSharedPropsFromConfig(config);
|
|
5611
5745
|
await emitPages(pages, config.codegen.outDir, {
|
|
5612
5746
|
propsExport: pagesConfig.propsExport,
|
|
@@ -5781,12 +5915,17 @@ async function watch(config, onChange, options = {}) {
|
|
|
5781
5915
|
await runInitialPass();
|
|
5782
5916
|
}
|
|
5783
5917
|
let pagesDebounceTimer;
|
|
5784
|
-
const
|
|
5785
|
-
const pagesWatcher = chokidar.watch(
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5918
|
+
const pageGlobs = allPageGlobs(config);
|
|
5919
|
+
const pagesWatcher = chokidar.watch(
|
|
5920
|
+
(pageGlobs.length ? pageGlobs : [".nestjs-codegen-no-pages"]).map(
|
|
5921
|
+
(glob) => join16(config.codegen.cwd, glob)
|
|
5922
|
+
),
|
|
5923
|
+
{
|
|
5924
|
+
ignoreInitial: true,
|
|
5925
|
+
persistent: true,
|
|
5926
|
+
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
5927
|
+
}
|
|
5928
|
+
);
|
|
5790
5929
|
function schedulePagesRegenerate() {
|
|
5791
5930
|
if (pagesDebounceTimer !== void 0) {
|
|
5792
5931
|
clearTimeout(pagesDebounceTimer);
|
|
@@ -5866,7 +6005,7 @@ async function watch(config, onChange, options = {}) {
|
|
|
5866
6005
|
}
|
|
5867
6006
|
|
|
5868
6007
|
// src/index.ts
|
|
5869
|
-
var VERSION = "0.
|
|
6008
|
+
var VERSION = "0.27.1";
|
|
5870
6009
|
|
|
5871
6010
|
// src/cli/codegen.ts
|
|
5872
6011
|
async function runCodegen(opts = {}) {
|