next-openapi-gen 1.2.1 → 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.
@@ -1306,6 +1306,17 @@ function mergeJSDocData(target, source) {
1306
1306
  function cleanComment(commentValue) {
1307
1307
  return commentValue.replace(/\*\s*/g, "").trim();
1308
1308
  }
1309
+ function extractSchemaIdFromComments(comments) {
1310
+ if (!comments)
1311
+ return null;
1312
+ for (const comment of comments) {
1313
+ const cleaned = cleanComment(comment.value);
1314
+ const id = extractTokenValue(cleaned, "@id");
1315
+ if (id)
1316
+ return id;
1317
+ }
1318
+ return null;
1319
+ }
1309
1320
  function extractLineValue(commentValue, tag) {
1310
1321
  return commentValue.match(new RegExp(`${escapeRegExp(tag)}\\s*(.*)`, "m"))?.[1]?.trim() || "";
1311
1322
  }
@@ -4168,7 +4179,8 @@ var DrizzleZodProcessor = class _DrizzleZodProcessor {
4168
4179
  if (firstArg && !t5.isSpreadElement(firstArg) && !t5.isArgumentPlaceholder(firstArg)) {
4169
4180
  const metadata = _DrizzleZodProcessor.extractStaticObject(firstArg);
4170
4181
  if (metadata) {
4171
- Object.assign(result, metadata);
4182
+ const { id: _id, ...rest } = metadata;
4183
+ Object.assign(result, rest);
4172
4184
  }
4173
4185
  }
4174
4186
  break;
@@ -12452,8 +12464,11 @@ var ZodRuntimeExporter = class {
12452
12464
  case "deprecated":
12453
12465
  return schema.meta({ deprecated: true });
12454
12466
  case "meta": {
12455
- const metadata = node.arguments[0] ? this.buildMetadataObject(node.arguments[0]) : null;
12456
- return metadata ? schema.meta(metadata) : schema;
12467
+ const rawMetadata = node.arguments[0] ? this.buildMetadataObject(node.arguments[0]) : null;
12468
+ if (!rawMetadata)
12469
+ return schema;
12470
+ const { id: _id, ...metadata } = rawMetadata;
12471
+ return Object.keys(metadata).length > 0 ? schema.meta(metadata) : schema;
12457
12472
  }
12458
12473
  case "default":
12459
12474
  case "prefault":
@@ -13243,6 +13258,8 @@ var ZodSchemaConverter = class {
13243
13258
  try {
13244
13259
  const content = this.fileAccess.readFileSync(filePath, "utf-8");
13245
13260
  const ast = parseTypeScriptFile(content);
13261
+ this.currentFilePath = filePath;
13262
+ this.currentAST = ast;
13246
13263
  resolvedTraverse(ast, {
13247
13264
  ExportNamedDeclaration: (path19) => {
13248
13265
  if (t11.isVariableDeclaration(path19.node.declaration)) {
@@ -13257,6 +13274,17 @@ var ZodSchemaConverter = class {
13257
13274
  }
13258
13275
  this.processingSchemas.delete(schemaName);
13259
13276
  }
13277
+ } else if (t11.isIdentifier(declaration.id) && declaration.init) {
13278
+ const schemaName = declaration.id.name;
13279
+ const overrideId = this.extractMetaIdFromNode(declaration.init);
13280
+ if (overrideId && !this.getStoredSchema(schemaName) && !this.processingSchemas.has(schemaName)) {
13281
+ this.processingSchemas.add(schemaName);
13282
+ const schema = this.processZodNode(declaration.init);
13283
+ this.processingSchemas.delete(schemaName);
13284
+ if (schema) {
13285
+ this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
13286
+ }
13287
+ }
13260
13288
  }
13261
13289
  });
13262
13290
  }
@@ -13810,6 +13838,24 @@ var ZodSchemaConverter = class {
13810
13838
  }
13811
13839
  return void 0;
13812
13840
  }
13841
+ extractMetaIdFromNode(node) {
13842
+ if (!t11.isCallExpression(node))
13843
+ return null;
13844
+ if (t11.isMemberExpression(node.callee) && t11.isIdentifier(node.callee.property)) {
13845
+ if (node.callee.property.name === "meta" && node.arguments.length > 0) {
13846
+ const metadata = this.extractStaticJsonValue(node.arguments[0]);
13847
+ if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
13848
+ const id = metadata.id;
13849
+ if (typeof id === "string" && id.length > 0)
13850
+ return id;
13851
+ }
13852
+ }
13853
+ if (t11.isCallExpression(node.callee.object)) {
13854
+ return this.extractMetaIdFromNode(node.callee.object);
13855
+ }
13856
+ }
13857
+ return null;
13858
+ }
13813
13859
  shouldUseRuntimeExport(node) {
13814
13860
  if (!t11.isCallExpression(node)) {
13815
13861
  return false;
@@ -14050,7 +14096,8 @@ var ZodSchemaConverter = class {
14050
14096
  if (node.arguments.length > 0) {
14051
14097
  const metadata = this.extractStaticJsonValue(node.arguments[0]);
14052
14098
  if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
14053
- Object.assign(schema, metadata);
14099
+ const { id: _id, ...rest } = metadata;
14100
+ Object.assign(schema, rest);
14054
14101
  }
14055
14102
  }
14056
14103
  break;
@@ -14336,6 +14383,7 @@ var ZodSchemaConverter = class {
14336
14383
  this.currentFilePath = filePath;
14337
14384
  this.currentAST = ast;
14338
14385
  this.currentImports = importedModules;
14386
+ this.preprocessedFiles.add(filePath);
14339
14387
  resolvedTraverse(ast, {
14340
14388
  ExportNamedDeclaration: (path19) => {
14341
14389
  if (t11.isVariableDeclaration(path19.node.declaration)) {
@@ -14343,15 +14391,19 @@ var ZodSchemaConverter = class {
14343
14391
  if (t11.isIdentifier(declaration.id) && declaration.init) {
14344
14392
  const schemaName = declaration.id.name;
14345
14393
  if (this.isZodSchema(declaration.init)) {
14346
- this.indexSchemaName(schemaName, filePath);
14347
14394
  if (!this.getStoredSchema(schemaName)) {
14348
14395
  logger.debug(`Pre-processing Zod schema: ${schemaName}`);
14349
14396
  this.processingSchemas.add(schemaName);
14350
14397
  const schema = this.processZodNode(declaration.init);
14398
+ this.processingSchemas.delete(schemaName);
14351
14399
  if (schema) {
14352
- this.storeResolvedSchema(schemaName, schema);
14400
+ const overrideId = this.extractMetaIdFromNode(declaration.init);
14401
+ this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
14402
+ } else {
14403
+ this.indexSchemaName(schemaName, filePath);
14353
14404
  }
14354
- this.processingSchemas.delete(schemaName);
14405
+ } else {
14406
+ this.indexSchemaName(schemaName, filePath);
14355
14407
  }
14356
14408
  }
14357
14409
  }
@@ -14364,22 +14416,25 @@ var ZodSchemaConverter = class {
14364
14416
  if (t11.isIdentifier(declaration.id) && declaration.init) {
14365
14417
  const schemaName = declaration.id.name;
14366
14418
  if (this.isZodSchema(declaration.init)) {
14367
- this.indexSchemaName(schemaName, filePath);
14368
14419
  if (!this.getStoredSchema(schemaName) && !this.processingSchemas.has(schemaName)) {
14369
14420
  logger.debug(`Pre-processing Zod schema: ${schemaName}`);
14370
14421
  this.processingSchemas.add(schemaName);
14371
14422
  const schema = this.processZodNode(declaration.init);
14423
+ this.processingSchemas.delete(schemaName);
14372
14424
  if (schema) {
14373
- this.storeResolvedSchema(schemaName, schema);
14425
+ const overrideId = this.extractMetaIdFromNode(declaration.init);
14426
+ this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
14427
+ } else {
14428
+ this.indexSchemaName(schemaName, filePath);
14374
14429
  }
14375
- this.processingSchemas.delete(schemaName);
14430
+ } else {
14431
+ this.indexSchemaName(schemaName, filePath);
14376
14432
  }
14377
14433
  }
14378
14434
  }
14379
14435
  });
14380
14436
  }
14381
14437
  });
14382
- this.preprocessedFiles.add(filePath);
14383
14438
  } catch (error2) {
14384
14439
  logger.error(`Error pre-processing file ${filePath}: ${error2}`);
14385
14440
  }
@@ -14397,6 +14452,21 @@ var ZodSchemaConverter = class {
14397
14452
  }
14398
14453
  bucket.add(filePath);
14399
14454
  }
14455
+ applyMetaIdOverride(schemaName, schema, overrideId, filePath) {
14456
+ const finalName = overrideId && overrideId !== schemaName ? overrideId : schemaName;
14457
+ this.indexSchemaName(schemaName, filePath);
14458
+ if (finalName !== schemaName) {
14459
+ this.indexSchemaName(finalName, filePath);
14460
+ }
14461
+ if (!this.getStoredSchema(finalName)) {
14462
+ if (overrideId && overrideId !== schemaName) {
14463
+ this.typeToSchemaMapping[schemaName] = overrideId;
14464
+ }
14465
+ this.storeResolvedSchema(finalName, schema);
14466
+ } else {
14467
+ logger.warn(`Schema component name '${overrideId ?? finalName}' conflicts with an existing schema, ignoring .meta({ id }) on '${schemaName}'`);
14468
+ }
14469
+ }
14400
14470
  /**
14401
14471
  * Check if node is Zod schema
14402
14472
  */
@@ -14628,7 +14698,7 @@ function parsePropertyComment(commentValue) {
14628
14698
  function getPropertyOptions(node, contentType) {
14629
14699
  const isOptional = !!node.optional;
14630
14700
  const options = {};
14631
- const leadingComment = node.leadingComments?.[node.leadingComments.length - 1];
14701
+ const leadingComment = node.leadingComments?.findLast((c) => c.type === "CommentBlock" || !node.trailingComments?.length);
14632
14702
  const trailingComment = node.trailingComments?.[0];
14633
14703
  const sourceComment = leadingComment ?? trailingComment;
14634
14704
  if (sourceComment) {
@@ -15031,31 +15101,60 @@ function resolveImportPath(importPath, fromFilePath, fileAccess) {
15031
15101
  }
15032
15102
  return null;
15033
15103
  }
15034
- function collectAllExportedDefinitions(ast, typeDefinitions, currentFile) {
15104
+ function collectFirstMemberLeadingComments(interfaceDecl) {
15105
+ const body = interfaceDecl?.body;
15106
+ if (!body)
15107
+ return [];
15108
+ const firstMember = body.body?.[0];
15109
+ return firstMember?.leadingComments ?? [];
15110
+ }
15111
+ function collectAllExportedDefinitions(ast, typeDefinitions, currentFile, schemaIdAliases) {
15112
+ function registerDefinition(name, entry, allComments) {
15113
+ if (!typeDefinitions[name]) {
15114
+ typeDefinitions[name] = entry;
15115
+ }
15116
+ const overrideId = extractSchemaIdFromComments(allComments);
15117
+ if (overrideId && schemaIdAliases) {
15118
+ schemaIdAliases[name] = overrideId;
15119
+ if (!typeDefinitions[overrideId]) {
15120
+ typeDefinitions[overrideId] = entry;
15121
+ }
15122
+ }
15123
+ }
15035
15124
  resolvedTraverse(ast, {
15036
15125
  TSTypeAliasDeclaration: (path19) => {
15037
15126
  if (path19.node.id && t13.isIdentifier(path19.node.id)) {
15038
15127
  const name = path19.node.id.name;
15039
- if (!typeDefinitions[name]) {
15040
- const node = path19.node.typeParameters && path19.node.typeParameters.params.length > 0 ? path19.node : path19.node.typeAnnotation;
15041
- typeDefinitions[name] = { node, filePath: currentFile };
15042
- }
15128
+ const node = path19.node.typeParameters && path19.node.typeParameters.params.length > 0 ? path19.node : path19.node.typeAnnotation;
15129
+ const allComments = [
15130
+ ...path19.parentPath?.node?.leadingComments ?? [],
15131
+ ...path19.node.leadingComments ?? [],
15132
+ ...path19.node.trailingComments ?? []
15133
+ ];
15134
+ registerDefinition(name, { node, filePath: currentFile }, allComments);
15043
15135
  }
15044
15136
  },
15045
15137
  TSInterfaceDeclaration: (path19) => {
15046
15138
  if (path19.node.id && t13.isIdentifier(path19.node.id)) {
15047
15139
  const name = path19.node.id.name;
15048
- if (!typeDefinitions[name]) {
15049
- typeDefinitions[name] = { node: path19.node, filePath: currentFile };
15050
- }
15140
+ const allComments = [
15141
+ ...path19.parentPath?.node?.leadingComments ?? [],
15142
+ ...path19.node.leadingComments ?? [],
15143
+ ...path19.node.trailingComments ?? [],
15144
+ ...collectFirstMemberLeadingComments(path19.node)
15145
+ ];
15146
+ registerDefinition(name, { node: path19.node, filePath: currentFile }, allComments);
15051
15147
  }
15052
15148
  },
15053
15149
  TSEnumDeclaration: (path19) => {
15054
15150
  if (path19.node.id && t13.isIdentifier(path19.node.id)) {
15055
15151
  const name = path19.node.id.name;
15056
- if (!typeDefinitions[name]) {
15057
- typeDefinitions[name] = { node: path19.node, filePath: currentFile };
15058
- }
15152
+ const allComments = [
15153
+ ...path19.parentPath?.node?.leadingComments ?? [],
15154
+ ...path19.node.leadingComments ?? [],
15155
+ ...path19.node.trailingComments ?? []
15156
+ ];
15157
+ registerDefinition(name, { node: path19.node, filePath: currentFile }, allComments);
15059
15158
  }
15060
15159
  },
15061
15160
  ExportNamedDeclaration: (path19) => {
@@ -15063,19 +15162,26 @@ function collectAllExportedDefinitions(ast, typeDefinitions, currentFile) {
15063
15162
  const interfaceDecl = path19.node.declaration;
15064
15163
  if (interfaceDecl.id && t13.isIdentifier(interfaceDecl.id)) {
15065
15164
  const name = interfaceDecl.id.name;
15066
- if (!typeDefinitions[name]) {
15067
- typeDefinitions[name] = { node: interfaceDecl, filePath: currentFile };
15068
- }
15165
+ const allComments = [
15166
+ ...path19.node.leadingComments ?? [],
15167
+ ...interfaceDecl.leadingComments ?? [],
15168
+ ...interfaceDecl.trailingComments ?? [],
15169
+ ...collectFirstMemberLeadingComments(interfaceDecl)
15170
+ ];
15171
+ registerDefinition(name, { node: interfaceDecl, filePath: currentFile }, allComments);
15069
15172
  }
15070
15173
  }
15071
15174
  if (t13.isTSTypeAliasDeclaration(path19.node.declaration)) {
15072
15175
  const typeDecl = path19.node.declaration;
15073
15176
  if (typeDecl.id && t13.isIdentifier(typeDecl.id)) {
15074
15177
  const name = typeDecl.id.name;
15075
- if (!typeDefinitions[name]) {
15076
- const node = typeDecl.typeParameters && typeDecl.typeParameters.params.length > 0 ? typeDecl : typeDecl.typeAnnotation;
15077
- typeDefinitions[name] = { node, filePath: currentFile };
15078
- }
15178
+ const node = typeDecl.typeParameters && typeDecl.typeParameters.params.length > 0 ? typeDecl : typeDecl.typeAnnotation;
15179
+ const allComments = [
15180
+ ...path19.node.leadingComments ?? [],
15181
+ ...typeDecl.leadingComments ?? [],
15182
+ ...typeDecl.trailingComments ?? []
15183
+ ];
15184
+ registerDefinition(name, { node, filePath: currentFile }, allComments);
15079
15185
  }
15080
15186
  }
15081
15187
  }
@@ -15492,6 +15598,7 @@ var SchemaProcessor = class {
15492
15598
  zodSchemaProcessor = null;
15493
15599
  schemaTypes;
15494
15600
  isResolvingPickOmitBase = false;
15601
+ schemaIdAliases = {};
15495
15602
  fileAccess;
15496
15603
  symbolResolver;
15497
15604
  // Track imports per file for resolving ReturnType<typeof func>
@@ -15532,7 +15639,7 @@ var SchemaProcessor = class {
15532
15639
  getDefinedSchemas() {
15533
15640
  const filteredSchemas = {};
15534
15641
  Object.entries(this.openapiDefinitions).forEach(([key, value]) => {
15535
- if (!this.isGenericTypeParameter(key) && !this.isInvalidSchemaName(key) && !this.isBuiltInUtilityType(key) && !this.isFunctionSchema(key)) {
15642
+ if (!this.schemaIdAliases[key] && !this.isGenericTypeParameter(key) && !this.isInvalidSchemaName(key) && !this.isBuiltInUtilityType(key) && !this.isFunctionSchema(key)) {
15536
15643
  filteredSchemas[key] = value;
15537
15644
  }
15538
15645
  });
@@ -15547,6 +15654,10 @@ var SchemaProcessor = class {
15547
15654
  if (schemaName.includes("<") && schemaName.includes(">")) {
15548
15655
  return this.resolveGenericTypeFromString(schemaName);
15549
15656
  }
15657
+ const overrideId = this.schemaIdAliases[schemaName];
15658
+ if (overrideId) {
15659
+ return this.findSchemaDefinition(overrideId, contentType);
15660
+ }
15550
15661
  if (this.openapiDefinitions[schemaName]) {
15551
15662
  return this.openapiDefinitions[schemaName];
15552
15663
  }
@@ -15628,6 +15739,7 @@ var SchemaProcessor = class {
15628
15739
  return;
15629
15740
  }
15630
15741
  this.collectImports(ast, filePath);
15742
+ const aliasesBeforeFile = new Set(Object.keys(this.schemaIdAliases));
15631
15743
  this.collectAllExportedDefinitions(ast, filePath);
15632
15744
  collectTopLevelDefinitionNames(ast).forEach((name) => {
15633
15745
  const indexedFiles = this.schemaDefinitionIndex[name];
@@ -15639,6 +15751,16 @@ var SchemaProcessor = class {
15639
15751
  }
15640
15752
  this.schemaDefinitionIndex[name] = [filePath];
15641
15753
  });
15754
+ Object.entries(this.schemaIdAliases).forEach(([originalName, aliasName]) => {
15755
+ if (aliasesBeforeFile.has(originalName))
15756
+ return;
15757
+ if (!this.schemaDefinitionIndex[aliasName]) {
15758
+ this.schemaDefinitionIndex[aliasName] = [];
15759
+ }
15760
+ if (!this.schemaDefinitionIndex[aliasName].includes(filePath)) {
15761
+ this.schemaDefinitionIndex[aliasName].push(filePath);
15762
+ }
15763
+ });
15642
15764
  }
15643
15765
  getParsedSchemaFile(filePath) {
15644
15766
  const cachedAst = this.fileASTCache.get(filePath);
@@ -15677,7 +15799,7 @@ var SchemaProcessor = class {
15677
15799
  * Used when processing imported files to ensure all referenced types are available
15678
15800
  */
15679
15801
  collectAllExportedDefinitions(ast, filePath) {
15680
- collectAllExportedDefinitions(ast, this.typeDefinitions, filePath || this.currentFilePath);
15802
+ collectAllExportedDefinitions(ast, this.typeDefinitions, filePath || this.currentFilePath, this.schemaIdAliases);
15681
15803
  }
15682
15804
  collectTypeDefinitions(ast, schemaName, filePath) {
15683
15805
  collectTypeDefinitions(ast, schemaName, this.typeDefinitions, filePath || this.currentFilePath);
@@ -16274,6 +16396,9 @@ var SchemaProcessor = class {
16274
16396
  logger.debug(`Record<...> used with ${node.typeParameters?.params.length ?? 0} type parameters; expected 2`);
16275
16397
  return { type: "object", additionalProperties: true };
16276
16398
  }
16399
+ if ((!node.typeParameters || node.typeParameters.params.length === 0) && this.schemaIdAliases[typeName] && this.openapiDefinitions[this.schemaIdAliases[typeName]]) {
16400
+ return { $ref: `#/components/schemas/${this.schemaIdAliases[typeName]}` };
16401
+ }
16277
16402
  const utilityType = resolveUtilityTypeReference(node, {
16278
16403
  currentFilePath: this.currentFilePath,
16279
16404
  contentType: this.contentType,
@@ -16449,7 +16574,9 @@ var SchemaProcessor = class {
16449
16574
  };
16450
16575
  }
16451
16576
  if (t16.isTSTypeReference(node) && t16.isIdentifier(node.typeName)) {
16452
- return { $ref: `#/components/schemas/${node.typeName.name}` };
16577
+ const refName = node.typeName.name;
16578
+ const aliasedName = this.schemaIdAliases[refName] ?? refName;
16579
+ return { $ref: `#/components/schemas/${aliasedName}` };
16453
16580
  }
16454
16581
  logger.debug("Unrecognized TypeScript type node:", node);
16455
16582
  return { type: "object" };
@@ -16590,7 +16717,8 @@ var SchemaProcessor = class {
16590
16717
  if (this.schemaTypes.includes("zod") && this.zodSchemaConverter) {
16591
16718
  return this.zodSchemaConverter.getSchemaReferenceName(baseTypeName, contentType);
16592
16719
  }
16593
- return baseTypeName;
16720
+ const aliasedName = this.schemaIdAliases[baseTypeName] ?? baseTypeName;
16721
+ return aliasedName;
16594
16722
  }
16595
16723
  /**
16596
16724
  * Parse and resolve a generic type from a string like "MyApiSuccessResponseBody<LLMSResponse>"