@dudousxd/nestjs-codegen 0.5.0 → 0.5.2

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/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { U as UserConfig, R as ResolvedConfig, a as RouteDescriptor, S as SchemaNode, b as SchemaModule, c as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext } from './index-B0mS84Jj.cjs';
2
- export { A as AdapterUsage, d as ContractDescriptor, e as ContractSource, f as ControllerRef, N as NumberCheck, g as RenderContext, h as RenderedModule, i as ScopeConfig, j as StringCheck, T as TypeRef, k as ValidationOption, r as resolveAdapter } from './index-B0mS84Jj.cjs';
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-_qRai4M3.cjs';
2
+ export { A as AdapterUsage, f as ContractDescriptor, g as ContractSource, h as ControllerRef, N as NumberCheck, i as ScopeConfig, j as StringCheck, T as TypeRef, k as ValidationOption, r as resolveAdapter } from './index-_qRai4M3.cjs';
3
3
  import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
4
4
 
5
5
  declare function defineConfig(c: UserConfig): UserConfig;
@@ -98,6 +98,31 @@ interface TsTypeContext {
98
98
  }
99
99
  declare function renderTsType(node: SchemaNode, ctx: TsTypeContext): string;
100
100
 
101
+ /** Schema const name → hoisted TS type-alias name (`ColumnFilterSchema` → `ColumnFilter`). */
102
+ declare function typeNameFor(schemaName: string): string;
103
+ /** Valid JS identifier → bare key, else quoted. */
104
+ declare function toObjectKey(name: string): string;
105
+ interface ChainModuleRendererOptions {
106
+ /** The adapter's node renderer (used for both the root and each hoisted named schema). */
107
+ render(node: SchemaNode, ctx: RenderContext): string;
108
+ /**
109
+ * Const type annotation for a recursive schema, e.g. `z.ZodType<ColumnFilter>`
110
+ * or `v.GenericSchema<ColumnFilter>`, emitted as `const <name>: <annotation> = ...`
111
+ * to break the implicit-any self-reference cycle.
112
+ */
113
+ recursiveAnnotation(typeName: string): string;
114
+ }
115
+ /**
116
+ * Builds the `renderModule` for a method-chain / pipe-style adapter (zod, valibot):
117
+ * render the root and every hoisted named schema, and for each recursive schema emit
118
+ * a structural `type` alias plus a const annotation. The only thing these adapters
119
+ * differ on is the annotation text, supplied via {@link ChainModuleRendererOptions.recursiveAnnotation};
120
+ * everything else (the alias-name derivation, the recursive-set handling, the
121
+ * `renderTsType` lowering) is identical. arktype does not use this — its module
122
+ * rendering degrades mutually-recursive cycles and emits no type aliases.
123
+ */
124
+ declare function createChainModuleRenderer(opts: ChainModuleRendererOptions): (mod: SchemaModule) => RenderedModule;
125
+
101
126
  /**
102
127
  * Pure-AST translation of class-validator-decorated DTO classes into the neutral
103
128
  * {@link SchemaModule} IR. Reads decorator names + literal args via ts-morph — it
@@ -264,6 +289,6 @@ interface FastDiscoveryOptions {
264
289
  }
265
290
  declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
266
291
 
267
- declare const VERSION = "0.5.0";
292
+ declare const VERSION = "0.5.2";
268
293
 
269
- export { CodegenError, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, watch };
294
+ 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 SchemaModule, c as ResolvedFormsConfig, V as ValidationAdapter, C as CodegenExtension, E as ExtensionContext } from './index-B0mS84Jj.js';
2
- export { A as AdapterUsage, d as ContractDescriptor, e as ContractSource, f as ControllerRef, N as NumberCheck, g as RenderContext, h as RenderedModule, i as ScopeConfig, j as StringCheck, T as TypeRef, k as ValidationOption, r as resolveAdapter } from './index-B0mS84Jj.js';
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-_qRai4M3.js';
2
+ export { A as AdapterUsage, f as ContractDescriptor, g as ContractSource, h as ControllerRef, N as NumberCheck, i as ScopeConfig, j as StringCheck, T as TypeRef, k as ValidationOption, r as resolveAdapter } from './index-_qRai4M3.js';
3
3
  import { ClassDeclaration, SourceFile, Project } from 'ts-morph';
4
4
 
5
5
  declare function defineConfig(c: UserConfig): UserConfig;
@@ -98,6 +98,31 @@ interface TsTypeContext {
98
98
  }
99
99
  declare function renderTsType(node: SchemaNode, ctx: TsTypeContext): string;
100
100
 
101
+ /** Schema const name → hoisted TS type-alias name (`ColumnFilterSchema` → `ColumnFilter`). */
102
+ declare function typeNameFor(schemaName: string): string;
103
+ /** Valid JS identifier → bare key, else quoted. */
104
+ declare function toObjectKey(name: string): string;
105
+ interface ChainModuleRendererOptions {
106
+ /** The adapter's node renderer (used for both the root and each hoisted named schema). */
107
+ render(node: SchemaNode, ctx: RenderContext): string;
108
+ /**
109
+ * Const type annotation for a recursive schema, e.g. `z.ZodType<ColumnFilter>`
110
+ * or `v.GenericSchema<ColumnFilter>`, emitted as `const <name>: <annotation> = ...`
111
+ * to break the implicit-any self-reference cycle.
112
+ */
113
+ recursiveAnnotation(typeName: string): string;
114
+ }
115
+ /**
116
+ * Builds the `renderModule` for a method-chain / pipe-style adapter (zod, valibot):
117
+ * render the root and every hoisted named schema, and for each recursive schema emit
118
+ * a structural `type` alias plus a const annotation. The only thing these adapters
119
+ * differ on is the annotation text, supplied via {@link ChainModuleRendererOptions.recursiveAnnotation};
120
+ * everything else (the alias-name derivation, the recursive-set handling, the
121
+ * `renderTsType` lowering) is identical. arktype does not use this — its module
122
+ * rendering degrades mutually-recursive cycles and emits no type aliases.
123
+ */
124
+ declare function createChainModuleRenderer(opts: ChainModuleRendererOptions): (mod: SchemaModule) => RenderedModule;
125
+
101
126
  /**
102
127
  * Pure-AST translation of class-validator-decorated DTO classes into the neutral
103
128
  * {@link SchemaModule} IR. Reads decorator names + literal args via ts-morph — it
@@ -264,6 +289,6 @@ interface FastDiscoveryOptions {
264
289
  }
265
290
  declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
266
291
 
267
- declare const VERSION = "0.5.0";
292
+ declare const VERSION = "0.5.2";
268
293
 
269
- export { CodegenError, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, watch };
294
+ 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
@@ -1159,18 +1159,27 @@ function refRootIdentifier(refName) {
1159
1159
  function hasSource(src) {
1160
1160
  return !!(src.schema || src.zodText || src.zodRef);
1161
1161
  }
1162
+ function escapeRegExp(s) {
1163
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1164
+ }
1165
+ var wordBoundaryRegexCache = /* @__PURE__ */ new Map();
1166
+ function wordBoundaryRegex(token) {
1167
+ let re = wordBoundaryRegexCache.get(token);
1168
+ if (re === void 0) {
1169
+ re = new RegExp(`\\b${escapeRegExp(token)}\\b`, "g");
1170
+ wordBoundaryRegexCache.set(token, re);
1171
+ }
1172
+ return re;
1173
+ }
1162
1174
  function applyRenames(text, renames) {
1163
1175
  if (!renames || renames.size === 0) return text;
1164
1176
  let out = text;
1165
1177
  for (const [from, to] of renames) {
1166
1178
  if (from === to) continue;
1167
- out = out.replace(new RegExp(`\\b${escapeRegExp(from)}\\b`, "g"), to);
1179
+ out = out.replace(wordBoundaryRegex(from), to);
1168
1180
  }
1169
1181
  return out;
1170
1182
  }
1171
- function escapeRegExp(s) {
1172
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1173
- }
1174
1183
  function isSelfReferential(name, text) {
1175
1184
  return new RegExp(`\\b${escapeRegExp(name)}\\b`).test(text);
1176
1185
  }
@@ -1182,7 +1191,23 @@ function planNestedSchemas(entries) {
1182
1191
  const local = Object.entries(entry.nestedSchemas);
1183
1192
  if (local.length === 0) continue;
1184
1193
  const rename = /* @__PURE__ */ new Map();
1185
- for (const [name] of local) rename.set(name, name);
1194
+ const renameValues = /* @__PURE__ */ new Set();
1195
+ const setRename = (key, value) => {
1196
+ const prev = rename.get(key);
1197
+ rename.set(key, value);
1198
+ if (prev !== void 0 && prev !== value) {
1199
+ let stillUsed = false;
1200
+ for (const v of rename.values()) {
1201
+ if (v === prev) {
1202
+ stillUsed = true;
1203
+ break;
1204
+ }
1205
+ }
1206
+ if (!stillUsed) renameValues.delete(prev);
1207
+ }
1208
+ renameValues.add(value);
1209
+ };
1210
+ for (const [name] of local) setRename(name, name);
1186
1211
  const textFor = (name) => {
1187
1212
  const raw = entry.nestedSchemas?.[name] ?? "";
1188
1213
  return applyRenames(raw, rename);
@@ -1200,11 +1225,11 @@ function planNestedSchemas(entries) {
1200
1225
  if (existing === text) continue;
1201
1226
  let i = 2;
1202
1227
  let candidate = `${name}_${i}`;
1203
- while (globalSchemas.has(candidate) && globalSchemas.get(candidate) !== textFor(name) || [...rename.values()].includes(candidate)) {
1228
+ while (globalSchemas.has(candidate) && globalSchemas.get(candidate) !== textFor(name) || renameValues.has(candidate)) {
1204
1229
  i += 1;
1205
1230
  candidate = `${name}_${i}`;
1206
1231
  }
1207
- rename.set(name, candidate);
1232
+ setRename(name, candidate);
1208
1233
  changed = true;
1209
1234
  }
1210
1235
  }
@@ -2502,6 +2527,7 @@ function extractSchemaFromDto(classDecl, sourceFile, project) {
2502
2527
  warnings: [],
2503
2528
  warnedDecorators: /* @__PURE__ */ new Set(),
2504
2529
  emittedClasses: /* @__PURE__ */ new Map(),
2530
+ usedSchemaNames: /* @__PURE__ */ new Set(),
2505
2531
  visiting: /* @__PURE__ */ new Set(),
2506
2532
  recursiveSchemas: /* @__PURE__ */ new Set(),
2507
2533
  depth: 0,
@@ -2529,37 +2555,28 @@ function buildProperty(prop, classFile, ctx) {
2529
2555
  const typeNode = prop.getTypeNode();
2530
2556
  const typeText = typeNode?.getText() ?? "unknown";
2531
2557
  const isArrayType = !!typeNode && Node3.isArrayTypeNode(typeNode);
2558
+ const asField = (child) => applyPresence(
2559
+ has("IsArray") || isArrayType ? { kind: "array", element: child } : child,
2560
+ decorators
2561
+ );
2532
2562
  const discriminator = resolveDiscriminator(dec("Type"));
2533
2563
  if (discriminator) {
2534
2564
  const options = discriminator.subTypes.map(
2535
2565
  (name) => buildNestedReference(name, classFile, ctx)
2536
2566
  );
2537
- const unionNode = {
2538
- kind: "union",
2539
- options,
2540
- discriminator: discriminator.property
2541
- };
2542
- const wrapArray = has("IsArray") || isArrayType;
2543
- const node2 = wrapArray ? { kind: "array", element: unionNode } : unionNode;
2544
- return applyPresence(node2, decorators);
2567
+ return asField({ kind: "union", options, discriminator: discriminator.property });
2545
2568
  }
2546
2569
  const propTypeParam = singularClassName(typeText);
2547
2570
  if (propTypeParam && ctx.typeBindings.has(propTypeParam)) {
2548
2571
  const bound = ctx.typeBindings.get(propTypeParam);
2549
- const childNode = buildNestedReference(bound, classFile, ctx);
2550
- const wrapArray = has("IsArray") || isArrayType;
2551
- const node2 = wrapArray ? { kind: "array", element: childNode } : childNode;
2552
- return applyPresence(node2, decorators);
2572
+ return asField(buildNestedReference(bound, classFile, ctx));
2553
2573
  }
2554
2574
  const typeRefName = resolveTypeFactoryName(dec("Type"));
2555
2575
  if (has("ValidateNested") || typeRefName) {
2556
2576
  const typeArgs = genericTypeArgNames(typeNode);
2557
2577
  const childName = typeRefName ?? singularClassName(typeText);
2558
2578
  if (childName) {
2559
- const childNode = buildNestedReference(childName, classFile, ctx, typeArgs);
2560
- const wrapArray = has("IsArray") || isArrayType;
2561
- const node2 = wrapArray ? { kind: "array", element: childNode } : childNode;
2562
- return applyPresence(node2, decorators);
2579
+ return asField(buildNestedReference(childName, classFile, ctx, typeArgs));
2563
2580
  }
2564
2581
  }
2565
2582
  let base = baseFromType(typeText, isArrayType);
@@ -2687,6 +2704,7 @@ function buildNestedReference(className, fromFile, ctx, typeArgs = []) {
2687
2704
  if (ctx.visiting.has(cacheKey)) {
2688
2705
  const reserved = ctx.emittedClasses.get(cacheKey) ?? aliasFor(schemaBase, ctx);
2689
2706
  ctx.emittedClasses.set(cacheKey, reserved);
2707
+ ctx.usedSchemaNames.add(reserved);
2690
2708
  ctx.recursiveSchemas.add(reserved);
2691
2709
  if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {
2692
2710
  ctx.warnedDecorators.add(`recursive:${reserved}`);
@@ -2720,6 +2738,7 @@ function buildNestedReference(className, fromFile, ctx, typeArgs = []) {
2720
2738
  });
2721
2739
  for (const [k, v] of newBindings) ctx.typeBindings.set(k, v);
2722
2740
  ctx.emittedClasses.set(cacheKey, schemaName);
2741
+ ctx.usedSchemaNames.add(schemaName);
2723
2742
  ctx.visiting.add(cacheKey);
2724
2743
  ctx.depth += 1;
2725
2744
  const childNode = buildObject(resolved.decl, resolved.file, ctx);
@@ -2727,15 +2746,14 @@ function buildNestedReference(className, fromFile, ctx, typeArgs = []) {
2727
2746
  ctx.visiting.delete(cacheKey);
2728
2747
  for (const [k] of newBindings) ctx.typeBindings.delete(k);
2729
2748
  ctx.named.set(schemaName, childNode);
2749
+ ctx.usedSchemaNames.add(schemaName);
2730
2750
  return { kind: "ref", name: schemaName };
2731
2751
  }
2732
2752
  function aliasFor(className, ctx) {
2733
2753
  const baseName = `${className}Schema`;
2734
2754
  let candidate = baseName;
2735
2755
  let i = 1;
2736
- const used = new Set(ctx.named.keys());
2737
- for (const v of ctx.emittedClasses.values()) used.add(v);
2738
- while (used.has(candidate)) {
2756
+ while (ctx.usedSchemaNames.has(candidate)) {
2739
2757
  candidate = `${baseName}_${i}`;
2740
2758
  i += 1;
2741
2759
  }
@@ -4467,8 +4485,42 @@ function renderTsType(node, ctx) {
4467
4485
  }
4468
4486
  }
4469
4487
 
4488
+ // src/adapters/chain-module.ts
4489
+ function typeNameFor(schemaName) {
4490
+ return schemaName.replace(/Schema(_\d+)?$/, "$1");
4491
+ }
4492
+ function toObjectKey2(name) {
4493
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
4494
+ }
4495
+ function createChainModuleRenderer(opts) {
4496
+ const { render, recursiveAnnotation } = opts;
4497
+ return (mod) => {
4498
+ const ctx = { named: mod.named };
4499
+ const recursive = mod.recursive ?? /* @__PURE__ */ new Set();
4500
+ const tctx = { named: mod.named, recursive, typeNameFor };
4501
+ const namedNestedSchemas = /* @__PURE__ */ new Map();
4502
+ const namedTypeAliases = /* @__PURE__ */ new Map();
4503
+ const namedAnnotations = /* @__PURE__ */ new Map();
4504
+ for (const [name, node] of mod.named) {
4505
+ namedNestedSchemas.set(name, render(node, ctx));
4506
+ if (recursive.has(name)) {
4507
+ const typeName = typeNameFor(name);
4508
+ namedTypeAliases.set(name, `type ${typeName} = ${renderTsType(node, tctx)}`);
4509
+ namedAnnotations.set(name, recursiveAnnotation(typeName));
4510
+ }
4511
+ }
4512
+ return {
4513
+ schemaText: render(mod.root, ctx),
4514
+ namedNestedSchemas,
4515
+ namedTypeAliases,
4516
+ namedAnnotations,
4517
+ warnings: mod.warnings
4518
+ };
4519
+ };
4520
+ }
4521
+
4470
4522
  // src/index.ts
4471
- var VERSION = "0.5.0";
4523
+ var VERSION = "0.5.2";
4472
4524
  export {
4473
4525
  CodegenError,
4474
4526
  ConfigError,
@@ -4476,6 +4528,7 @@ export {
4476
4528
  acquireLock,
4477
4529
  buildMocksFile,
4478
4530
  buildOpenApiSpec,
4531
+ createChainModuleRenderer,
4479
4532
  defineConfig,
4480
4533
  discoverContractsFast,
4481
4534
  emitApi,
@@ -4491,6 +4544,8 @@ export {
4491
4544
  resolveConfig,
4492
4545
  schemaModuleToJsonSchema,
4493
4546
  schemaNodeToJsonSchema,
4547
+ toObjectKey2 as toObjectKey,
4548
+ typeNameFor,
4494
4549
  watch
4495
4550
  };
4496
4551
  //# sourceMappingURL=index.js.map