@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/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-
|
|
2
|
-
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-
|
|
1
|
+
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-Dc4s883u.cjs';
|
|
2
|
+
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-Dc4s883u.cjs';
|
|
3
3
|
import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
declare function defineConfig(c: UserConfig): UserConfig;
|
|
@@ -382,6 +382,6 @@ interface FastDiscoveryOptions {
|
|
|
382
382
|
}
|
|
383
383
|
declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
|
|
384
384
|
|
|
385
|
-
declare const VERSION = "0.
|
|
385
|
+
declare const VERSION = "0.27.1";
|
|
386
386
|
|
|
387
387
|
export { type ChainModuleRendererOptions, CodegenError, type CodegenManifest, ConfigError, DriftGuardError, type EntryPoint, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type WatchOptions, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-
|
|
2
|
-
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-
|
|
1
|
+
import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as RenderContext, c as SchemaModule, d as RenderedModule, e as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext, f as SerializationMode } from './index-Dc4s883u.js';
|
|
2
|
+
export { A as AdapterUsage, g as ContractDescriptor, h as ContractSource, i as ControllerRef, N as NumberCheck, j as ScopeConfig, k as StringCheck, T as TypeRef, l as ValidationOption, r as resolveAdapter } from './index-Dc4s883u.js';
|
|
3
3
|
import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
declare function defineConfig(c: UserConfig): UserConfig;
|
|
@@ -382,6 +382,6 @@ interface FastDiscoveryOptions {
|
|
|
382
382
|
}
|
|
383
383
|
declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
|
|
384
384
|
|
|
385
|
-
declare const VERSION = "0.
|
|
385
|
+
declare const VERSION = "0.27.1";
|
|
386
386
|
|
|
387
387
|
export { type ChainModuleRendererOptions, CodegenError, type CodegenManifest, ConfigError, DriftGuardError, type EntryPoint, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type WatchOptions, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
|
package/dist/index.js
CHANGED
|
@@ -88,12 +88,33 @@ function validateUserConfig(userConfig) {
|
|
|
88
88
|
"validation adapter is required \u2014 install @dudousxd/nestjs-codegen-zod and pass zodAdapter, or use @dudousxd/nestjs-codegen-valibot / -arktype"
|
|
89
89
|
);
|
|
90
90
|
}
|
|
91
|
-
if (userConfig.pages &&
|
|
91
|
+
if (userConfig.pages && !isGlobInput(userConfig.pages.glob)) {
|
|
92
92
|
throw new ConfigError(
|
|
93
|
-
"Config validation failed: `pages.glob` must be a string when `pages` is set"
|
|
93
|
+
"Config validation failed: `pages.glob` must be a string or a non-empty array of strings when `pages` is set"
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
for (const [scope, scopeConfig] of Object.entries(userConfig.pages?.scopes ?? {})) {
|
|
97
|
+
if (scope === "default") {
|
|
98
|
+
throw new ConfigError(
|
|
99
|
+
'Config validation failed: `pages.scopes` cannot declare "default" \u2014 the default app is `pages.glob` (InertiaModule.forRoot).'
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
if (!isGlobInput(scopeConfig?.glob)) {
|
|
103
|
+
throw new ConfigError(
|
|
104
|
+
`Config validation failed: \`pages.scopes.${scope}.glob\` must be a string or a non-empty array of strings`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (userConfig.scopes && Object.keys(userConfig.scopes).length > 0) {
|
|
109
|
+
console.warn(
|
|
110
|
+
"[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)."
|
|
94
111
|
);
|
|
95
112
|
}
|
|
96
113
|
}
|
|
114
|
+
function isGlobInput(value) {
|
|
115
|
+
if (typeof value === "string") return true;
|
|
116
|
+
return Array.isArray(value) && value.length > 0 && value.every((glob) => typeof glob === "string");
|
|
117
|
+
}
|
|
97
118
|
function applyDefaults(userConfig, cwd) {
|
|
98
119
|
validateUserConfig(userConfig);
|
|
99
120
|
const outDir = userConfig.codegen?.outDir ? resolveAbsolute(cwd, userConfig.codegen.outDir) : join(cwd, ".nestjs-codegen");
|
|
@@ -120,7 +141,17 @@ function applyDefaults(userConfig, cwd) {
|
|
|
120
141
|
pages: userConfig.pages ? {
|
|
121
142
|
glob: userConfig.pages.glob,
|
|
122
143
|
propsExport: userConfig.pages.propsExport ?? "ComponentProps",
|
|
123
|
-
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext"
|
|
144
|
+
componentNameStrategy: userConfig.pages.componentNameStrategy ?? "relative-no-ext",
|
|
145
|
+
scopes: Object.fromEntries(
|
|
146
|
+
Object.entries(userConfig.pages.scopes ?? {}).map(([scope, scopeConfig]) => [
|
|
147
|
+
scope,
|
|
148
|
+
{
|
|
149
|
+
glob: scopeConfig.glob,
|
|
150
|
+
prefix: scopeConfig.prefix ?? `${scope}/`,
|
|
151
|
+
componentNameStrategy: scopeConfig.componentNameStrategy ?? userConfig.pages?.componentNameStrategy ?? "relative-no-ext"
|
|
152
|
+
}
|
|
153
|
+
])
|
|
154
|
+
)
|
|
124
155
|
} : null,
|
|
125
156
|
contracts: {
|
|
126
157
|
glob: userConfig.contracts?.glob ?? "src/**/*.controller.ts",
|
|
@@ -194,26 +225,84 @@ import { dirname as dirname4, join as join14 } from "path";
|
|
|
194
225
|
|
|
195
226
|
// src/discovery/pages.ts
|
|
196
227
|
import { readFile } from "fs/promises";
|
|
197
|
-
import { join as join2, relative as relative2 } from "path";
|
|
228
|
+
import { join as join2, relative as relative2, sep as sep2 } from "path";
|
|
198
229
|
import fg from "fast-glob";
|
|
199
230
|
var NON_PAGE_FILE_RE = /\.(?:test|spec|stories|story)\.(?:tsx?|jsx?|vue|svelte)$/i;
|
|
231
|
+
var MAGIC_SEGMENT_RE = /[*?{}[\]()!]/;
|
|
232
|
+
function globStaticBase(glob) {
|
|
233
|
+
const segments = glob.split("/");
|
|
234
|
+
const staticSegments = [];
|
|
235
|
+
for (const segment of segments.slice(0, -1)) {
|
|
236
|
+
if (MAGIC_SEGMENT_RE.test(segment)) break;
|
|
237
|
+
staticSegments.push(segment);
|
|
238
|
+
}
|
|
239
|
+
return staticSegments.join("/");
|
|
240
|
+
}
|
|
200
241
|
async function discoverPages(opts) {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
const pagesBase = join2(opts.cwd, globStatic);
|
|
242
|
+
const globs = typeof opts.glob === "string" ? [opts.glob] : opts.glob;
|
|
243
|
+
const prefix = opts.prefix ?? "";
|
|
244
|
+
const scope = opts.scope ?? "default";
|
|
245
|
+
const seenFiles = /* @__PURE__ */ new Set();
|
|
206
246
|
const out = [];
|
|
207
|
-
for (const
|
|
208
|
-
const
|
|
209
|
-
const
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
247
|
+
for (const glob of globs) {
|
|
248
|
+
const files = (await fg(glob, { cwd: opts.cwd, absolute: true })).filter((f) => !NON_PAGE_FILE_RE.test(f) && !seenFiles.has(f)).sort();
|
|
249
|
+
const pagesBase = join2(opts.cwd, globStaticBase(glob));
|
|
250
|
+
for (const file of files) {
|
|
251
|
+
seenFiles.add(file);
|
|
252
|
+
const rel = relative2(opts.cwd, file);
|
|
253
|
+
const nameRel = relative2(pagesBase, file).split(sep2).join("/");
|
|
254
|
+
const name = `${prefix}${computeName(nameRel, opts.componentNameStrategy)}`;
|
|
255
|
+
const source = await readFile(file, "utf8");
|
|
256
|
+
const propsSource = extractPropsSource(source, opts.propsExport);
|
|
257
|
+
out.push({ name, absolutePath: file, relativePath: rel, propsSource, scope });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
assertUniqueNames(out);
|
|
261
|
+
return out;
|
|
262
|
+
}
|
|
263
|
+
async function discoverPageScopes(config) {
|
|
264
|
+
const pages = config.pages;
|
|
265
|
+
if (!pages) return [];
|
|
266
|
+
const common = { cwd: config.codegen.cwd, propsExport: pages.propsExport };
|
|
267
|
+
const out = await discoverPages({
|
|
268
|
+
...common,
|
|
269
|
+
glob: pages.glob,
|
|
270
|
+
componentNameStrategy: pages.componentNameStrategy
|
|
271
|
+
});
|
|
272
|
+
for (const [scope, scopeConfig] of Object.entries(pages.scopes ?? {})) {
|
|
273
|
+
out.push(
|
|
274
|
+
...await discoverPages({
|
|
275
|
+
...common,
|
|
276
|
+
glob: scopeConfig.glob,
|
|
277
|
+
componentNameStrategy: scopeConfig.componentNameStrategy,
|
|
278
|
+
prefix: scopeConfig.prefix,
|
|
279
|
+
scope
|
|
280
|
+
})
|
|
281
|
+
);
|
|
214
282
|
}
|
|
283
|
+
assertUniqueNames(out);
|
|
215
284
|
return out;
|
|
216
285
|
}
|
|
286
|
+
function allPageGlobs(config) {
|
|
287
|
+
if (!config.pages) return [];
|
|
288
|
+
const asList = (glob) => typeof glob === "string" ? [glob] : glob;
|
|
289
|
+
return [
|
|
290
|
+
...asList(config.pages.glob),
|
|
291
|
+
...Object.values(config.pages.scopes ?? {}).flatMap((scope) => asList(scope.glob))
|
|
292
|
+
];
|
|
293
|
+
}
|
|
294
|
+
function assertUniqueNames(pages) {
|
|
295
|
+
const byName = /* @__PURE__ */ new Map();
|
|
296
|
+
for (const page of pages) {
|
|
297
|
+
const previous = byName.get(page.name);
|
|
298
|
+
if (previous) {
|
|
299
|
+
throw new Error(
|
|
300
|
+
`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.`
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
byName.set(page.name, page);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
217
306
|
function computeName(rel, strat) {
|
|
218
307
|
if (typeof strat === "function") return strat(rel);
|
|
219
308
|
const noExt = rel.replace(/\.(tsx?|vue|svelte)$/, "");
|
|
@@ -636,10 +725,11 @@ function resolveModuleSpecifier(moduleSpecifier, sourceFile, project) {
|
|
|
636
725
|
}
|
|
637
726
|
return [];
|
|
638
727
|
}
|
|
639
|
-
function resolveImportedType(name, sourceFile, project) {
|
|
728
|
+
function resolveImportedType(name, sourceFile, project, seen = /* @__PURE__ */ new Set()) {
|
|
640
729
|
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
641
|
-
const namedImport = importDecl.getNamedImports().find((n) => n.getName() === name);
|
|
730
|
+
const namedImport = importDecl.getNamedImports().find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name);
|
|
642
731
|
if (!namedImport) continue;
|
|
732
|
+
const sourceName = namedImport.getName();
|
|
643
733
|
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
644
734
|
const candidates = resolveModuleSpecifier(moduleSpecifier, sourceFile, project);
|
|
645
735
|
for (const candidate of candidates) {
|
|
@@ -651,17 +741,17 @@ function resolveImportedType(name, sourceFile, project) {
|
|
|
651
741
|
continue;
|
|
652
742
|
}
|
|
653
743
|
}
|
|
654
|
-
const result = findTypeInFile(
|
|
744
|
+
const result = findTypeInFile(sourceName, importedFile);
|
|
655
745
|
if (result) return result;
|
|
656
|
-
const viaReExport = resolveReExportedType(
|
|
746
|
+
const viaReExport = resolveReExportedType(sourceName, importedFile, project, /* @__PURE__ */ new Set());
|
|
657
747
|
if (viaReExport) return viaReExport;
|
|
658
748
|
}
|
|
659
749
|
if (candidates.length === 0) {
|
|
660
|
-
const viaCompiler = resolveBareSpecifierType(
|
|
750
|
+
const viaCompiler = resolveBareSpecifierType(sourceName, importDecl, project);
|
|
661
751
|
if (viaCompiler) return viaCompiler;
|
|
662
752
|
}
|
|
663
753
|
}
|
|
664
|
-
return resolveReExportedType(name, sourceFile, project,
|
|
754
|
+
return resolveReExportedType(name, sourceFile, project, seen);
|
|
665
755
|
}
|
|
666
756
|
function resolveBareSpecifierType(name, importDecl, project) {
|
|
667
757
|
let target;
|
|
@@ -676,9 +766,9 @@ function resolveBareSpecifierType(name, importDecl, project) {
|
|
|
676
766
|
return resolveReExportedType(name, target, project, /* @__PURE__ */ new Set());
|
|
677
767
|
}
|
|
678
768
|
function resolveReExportedType(name, file, project, seen) {
|
|
679
|
-
const
|
|
680
|
-
if (seen.has(
|
|
681
|
-
seen.add(
|
|
769
|
+
const visit = `${file.getFilePath()}#${name}`;
|
|
770
|
+
if (seen.has(visit)) return null;
|
|
771
|
+
seen.add(visit);
|
|
682
772
|
for (const exportDecl of file.getExportDeclarations()) {
|
|
683
773
|
const moduleSpecifier = exportDecl.getModuleSpecifierValue();
|
|
684
774
|
const namedExports = exportDecl.getNamedExports();
|
|
@@ -700,7 +790,7 @@ function resolveReExportedType(name, file, project, seen) {
|
|
|
700
790
|
const sourceName = namedExports.find((n) => (n.getAliasNode()?.getText() ?? n.getName()) === name)?.getName() ?? name;
|
|
701
791
|
const local = findTypeInFile(sourceName, file);
|
|
702
792
|
if (local) return local;
|
|
703
|
-
const imported = resolveImportedType(sourceName, file, project);
|
|
793
|
+
const imported = resolveImportedType(sourceName, file, project, seen);
|
|
704
794
|
if (imported) return imported;
|
|
705
795
|
}
|
|
706
796
|
return null;
|
|
@@ -4102,28 +4192,28 @@ function renderFetcherRequest(req, binaryResponse) {
|
|
|
4102
4192
|
}
|
|
4103
4193
|
function emitReqHelper() {
|
|
4104
4194
|
return [
|
|
4105
|
-
"/**
|
|
4106
|
-
"type
|
|
4107
|
-
"
|
|
4195
|
+
"/** An awaitable request handle: a lazy, memoized `Promise` that also carries `fetch()` and the members extensions add. */",
|
|
4196
|
+
"export type RequestHandle<R, M = {}> = Promise<R> & { fetch(): Promise<R> } & M;",
|
|
4197
|
+
"class __Request<R> extends Promise<R> {",
|
|
4198
|
+
" static override get [Symbol.species](): PromiseConstructor {",
|
|
4199
|
+
" return Promise;",
|
|
4200
|
+
" }",
|
|
4201
|
+
" private __run: () => Promise<R>;",
|
|
4202
|
+
" private __p: Promise<R> | undefined;",
|
|
4203
|
+
" constructor(run: () => Promise<R>) {",
|
|
4204
|
+
" super(() => {});",
|
|
4205
|
+
" this.__run = run;",
|
|
4206
|
+
" }",
|
|
4207
|
+
" override then<T1 = R, T2 = never>(",
|
|
4108
4208
|
" onfulfilled?: ((value: R) => T1 | PromiseLike<T1>) | null,",
|
|
4109
4209
|
" onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null,",
|
|
4110
|
-
" ): Promise<T1 | T2
|
|
4111
|
-
"
|
|
4112
|
-
"
|
|
4113
|
-
"
|
|
4114
|
-
"}
|
|
4115
|
-
"function __req<R>(run: () => Promise<R
|
|
4116
|
-
"
|
|
4117
|
-
" const __promise = () => {",
|
|
4118
|
-
" __p ??= run();",
|
|
4119
|
-
" return __p;",
|
|
4120
|
-
" };",
|
|
4121
|
-
" return {",
|
|
4122
|
-
" then: (onfulfilled, onrejected) => __promise().then(onfulfilled, onrejected),",
|
|
4123
|
-
" catch: (onrejected) => __promise().catch(onrejected),",
|
|
4124
|
-
" finally: (onfinally) => __promise().finally(onfinally),",
|
|
4125
|
-
" fetch: run,",
|
|
4126
|
-
" };",
|
|
4210
|
+
" ): Promise<T1 | T2> {",
|
|
4211
|
+
" this.__p ??= this.__run();",
|
|
4212
|
+
" return this.__p.then(onfulfilled, onrejected);",
|
|
4213
|
+
" }",
|
|
4214
|
+
"}",
|
|
4215
|
+
"function __req<R, M extends object = {}>(run: () => Promise<R>, members?: M): RequestHandle<R, M> {",
|
|
4216
|
+
" return Object.assign(new __Request<R>(run), { fetch: run }, members) as RequestHandle<R, M>;",
|
|
4127
4217
|
"}",
|
|
4128
4218
|
""
|
|
4129
4219
|
];
|
|
@@ -4141,18 +4231,26 @@ function emitFilterFieldGuard() {
|
|
|
4141
4231
|
];
|
|
4142
4232
|
}
|
|
4143
4233
|
function renderLeaf(pad, objKey, req, requestExpr, members, streamExpr) {
|
|
4144
|
-
const
|
|
4145
|
-
lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4234
|
+
const memberLines = [];
|
|
4146
4235
|
if (req.filterFieldsExpr) {
|
|
4147
|
-
|
|
4236
|
+
memberLines.push(`${pad} filterFields: ${req.filterFieldsExpr},`);
|
|
4148
4237
|
}
|
|
4149
4238
|
if (streamExpr) {
|
|
4150
|
-
|
|
4239
|
+
memberLines.push(`${pad} stream: () => ${streamExpr},`);
|
|
4151
4240
|
}
|
|
4152
4241
|
for (const [name, value] of Object.entries(members)) {
|
|
4153
|
-
|
|
4154
|
-
}
|
|
4155
|
-
|
|
4242
|
+
memberLines.push(`${pad} ${name}: ${value},`);
|
|
4243
|
+
}
|
|
4244
|
+
const body = [requestExpr, ...memberLines].join("\n");
|
|
4245
|
+
const param = /\binput\b/.test(body) ? `input?: ${req.inputType}` : "";
|
|
4246
|
+
const lines = [`${pad}${objKey}: (${param}) =>`];
|
|
4247
|
+
if (memberLines.length === 0) {
|
|
4248
|
+
lines.push(`${pad} __req<${req.responseType}>(() => ${requestExpr}),`);
|
|
4249
|
+
return lines;
|
|
4250
|
+
}
|
|
4251
|
+
lines.push(`${pad} __req(() => ${requestExpr}, {`);
|
|
4252
|
+
lines.push(...memberLines);
|
|
4253
|
+
lines.push(`${pad} }),`);
|
|
4156
4254
|
return lines;
|
|
4157
4255
|
}
|
|
4158
4256
|
function renderStreamExpr(req) {
|
|
@@ -4286,6 +4384,23 @@ var EMPTY_PATH_NAMESPACE = [
|
|
|
4286
4384
|
function isClientCallable(route) {
|
|
4287
4385
|
return route.method.toUpperCase() !== "ALL";
|
|
4288
4386
|
}
|
|
4387
|
+
var ROUTES_IMPORT_PLACEHOLDER = "/* @@routes-import@@ */";
|
|
4388
|
+
var ROUTES_EXPORTS = [
|
|
4389
|
+
// Called, never mentioned in prose: match the call so a comment saying "route" doesn't count.
|
|
4390
|
+
{ name: "route", typeOnly: false },
|
|
4391
|
+
{ name: "ROUTES", typeOnly: false },
|
|
4392
|
+
{ name: "RouteName", typeOnly: true },
|
|
4393
|
+
{ name: "ExtractParams", typeOnly: true },
|
|
4394
|
+
{ name: "RouteParams", typeOnly: true }
|
|
4395
|
+
];
|
|
4396
|
+
function finishRoutesImport(lines) {
|
|
4397
|
+
const body = lines.filter((l) => l !== ROUTES_IMPORT_PLACEHOLDER).join("\n");
|
|
4398
|
+
const used = ROUTES_EXPORTS.filter(
|
|
4399
|
+
({ name }) => new RegExp(name === "route" ? "\\broute\\(" : `\\b${name}\\b`).test(body)
|
|
4400
|
+
).map(({ name, typeOnly }) => typeOnly ? `type ${name}` : name);
|
|
4401
|
+
const importLine = used.length ? `import { ${used.join(", ")} } from './routes.js';` : null;
|
|
4402
|
+
return lines.flatMap((l) => l === ROUTES_IMPORT_PLACEHOLDER ? importLine ? [importLine] : [] : [l]).join("\n");
|
|
4403
|
+
}
|
|
4289
4404
|
function buildApiFile(routes, outDir, opts = {}) {
|
|
4290
4405
|
const fetcherImportPath = opts.fetcherImportPath;
|
|
4291
4406
|
const serialization = opts.serialization ?? "json";
|
|
@@ -4345,9 +4460,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4345
4460
|
for (const imp of ext.apiHeader?.(ctx)?.imports ?? []) pushImport(imp);
|
|
4346
4461
|
}
|
|
4347
4462
|
lines.push(...extImports);
|
|
4348
|
-
lines.push(
|
|
4349
|
-
"import { route, ROUTES, type RouteName, type ExtractParams, type RouteParams } from './routes.js';"
|
|
4350
|
-
);
|
|
4463
|
+
lines.push(ROUTES_IMPORT_PLACEHOLDER);
|
|
4351
4464
|
const runtimeImport = fetcherImportPath ?? "@dudousxd/nestjs-client";
|
|
4352
4465
|
lines.push(`import type { Fetcher } from '${runtimeImport}';`);
|
|
4353
4466
|
if (serialization === "json" && contracted.length > 0) {
|
|
@@ -4398,7 +4511,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4398
4511
|
lines.push(...statements, "");
|
|
4399
4512
|
}
|
|
4400
4513
|
}
|
|
4401
|
-
return lines
|
|
4514
|
+
return finishRoutesImport(lines);
|
|
4402
4515
|
}
|
|
4403
4516
|
const tree = /* @__PURE__ */ new Map();
|
|
4404
4517
|
for (const r of contracted) {
|
|
@@ -4451,7 +4564,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
4451
4564
|
lines.push(...statements, "");
|
|
4452
4565
|
}
|
|
4453
4566
|
}
|
|
4454
|
-
return lines
|
|
4567
|
+
return finishRoutesImport(lines);
|
|
4455
4568
|
}
|
|
4456
4569
|
|
|
4457
4570
|
// src/emit/emit-cache.ts
|
|
@@ -4464,6 +4577,7 @@ async function emitCache(pages, outDir) {
|
|
|
4464
4577
|
const s = await stat(p.absolutePath);
|
|
4465
4578
|
return {
|
|
4466
4579
|
name: p.name,
|
|
4580
|
+
scope: p.scope ?? "default",
|
|
4467
4581
|
relativePath: p.relativePath,
|
|
4468
4582
|
mtime: s.mtime.toISOString()
|
|
4469
4583
|
};
|
|
@@ -5258,10 +5372,11 @@ async function emitPages(pages, outDir, _options = {}) {
|
|
|
5258
5372
|
}).join("\n");
|
|
5259
5373
|
const propsHelper = "\nexport type InertiaProps<K extends InertiaPageName> = import('@dudousxd/nestjs-inertia').InertiaPages[K];\n";
|
|
5260
5374
|
const sharedPropsBlock = buildSharedPropsBlock(_options.sharedProps ?? null);
|
|
5375
|
+
const scopesBlock = buildScopesBlock(pages);
|
|
5261
5376
|
const content = `// Generated by @dudousxd/nestjs-codegen. Do not edit.
|
|
5262
5377
|
|
|
5263
5378
|
export type InertiaPageName = ${pageNameUnion};
|
|
5264
|
-
${propsHelper}
|
|
5379
|
+
${propsHelper}${scopesBlock}
|
|
5265
5380
|
declare module '@dudousxd/nestjs-inertia' {
|
|
5266
5381
|
interface InertiaPages {
|
|
5267
5382
|
${augBody}
|
|
@@ -5270,6 +5385,31 @@ ${sharedPropsBlock}}
|
|
|
5270
5385
|
`;
|
|
5271
5386
|
await writeFile7(join11(outDir, "pages.d.ts"), content, "utf8");
|
|
5272
5387
|
}
|
|
5388
|
+
function buildScopesBlock(pages) {
|
|
5389
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
5390
|
+
for (const page of pages) {
|
|
5391
|
+
const scope = page.scope ?? "default";
|
|
5392
|
+
const names = byScope.get(scope) ?? [];
|
|
5393
|
+
names.push(JSON.stringify(page.name));
|
|
5394
|
+
byScope.set(scope, names);
|
|
5395
|
+
}
|
|
5396
|
+
if (![...byScope.keys()].some((scope) => scope !== "default")) return "";
|
|
5397
|
+
if (!byScope.has("default")) byScope.set("default", []);
|
|
5398
|
+
const scopes = ["default", ...[...byScope.keys()].filter((s) => s !== "default")];
|
|
5399
|
+
const body = scopes.map((scope) => {
|
|
5400
|
+
const key = needsQuotes(scope) ? JSON.stringify(scope) : scope;
|
|
5401
|
+
const names = byScope.get(scope) ?? [];
|
|
5402
|
+
return ` ${key}: ${names.length ? names.join(" | ") : "never"};`;
|
|
5403
|
+
}).join("\n");
|
|
5404
|
+
return `
|
|
5405
|
+
/** The page names of each Inertia app: \`default\` (forRoot) and every \`pages.scopes\` entry. */
|
|
5406
|
+
export interface InertiaScopePages {
|
|
5407
|
+
${body}
|
|
5408
|
+
}
|
|
5409
|
+
|
|
5410
|
+
export type InertiaScopePageName<S extends keyof InertiaScopePages> = InertiaScopePages[S];
|
|
5411
|
+
`;
|
|
5412
|
+
}
|
|
5273
5413
|
function buildSharedPropsBlock(sharedProps) {
|
|
5274
5414
|
if (!sharedProps) return "";
|
|
5275
5415
|
if (sharedProps.isImportRef) {
|
|
@@ -5477,8 +5617,7 @@ function diffConfigKeyHashes(previous, current) {
|
|
|
5477
5617
|
return [...keys].filter((key) => previous[key] !== current[key]).sort();
|
|
5478
5618
|
}
|
|
5479
5619
|
async function discoverInputFiles(config) {
|
|
5480
|
-
const globs = [config.contracts.glob, config.forms.watch];
|
|
5481
|
-
if (config.pages) globs.push(config.pages.glob);
|
|
5620
|
+
const globs = [config.contracts.glob, config.forms.watch, ...allPageGlobs(config)];
|
|
5482
5621
|
const cwd = config.codegen.cwd;
|
|
5483
5622
|
const matched = await fg3(globs, { cwd, absolute: true, onlyFiles: true });
|
|
5484
5623
|
return [...new Set(matched)].sort();
|
|
@@ -5609,12 +5748,7 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
|
|
|
5609
5748
|
}
|
|
5610
5749
|
if (config.pages) {
|
|
5611
5750
|
const pagesConfig = config.pages;
|
|
5612
|
-
const pages = await
|
|
5613
|
-
glob: pagesConfig.glob,
|
|
5614
|
-
cwd: config.codegen.cwd,
|
|
5615
|
-
propsExport: pagesConfig.propsExport,
|
|
5616
|
-
componentNameStrategy: pagesConfig.componentNameStrategy
|
|
5617
|
-
});
|
|
5751
|
+
const pages = await discoverPageScopes(config);
|
|
5618
5752
|
const sharedProps = discoverSharedPropsFromConfig(config);
|
|
5619
5753
|
await emitPages(pages, config.codegen.outDir, {
|
|
5620
5754
|
propsExport: pagesConfig.propsExport,
|
|
@@ -5789,12 +5923,17 @@ async function watch(config, onChange, options = {}) {
|
|
|
5789
5923
|
await runInitialPass();
|
|
5790
5924
|
}
|
|
5791
5925
|
let pagesDebounceTimer;
|
|
5792
|
-
const
|
|
5793
|
-
const pagesWatcher = chokidar.watch(
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5926
|
+
const pageGlobs = allPageGlobs(config);
|
|
5927
|
+
const pagesWatcher = chokidar.watch(
|
|
5928
|
+
(pageGlobs.length ? pageGlobs : [".nestjs-codegen-no-pages"]).map(
|
|
5929
|
+
(glob) => join16(config.codegen.cwd, glob)
|
|
5930
|
+
),
|
|
5931
|
+
{
|
|
5932
|
+
ignoreInitial: true,
|
|
5933
|
+
persistent: true,
|
|
5934
|
+
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
5935
|
+
}
|
|
5936
|
+
);
|
|
5798
5937
|
function schedulePagesRegenerate() {
|
|
5799
5938
|
if (pagesDebounceTimer !== void 0) {
|
|
5800
5939
|
clearTimeout(pagesDebounceTimer);
|
|
@@ -5957,7 +6096,7 @@ function createChainModuleRenderer(opts) {
|
|
|
5957
6096
|
}
|
|
5958
6097
|
|
|
5959
6098
|
// src/index.ts
|
|
5960
|
-
var VERSION = "0.
|
|
6099
|
+
var VERSION = "0.27.1";
|
|
5961
6100
|
export {
|
|
5962
6101
|
CodegenError,
|
|
5963
6102
|
ConfigError,
|