@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.
@@ -1,5 +1,5 @@
1
1
  import { DynamicModule, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
2
- import { U as UserConfig } from '../index-oH5t7x4G.cjs';
2
+ import { U as UserConfig } from '../index-DA4uySjo.cjs';
3
3
  import 'ts-morph';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { DynamicModule, OnApplicationBootstrap, OnModuleDestroy } from '@nestjs/common';
2
- import { U as UserConfig } from '../index-oH5t7x4G.js';
2
+ import { U as UserConfig } from '../index-DA4uySjo.js';
3
3
  import 'ts-morph';
4
4
 
5
5
  /**
@@ -310,10 +310,19 @@ function followModuleForType(name, moduleSpecifier, fromFile, project, seen) {
310
310
  }
311
311
  return null;
312
312
  }
313
+ var _findTypeCache = /* @__PURE__ */ new WeakMap();
313
314
  function findType(name, sourceFile, project) {
315
+ let byKey = _findTypeCache.get(project);
316
+ if (byKey === void 0) {
317
+ byKey = /* @__PURE__ */ new Map();
318
+ _findTypeCache.set(project, byKey);
319
+ }
320
+ const key = `${sourceFile.getFilePath()}\0${name}`;
321
+ if (byKey.has(key)) return byKey.get(key) ?? null;
314
322
  const local = findTypeInFile(name, sourceFile);
315
- if (local) return local;
316
- return resolveImportedType(name, sourceFile, project);
323
+ const result = local ?? resolveImportedType(name, sourceFile, project);
324
+ byKey.set(key, result);
325
+ return result;
317
326
  }
318
327
  var _NON_REF_NAMES = /* @__PURE__ */ new Set(["string", "number", "boolean", "void", "unknown", "any", "Date"]);
319
328
  function _localDeclForKinds(name, file, kinds) {
@@ -350,6 +359,26 @@ function resolveTypeRef(nodeOrName, sourceFile, project, opts) {
350
359
  if (_NON_REF_NAMES.has(refName)) return null;
351
360
  name = refName;
352
361
  }
362
+ return _resolveNamedRef(name, sourceFile, project, opts);
363
+ }
364
+ var _resolveNamedRefCache = /* @__PURE__ */ new WeakMap();
365
+ function _resolveNamedRef(name, sourceFile, project, opts) {
366
+ let byKey = _resolveNamedRefCache.get(project);
367
+ if (byKey === void 0) {
368
+ byKey = /* @__PURE__ */ new Map();
369
+ _resolveNamedRefCache.set(project, byKey);
370
+ }
371
+ const kindsKey = [...opts.kinds].sort().join(",");
372
+ const key = `${sourceFile.getFilePath()}\0${name}\0${kindsKey}\0${opts.allowBareSpecifier ? 1 : 0}`;
373
+ if (byKey.has(key)) {
374
+ const cached = byKey.get(key) ?? null;
375
+ return cached ? { ...cached } : null;
376
+ }
377
+ const computed = _computeNamedRef(name, sourceFile, project, opts);
378
+ byKey.set(key, computed);
379
+ return computed ? { ...computed } : null;
380
+ }
381
+ function _computeNamedRef(name, sourceFile, project, opts) {
353
382
  if (_localDeclForKinds(name, sourceFile, opts.kinds)) {
354
383
  return { name, filePath: sourceFile.getFilePath() };
355
384
  }
@@ -427,10 +456,7 @@ function extractSchemaFromDto(classDecl, sourceFile, project) {
427
456
  depth: 0
428
457
  };
429
458
  const root = buildObject(classDecl, sourceFile, ctx);
430
- for (const schemaName of ctx.recursiveSchemas) {
431
- ctx.named.set(schemaName, { kind: "unknown", note: "recursive type \u2014 not expanded" });
432
- }
433
- return { root, named: ctx.named, warnings: ctx.warnings };
459
+ return { root, named: ctx.named, warnings: ctx.warnings, recursive: ctx.recursiveSchemas };
434
460
  }
435
461
  function buildObject(classDecl, classFile, ctx) {
436
462
  const props = classDecl.getProperties();
@@ -450,7 +476,7 @@ function buildProperty(prop, classFile, ctx) {
450
476
  const dec = (n) => decorators.get(n);
451
477
  const typeNode = prop.getTypeNode();
452
478
  const typeText = typeNode?.getText() ?? "unknown";
453
- const isArrayType = !!typeNode && typeNode.getText().endsWith("[]");
479
+ const isArrayType = !!typeNode && Node2.isArrayTypeNode(typeNode);
454
480
  const typeRefName = resolveTypeFactoryName(dec("Type"));
455
481
  if (has("ValidateNested") || typeRefName) {
456
482
  const childName = typeRefName ?? singularClassName(typeText);
@@ -581,18 +607,27 @@ function baseFromType(typeText, isArrayType) {
581
607
  }
582
608
  }
583
609
  function buildNestedReference(className, fromFile, ctx) {
584
- if (ctx.visiting.has(className) || ctx.depth >= 8) {
610
+ if (ctx.visiting.has(className)) {
585
611
  const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);
586
612
  ctx.emittedClasses.set(className, reserved);
587
613
  ctx.recursiveSchemas.add(reserved);
588
614
  if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {
589
615
  ctx.warnedDecorators.add(`recursive:${reserved}`);
590
- const msg = `${className} is a recursive type and was not expanded; the generated schema uses unknown for it.`;
616
+ const msg = `${className} is a recursive type; the generated schema validates it via a lazy self-reference.`;
591
617
  ctx.warnings.push(msg);
592
618
  console.warn(`[nestjs-codegen] ${msg}`);
593
619
  }
594
620
  return { kind: "lazyRef", name: reserved };
595
621
  }
622
+ if (ctx.depth >= 8) {
623
+ if (!ctx.warnedDecorators.has(`deep:${className}`)) {
624
+ ctx.warnedDecorators.add(`deep:${className}`);
625
+ const msg = `${className} nesting is too deep to expand; the generated schema uses unknown for it.`;
626
+ ctx.warnings.push(msg);
627
+ console.warn(`[nestjs-codegen] ${msg}`);
628
+ }
629
+ return { kind: "unknown", note: "nesting too deep \u2014 not expanded" };
630
+ }
596
631
  const existing = ctx.emittedClasses.get(className);
597
632
  if (existing) return { kind: "ref", name: existing };
598
633
  const schemaName = aliasFor(className, ctx);
@@ -723,17 +758,31 @@ import {
723
758
  } from "ts-morph";
724
759
 
725
760
  // src/discovery/enum-resolution.ts
761
+ var _enumCache = /* @__PURE__ */ new WeakMap();
726
762
  function resolveEnumValues(name, sourceFile, project) {
763
+ let byKey = _enumCache.get(project);
764
+ if (byKey === void 0) {
765
+ byKey = /* @__PURE__ */ new Map();
766
+ _enumCache.set(project, byKey);
767
+ }
768
+ const key = `${sourceFile.getFilePath()}\0${name}`;
769
+ if (byKey.has(key)) {
770
+ const cached = byKey.get(key) ?? null;
771
+ return cached ? { values: [...cached.values], numeric: cached.numeric } : null;
772
+ }
727
773
  const resolved = findType(name, sourceFile, project);
728
- if (!resolved || resolved.kind !== "enum") return null;
729
- let numeric = true;
730
- const values = resolved.members.map((m) => {
731
- const parsed = JSON.parse(m);
732
- if (typeof parsed === "string") numeric = false;
733
- return String(parsed);
734
- });
735
- if (values.length === 0) return null;
736
- return { values, numeric };
774
+ let result = null;
775
+ if (resolved && resolved.kind === "enum") {
776
+ let numeric = true;
777
+ const values = resolved.members.map((m) => {
778
+ const parsed = JSON.parse(m);
779
+ if (typeof parsed === "string") numeric = false;
780
+ return String(parsed);
781
+ });
782
+ if (values.length > 0) result = { values, numeric };
783
+ }
784
+ byKey.set(key, result);
785
+ return result ? { values: [...result.values], numeric: result.numeric } : null;
737
786
  }
738
787
 
739
788
  // src/discovery/filter-field-types.ts
@@ -2926,6 +2975,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
2926
2975
  }
2927
2976
  const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);
2928
2977
  const irNamed = /* @__PURE__ */ new Map();
2978
+ const irTypeAliases = /* @__PURE__ */ new Map();
2979
+ const irAnnotations = /* @__PURE__ */ new Map();
2929
2980
  const decls = [];
2930
2981
  const mapEntries = [];
2931
2982
  let used = false;
@@ -2933,6 +2984,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
2933
2984
  if (src.schema) {
2934
2985
  const r = adapter.renderModule(src.schema);
2935
2986
  for (const [n, t] of r.namedNestedSchemas) irNamed.set(n, t);
2987
+ if (r.namedTypeAliases) for (const [n, t] of r.namedTypeAliases) irTypeAliases.set(n, t);
2988
+ if (r.namedAnnotations) for (const [n, a] of r.namedAnnotations) irAnnotations.set(n, a);
2936
2989
  return { text: r.schemaText };
2937
2990
  }
2938
2991
  if (src.zodText) {
@@ -3006,7 +3059,13 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
3006
3059
  for (const [n, t] of irNamed) if (!allNested.has(n)) allNested.set(n, t);
3007
3060
  if (allNested.size > 0) {
3008
3061
  lines.push("// Hoisted nested schemas (shared across endpoints).");
3009
- for (const [n, t] of allNested) lines.push(`const ${n} = ${t};`);
3062
+ for (const [n, alias] of irTypeAliases) {
3063
+ if (allNested.has(n)) lines.push(`${alias};`);
3064
+ }
3065
+ for (const [n, t] of allNested) {
3066
+ const annotation = irAnnotations.get(n);
3067
+ lines.push(`const ${n}${annotation ? `: ${annotation}` : ""} = ${t};`);
3068
+ }
3010
3069
  lines.push("");
3011
3070
  }
3012
3071
  lines.push(...decls);