@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
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 } from './index-
|
|
2
|
-
export { A as AdapterUsage,
|
|
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-DgIAN5k5.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-DgIAN5k5.cjs';
|
|
3
3
|
import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
declare function defineConfig(c: UserConfig): UserConfig;
|
|
@@ -160,13 +160,20 @@ declare function emitForms(routes: RouteDescriptor[], outDir: string, config: Re
|
|
|
160
160
|
* output: an `apiClientLayer` (e.g. `@dudousxd/nestjs-codegen-tanstack`) turns leaves into
|
|
161
161
|
* handles wrapping the neutral fetcher request; `apiMembers` add handle members; `apiHeader`
|
|
162
162
|
* contributes top-level imports/statements.
|
|
163
|
+
*
|
|
164
|
+
* `serialization` controls how response types are emitted (default `'json'`):
|
|
165
|
+
* in `'json'` mode each `response` type is wrapped in `Jsonify<...>` (so the
|
|
166
|
+
* generated type reflects the JSON wire shape, e.g. `Date` → `string`); in
|
|
167
|
+
* `'superjson'` mode the raw controller return type is emitted unchanged.
|
|
163
168
|
*/
|
|
164
169
|
interface ApiEmitOptions {
|
|
165
|
-
fetcherImportPath?: string;
|
|
170
|
+
fetcherImportPath?: string | undefined;
|
|
166
171
|
/** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */
|
|
167
|
-
extensions?: CodegenExtension[];
|
|
172
|
+
extensions?: CodegenExtension[] | undefined;
|
|
168
173
|
/** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */
|
|
169
|
-
ctx?: ExtensionContext;
|
|
174
|
+
ctx?: ExtensionContext | undefined;
|
|
175
|
+
/** How response payloads deserialize on the client. Default `'json'`. */
|
|
176
|
+
serialization?: SerializationMode | undefined;
|
|
170
177
|
}
|
|
171
178
|
declare function emitApi(routes: RouteDescriptor[], outDir: string, opts?: ApiEmitOptions): Promise<void>;
|
|
172
179
|
|
|
@@ -289,6 +296,6 @@ interface FastDiscoveryOptions {
|
|
|
289
296
|
}
|
|
290
297
|
declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
|
|
291
298
|
|
|
292
|
-
declare const VERSION = "0.
|
|
299
|
+
declare const VERSION = "0.7.0";
|
|
293
300
|
|
|
294
301
|
export { type ChainModuleRendererOptions, CodegenError, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, 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 } from './index-
|
|
2
|
-
export { A as AdapterUsage,
|
|
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-DgIAN5k5.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-DgIAN5k5.js';
|
|
3
3
|
import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
|
|
4
4
|
|
|
5
5
|
declare function defineConfig(c: UserConfig): UserConfig;
|
|
@@ -160,13 +160,20 @@ declare function emitForms(routes: RouteDescriptor[], outDir: string, config: Re
|
|
|
160
160
|
* output: an `apiClientLayer` (e.g. `@dudousxd/nestjs-codegen-tanstack`) turns leaves into
|
|
161
161
|
* handles wrapping the neutral fetcher request; `apiMembers` add handle members; `apiHeader`
|
|
162
162
|
* contributes top-level imports/statements.
|
|
163
|
+
*
|
|
164
|
+
* `serialization` controls how response types are emitted (default `'json'`):
|
|
165
|
+
* in `'json'` mode each `response` type is wrapped in `Jsonify<...>` (so the
|
|
166
|
+
* generated type reflects the JSON wire shape, e.g. `Date` → `string`); in
|
|
167
|
+
* `'superjson'` mode the raw controller return type is emitted unchanged.
|
|
163
168
|
*/
|
|
164
169
|
interface ApiEmitOptions {
|
|
165
|
-
fetcherImportPath?: string;
|
|
170
|
+
fetcherImportPath?: string | undefined;
|
|
166
171
|
/** Registered extensions. Their api.ts hooks (transport/layer/members/header) are applied. */
|
|
167
|
-
extensions?: CodegenExtension[];
|
|
172
|
+
extensions?: CodegenExtension[] | undefined;
|
|
168
173
|
/** Shared extension context (from `generate()`). When omitted, a minimal one is built from routes. */
|
|
169
|
-
ctx?: ExtensionContext;
|
|
174
|
+
ctx?: ExtensionContext | undefined;
|
|
175
|
+
/** How response payloads deserialize on the client. Default `'json'`. */
|
|
176
|
+
serialization?: SerializationMode | undefined;
|
|
170
177
|
}
|
|
171
178
|
declare function emitApi(routes: RouteDescriptor[], outDir: string, opts?: ApiEmitOptions): Promise<void>;
|
|
172
179
|
|
|
@@ -289,6 +296,6 @@ interface FastDiscoveryOptions {
|
|
|
289
296
|
}
|
|
290
297
|
declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
|
|
291
298
|
|
|
292
|
-
declare const VERSION = "0.
|
|
299
|
+
declare const VERSION = "0.7.0";
|
|
293
300
|
|
|
294
301
|
export { type ChainModuleRendererOptions, CodegenError, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, 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
|
@@ -127,6 +127,7 @@ function applyDefaults(userConfig, cwd) {
|
|
|
127
127
|
},
|
|
128
128
|
app,
|
|
129
129
|
fetcher: userConfig.fetcher ?? null,
|
|
130
|
+
serialization: userConfig.serialization ?? "json",
|
|
130
131
|
forms: {
|
|
131
132
|
enabled: userConfig.forms?.enabled ?? true,
|
|
132
133
|
watch: userConfig.forms?.watch ?? "src/**/*.dto.ts",
|
|
@@ -710,7 +711,11 @@ function emitFilterQueryTypeArgs(c) {
|
|
|
710
711
|
function emitFilterQueryType(c) {
|
|
711
712
|
return `import('@dudousxd/nestjs-filter-client').TypedFilterQuery<${emitFilterQueryTypeArgs(c)}>`;
|
|
712
713
|
}
|
|
713
|
-
function buildResponseType(c, outDir) {
|
|
714
|
+
function buildResponseType(c, outDir, serialization) {
|
|
715
|
+
const raw = rawResponseType(c, outDir);
|
|
716
|
+
return serialization === "json" ? `Jsonify<${raw}>` : raw;
|
|
717
|
+
}
|
|
718
|
+
function rawResponseType(c, outDir) {
|
|
714
719
|
const respRef = c.contractSource.responseRef;
|
|
715
720
|
if (c.contractSource.stream) {
|
|
716
721
|
if (respRef) return respRef.isArray ? `Array<${respRef.name}>` : respRef.name;
|
|
@@ -733,7 +738,7 @@ function buildErrorType(c) {
|
|
|
733
738
|
}
|
|
734
739
|
return c.contractSource.error ?? "unknown";
|
|
735
740
|
}
|
|
736
|
-
function emitRouterTypeBlock(tree, indent, outDir) {
|
|
741
|
+
function emitRouterTypeBlock(tree, indent, outDir, serialization) {
|
|
737
742
|
const pad = " ".repeat(indent);
|
|
738
743
|
const lines = [];
|
|
739
744
|
for (const [key, node] of tree) {
|
|
@@ -746,7 +751,7 @@ function emitRouterTypeBlock(tree, indent, outDir) {
|
|
|
746
751
|
const query = queryRef ? queryRef.isArray ? `Array<${queryRef.name}>` : queryRef.name : isFilterQuery ? emitFilterQueryType(c) : c.contractSource.query ?? "never";
|
|
747
752
|
const bodyRef = c.contractSource.bodyRef;
|
|
748
753
|
const body = method === "GET" ? "never" : bodyRef ? bodyRef.isArray ? `Array<${bodyRef.name}>` : bodyRef.name : c.contractSource.body ?? "never";
|
|
749
|
-
const response = buildResponseType(c, outDir);
|
|
754
|
+
const response = buildResponseType(c, outDir, serialization);
|
|
750
755
|
const error = buildErrorType(c);
|
|
751
756
|
const params = buildParamsType(c.params);
|
|
752
757
|
const safeMethod = JSON.stringify(method);
|
|
@@ -758,7 +763,7 @@ function emitRouterTypeBlock(tree, indent, outDir) {
|
|
|
758
763
|
);
|
|
759
764
|
} else {
|
|
760
765
|
lines.push(`${pad}${objKey}: {`);
|
|
761
|
-
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir));
|
|
766
|
+
lines.push(...emitRouterTypeBlock(node.children, indent + 2, outDir, serialization));
|
|
762
767
|
lines.push(`${pad}};`);
|
|
763
768
|
}
|
|
764
769
|
}
|
|
@@ -963,6 +968,7 @@ var EMPTY_PATH_NAMESPACE = [
|
|
|
963
968
|
];
|
|
964
969
|
function buildApiFile(routes, outDir, opts = {}) {
|
|
965
970
|
const fetcherImportPath = opts.fetcherImportPath;
|
|
971
|
+
const serialization = opts.serialization ?? "json";
|
|
966
972
|
const extensions = opts.extensions ?? [];
|
|
967
973
|
const { layer } = resolveApiSlots(extensions);
|
|
968
974
|
const memberExts = extensions.filter((e) => e.apiMembers);
|
|
@@ -1019,6 +1025,9 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
1019
1025
|
);
|
|
1020
1026
|
const runtimeImport = fetcherImportPath ?? "@dudousxd/nestjs-client";
|
|
1021
1027
|
lines.push(`import type { Fetcher } from '${runtimeImport}';`);
|
|
1028
|
+
if (serialization === "json" && contracted.length > 0) {
|
|
1029
|
+
lines.push(`import type { Jsonify } from '${runtimeImport}';`);
|
|
1030
|
+
}
|
|
1022
1031
|
if (importsByFile.size > 0 && outDir) {
|
|
1023
1032
|
lines.push("");
|
|
1024
1033
|
const emittedNames = /* @__PURE__ */ new Set();
|
|
@@ -1078,7 +1087,7 @@ function buildApiFile(routes, outDir, opts = {}) {
|
|
|
1078
1087
|
insertIntoTree(tree, segments, leaf, name);
|
|
1079
1088
|
}
|
|
1080
1089
|
lines.push("export type ApiRouter = {");
|
|
1081
|
-
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? ""));
|
|
1090
|
+
lines.push(...emitRouterTypeBlock(tree, 2, outDir ?? "", serialization));
|
|
1082
1091
|
lines.push("};");
|
|
1083
1092
|
lines.push("");
|
|
1084
1093
|
lines.push(...emitReqHelper());
|
|
@@ -2099,6 +2108,7 @@ async function generate(config, inputRoutes = []) {
|
|
|
2099
2108
|
if (hasContracts) {
|
|
2100
2109
|
await emitApi(routes, config.codegen.outDir, {
|
|
2101
2110
|
...config.fetcher?.importPath ? { fetcherImportPath: config.fetcher.importPath } : {},
|
|
2111
|
+
serialization: config.serialization,
|
|
2102
2112
|
extensions,
|
|
2103
2113
|
ctx
|
|
2104
2114
|
});
|
|
@@ -4344,6 +4354,7 @@ async function watch(config, onChange) {
|
|
|
4344
4354
|
return NO_OP_WATCHER;
|
|
4345
4355
|
}
|
|
4346
4356
|
let discovery = null;
|
|
4357
|
+
let lastRoutes = [];
|
|
4347
4358
|
async function getDiscovery() {
|
|
4348
4359
|
if (discovery === null) {
|
|
4349
4360
|
discovery = await PersistentDiscovery.create({
|
|
@@ -4357,13 +4368,14 @@ async function watch(config, onChange) {
|
|
|
4357
4368
|
}
|
|
4358
4369
|
try {
|
|
4359
4370
|
const initialRoutes = (await getDiscovery()).discover();
|
|
4371
|
+
lastRoutes = initialRoutes;
|
|
4360
4372
|
await generate(config, initialRoutes);
|
|
4361
4373
|
} catch (err) {
|
|
4362
4374
|
console.warn(
|
|
4363
4375
|
`[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`
|
|
4364
4376
|
);
|
|
4365
4377
|
try {
|
|
4366
|
-
await generate(config);
|
|
4378
|
+
await generate(config, lastRoutes);
|
|
4367
4379
|
} catch {
|
|
4368
4380
|
}
|
|
4369
4381
|
}
|
|
@@ -4381,7 +4393,7 @@ async function watch(config, onChange) {
|
|
|
4381
4393
|
pagesDebounceTimer = setTimeout(async () => {
|
|
4382
4394
|
pagesDebounceTimer = void 0;
|
|
4383
4395
|
try {
|
|
4384
|
-
await generate(config);
|
|
4396
|
+
await generate(config, lastRoutes);
|
|
4385
4397
|
} catch (err) {
|
|
4386
4398
|
console.error(
|
|
4387
4399
|
"[nestjs-codegen] Pages generation failed:",
|
|
@@ -4412,6 +4424,7 @@ async function watch(config, onChange) {
|
|
|
4412
4424
|
pendingChangedPaths.clear();
|
|
4413
4425
|
try {
|
|
4414
4426
|
const routes = await (await getDiscovery()).rediscover(changed);
|
|
4427
|
+
lastRoutes = routes;
|
|
4415
4428
|
await generate(config, routes);
|
|
4416
4429
|
} catch (err) {
|
|
4417
4430
|
console.error(
|
|
@@ -4535,7 +4548,7 @@ function createChainModuleRenderer(opts) {
|
|
|
4535
4548
|
}
|
|
4536
4549
|
|
|
4537
4550
|
// src/index.ts
|
|
4538
|
-
var VERSION = "0.
|
|
4551
|
+
var VERSION = "0.7.0";
|
|
4539
4552
|
export {
|
|
4540
4553
|
CodegenError,
|
|
4541
4554
|
ConfigError,
|