@dudousxd/nestjs-codegen 0.6.1 → 0.7.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 +18 -0
- package/dist/cli/main.cjs +31 -16
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +31 -16
- 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 +31 -16
- 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 +31 -16
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +15 -5
- 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 +15 -5
- 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
|
@@ -106,18 +106,23 @@ async function fileExists(filePath) {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
async function importTs(filePath) {
|
|
109
|
-
|
|
109
|
+
const fileUrl = (0, import_node_url.pathToFileURL)(filePath).href;
|
|
110
110
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
return await import(fileUrl);
|
|
112
|
+
} catch (nativeError) {
|
|
113
|
+
let tsImport;
|
|
114
|
+
try {
|
|
115
|
+
const tsxEsm = await import("tsx/esm/api");
|
|
116
|
+
tsImport = tsxEsm.tsImport;
|
|
117
|
+
} catch {
|
|
118
|
+
throw new ConfigError(
|
|
119
|
+
"Failed to load config: `tsx` is required for loading TypeScript config files. Install it as a dev dependency: pnpm add -D tsx",
|
|
120
|
+
{ cause: nativeError }
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const parentURL = (0, import_node_url.pathToFileURL)(`${filePath}__parent__`).href;
|
|
124
|
+
return tsImport(fileUrl, { parentURL });
|
|
117
125
|
}
|
|
118
|
-
const parentURL = (0, import_node_url.pathToFileURL)(`${filePath}__parent__`).href;
|
|
119
|
-
const fileUrl = (0, import_node_url.pathToFileURL)(filePath).href;
|
|
120
|
-
return tsImport(fileUrl, { parentURL });
|
|
121
126
|
}
|
|
122
127
|
function resolveAbsolute(cwd, p) {
|
|
123
128
|
if ((0, import_node_path.isAbsolute)(p)) return p;
|
|
@@ -187,6 +192,7 @@ function applyDefaults(userConfig, cwd) {
|
|
|
187
192
|
},
|
|
188
193
|
app,
|
|
189
194
|
fetcher: userConfig.fetcher ?? null,
|
|
195
|
+
serialization: userConfig.serialization ?? "json",
|
|
190
196
|
forms: {
|
|
191
197
|
enabled: userConfig.forms?.enabled ?? true,
|
|
192
198
|
watch: userConfig.forms?.watch ?? "src/**/*.dto.ts",
|
|
@@ -770,7 +776,11 @@ function emitFilterQueryTypeArgs(c) {
|
|
|
770
776
|
function emitFilterQueryType(c) {
|
|
771
777
|
return `import('@dudousxd/nestjs-filter-client').TypedFilterQuery<${emitFilterQueryTypeArgs(c)}>`;
|
|
772
778
|
}
|
|
773
|
-
function buildResponseType(c, outDir) {
|
|
779
|
+
function buildResponseType(c, outDir, serialization) {
|
|
780
|
+
const raw = rawResponseType(c, outDir);
|
|
781
|
+
return serialization === "json" ? `Jsonify<${raw}>` : raw;
|
|
782
|
+
}
|
|
783
|
+
function rawResponseType(c, outDir) {
|
|
774
784
|
const respRef = c.contractSource.responseRef;
|
|
775
785
|
if (c.contractSource.stream) {
|
|
776
786
|
if (respRef) return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;
|
|
@@ -793,7 +803,7 @@ function buildErrorType(c) {
|
|
|
793
803
|
}
|
|
794
804
|
return c.contractSource.error ?? "unknown";
|
|
795
805
|
}
|
|
796
|
-
function emitRouterTypeBlock(tree, indent, outDir) {
|
|
806
|
+
function emitRouterTypeBlock(tree, indent, outDir, serialization) {
|
|
797
807
|
const pad = " ".repeat(indent);
|
|
798
808
|
const lines = [];
|
|
799
809
|
for (const [key, node] of tree) {
|
|
@@ -806,7 +816,7 @@ function emitRouterTypeBlock(tree, indent, outDir) {
|
|
|
806
816
|
const query = queryRef ? queryRef.isArray ? `Array<${queryRef.name}>` : queryRef.name : isFilterQuery ? emitFilterQueryType(c) : c.contractSource.query ?? "never";
|
|
807
817
|
const bodyRef = c.contractSource.bodyRef;
|
|
808
818
|
const body = method === "GET" ? "never" : bodyRef ? bodyRef.isArray ? `Array<${bodyRef.name}>` : bodyRef.name : c.contractSource.body ?? "never";
|
|
809
|
-
const response = buildResponseType(c, outDir);
|
|
819
|
+
const response = buildResponseType(c, outDir, serialization);
|
|
810
820
|
const error = buildErrorType(c);
|
|
811
821
|
const params = buildParamsType(c.params);
|
|
812
822
|
const safeMethod = JSON.stringify(method);
|
|
@@ -818,7 +828,7 @@ function emitRouterTypeBlock(tree, indent, outDir) {
|
|
|
818
828
|
);
|
|
819
829
|
} else {
|
|
820
830
|
lines.push(`${pad}${objKey}: {`);
|
|
821
|
-
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));
|
|
831
|
+
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir, serialization));
|
|
822
832
|
lines.push(`${pad}};`);
|
|
823
833
|
}
|
|
824
834
|
}
|
|
@@ -1023,6 +1033,7 @@ var EMPTY_PATH_NAMESPACE = [
|
|
|
1023
1033
|
];
|
|
1024
1034
|
function buildApiFile(routes, outDir, opts = {}) {
|
|
1025
1035
|
const fetcherImportPath = opts.fetcherImportPath;
|
|
1036
|
+
const serialization = opts.serialization ?? "json";
|
|
1026
1037
|
const extensions = opts.extensions ?? [];
|
|
1027
1038
|
const { layer } = resolveApiSlots(extensions);
|
|
1028
1039
|
const memberExts = extensions.filter((e) => e.apiMembers);
|
|
@@ -1079,6 +1090,9 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
1079
1090
|
);
|
|
1080
1091
|
const runtimeImport = fetcherImportPath ?? "@dudousxd/nestjs-client";
|
|
1081
1092
|
lines.push(`import type { Fetcher } from '${runtimeImport}';`);
|
|
1093
|
+
if (serialization === "json" && contracted.length > 0) {
|
|
1094
|
+
lines.push(`import type { Jsonify } from '${runtimeImport}';`);
|
|
1095
|
+
}
|
|
1082
1096
|
if (importsByFile.size > 0 && outDir) {
|
|
1083
1097
|
lines.push("");
|
|
1084
1098
|
const emittedNames = /* @__PURE__ */ new Set();
|
|
@@ -1138,7 +1152,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
1138
1152
|
insertIntoTree(tree, segments, leaf, name);
|
|
1139
1153
|
}
|
|
1140
1154
|
lines.push("export type ApiRouter = {");
|
|
1141
|
-
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ""));
|
|
1155
|
+
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? "", serialization));
|
|
1142
1156
|
lines.push("};");
|
|
1143
1157
|
lines.push("");
|
|
1144
1158
|
lines.push(...emitReqHelper());
|
|
@@ -2159,6 +2173,7 @@ async function generate(config, inputRoutes = []) {
|
|
|
2159
2173
|
if (hasContracts) {
|
|
2160
2174
|
await emitApi(routes, config.codegen.outDir, {
|
|
2161
2175
|
...config.fetcher?.importPath ? { fetcherImportPath: config.fetcher.importPath } : {},
|
|
2176
|
+
serialization: config.serialization,
|
|
2162
2177
|
extensions,
|
|
2163
2178
|
ctx
|
|
2164
2179
|
});
|
|
@@ -4583,7 +4598,7 @@ function createChainModuleRenderer(opts) {
|
|
|
4583
4598
|
}
|
|
4584
4599
|
|
|
4585
4600
|
// src/index.ts
|
|
4586
|
-
var VERSION = "0.
|
|
4601
|
+
var VERSION = "0.7.1";
|
|
4587
4602
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4588
4603
|
0 && (module.exports = {
|
|
4589
4604
|
CodegenError,
|