next-openapi-gen 1.2.0 → 1.2.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/README.md CHANGED
@@ -184,6 +184,23 @@ z.number()
184
184
 
185
185
  Both work inside `z.object({...})` properties, in drizzle-zod override callbacks, and at the top level of named schemas. See [docs/zod4-support-matrix.md](./docs/zod4-support-matrix.md) for the full supported metadata surface.
186
186
 
187
+ ### Decouple component names from source identifiers
188
+
189
+ Use `.meta({ id })` for Zod schemas or `/** @id */` for TypeScript types to set the OpenAPI component name independently of the export name — useful when enforcing PascalCase naming or migrating from another generator without renaming existing exports:
190
+
191
+ ```ts
192
+ // Zod: use .meta({ id }) to decouple the component name from the variable name
193
+ export const audioSchema = z.object({ ... }).meta({ id: "Audio" });
194
+ // → components.schemas.Audio (not: audioSchema)
195
+
196
+ // TypeScript: use /** @id */ at the declaration level
197
+ /** @id Audio */
198
+ export interface AudioInterface { ... }
199
+ // → components.schemas.Audio (not: AudioInterface)
200
+ ```
201
+
202
+ Existing `@body audioSchema` or `@response audioSchema` references in route handlers continue to work — the generator resolves them transparently to the override name. See [docs/jsdoc-reference.md#component-naming](./docs/jsdoc-reference.md#component-naming) for details.
203
+
187
204
  ### Generate docs from Drizzle schemas
188
205
 
189
206
  `next-openapi-gen` works well with `drizzle-zod`, so your database schema, validation, and API docs can share the same source of truth.
package/dist/cli.js CHANGED
@@ -1406,6 +1406,17 @@ function mergeJSDocData(target, source) {
1406
1406
  function cleanComment(commentValue) {
1407
1407
  return commentValue.replace(/\*\s*/g, "").trim();
1408
1408
  }
1409
+ function extractSchemaIdFromComments(comments) {
1410
+ if (!comments)
1411
+ return null;
1412
+ for (const comment of comments) {
1413
+ const cleaned = cleanComment(comment.value);
1414
+ const id = extractTokenValue(cleaned, "@id");
1415
+ if (id)
1416
+ return id;
1417
+ }
1418
+ return null;
1419
+ }
1409
1420
  function extractLineValue(commentValue, tag) {
1410
1421
  return commentValue.match(new RegExp(`${escapeRegExp(tag)}\\s*(.*)`, "m"))?.[1]?.trim() || "";
1411
1422
  }
@@ -3585,7 +3596,8 @@ var DrizzleZodProcessor = class _DrizzleZodProcessor {
3585
3596
  if (firstArg && !t4.isSpreadElement(firstArg) && !t4.isArgumentPlaceholder(firstArg)) {
3586
3597
  const metadata = _DrizzleZodProcessor.extractStaticObject(firstArg);
3587
3598
  if (metadata) {
3588
- Object.assign(result, metadata);
3599
+ const { id: _id, ...rest } = metadata;
3600
+ Object.assign(result, rest);
3589
3601
  }
3590
3602
  }
3591
3603
  break;
@@ -11869,8 +11881,11 @@ var ZodRuntimeExporter = class {
11869
11881
  case "deprecated":
11870
11882
  return schema.meta({ deprecated: true });
11871
11883
  case "meta": {
11872
- const metadata = node.arguments[0] ? this.buildMetadataObject(node.arguments[0]) : null;
11873
- return metadata ? schema.meta(metadata) : schema;
11884
+ const rawMetadata = node.arguments[0] ? this.buildMetadataObject(node.arguments[0]) : null;
11885
+ if (!rawMetadata)
11886
+ return schema;
11887
+ const { id: _id, ...metadata } = rawMetadata;
11888
+ return Object.keys(metadata).length > 0 ? schema.meta(metadata) : schema;
11874
11889
  }
11875
11890
  case "default":
11876
11891
  case "prefault":
@@ -12106,7 +12121,9 @@ var ZodSchemaConverter = class {
12106
12121
  apiDir;
12107
12122
  zodSchemas = {};
12108
12123
  processingSchemas = /* @__PURE__ */ new Set();
12109
- processedModules = /* @__PURE__ */ new Set();
12124
+ /** Memoization guard for processFileForZodSchema. Keys: `${filePath}|${schemaName}`.
12125
+ * Prevents infinite recursion when re-export files reference schemas via z.infer<typeof X>. */
12126
+ processedFileSchemaPairs = /* @__PURE__ */ new Set();
12110
12127
  typeToSchemaMapping = {};
12111
12128
  drizzleZodImports = /* @__PURE__ */ new Set();
12112
12129
  factoryCache = /* @__PURE__ */ new Map();
@@ -12320,6 +12337,11 @@ var ZodSchemaConverter = class {
12320
12337
  * Process a file to find Zod schema definitions
12321
12338
  */
12322
12339
  processFileForZodSchema(filePath, schemaName) {
12340
+ const visitKey = `${filePath}|${schemaName}|${this.currentContentType}`;
12341
+ if (this.processedFileSchemaPairs.has(visitKey)) {
12342
+ return;
12343
+ }
12344
+ this.processedFileSchemaPairs.add(visitKey);
12323
12345
  try {
12324
12346
  const content = this.fileAccess.readFileSync(filePath, "utf-8");
12325
12347
  if (!content.includes(schemaName)) {
@@ -12633,7 +12655,9 @@ var ZodSchemaConverter = class {
12633
12655
  const param = path25.node.typeAnnotation.typeParameters.params[0];
12634
12656
  if (t10.isTSTypeQuery(param) && t10.isIdentifier(param.exprName)) {
12635
12657
  const referencedSchemaName = param.exprName.name;
12636
- this.processFileForZodSchema(filePath, referencedSchemaName);
12658
+ if (!this.getStoredSchema(referencedSchemaName)) {
12659
+ this.processFileForZodSchema(filePath, referencedSchemaName);
12660
+ }
12637
12661
  }
12638
12662
  }
12639
12663
  }
@@ -12651,6 +12675,8 @@ var ZodSchemaConverter = class {
12651
12675
  try {
12652
12676
  const content = this.fileAccess.readFileSync(filePath, "utf-8");
12653
12677
  const ast = parseTypeScriptFile(content);
12678
+ this.currentFilePath = filePath;
12679
+ this.currentAST = ast;
12654
12680
  resolvedTraverse(ast, {
12655
12681
  ExportNamedDeclaration: (path25) => {
12656
12682
  if (t10.isVariableDeclaration(path25.node.declaration)) {
@@ -12665,6 +12691,17 @@ var ZodSchemaConverter = class {
12665
12691
  }
12666
12692
  this.processingSchemas.delete(schemaName);
12667
12693
  }
12694
+ } else if (t10.isIdentifier(declaration.id) && declaration.init) {
12695
+ const schemaName = declaration.id.name;
12696
+ const overrideId = this.extractMetaIdFromNode(declaration.init);
12697
+ if (overrideId && !this.getStoredSchema(schemaName) && !this.processingSchemas.has(schemaName)) {
12698
+ this.processingSchemas.add(schemaName);
12699
+ const schema = this.processZodNode(declaration.init);
12700
+ this.processingSchemas.delete(schemaName);
12701
+ if (schema) {
12702
+ this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
12703
+ }
12704
+ }
12668
12705
  }
12669
12706
  });
12670
12707
  }
@@ -13218,6 +13255,24 @@ var ZodSchemaConverter = class {
13218
13255
  }
13219
13256
  return void 0;
13220
13257
  }
13258
+ extractMetaIdFromNode(node) {
13259
+ if (!t10.isCallExpression(node))
13260
+ return null;
13261
+ if (t10.isMemberExpression(node.callee) && t10.isIdentifier(node.callee.property)) {
13262
+ if (node.callee.property.name === "meta" && node.arguments.length > 0) {
13263
+ const metadata = this.extractStaticJsonValue(node.arguments[0]);
13264
+ if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
13265
+ const id = metadata.id;
13266
+ if (typeof id === "string" && id.length > 0)
13267
+ return id;
13268
+ }
13269
+ }
13270
+ if (t10.isCallExpression(node.callee.object)) {
13271
+ return this.extractMetaIdFromNode(node.callee.object);
13272
+ }
13273
+ }
13274
+ return null;
13275
+ }
13221
13276
  shouldUseRuntimeExport(node) {
13222
13277
  if (!t10.isCallExpression(node)) {
13223
13278
  return false;
@@ -13458,7 +13513,8 @@ var ZodSchemaConverter = class {
13458
13513
  if (node.arguments.length > 0) {
13459
13514
  const metadata = this.extractStaticJsonValue(node.arguments[0]);
13460
13515
  if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
13461
- Object.assign(schema, metadata);
13516
+ const { id: _id, ...rest } = metadata;
13517
+ Object.assign(schema, rest);
13462
13518
  }
13463
13519
  }
13464
13520
  break;
@@ -13744,6 +13800,7 @@ var ZodSchemaConverter = class {
13744
13800
  this.currentFilePath = filePath;
13745
13801
  this.currentAST = ast;
13746
13802
  this.currentImports = importedModules;
13803
+ this.preprocessedFiles.add(filePath);
13747
13804
  resolvedTraverse(ast, {
13748
13805
  ExportNamedDeclaration: (path25) => {
13749
13806
  if (t10.isVariableDeclaration(path25.node.declaration)) {
@@ -13751,15 +13808,19 @@ var ZodSchemaConverter = class {
13751
13808
  if (t10.isIdentifier(declaration.id) && declaration.init) {
13752
13809
  const schemaName = declaration.id.name;
13753
13810
  if (this.isZodSchema(declaration.init)) {
13754
- this.indexSchemaName(schemaName, filePath);
13755
13811
  if (!this.getStoredSchema(schemaName)) {
13756
13812
  logger.debug(`Pre-processing Zod schema: ${schemaName}`);
13757
13813
  this.processingSchemas.add(schemaName);
13758
13814
  const schema = this.processZodNode(declaration.init);
13815
+ this.processingSchemas.delete(schemaName);
13759
13816
  if (schema) {
13760
- this.storeResolvedSchema(schemaName, schema);
13817
+ const overrideId = this.extractMetaIdFromNode(declaration.init);
13818
+ this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
13819
+ } else {
13820
+ this.indexSchemaName(schemaName, filePath);
13761
13821
  }
13762
- this.processingSchemas.delete(schemaName);
13822
+ } else {
13823
+ this.indexSchemaName(schemaName, filePath);
13763
13824
  }
13764
13825
  }
13765
13826
  }
@@ -13772,22 +13833,25 @@ var ZodSchemaConverter = class {
13772
13833
  if (t10.isIdentifier(declaration.id) && declaration.init) {
13773
13834
  const schemaName = declaration.id.name;
13774
13835
  if (this.isZodSchema(declaration.init)) {
13775
- this.indexSchemaName(schemaName, filePath);
13776
13836
  if (!this.getStoredSchema(schemaName) && !this.processingSchemas.has(schemaName)) {
13777
13837
  logger.debug(`Pre-processing Zod schema: ${schemaName}`);
13778
13838
  this.processingSchemas.add(schemaName);
13779
13839
  const schema = this.processZodNode(declaration.init);
13840
+ this.processingSchemas.delete(schemaName);
13780
13841
  if (schema) {
13781
- this.storeResolvedSchema(schemaName, schema);
13842
+ const overrideId = this.extractMetaIdFromNode(declaration.init);
13843
+ this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
13844
+ } else {
13845
+ this.indexSchemaName(schemaName, filePath);
13782
13846
  }
13783
- this.processingSchemas.delete(schemaName);
13847
+ } else {
13848
+ this.indexSchemaName(schemaName, filePath);
13784
13849
  }
13785
13850
  }
13786
13851
  }
13787
13852
  });
13788
13853
  }
13789
13854
  });
13790
- this.preprocessedFiles.add(filePath);
13791
13855
  } catch (error2) {
13792
13856
  logger.error(`Error pre-processing file ${filePath}: ${error2}`);
13793
13857
  }
@@ -13805,6 +13869,21 @@ var ZodSchemaConverter = class {
13805
13869
  }
13806
13870
  bucket.add(filePath);
13807
13871
  }
13872
+ applyMetaIdOverride(schemaName, schema, overrideId, filePath) {
13873
+ const finalName = overrideId && overrideId !== schemaName ? overrideId : schemaName;
13874
+ this.indexSchemaName(schemaName, filePath);
13875
+ if (finalName !== schemaName) {
13876
+ this.indexSchemaName(finalName, filePath);
13877
+ }
13878
+ if (!this.getStoredSchema(finalName)) {
13879
+ if (overrideId && overrideId !== schemaName) {
13880
+ this.typeToSchemaMapping[schemaName] = overrideId;
13881
+ }
13882
+ this.storeResolvedSchema(finalName, schema);
13883
+ } else {
13884
+ logger.warn(`Schema component name '${overrideId ?? finalName}' conflicts with an existing schema, ignoring .meta({ id }) on '${schemaName}'`);
13885
+ }
13886
+ }
13808
13887
  /**
13809
13888
  * Check if node is Zod schema
13810
13889
  */
@@ -14008,15 +14087,39 @@ function extractKeysFromLiteralType(node) {
14008
14087
  }
14009
14088
  return [];
14010
14089
  }
14090
+ function parsePropertyComment(commentValue) {
14091
+ const text = commentValue.split("\n").map((line) => line.replace(/^\s*\*\s?/, "").trim()).filter((line) => line.length > 0).join(" ").trim();
14092
+ const result = {};
14093
+ let remaining = text;
14094
+ const formatMatch = remaining.match(/@format\s+(\S+)/);
14095
+ if (formatMatch?.[1]) {
14096
+ result.format = formatMatch[1];
14097
+ remaining = remaining.replace(formatMatch[0], "").trim();
14098
+ }
14099
+ const exampleMatch = remaining.match(/@example\s+(.+?)(?=\s*@\w|$)/);
14100
+ if (exampleMatch?.[1]) {
14101
+ const raw = exampleMatch[1].trim();
14102
+ try {
14103
+ result.example = JSON.parse(raw);
14104
+ } catch {
14105
+ result.example = raw;
14106
+ }
14107
+ remaining = remaining.replace(exampleMatch[0], "").trim();
14108
+ }
14109
+ remaining = remaining.replace(/@\w+(?:\s+\S+)*/g, "").trim();
14110
+ if (remaining) {
14111
+ result.description = remaining;
14112
+ }
14113
+ return result;
14114
+ }
14011
14115
  function getPropertyOptions(node, contentType) {
14012
14116
  const isOptional = !!node.optional;
14013
- let description = null;
14014
- if (node.trailingComments && node.trailingComments.length) {
14015
- description = node.trailingComments[0].value.trim();
14016
- }
14017
14117
  const options = {};
14018
- if (description) {
14019
- options.description = description;
14118
+ const leadingComment = node.leadingComments?.findLast((c) => c.type === "CommentBlock" || !node.trailingComments?.length);
14119
+ const trailingComment = node.trailingComments?.[0];
14120
+ const sourceComment = leadingComment ?? trailingComment;
14121
+ if (sourceComment) {
14122
+ Object.assign(options, parsePropertyComment(sourceComment.value));
14020
14123
  }
14021
14124
  if (contentType === "body") {
14022
14125
  options.nullable = isOptional;
@@ -14415,31 +14518,60 @@ function resolveImportPath(importPath, fromFilePath, fileAccess) {
14415
14518
  }
14416
14519
  return null;
14417
14520
  }
14418
- function collectAllExportedDefinitions(ast, typeDefinitions, currentFile) {
14521
+ function collectFirstMemberLeadingComments(interfaceDecl) {
14522
+ const body = interfaceDecl?.body;
14523
+ if (!body)
14524
+ return [];
14525
+ const firstMember = body.body?.[0];
14526
+ return firstMember?.leadingComments ?? [];
14527
+ }
14528
+ function collectAllExportedDefinitions(ast, typeDefinitions, currentFile, schemaIdAliases) {
14529
+ function registerDefinition(name, entry, allComments) {
14530
+ if (!typeDefinitions[name]) {
14531
+ typeDefinitions[name] = entry;
14532
+ }
14533
+ const overrideId = extractSchemaIdFromComments(allComments);
14534
+ if (overrideId && schemaIdAliases) {
14535
+ schemaIdAliases[name] = overrideId;
14536
+ if (!typeDefinitions[overrideId]) {
14537
+ typeDefinitions[overrideId] = entry;
14538
+ }
14539
+ }
14540
+ }
14419
14541
  resolvedTraverse(ast, {
14420
14542
  TSTypeAliasDeclaration: (path25) => {
14421
14543
  if (path25.node.id && t12.isIdentifier(path25.node.id)) {
14422
14544
  const name = path25.node.id.name;
14423
- if (!typeDefinitions[name]) {
14424
- const node = path25.node.typeParameters && path25.node.typeParameters.params.length > 0 ? path25.node : path25.node.typeAnnotation;
14425
- typeDefinitions[name] = { node, filePath: currentFile };
14426
- }
14545
+ const node = path25.node.typeParameters && path25.node.typeParameters.params.length > 0 ? path25.node : path25.node.typeAnnotation;
14546
+ const allComments = [
14547
+ ...path25.parentPath?.node?.leadingComments ?? [],
14548
+ ...path25.node.leadingComments ?? [],
14549
+ ...path25.node.trailingComments ?? []
14550
+ ];
14551
+ registerDefinition(name, { node, filePath: currentFile }, allComments);
14427
14552
  }
14428
14553
  },
14429
14554
  TSInterfaceDeclaration: (path25) => {
14430
14555
  if (path25.node.id && t12.isIdentifier(path25.node.id)) {
14431
14556
  const name = path25.node.id.name;
14432
- if (!typeDefinitions[name]) {
14433
- typeDefinitions[name] = { node: path25.node, filePath: currentFile };
14434
- }
14557
+ const allComments = [
14558
+ ...path25.parentPath?.node?.leadingComments ?? [],
14559
+ ...path25.node.leadingComments ?? [],
14560
+ ...path25.node.trailingComments ?? [],
14561
+ ...collectFirstMemberLeadingComments(path25.node)
14562
+ ];
14563
+ registerDefinition(name, { node: path25.node, filePath: currentFile }, allComments);
14435
14564
  }
14436
14565
  },
14437
14566
  TSEnumDeclaration: (path25) => {
14438
14567
  if (path25.node.id && t12.isIdentifier(path25.node.id)) {
14439
14568
  const name = path25.node.id.name;
14440
- if (!typeDefinitions[name]) {
14441
- typeDefinitions[name] = { node: path25.node, filePath: currentFile };
14442
- }
14569
+ const allComments = [
14570
+ ...path25.parentPath?.node?.leadingComments ?? [],
14571
+ ...path25.node.leadingComments ?? [],
14572
+ ...path25.node.trailingComments ?? []
14573
+ ];
14574
+ registerDefinition(name, { node: path25.node, filePath: currentFile }, allComments);
14443
14575
  }
14444
14576
  },
14445
14577
  ExportNamedDeclaration: (path25) => {
@@ -14447,19 +14579,26 @@ function collectAllExportedDefinitions(ast, typeDefinitions, currentFile) {
14447
14579
  const interfaceDecl = path25.node.declaration;
14448
14580
  if (interfaceDecl.id && t12.isIdentifier(interfaceDecl.id)) {
14449
14581
  const name = interfaceDecl.id.name;
14450
- if (!typeDefinitions[name]) {
14451
- typeDefinitions[name] = { node: interfaceDecl, filePath: currentFile };
14452
- }
14582
+ const allComments = [
14583
+ ...path25.node.leadingComments ?? [],
14584
+ ...interfaceDecl.leadingComments ?? [],
14585
+ ...interfaceDecl.trailingComments ?? [],
14586
+ ...collectFirstMemberLeadingComments(interfaceDecl)
14587
+ ];
14588
+ registerDefinition(name, { node: interfaceDecl, filePath: currentFile }, allComments);
14453
14589
  }
14454
14590
  }
14455
14591
  if (t12.isTSTypeAliasDeclaration(path25.node.declaration)) {
14456
14592
  const typeDecl = path25.node.declaration;
14457
14593
  if (typeDecl.id && t12.isIdentifier(typeDecl.id)) {
14458
14594
  const name = typeDecl.id.name;
14459
- if (!typeDefinitions[name]) {
14460
- const node = typeDecl.typeParameters && typeDecl.typeParameters.params.length > 0 ? typeDecl : typeDecl.typeAnnotation;
14461
- typeDefinitions[name] = { node, filePath: currentFile };
14462
- }
14595
+ const node = typeDecl.typeParameters && typeDecl.typeParameters.params.length > 0 ? typeDecl : typeDecl.typeAnnotation;
14596
+ const allComments = [
14597
+ ...path25.node.leadingComments ?? [],
14598
+ ...typeDecl.leadingComments ?? [],
14599
+ ...typeDecl.trailingComments ?? []
14600
+ ];
14601
+ registerDefinition(name, { node, filePath: currentFile }, allComments);
14463
14602
  }
14464
14603
  }
14465
14604
  }
@@ -14876,6 +15015,7 @@ var SchemaProcessor = class {
14876
15015
  zodSchemaProcessor = null;
14877
15016
  schemaTypes;
14878
15017
  isResolvingPickOmitBase = false;
15018
+ schemaIdAliases = {};
14879
15019
  fileAccess;
14880
15020
  symbolResolver;
14881
15021
  // Track imports per file for resolving ReturnType<typeof func>
@@ -14916,7 +15056,7 @@ var SchemaProcessor = class {
14916
15056
  getDefinedSchemas() {
14917
15057
  const filteredSchemas = {};
14918
15058
  Object.entries(this.openapiDefinitions).forEach(([key, value]) => {
14919
- if (!this.isGenericTypeParameter(key) && !this.isInvalidSchemaName(key) && !this.isBuiltInUtilityType(key) && !this.isFunctionSchema(key)) {
15059
+ if (!this.schemaIdAliases[key] && !this.isGenericTypeParameter(key) && !this.isInvalidSchemaName(key) && !this.isBuiltInUtilityType(key) && !this.isFunctionSchema(key)) {
14920
15060
  filteredSchemas[key] = value;
14921
15061
  }
14922
15062
  });
@@ -14931,6 +15071,10 @@ var SchemaProcessor = class {
14931
15071
  if (schemaName.includes("<") && schemaName.includes(">")) {
14932
15072
  return this.resolveGenericTypeFromString(schemaName);
14933
15073
  }
15074
+ const overrideId = this.schemaIdAliases[schemaName];
15075
+ if (overrideId) {
15076
+ return this.findSchemaDefinition(overrideId, contentType);
15077
+ }
14934
15078
  if (this.openapiDefinitions[schemaName]) {
14935
15079
  return this.openapiDefinitions[schemaName];
14936
15080
  }
@@ -15012,6 +15156,7 @@ var SchemaProcessor = class {
15012
15156
  return;
15013
15157
  }
15014
15158
  this.collectImports(ast, filePath);
15159
+ const aliasesBeforeFile = new Set(Object.keys(this.schemaIdAliases));
15015
15160
  this.collectAllExportedDefinitions(ast, filePath);
15016
15161
  collectTopLevelDefinitionNames(ast).forEach((name) => {
15017
15162
  const indexedFiles = this.schemaDefinitionIndex[name];
@@ -15023,6 +15168,16 @@ var SchemaProcessor = class {
15023
15168
  }
15024
15169
  this.schemaDefinitionIndex[name] = [filePath];
15025
15170
  });
15171
+ Object.entries(this.schemaIdAliases).forEach(([originalName, aliasName]) => {
15172
+ if (aliasesBeforeFile.has(originalName))
15173
+ return;
15174
+ if (!this.schemaDefinitionIndex[aliasName]) {
15175
+ this.schemaDefinitionIndex[aliasName] = [];
15176
+ }
15177
+ if (!this.schemaDefinitionIndex[aliasName].includes(filePath)) {
15178
+ this.schemaDefinitionIndex[aliasName].push(filePath);
15179
+ }
15180
+ });
15026
15181
  }
15027
15182
  getParsedSchemaFile(filePath) {
15028
15183
  const cachedAst = this.fileASTCache.get(filePath);
@@ -15061,7 +15216,7 @@ var SchemaProcessor = class {
15061
15216
  * Used when processing imported files to ensure all referenced types are available
15062
15217
  */
15063
15218
  collectAllExportedDefinitions(ast, filePath) {
15064
- collectAllExportedDefinitions(ast, this.typeDefinitions, filePath || this.currentFilePath);
15219
+ collectAllExportedDefinitions(ast, this.typeDefinitions, filePath || this.currentFilePath, this.schemaIdAliases);
15065
15220
  }
15066
15221
  collectTypeDefinitions(ast, schemaName, filePath) {
15067
15222
  collectTypeDefinitions(ast, schemaName, this.typeDefinitions, filePath || this.currentFilePath);
@@ -15658,6 +15813,9 @@ var SchemaProcessor = class {
15658
15813
  logger.debug(`Record<...> used with ${node.typeParameters?.params.length ?? 0} type parameters; expected 2`);
15659
15814
  return { type: "object", additionalProperties: true };
15660
15815
  }
15816
+ if ((!node.typeParameters || node.typeParameters.params.length === 0) && this.schemaIdAliases[typeName] && this.openapiDefinitions[this.schemaIdAliases[typeName]]) {
15817
+ return { $ref: `#/components/schemas/${this.schemaIdAliases[typeName]}` };
15818
+ }
15661
15819
  const utilityType = resolveUtilityTypeReference(node, {
15662
15820
  currentFilePath: this.currentFilePath,
15663
15821
  contentType: this.contentType,
@@ -15833,7 +15991,9 @@ var SchemaProcessor = class {
15833
15991
  };
15834
15992
  }
15835
15993
  if (t15.isTSTypeReference(node) && t15.isIdentifier(node.typeName)) {
15836
- return { $ref: `#/components/schemas/${node.typeName.name}` };
15994
+ const refName = node.typeName.name;
15995
+ const aliasedName = this.schemaIdAliases[refName] ?? refName;
15996
+ return { $ref: `#/components/schemas/${aliasedName}` };
15837
15997
  }
15838
15998
  logger.debug("Unrecognized TypeScript type node:", node);
15839
15999
  return { type: "object" };
@@ -15974,7 +16134,8 @@ var SchemaProcessor = class {
15974
16134
  if (this.schemaTypes.includes("zod") && this.zodSchemaConverter) {
15975
16135
  return this.zodSchemaConverter.getSchemaReferenceName(baseTypeName, contentType);
15976
16136
  }
15977
- return baseTypeName;
16137
+ const aliasedName = this.schemaIdAliases[baseTypeName] ?? baseTypeName;
16138
+ return aliasedName;
15978
16139
  }
15979
16140
  /**
15980
16141
  * Parse and resolve a generic type from a string like "MyApiSuccessResponseBody<LLMSResponse>"