@dudousxd/nestjs-codegen 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/cli/main.cjs +21 -8
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +21 -8
- 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-_qRai4M3.d.cts → index-DgIAN5k5.d.cts} +16 -1
- package/dist/{index-_qRai4M3.d.ts → index-DgIAN5k5.d.ts} +16 -1
- package/dist/index.cjs +21 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.js +21 -8
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +20 -7
- 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 +20 -7
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { m as ApiClientLayer, n as ApiHeaderContribution, o as ApiModuleDeps, C as CodegenExtension, p as EmittedFile, E as ExtensionContext, L as LeafModel, q as RequestModel, s as RequestShape, t as defineExtension, u as requestShape } from '../index-DgIAN5k5.cjs';
|
|
2
2
|
import 'ts-morph';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { m as ApiClientLayer, n as ApiHeaderContribution, o as ApiModuleDeps, C as CodegenExtension, p as EmittedFile, E as ExtensionContext, L as LeafModel, q as RequestModel, s as RequestShape, t as defineExtension, u as requestShape } from '../index-DgIAN5k5.js';
|
|
2
2
|
import 'ts-morph';
|
|
@@ -254,6 +254,18 @@ interface UserConfig {
|
|
|
254
254
|
fetcher?: {
|
|
255
255
|
importPath: string;
|
|
256
256
|
};
|
|
257
|
+
/**
|
|
258
|
+
* How response payloads are deserialized on the client, which determines the
|
|
259
|
+
* generated `response` type shape.
|
|
260
|
+
*
|
|
261
|
+
* - `'json'` (default): responses cross the wire as plain JSON, so the
|
|
262
|
+
* generated type is wrapped in `Jsonify<...>` (e.g. `Date` → `string`).
|
|
263
|
+
* - `'superjson'`: responses are revived (Dates/Maps/Sets restored), so the
|
|
264
|
+
* raw controller return type is emitted unchanged.
|
|
265
|
+
*
|
|
266
|
+
* @default 'json'
|
|
267
|
+
*/
|
|
268
|
+
serialization?: 'json' | 'superjson';
|
|
257
269
|
/**
|
|
258
270
|
* Typed-form schema emit (`forms.ts`). Re-exports / translates contract and
|
|
259
271
|
* class-validator-decorated DTO schemas into zod schemas for client-side
|
|
@@ -319,6 +331,8 @@ interface ResolvedCodegenConfig {
|
|
|
319
331
|
outDir: string;
|
|
320
332
|
cwd: string;
|
|
321
333
|
}
|
|
334
|
+
/** How response payloads are deserialized on the client. */
|
|
335
|
+
type SerializationMode = 'json' | 'superjson';
|
|
322
336
|
interface ResolvedAppConfig {
|
|
323
337
|
moduleEntry: string;
|
|
324
338
|
tsconfig: string | null;
|
|
@@ -352,6 +366,7 @@ interface ResolvedConfig {
|
|
|
352
366
|
fetcher: {
|
|
353
367
|
importPath: string;
|
|
354
368
|
} | null;
|
|
369
|
+
serialization: SerializationMode;
|
|
355
370
|
forms: ResolvedFormsConfig;
|
|
356
371
|
openapi: ResolvedOpenApiConfig;
|
|
357
372
|
mocks: ResolvedMocksConfig;
|
|
@@ -631,4 +646,4 @@ declare function requestShape(route: RouteDescriptor): RequestShape;
|
|
|
631
646
|
/** Identity helper for authoring extensions with full type inference. */
|
|
632
647
|
declare function defineExtension(ext: CodegenExtension): CodegenExtension;
|
|
633
648
|
|
|
634
|
-
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type SchemaNode as S, type TypeRef as T, type UserConfig as U, type ValidationAdapter as V, type RouteDescriptor as a, type RenderContext as b, type SchemaModule as c, type RenderedModule as d, type ResolvedFormsConfig as e, type
|
|
649
|
+
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type SchemaNode as S, type TypeRef as T, type UserConfig as U, type ValidationAdapter as V, type RouteDescriptor as a, type RenderContext as b, type SchemaModule as c, type RenderedModule as d, type ResolvedFormsConfig as e, type SerializationMode as f, type ContractDescriptor as g, type ContractSource as h, type ControllerRef as i, type ScopeConfig as j, type StringCheck as k, type ValidationOption as l, type ApiClientLayer as m, type ApiHeaderContribution as n, type ApiModuleDeps as o, type EmittedFile as p, type RequestModel as q, resolveAdapter as r, type RequestShape as s, defineExtension as t, requestShape as u };
|
|
@@ -254,6 +254,18 @@ interface UserConfig {
|
|
|
254
254
|
fetcher?: {
|
|
255
255
|
importPath: string;
|
|
256
256
|
};
|
|
257
|
+
/**
|
|
258
|
+
* How response payloads are deserialized on the client, which determines the
|
|
259
|
+
* generated `response` type shape.
|
|
260
|
+
*
|
|
261
|
+
* - `'json'` (default): responses cross the wire as plain JSON, so the
|
|
262
|
+
* generated type is wrapped in `Jsonify<...>` (e.g. `Date` → `string`).
|
|
263
|
+
* - `'superjson'`: responses are revived (Dates/Maps/Sets restored), so the
|
|
264
|
+
* raw controller return type is emitted unchanged.
|
|
265
|
+
*
|
|
266
|
+
* @default 'json'
|
|
267
|
+
*/
|
|
268
|
+
serialization?: 'json' | 'superjson';
|
|
257
269
|
/**
|
|
258
270
|
* Typed-form schema emit (`forms.ts`). Re-exports / translates contract and
|
|
259
271
|
* class-validator-decorated DTO schemas into zod schemas for client-side
|
|
@@ -319,6 +331,8 @@ interface ResolvedCodegenConfig {
|
|
|
319
331
|
outDir: string;
|
|
320
332
|
cwd: string;
|
|
321
333
|
}
|
|
334
|
+
/** How response payloads are deserialized on the client. */
|
|
335
|
+
type SerializationMode = 'json' | 'superjson';
|
|
322
336
|
interface ResolvedAppConfig {
|
|
323
337
|
moduleEntry: string;
|
|
324
338
|
tsconfig: string | null;
|
|
@@ -352,6 +366,7 @@ interface ResolvedConfig {
|
|
|
352
366
|
fetcher: {
|
|
353
367
|
importPath: string;
|
|
354
368
|
} | null;
|
|
369
|
+
serialization: SerializationMode;
|
|
355
370
|
forms: ResolvedFormsConfig;
|
|
356
371
|
openapi: ResolvedOpenApiConfig;
|
|
357
372
|
mocks: ResolvedMocksConfig;
|
|
@@ -631,4 +646,4 @@ declare function requestShape(route: RouteDescriptor): RequestShape;
|
|
|
631
646
|
/** Identity helper for authoring extensions with full type inference. */
|
|
632
647
|
declare function defineExtension(ext: CodegenExtension): CodegenExtension;
|
|
633
648
|
|
|
634
|
-
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type SchemaNode as S, type TypeRef as T, type UserConfig as U, type ValidationAdapter as V, type RouteDescriptor as a, type RenderContext as b, type SchemaModule as c, type RenderedModule as d, type ResolvedFormsConfig as e, type
|
|
649
|
+
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type SchemaNode as S, type TypeRef as T, type UserConfig as U, type ValidationAdapter as V, type RouteDescriptor as a, type RenderContext as b, type SchemaModule as c, type RenderedModule as d, type ResolvedFormsConfig as e, type SerializationMode as f, type ContractDescriptor as g, type ContractSource as h, type ControllerRef as i, type ScopeConfig as j, type StringCheck as k, type ValidationOption as l, type ApiClientLayer as m, type ApiHeaderContribution as n, type ApiModuleDeps as o, type EmittedFile as p, type RequestModel as q, resolveAdapter as r, type RequestShape as s, defineExtension as t, requestShape as u };
|
package/dist/index.cjs
CHANGED
|
@@ -187,6 +187,7 @@ function applyDefaults(userConfig, cwd) {
|
|
|
187
187
|
},
|
|
188
188
|
app,
|
|
189
189
|
fetcher: userConfig.fetcher ?? null,
|
|
190
|
+
serialization: userConfig.serialization ?? "json",
|
|
190
191
|
forms: {
|
|
191
192
|
enabled: userConfig.forms?.enabled ?? true,
|
|
192
193
|
watch: userConfig.forms?.watch ?? "src/**/*.dto.ts",
|
|
@@ -770,7 +771,11 @@ function emitFilterQueryTypeArgs(c) {
|
|
|
770
771
|
function emitFilterQueryType(c) {
|
|
771
772
|
return `import('@dudousxd/nestjs-filter-client').TypedFilterQuery<${emitFilterQueryTypeArgs(c)}>`;
|
|
772
773
|
}
|
|
773
|
-
function buildResponseType(c, outDir) {
|
|
774
|
+
function buildResponseType(c, outDir, serialization) {
|
|
775
|
+
const raw = rawResponseType(c, outDir);
|
|
776
|
+
return serialization === "json" ? `Jsonify<${raw}>` : raw;
|
|
777
|
+
}
|
|
778
|
+
function rawResponseType(c, outDir) {
|
|
774
779
|
const respRef = c.contractSource.responseRef;
|
|
775
780
|
if (c.contractSource.stream) {
|
|
776
781
|
if (respRef) return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;
|
|
@@ -793,7 +798,7 @@ function buildErrorType(c) {
|
|
|
793
798
|
}
|
|
794
799
|
return c.contractSource.error ?? "unknown";
|
|
795
800
|
}
|
|
796
|
-
function emitRouterTypeBlock(tree, indent, outDir) {
|
|
801
|
+
function emitRouterTypeBlock(tree, indent, outDir, serialization) {
|
|
797
802
|
const pad = " ".repeat(indent);
|
|
798
803
|
const lines = [];
|
|
799
804
|
for (const [key, node] of tree) {
|
|
@@ -806,7 +811,7 @@ function emitRouterTypeBlock(tree, indent, outDir) {
|
|
|
806
811
|
const query = queryRef ? queryRef.isArray ? `Array<${queryRef.name}>` : queryRef.name : isFilterQuery ? emitFilterQueryType(c) : c.contractSource.query ?? "never";
|
|
807
812
|
const bodyRef = c.contractSource.bodyRef;
|
|
808
813
|
const body = method === "GET" ? "never" : bodyRef ? bodyRef.isArray ? `Array<${bodyRef.name}>` : bodyRef.name : c.contractSource.body ?? "never";
|
|
809
|
-
const response = buildResponseType(c, outDir);
|
|
814
|
+
const response = buildResponseType(c, outDir, serialization);
|
|
810
815
|
const error = buildErrorType(c);
|
|
811
816
|
const params = buildParamsType(c.params);
|
|
812
817
|
const safeMethod = JSON.stringify(method);
|
|
@@ -818,7 +823,7 @@ function emitRouterTypeBlock(tree, indent, outDir) {
|
|
|
818
823
|
);
|
|
819
824
|
} else {
|
|
820
825
|
lines.push(`${pad}${objKey}: {`);
|
|
821
|
-
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));
|
|
826
|
+
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir, serialization));
|
|
822
827
|
lines.push(`${pad}};`);
|
|
823
828
|
}
|
|
824
829
|
}
|
|
@@ -1023,6 +1028,7 @@ var EMPTY_PATH_NAMESPACE = [
|
|
|
1023
1028
|
];
|
|
1024
1029
|
function buildApiFile(routes, outDir, opts = {}) {
|
|
1025
1030
|
const fetcherImportPath = opts.fetcherImportPath;
|
|
1031
|
+
const serialization = opts.serialization ?? "json";
|
|
1026
1032
|
const extensions = opts.extensions ?? [];
|
|
1027
1033
|
const { layer } = resolveApiSlots(extensions);
|
|
1028
1034
|
const memberExts = extensions.filter((e) => e.apiMembers);
|
|
@@ -1079,6 +1085,9 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
1079
1085
|
);
|
|
1080
1086
|
const runtimeImport = fetcherImportPath ?? "@dudousxd/nestjs-client";
|
|
1081
1087
|
lines.push(`import type { Fetcher } from '${runtimeImport}';`);
|
|
1088
|
+
if (serialization === "json" && contracted.length > 0) {
|
|
1089
|
+
lines.push(`import type { Jsonify } from '${runtimeImport}';`);
|
|
1090
|
+
}
|
|
1082
1091
|
if (importsByFile.size > 0 && outDir) {
|
|
1083
1092
|
lines.push("");
|
|
1084
1093
|
const emittedNames = /* @__PURE__ */ new Set();
|
|
@@ -1138,7 +1147,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
1138
1147
|
insertIntoTree(tree, segments, leaf, name);
|
|
1139
1148
|
}
|
|
1140
1149
|
lines.push("export type ApiRouter = {");
|
|
1141
|
-
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ""));
|
|
1150
|
+
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? "", serialization));
|
|
1142
1151
|
lines.push("};");
|
|
1143
1152
|
lines.push("");
|
|
1144
1153
|
lines.push(...emitReqHelper());
|
|
@@ -2159,6 +2168,7 @@ async function generate(config, inputRoutes = []) {
|
|
|
2159
2168
|
if (hasContracts) {
|
|
2160
2169
|
await emitApi(routes, config.codegen.outDir, {
|
|
2161
2170
|
...config.fetcher?.importPath ? { fetcherImportPath: config.fetcher.importPath } : {},
|
|
2171
|
+
serialization: config.serialization,
|
|
2162
2172
|
extensions,
|
|
2163
2173
|
ctx
|
|
2164
2174
|
});
|
|
@@ -4389,6 +4399,7 @@ async function watch(config, onChange) {
|
|
|
4389
4399
|
return NO_OP_WATCHER;
|
|
4390
4400
|
}
|
|
4391
4401
|
let discovery = null;
|
|
4402
|
+
let lastRoutes = [];
|
|
4392
4403
|
async function getDiscovery() {
|
|
4393
4404
|
if (discovery === null) {
|
|
4394
4405
|
discovery = await PersistentDiscovery.create({
|
|
@@ -4402,13 +4413,14 @@ async function watch(config, onChange) {
|
|
|
4402
4413
|
}
|
|
4403
4414
|
try {
|
|
4404
4415
|
const initialRoutes = (await getDiscovery()).discover();
|
|
4416
|
+
lastRoutes = initialRoutes;
|
|
4405
4417
|
await generate(config, initialRoutes);
|
|
4406
4418
|
} catch (err) {
|
|
4407
4419
|
console.warn(
|
|
4408
4420
|
`[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`
|
|
4409
4421
|
);
|
|
4410
4422
|
try {
|
|
4411
|
-
await generate(config);
|
|
4423
|
+
await generate(config, lastRoutes);
|
|
4412
4424
|
} catch {
|
|
4413
4425
|
}
|
|
4414
4426
|
}
|
|
@@ -4426,7 +4438,7 @@ async function watch(config, onChange) {
|
|
|
4426
4438
|
pagesDebounceTimer = setTimeout(async () => {
|
|
4427
4439
|
pagesDebounceTimer = void 0;
|
|
4428
4440
|
try {
|
|
4429
|
-
await generate(config);
|
|
4441
|
+
await generate(config, lastRoutes);
|
|
4430
4442
|
} catch (err) {
|
|
4431
4443
|
console.error(
|
|
4432
4444
|
"[nestjs-codegen] Pages generation failed:",
|
|
@@ -4457,6 +4469,7 @@ async function watch(config, onChange) {
|
|
|
4457
4469
|
pendingChangedPaths.clear();
|
|
4458
4470
|
try {
|
|
4459
4471
|
const routes = await (await getDiscovery()).rediscover(changed);
|
|
4472
|
+
lastRoutes = routes;
|
|
4460
4473
|
await generate(config, routes);
|
|
4461
4474
|
} catch (err) {
|
|
4462
4475
|
console.error(
|
|
@@ -4580,7 +4593,7 @@ function createChainModuleRenderer(opts) {
|
|
|
4580
4593
|
}
|
|
4581
4594
|
|
|
4582
4595
|
// src/index.ts
|
|
4583
|
-
var VERSION = "0.
|
|
4596
|
+
var VERSION = "0.7.0";
|
|
4584
4597
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4585
4598
|
0 && (module.exports = {
|
|
4586
4599
|
CodegenError,
|