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 +17 -0
- package/dist/cli.js +202 -41
- package/dist/index.js +202 -41
- package/dist/next/index.js +202 -41
- package/dist/react-router/index.js +202 -41
- package/dist/vite/index.js +202 -41
- package/package.json +1 -1
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
|
-
|
|
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
|
|
11873
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
13817
|
+
const overrideId = this.extractMetaIdFromNode(declaration.init);
|
|
13818
|
+
this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
|
|
13819
|
+
} else {
|
|
13820
|
+
this.indexSchemaName(schemaName, filePath);
|
|
13761
13821
|
}
|
|
13762
|
-
|
|
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.
|
|
13842
|
+
const overrideId = this.extractMetaIdFromNode(declaration.init);
|
|
13843
|
+
this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
|
|
13844
|
+
} else {
|
|
13845
|
+
this.indexSchemaName(schemaName, filePath);
|
|
13782
13846
|
}
|
|
13783
|
-
|
|
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
|
-
|
|
14019
|
-
|
|
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
|
|
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
|
-
|
|
14424
|
-
|
|
14425
|
-
|
|
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
|
-
|
|
14433
|
-
|
|
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
|
-
|
|
14441
|
-
|
|
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
|
-
|
|
14451
|
-
|
|
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
|
-
|
|
14460
|
-
|
|
14461
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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>"
|