@dudousxd/nestjs-codegen 0.3.0 → 0.4.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/dist/cli/main.js CHANGED
@@ -1251,6 +1251,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
1251
1251
  }
1252
1252
  const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);
1253
1253
  const irNamed = /* @__PURE__ */ new Map();
1254
+ const irTypeAliases = /* @__PURE__ */ new Map();
1255
+ const irAnnotations = /* @__PURE__ */ new Map();
1254
1256
  const decls = [];
1255
1257
  const mapEntries = [];
1256
1258
  let used = false;
@@ -1258,6 +1260,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
1258
1260
  if (src.schema) {
1259
1261
  const r = adapter.renderModule(src.schema);
1260
1262
  for (const [n, t] of r.namedNestedSchemas) irNamed.set(n, t);
1263
+ if (r.namedTypeAliases) for (const [n, t] of r.namedTypeAliases) irTypeAliases.set(n, t);
1264
+ if (r.namedAnnotations) for (const [n, a] of r.namedAnnotations) irAnnotations.set(n, a);
1261
1265
  return { text: r.schemaText };
1262
1266
  }
1263
1267
  if (src.zodText) {
@@ -1331,7 +1335,13 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
1331
1335
  for (const [n, t] of irNamed) if (!allNested.has(n)) allNested.set(n, t);
1332
1336
  if (allNested.size > 0) {
1333
1337
  lines.push("// Hoisted nested schemas (shared across endpoints).");
1334
- for (const [n, t] of allNested) lines.push(`const ${n} = ${t};`);
1338
+ for (const [n, alias] of irTypeAliases) {
1339
+ if (allNested.has(n)) lines.push(`${alias};`);
1340
+ }
1341
+ for (const [n, t] of allNested) {
1342
+ const annotation = irAnnotations.get(n);
1343
+ lines.push(`const ${n}${annotation ? `: ${annotation}` : ""} = ${t};`);
1344
+ }
1335
1345
  lines.push("");
1336
1346
  }
1337
1347
  lines.push(...decls);
@@ -1766,10 +1776,19 @@ function followModuleForType(name, moduleSpecifier, fromFile, project, seen) {
1766
1776
  }
1767
1777
  return null;
1768
1778
  }
1779
+ var _findTypeCache = /* @__PURE__ */ new WeakMap();
1769
1780
  function findType(name, sourceFile, project) {
1781
+ let byKey = _findTypeCache.get(project);
1782
+ if (byKey === void 0) {
1783
+ byKey = /* @__PURE__ */ new Map();
1784
+ _findTypeCache.set(project, byKey);
1785
+ }
1786
+ const key = `${sourceFile.getFilePath()}\0${name}`;
1787
+ if (byKey.has(key)) return byKey.get(key) ?? null;
1770
1788
  const local = findTypeInFile(name, sourceFile);
1771
- if (local) return local;
1772
- return resolveImportedType(name, sourceFile, project);
1789
+ const result = local ?? resolveImportedType(name, sourceFile, project);
1790
+ byKey.set(key, result);
1791
+ return result;
1773
1792
  }
1774
1793
  var _NON_REF_NAMES = /* @__PURE__ */ new Set(["string", "number", "boolean", "void", "unknown", "any", "Date"]);
1775
1794
  function _localDeclForKinds(name, file, kinds) {
@@ -1806,6 +1825,26 @@ function resolveTypeRef(nodeOrName, sourceFile, project, opts) {
1806
1825
  if (_NON_REF_NAMES.has(refName)) return null;
1807
1826
  name = refName;
1808
1827
  }
1828
+ return _resolveNamedRef(name, sourceFile, project, opts);
1829
+ }
1830
+ var _resolveNamedRefCache = /* @__PURE__ */ new WeakMap();
1831
+ function _resolveNamedRef(name, sourceFile, project, opts) {
1832
+ let byKey = _resolveNamedRefCache.get(project);
1833
+ if (byKey === void 0) {
1834
+ byKey = /* @__PURE__ */ new Map();
1835
+ _resolveNamedRefCache.set(project, byKey);
1836
+ }
1837
+ const kindsKey = [...opts.kinds].sort().join(",");
1838
+ const key = `${sourceFile.getFilePath()}\0${name}\0${kindsKey}\0${opts.allowBareSpecifier ? 1 : 0}`;
1839
+ if (byKey.has(key)) {
1840
+ const cached = byKey.get(key) ?? null;
1841
+ return cached ? { ...cached } : null;
1842
+ }
1843
+ const computed = _computeNamedRef(name, sourceFile, project, opts);
1844
+ byKey.set(key, computed);
1845
+ return computed ? { ...computed } : null;
1846
+ }
1847
+ function _computeNamedRef(name, sourceFile, project, opts) {
1809
1848
  if (_localDeclForKinds(name, sourceFile, opts.kinds)) {
1810
1849
  return { name, filePath: sourceFile.getFilePath() };
1811
1850
  }
@@ -1883,10 +1922,7 @@ function extractSchemaFromDto(classDecl, sourceFile, project) {
1883
1922
  depth: 0
1884
1923
  };
1885
1924
  const root = buildObject(classDecl, sourceFile, ctx);
1886
- for (const schemaName of ctx.recursiveSchemas) {
1887
- ctx.named.set(schemaName, { kind: "unknown", note: "recursive type \u2014 not expanded" });
1888
- }
1889
- return { root, named: ctx.named, warnings: ctx.warnings };
1925
+ return { root, named: ctx.named, warnings: ctx.warnings, recursive: ctx.recursiveSchemas };
1890
1926
  }
1891
1927
  function buildObject(classDecl, classFile, ctx) {
1892
1928
  const props = classDecl.getProperties();
@@ -1906,7 +1942,7 @@ function buildProperty(prop, classFile, ctx) {
1906
1942
  const dec = (n) => decorators.get(n);
1907
1943
  const typeNode = prop.getTypeNode();
1908
1944
  const typeText = typeNode?.getText() ?? "unknown";
1909
- const isArrayType = !!typeNode && typeNode.getText().endsWith("[]");
1945
+ const isArrayType = !!typeNode && Node3.isArrayTypeNode(typeNode);
1910
1946
  const typeRefName = resolveTypeFactoryName(dec("Type"));
1911
1947
  if (has("ValidateNested") || typeRefName) {
1912
1948
  const childName = typeRefName ?? singularClassName(typeText);
@@ -2037,18 +2073,27 @@ function baseFromType(typeText, isArrayType) {
2037
2073
  }
2038
2074
  }
2039
2075
  function buildNestedReference(className, fromFile, ctx) {
2040
- if (ctx.visiting.has(className) || ctx.depth >= 8) {
2076
+ if (ctx.visiting.has(className)) {
2041
2077
  const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);
2042
2078
  ctx.emittedClasses.set(className, reserved);
2043
2079
  ctx.recursiveSchemas.add(reserved);
2044
2080
  if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {
2045
2081
  ctx.warnedDecorators.add(`recursive:${reserved}`);
2046
- const msg = `${className} is a recursive type and was not expanded; the generated schema uses unknown for it.`;
2082
+ const msg = `${className} is a recursive type; the generated schema validates it via a lazy self-reference.`;
2047
2083
  ctx.warnings.push(msg);
2048
2084
  console.warn(`[nestjs-codegen] ${msg}`);
2049
2085
  }
2050
2086
  return { kind: "lazyRef", name: reserved };
2051
2087
  }
2088
+ if (ctx.depth >= 8) {
2089
+ if (!ctx.warnedDecorators.has(`deep:${className}`)) {
2090
+ ctx.warnedDecorators.add(`deep:${className}`);
2091
+ const msg = `${className} nesting is too deep to expand; the generated schema uses unknown for it.`;
2092
+ ctx.warnings.push(msg);
2093
+ console.warn(`[nestjs-codegen] ${msg}`);
2094
+ }
2095
+ return { kind: "unknown", note: "nesting too deep \u2014 not expanded" };
2096
+ }
2052
2097
  const existing = ctx.emittedClasses.get(className);
2053
2098
  if (existing) return { kind: "ref", name: existing };
2054
2099
  const schemaName = aliasFor(className, ctx);
@@ -2179,17 +2224,31 @@ import {
2179
2224
  } from "ts-morph";
2180
2225
 
2181
2226
  // src/discovery/enum-resolution.ts
2227
+ var _enumCache = /* @__PURE__ */ new WeakMap();
2182
2228
  function resolveEnumValues(name, sourceFile, project) {
2229
+ let byKey = _enumCache.get(project);
2230
+ if (byKey === void 0) {
2231
+ byKey = /* @__PURE__ */ new Map();
2232
+ _enumCache.set(project, byKey);
2233
+ }
2234
+ const key = `${sourceFile.getFilePath()}\0${name}`;
2235
+ if (byKey.has(key)) {
2236
+ const cached = byKey.get(key) ?? null;
2237
+ return cached ? { values: [...cached.values], numeric: cached.numeric } : null;
2238
+ }
2183
2239
  const resolved = findType(name, sourceFile, project);
2184
- if (!resolved || resolved.kind !== "enum") return null;
2185
- let numeric = true;
2186
- const values = resolved.members.map((m) => {
2187
- const parsed = JSON.parse(m);
2188
- if (typeof parsed === "string") numeric = false;
2189
- return String(parsed);
2190
- });
2191
- if (values.length === 0) return null;
2192
- return { values, numeric };
2240
+ let result = null;
2241
+ if (resolved && resolved.kind === "enum") {
2242
+ let numeric = true;
2243
+ const values = resolved.members.map((m) => {
2244
+ const parsed = JSON.parse(m);
2245
+ if (typeof parsed === "string") numeric = false;
2246
+ return String(parsed);
2247
+ });
2248
+ if (values.length > 0) result = { values, numeric };
2249
+ }
2250
+ byKey.set(key, result);
2251
+ return result ? { values: [...result.values], numeric: result.numeric } : null;
2193
2252
  }
2194
2253
 
2195
2254
  // src/discovery/filter-field-types.ts
@@ -3459,7 +3518,7 @@ async function watch(config, onChange) {
3459
3518
  }
3460
3519
 
3461
3520
  // src/index.ts
3462
- var VERSION = "0.3.0";
3521
+ var VERSION = "0.4.1";
3463
3522
 
3464
3523
  // src/cli/codegen.ts
3465
3524
  async function runCodegen(opts = {}) {