@dudousxd/nestjs-codegen 0.3.0 → 0.4.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 +27 -0
- package/dist/cli/main.cjs +25 -9
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +25 -9
- 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-oH5t7x4G.d.cts → index-DA4uySjo.d.cts} +29 -1
- package/dist/{index-oH5t7x4G.d.ts → index-DA4uySjo.d.ts} +29 -1
- package/dist/index.cjs +76 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -4
- package/dist/index.d.ts +29 -4
- package/dist/index.js +75 -9
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +24 -8
- 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 +24 -8
- package/dist/nest/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @dudousxd/nestjs-codegen
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ed04cdc: Validate recursive DTOs instead of degrading them to `unknown`.
|
|
8
|
+
|
|
9
|
+
Self/mutually-recursive `@ValidateNested` DTOs (e.g. a `ColumnFilter` whose `and`/`or`
|
|
10
|
+
reference `ColumnFilter[]`) used to be degraded to `unknown` with a warning, dropping all
|
|
11
|
+
client-side validation for that field. They are now expanded with a real lazy schema:
|
|
12
|
+
|
|
13
|
+
- **zod / valibot** hoist a structural TS `type` alias and annotate the recursive const
|
|
14
|
+
(`z.ZodType<T>` / `v.GenericSchema<T>`) so the implicit-any self-reference cycle is broken;
|
|
15
|
+
the recursion site uses `z.lazy` / `v.lazy`.
|
|
16
|
+
- **arktype** uses the native `this` keyword for self-recursion. Mutual recursion (A ↔ B)
|
|
17
|
+
cannot be expressed per-schema without a scope, so the back-edge schema still degrades to
|
|
18
|
+
`unknown` with a clear warning — use the zod or valibot adapter for full validation there.
|
|
19
|
+
|
|
20
|
+
The over-deep nesting guard is now reported separately ("nesting too deep") instead of being
|
|
21
|
+
mislabelled as recursion. The raw-zod `defineContract` path is unchanged.
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- ed04cdc: Fix array detection for union types. A property typed `unknown | unknown[]` (or any
|
|
26
|
+
union whose text happens to end in `[]`) was mistakenly treated as an array and wrapped
|
|
27
|
+
in `z.array(...)`. Array detection now uses the AST (`ArrayTypeNode`) instead of a
|
|
28
|
+
`.endsWith('[]')` text check, so only genuine `T[]` properties become arrays.
|
|
29
|
+
|
|
3
30
|
## 0.3.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
package/dist/cli/main.cjs
CHANGED
|
@@ -1285,6 +1285,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
|
|
|
1285
1285
|
}
|
|
1286
1286
|
const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);
|
|
1287
1287
|
const irNamed = /* @__PURE__ */ new Map();
|
|
1288
|
+
const irTypeAliases = /* @__PURE__ */ new Map();
|
|
1289
|
+
const irAnnotations = /* @__PURE__ */ new Map();
|
|
1288
1290
|
const decls = [];
|
|
1289
1291
|
const mapEntries = [];
|
|
1290
1292
|
let used = false;
|
|
@@ -1292,6 +1294,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
|
|
|
1292
1294
|
if (src.schema) {
|
|
1293
1295
|
const r = adapter.renderModule(src.schema);
|
|
1294
1296
|
for (const [n, t] of r.namedNestedSchemas) irNamed.set(n, t);
|
|
1297
|
+
if (r.namedTypeAliases) for (const [n, t] of r.namedTypeAliases) irTypeAliases.set(n, t);
|
|
1298
|
+
if (r.namedAnnotations) for (const [n, a] of r.namedAnnotations) irAnnotations.set(n, a);
|
|
1295
1299
|
return { text: r.schemaText };
|
|
1296
1300
|
}
|
|
1297
1301
|
if (src.zodText) {
|
|
@@ -1365,7 +1369,13 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
|
|
|
1365
1369
|
for (const [n, t] of irNamed) if (!allNested.has(n)) allNested.set(n, t);
|
|
1366
1370
|
if (allNested.size > 0) {
|
|
1367
1371
|
lines.push("// Hoisted nested schemas (shared across endpoints).");
|
|
1368
|
-
for (const [n,
|
|
1372
|
+
for (const [n, alias] of irTypeAliases) {
|
|
1373
|
+
if (allNested.has(n)) lines.push(`${alias};`);
|
|
1374
|
+
}
|
|
1375
|
+
for (const [n, t] of allNested) {
|
|
1376
|
+
const annotation = irAnnotations.get(n);
|
|
1377
|
+
lines.push(`const ${n}${annotation ? `: ${annotation}` : ""} = ${t};`);
|
|
1378
|
+
}
|
|
1369
1379
|
lines.push("");
|
|
1370
1380
|
}
|
|
1371
1381
|
lines.push(...decls);
|
|
@@ -1907,10 +1917,7 @@ function extractSchemaFromDto(classDecl, sourceFile, project) {
|
|
|
1907
1917
|
depth: 0
|
|
1908
1918
|
};
|
|
1909
1919
|
const root = buildObject(classDecl, sourceFile, ctx);
|
|
1910
|
-
|
|
1911
|
-
ctx.named.set(schemaName, { kind: "unknown", note: "recursive type \u2014 not expanded" });
|
|
1912
|
-
}
|
|
1913
|
-
return { root, named: ctx.named, warnings: ctx.warnings };
|
|
1920
|
+
return { root, named: ctx.named, warnings: ctx.warnings, recursive: ctx.recursiveSchemas };
|
|
1914
1921
|
}
|
|
1915
1922
|
function buildObject(classDecl, classFile, ctx) {
|
|
1916
1923
|
const props = classDecl.getProperties();
|
|
@@ -1930,7 +1937,7 @@ function buildProperty(prop, classFile, ctx) {
|
|
|
1930
1937
|
const dec = (n) => decorators.get(n);
|
|
1931
1938
|
const typeNode = prop.getTypeNode();
|
|
1932
1939
|
const typeText = typeNode?.getText() ?? "unknown";
|
|
1933
|
-
const isArrayType = !!typeNode &&
|
|
1940
|
+
const isArrayType = !!typeNode && import_ts_morph4.Node.isArrayTypeNode(typeNode);
|
|
1934
1941
|
const typeRefName = resolveTypeFactoryName(dec("Type"));
|
|
1935
1942
|
if (has("ValidateNested") || typeRefName) {
|
|
1936
1943
|
const childName = typeRefName ?? singularClassName(typeText);
|
|
@@ -2061,18 +2068,27 @@ function baseFromType(typeText, isArrayType) {
|
|
|
2061
2068
|
}
|
|
2062
2069
|
}
|
|
2063
2070
|
function buildNestedReference(className, fromFile, ctx) {
|
|
2064
|
-
if (ctx.visiting.has(className)
|
|
2071
|
+
if (ctx.visiting.has(className)) {
|
|
2065
2072
|
const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);
|
|
2066
2073
|
ctx.emittedClasses.set(className, reserved);
|
|
2067
2074
|
ctx.recursiveSchemas.add(reserved);
|
|
2068
2075
|
if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {
|
|
2069
2076
|
ctx.warnedDecorators.add(`recursive:${reserved}`);
|
|
2070
|
-
const msg = `${className} is a recursive type
|
|
2077
|
+
const msg = `${className} is a recursive type; the generated schema validates it via a lazy self-reference.`;
|
|
2071
2078
|
ctx.warnings.push(msg);
|
|
2072
2079
|
console.warn(`[nestjs-codegen] ${msg}`);
|
|
2073
2080
|
}
|
|
2074
2081
|
return { kind: "lazyRef", name: reserved };
|
|
2075
2082
|
}
|
|
2083
|
+
if (ctx.depth >= 8) {
|
|
2084
|
+
if (!ctx.warnedDecorators.has(`deep:${className}`)) {
|
|
2085
|
+
ctx.warnedDecorators.add(`deep:${className}`);
|
|
2086
|
+
const msg = `${className} nesting is too deep to expand; the generated schema uses unknown for it.`;
|
|
2087
|
+
ctx.warnings.push(msg);
|
|
2088
|
+
console.warn(`[nestjs-codegen] ${msg}`);
|
|
2089
|
+
}
|
|
2090
|
+
return { kind: "unknown", note: "nesting too deep \u2014 not expanded" };
|
|
2091
|
+
}
|
|
2076
2092
|
const existing = ctx.emittedClasses.get(className);
|
|
2077
2093
|
if (existing) return { kind: "ref", name: existing };
|
|
2078
2094
|
const schemaName = aliasFor(className, ctx);
|
|
@@ -3478,7 +3494,7 @@ async function watch(config, onChange) {
|
|
|
3478
3494
|
}
|
|
3479
3495
|
|
|
3480
3496
|
// src/index.ts
|
|
3481
|
-
var VERSION = "0.
|
|
3497
|
+
var VERSION = "0.4.0";
|
|
3482
3498
|
|
|
3483
3499
|
// src/cli/codegen.ts
|
|
3484
3500
|
async function runCodegen(opts = {}) {
|