next-openapi-gen 1.2.1 → 1.2.3
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 +216 -36
- package/dist/index.js +216 -36
- package/dist/next/index.js +216 -36
- package/dist/react-router/index.js +216 -36
- package/dist/vite/index.js +216 -36
- 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":
|
|
@@ -12127,6 +12142,9 @@ var ZodSchemaConverter = class {
|
|
|
12127
12142
|
schemaNameToFiles = /* @__PURE__ */ new Map();
|
|
12128
12143
|
/** Per-file import alias for the `zod` module (`import { z as zod }` sets this to `"zod"`). */
|
|
12129
12144
|
zodImportAlias = /* @__PURE__ */ new Map();
|
|
12145
|
+
/** Schema variable names whose component name was overridden via .meta({ id }). These must
|
|
12146
|
+
* NOT be copied back under the original variable name in the OpenAPI components object. */
|
|
12147
|
+
metaIdSchemaNames = /* @__PURE__ */ new Set();
|
|
12130
12148
|
// Current processing context (set during file processing)
|
|
12131
12149
|
currentFilePath;
|
|
12132
12150
|
currentAST;
|
|
@@ -12153,7 +12171,14 @@ var ZodSchemaConverter = class {
|
|
|
12153
12171
|
}
|
|
12154
12172
|
logger.debug(`Looking for Zod schema: ${schemaName}`);
|
|
12155
12173
|
const requestedSchemaName = schemaName;
|
|
12156
|
-
|
|
12174
|
+
let mappedSchemaName = this.typeToSchemaMapping[schemaName];
|
|
12175
|
+
if (!mappedSchemaName) {
|
|
12176
|
+
const candidate = this.deriveSchemaNameByConvention(schemaName);
|
|
12177
|
+
if (candidate && this.locateSchemaByConvention(candidate)) {
|
|
12178
|
+
this.typeToSchemaMapping[schemaName] = candidate;
|
|
12179
|
+
mappedSchemaName = candidate;
|
|
12180
|
+
}
|
|
12181
|
+
}
|
|
12157
12182
|
if (mappedSchemaName) {
|
|
12158
12183
|
logger.debug(`Type '${schemaName}' is mapped to schema '${mappedSchemaName}'`);
|
|
12159
12184
|
schemaName = mappedSchemaName;
|
|
@@ -12203,7 +12228,7 @@ var ZodSchemaConverter = class {
|
|
|
12203
12228
|
this.processingSchemas.delete(schemaName);
|
|
12204
12229
|
if (mappedSchemaName && requestedSchemaName !== schemaName) {
|
|
12205
12230
|
const resolvedReference = this.getSchemaReferenceName(schemaName, this.currentContentType);
|
|
12206
|
-
if (this.zodSchemas[resolvedReference] && !this.zodSchemas[requestedSchemaName]) {
|
|
12231
|
+
if (!this.metaIdSchemaNames.has(requestedSchemaName) && this.zodSchemas[resolvedReference] && !this.zodSchemas[requestedSchemaName]) {
|
|
12207
12232
|
this.zodSchemas[requestedSchemaName] = this.zodSchemas[resolvedReference];
|
|
12208
12233
|
}
|
|
12209
12234
|
this.schemaVariantRefs.set(this.getVariantKey(requestedSchemaName, this.currentContentType), this.zodSchemas[requestedSchemaName] ? requestedSchemaName : resolvedReference);
|
|
@@ -12660,6 +12685,8 @@ var ZodSchemaConverter = class {
|
|
|
12660
12685
|
try {
|
|
12661
12686
|
const content = this.fileAccess.readFileSync(filePath, "utf-8");
|
|
12662
12687
|
const ast = parseTypeScriptFile(content);
|
|
12688
|
+
this.currentFilePath = filePath;
|
|
12689
|
+
this.currentAST = ast;
|
|
12663
12690
|
resolvedTraverse(ast, {
|
|
12664
12691
|
ExportNamedDeclaration: (path25) => {
|
|
12665
12692
|
if (t10.isVariableDeclaration(path25.node.declaration)) {
|
|
@@ -12674,6 +12701,17 @@ var ZodSchemaConverter = class {
|
|
|
12674
12701
|
}
|
|
12675
12702
|
this.processingSchemas.delete(schemaName);
|
|
12676
12703
|
}
|
|
12704
|
+
} else if (t10.isIdentifier(declaration.id) && declaration.init) {
|
|
12705
|
+
const schemaName = declaration.id.name;
|
|
12706
|
+
const overrideId = this.extractMetaIdFromNode(declaration.init);
|
|
12707
|
+
if (overrideId && !this.getStoredSchema(schemaName) && !this.processingSchemas.has(schemaName)) {
|
|
12708
|
+
this.processingSchemas.add(schemaName);
|
|
12709
|
+
const schema = this.processZodNode(declaration.init);
|
|
12710
|
+
this.processingSchemas.delete(schemaName);
|
|
12711
|
+
if (schema) {
|
|
12712
|
+
this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
|
|
12713
|
+
}
|
|
12714
|
+
}
|
|
12677
12715
|
}
|
|
12678
12716
|
});
|
|
12679
12717
|
}
|
|
@@ -13227,6 +13265,24 @@ var ZodSchemaConverter = class {
|
|
|
13227
13265
|
}
|
|
13228
13266
|
return void 0;
|
|
13229
13267
|
}
|
|
13268
|
+
extractMetaIdFromNode(node) {
|
|
13269
|
+
if (!t10.isCallExpression(node))
|
|
13270
|
+
return null;
|
|
13271
|
+
if (t10.isMemberExpression(node.callee) && t10.isIdentifier(node.callee.property)) {
|
|
13272
|
+
if (node.callee.property.name === "meta" && node.arguments.length > 0) {
|
|
13273
|
+
const metadata = this.extractStaticJsonValue(node.arguments[0]);
|
|
13274
|
+
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
13275
|
+
const id = metadata.id;
|
|
13276
|
+
if (typeof id === "string" && id.length > 0)
|
|
13277
|
+
return id;
|
|
13278
|
+
}
|
|
13279
|
+
}
|
|
13280
|
+
if (t10.isCallExpression(node.callee.object)) {
|
|
13281
|
+
return this.extractMetaIdFromNode(node.callee.object);
|
|
13282
|
+
}
|
|
13283
|
+
}
|
|
13284
|
+
return null;
|
|
13285
|
+
}
|
|
13230
13286
|
shouldUseRuntimeExport(node) {
|
|
13231
13287
|
if (!t10.isCallExpression(node)) {
|
|
13232
13288
|
return false;
|
|
@@ -13467,7 +13523,8 @@ var ZodSchemaConverter = class {
|
|
|
13467
13523
|
if (node.arguments.length > 0) {
|
|
13468
13524
|
const metadata = this.extractStaticJsonValue(node.arguments[0]);
|
|
13469
13525
|
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
13470
|
-
|
|
13526
|
+
const { id: _id, ...rest } = metadata;
|
|
13527
|
+
Object.assign(schema, rest);
|
|
13471
13528
|
}
|
|
13472
13529
|
}
|
|
13473
13530
|
break;
|
|
@@ -13753,6 +13810,7 @@ var ZodSchemaConverter = class {
|
|
|
13753
13810
|
this.currentFilePath = filePath;
|
|
13754
13811
|
this.currentAST = ast;
|
|
13755
13812
|
this.currentImports = importedModules;
|
|
13813
|
+
this.preprocessedFiles.add(filePath);
|
|
13756
13814
|
resolvedTraverse(ast, {
|
|
13757
13815
|
ExportNamedDeclaration: (path25) => {
|
|
13758
13816
|
if (t10.isVariableDeclaration(path25.node.declaration)) {
|
|
@@ -13760,15 +13818,19 @@ var ZodSchemaConverter = class {
|
|
|
13760
13818
|
if (t10.isIdentifier(declaration.id) && declaration.init) {
|
|
13761
13819
|
const schemaName = declaration.id.name;
|
|
13762
13820
|
if (this.isZodSchema(declaration.init)) {
|
|
13763
|
-
this.indexSchemaName(schemaName, filePath);
|
|
13764
13821
|
if (!this.getStoredSchema(schemaName)) {
|
|
13765
13822
|
logger.debug(`Pre-processing Zod schema: ${schemaName}`);
|
|
13766
13823
|
this.processingSchemas.add(schemaName);
|
|
13767
13824
|
const schema = this.processZodNode(declaration.init);
|
|
13825
|
+
this.processingSchemas.delete(schemaName);
|
|
13768
13826
|
if (schema) {
|
|
13769
|
-
this.
|
|
13827
|
+
const overrideId = this.extractMetaIdFromNode(declaration.init);
|
|
13828
|
+
this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
|
|
13829
|
+
} else {
|
|
13830
|
+
this.indexSchemaName(schemaName, filePath);
|
|
13770
13831
|
}
|
|
13771
|
-
|
|
13832
|
+
} else {
|
|
13833
|
+
this.indexSchemaName(schemaName, filePath);
|
|
13772
13834
|
}
|
|
13773
13835
|
}
|
|
13774
13836
|
}
|
|
@@ -13781,22 +13843,25 @@ var ZodSchemaConverter = class {
|
|
|
13781
13843
|
if (t10.isIdentifier(declaration.id) && declaration.init) {
|
|
13782
13844
|
const schemaName = declaration.id.name;
|
|
13783
13845
|
if (this.isZodSchema(declaration.init)) {
|
|
13784
|
-
this.indexSchemaName(schemaName, filePath);
|
|
13785
13846
|
if (!this.getStoredSchema(schemaName) && !this.processingSchemas.has(schemaName)) {
|
|
13786
13847
|
logger.debug(`Pre-processing Zod schema: ${schemaName}`);
|
|
13787
13848
|
this.processingSchemas.add(schemaName);
|
|
13788
13849
|
const schema = this.processZodNode(declaration.init);
|
|
13850
|
+
this.processingSchemas.delete(schemaName);
|
|
13789
13851
|
if (schema) {
|
|
13790
|
-
this.
|
|
13852
|
+
const overrideId = this.extractMetaIdFromNode(declaration.init);
|
|
13853
|
+
this.applyMetaIdOverride(schemaName, schema, overrideId, filePath);
|
|
13854
|
+
} else {
|
|
13855
|
+
this.indexSchemaName(schemaName, filePath);
|
|
13791
13856
|
}
|
|
13792
|
-
|
|
13857
|
+
} else {
|
|
13858
|
+
this.indexSchemaName(schemaName, filePath);
|
|
13793
13859
|
}
|
|
13794
13860
|
}
|
|
13795
13861
|
}
|
|
13796
13862
|
});
|
|
13797
13863
|
}
|
|
13798
13864
|
});
|
|
13799
|
-
this.preprocessedFiles.add(filePath);
|
|
13800
13865
|
} catch (error2) {
|
|
13801
13866
|
logger.error(`Error pre-processing file ${filePath}: ${error2}`);
|
|
13802
13867
|
}
|
|
@@ -13814,6 +13879,63 @@ var ZodSchemaConverter = class {
|
|
|
13814
13879
|
}
|
|
13815
13880
|
bucket.add(filePath);
|
|
13816
13881
|
}
|
|
13882
|
+
applyMetaIdOverride(schemaName, schema, overrideId, filePath) {
|
|
13883
|
+
const finalName = overrideId && overrideId !== schemaName ? overrideId : schemaName;
|
|
13884
|
+
this.indexSchemaName(schemaName, filePath);
|
|
13885
|
+
if (finalName !== schemaName) {
|
|
13886
|
+
this.indexSchemaName(finalName, filePath);
|
|
13887
|
+
}
|
|
13888
|
+
if (!this.zodSchemas[finalName]) {
|
|
13889
|
+
if (overrideId && overrideId !== schemaName) {
|
|
13890
|
+
this.typeToSchemaMapping[schemaName] = overrideId;
|
|
13891
|
+
this.metaIdSchemaNames.add(schemaName);
|
|
13892
|
+
if (this.typeToSchemaMapping[overrideId] === schemaName) {
|
|
13893
|
+
delete this.typeToSchemaMapping[overrideId];
|
|
13894
|
+
}
|
|
13895
|
+
}
|
|
13896
|
+
const variantKey = this.getVariantKey(finalName, this.currentContentType);
|
|
13897
|
+
this.zodSchemas[finalName] = schema;
|
|
13898
|
+
this.schemaVariantRefs.set(variantKey, finalName);
|
|
13899
|
+
} else {
|
|
13900
|
+
logger.warn(`Schema component name '${overrideId ?? finalName}' conflicts with an existing schema, ignoring .meta({ id }) on '${schemaName}'`);
|
|
13901
|
+
}
|
|
13902
|
+
}
|
|
13903
|
+
/**
|
|
13904
|
+
* Derives the conventional Zod schema name from a TypeScript type name.
|
|
13905
|
+
* e.g. "Slider" → "sliderSchema", "SliderItem" → "sliderItemSchema".
|
|
13906
|
+
* Returns null when the input is already a schema name or is not PascalCase.
|
|
13907
|
+
*/
|
|
13908
|
+
deriveSchemaNameByConvention(typeName) {
|
|
13909
|
+
if (!typeName || !/^[A-Z]/.test(typeName) || typeName.endsWith("Schema")) {
|
|
13910
|
+
return null;
|
|
13911
|
+
}
|
|
13912
|
+
return typeName[0].toLowerCase() + typeName.slice(1) + "Schema";
|
|
13913
|
+
}
|
|
13914
|
+
/**
|
|
13915
|
+
* Checks whether a Zod schema with the given name is present in schemaDirs
|
|
13916
|
+
* WITHOUT populating the processed-schema cache. A file-content substring check
|
|
13917
|
+
* (the same heuristic used by processFileForZodSchema) is sufficient here: we
|
|
13918
|
+
* only want to know whether the candidate *might* live in schemaDirs so that the
|
|
13919
|
+
* convention mapping can be registered; the actual processing happens later in
|
|
13920
|
+
* the normal convertZodSchemaToOpenApi lookup flow.
|
|
13921
|
+
*/
|
|
13922
|
+
locateSchemaByConvention(candidate) {
|
|
13923
|
+
if (this.schemaNameToFiles.has(candidate)) {
|
|
13924
|
+
return true;
|
|
13925
|
+
}
|
|
13926
|
+
for (const dir of this.schemaDirs) {
|
|
13927
|
+
for (const filePath of this.getSchemaFiles(dir)) {
|
|
13928
|
+
try {
|
|
13929
|
+
const content = this.fileAccess.readFileSync(filePath, "utf-8");
|
|
13930
|
+
if (content.includes(candidate)) {
|
|
13931
|
+
return true;
|
|
13932
|
+
}
|
|
13933
|
+
} catch {
|
|
13934
|
+
}
|
|
13935
|
+
}
|
|
13936
|
+
}
|
|
13937
|
+
return false;
|
|
13938
|
+
}
|
|
13817
13939
|
/**
|
|
13818
13940
|
* Check if node is Zod schema
|
|
13819
13941
|
*/
|
|
@@ -14045,7 +14167,7 @@ function parsePropertyComment(commentValue) {
|
|
|
14045
14167
|
function getPropertyOptions(node, contentType) {
|
|
14046
14168
|
const isOptional = !!node.optional;
|
|
14047
14169
|
const options = {};
|
|
14048
|
-
const leadingComment = node.leadingComments?.
|
|
14170
|
+
const leadingComment = node.leadingComments?.findLast((c) => c.type === "CommentBlock" || !node.trailingComments?.length);
|
|
14049
14171
|
const trailingComment = node.trailingComments?.[0];
|
|
14050
14172
|
const sourceComment = leadingComment ?? trailingComment;
|
|
14051
14173
|
if (sourceComment) {
|
|
@@ -14448,31 +14570,60 @@ function resolveImportPath(importPath, fromFilePath, fileAccess) {
|
|
|
14448
14570
|
}
|
|
14449
14571
|
return null;
|
|
14450
14572
|
}
|
|
14451
|
-
function
|
|
14573
|
+
function collectFirstMemberLeadingComments(interfaceDecl) {
|
|
14574
|
+
const body = interfaceDecl?.body;
|
|
14575
|
+
if (!body)
|
|
14576
|
+
return [];
|
|
14577
|
+
const firstMember = body.body?.[0];
|
|
14578
|
+
return firstMember?.leadingComments ?? [];
|
|
14579
|
+
}
|
|
14580
|
+
function collectAllExportedDefinitions(ast, typeDefinitions, currentFile, schemaIdAliases) {
|
|
14581
|
+
function registerDefinition(name, entry, allComments) {
|
|
14582
|
+
if (!typeDefinitions[name]) {
|
|
14583
|
+
typeDefinitions[name] = entry;
|
|
14584
|
+
}
|
|
14585
|
+
const overrideId = extractSchemaIdFromComments(allComments);
|
|
14586
|
+
if (overrideId && schemaIdAliases) {
|
|
14587
|
+
schemaIdAliases[name] = overrideId;
|
|
14588
|
+
if (!typeDefinitions[overrideId]) {
|
|
14589
|
+
typeDefinitions[overrideId] = entry;
|
|
14590
|
+
}
|
|
14591
|
+
}
|
|
14592
|
+
}
|
|
14452
14593
|
resolvedTraverse(ast, {
|
|
14453
14594
|
TSTypeAliasDeclaration: (path25) => {
|
|
14454
14595
|
if (path25.node.id && t12.isIdentifier(path25.node.id)) {
|
|
14455
14596
|
const name = path25.node.id.name;
|
|
14456
|
-
|
|
14457
|
-
|
|
14458
|
-
|
|
14459
|
-
|
|
14597
|
+
const node = path25.node.typeParameters && path25.node.typeParameters.params.length > 0 ? path25.node : path25.node.typeAnnotation;
|
|
14598
|
+
const allComments = [
|
|
14599
|
+
...path25.parentPath?.node?.leadingComments ?? [],
|
|
14600
|
+
...path25.node.leadingComments ?? [],
|
|
14601
|
+
...path25.node.trailingComments ?? []
|
|
14602
|
+
];
|
|
14603
|
+
registerDefinition(name, { node, filePath: currentFile }, allComments);
|
|
14460
14604
|
}
|
|
14461
14605
|
},
|
|
14462
14606
|
TSInterfaceDeclaration: (path25) => {
|
|
14463
14607
|
if (path25.node.id && t12.isIdentifier(path25.node.id)) {
|
|
14464
14608
|
const name = path25.node.id.name;
|
|
14465
|
-
|
|
14466
|
-
|
|
14467
|
-
|
|
14609
|
+
const allComments = [
|
|
14610
|
+
...path25.parentPath?.node?.leadingComments ?? [],
|
|
14611
|
+
...path25.node.leadingComments ?? [],
|
|
14612
|
+
...path25.node.trailingComments ?? [],
|
|
14613
|
+
...collectFirstMemberLeadingComments(path25.node)
|
|
14614
|
+
];
|
|
14615
|
+
registerDefinition(name, { node: path25.node, filePath: currentFile }, allComments);
|
|
14468
14616
|
}
|
|
14469
14617
|
},
|
|
14470
14618
|
TSEnumDeclaration: (path25) => {
|
|
14471
14619
|
if (path25.node.id && t12.isIdentifier(path25.node.id)) {
|
|
14472
14620
|
const name = path25.node.id.name;
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
|
|
14621
|
+
const allComments = [
|
|
14622
|
+
...path25.parentPath?.node?.leadingComments ?? [],
|
|
14623
|
+
...path25.node.leadingComments ?? [],
|
|
14624
|
+
...path25.node.trailingComments ?? []
|
|
14625
|
+
];
|
|
14626
|
+
registerDefinition(name, { node: path25.node, filePath: currentFile }, allComments);
|
|
14476
14627
|
}
|
|
14477
14628
|
},
|
|
14478
14629
|
ExportNamedDeclaration: (path25) => {
|
|
@@ -14480,19 +14631,26 @@ function collectAllExportedDefinitions(ast, typeDefinitions, currentFile) {
|
|
|
14480
14631
|
const interfaceDecl = path25.node.declaration;
|
|
14481
14632
|
if (interfaceDecl.id && t12.isIdentifier(interfaceDecl.id)) {
|
|
14482
14633
|
const name = interfaceDecl.id.name;
|
|
14483
|
-
|
|
14484
|
-
|
|
14485
|
-
|
|
14634
|
+
const allComments = [
|
|
14635
|
+
...path25.node.leadingComments ?? [],
|
|
14636
|
+
...interfaceDecl.leadingComments ?? [],
|
|
14637
|
+
...interfaceDecl.trailingComments ?? [],
|
|
14638
|
+
...collectFirstMemberLeadingComments(interfaceDecl)
|
|
14639
|
+
];
|
|
14640
|
+
registerDefinition(name, { node: interfaceDecl, filePath: currentFile }, allComments);
|
|
14486
14641
|
}
|
|
14487
14642
|
}
|
|
14488
14643
|
if (t12.isTSTypeAliasDeclaration(path25.node.declaration)) {
|
|
14489
14644
|
const typeDecl = path25.node.declaration;
|
|
14490
14645
|
if (typeDecl.id && t12.isIdentifier(typeDecl.id)) {
|
|
14491
14646
|
const name = typeDecl.id.name;
|
|
14492
|
-
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
|
|
14647
|
+
const node = typeDecl.typeParameters && typeDecl.typeParameters.params.length > 0 ? typeDecl : typeDecl.typeAnnotation;
|
|
14648
|
+
const allComments = [
|
|
14649
|
+
...path25.node.leadingComments ?? [],
|
|
14650
|
+
...typeDecl.leadingComments ?? [],
|
|
14651
|
+
...typeDecl.trailingComments ?? []
|
|
14652
|
+
];
|
|
14653
|
+
registerDefinition(name, { node, filePath: currentFile }, allComments);
|
|
14496
14654
|
}
|
|
14497
14655
|
}
|
|
14498
14656
|
}
|
|
@@ -14909,6 +15067,7 @@ var SchemaProcessor = class {
|
|
|
14909
15067
|
zodSchemaProcessor = null;
|
|
14910
15068
|
schemaTypes;
|
|
14911
15069
|
isResolvingPickOmitBase = false;
|
|
15070
|
+
schemaIdAliases = {};
|
|
14912
15071
|
fileAccess;
|
|
14913
15072
|
symbolResolver;
|
|
14914
15073
|
// Track imports per file for resolving ReturnType<typeof func>
|
|
@@ -14949,7 +15108,7 @@ var SchemaProcessor = class {
|
|
|
14949
15108
|
getDefinedSchemas() {
|
|
14950
15109
|
const filteredSchemas = {};
|
|
14951
15110
|
Object.entries(this.openapiDefinitions).forEach(([key, value]) => {
|
|
14952
|
-
if (!this.isGenericTypeParameter(key) && !this.isInvalidSchemaName(key) && !this.isBuiltInUtilityType(key) && !this.isFunctionSchema(key)) {
|
|
15111
|
+
if (!this.schemaIdAliases[key] && !this.isGenericTypeParameter(key) && !this.isInvalidSchemaName(key) && !this.isBuiltInUtilityType(key) && !this.isFunctionSchema(key)) {
|
|
14953
15112
|
filteredSchemas[key] = value;
|
|
14954
15113
|
}
|
|
14955
15114
|
});
|
|
@@ -14964,6 +15123,10 @@ var SchemaProcessor = class {
|
|
|
14964
15123
|
if (schemaName.includes("<") && schemaName.includes(">")) {
|
|
14965
15124
|
return this.resolveGenericTypeFromString(schemaName);
|
|
14966
15125
|
}
|
|
15126
|
+
const overrideId = this.schemaIdAliases[schemaName];
|
|
15127
|
+
if (overrideId) {
|
|
15128
|
+
return this.findSchemaDefinition(overrideId, contentType);
|
|
15129
|
+
}
|
|
14967
15130
|
if (this.openapiDefinitions[schemaName]) {
|
|
14968
15131
|
return this.openapiDefinitions[schemaName];
|
|
14969
15132
|
}
|
|
@@ -15045,6 +15208,7 @@ var SchemaProcessor = class {
|
|
|
15045
15208
|
return;
|
|
15046
15209
|
}
|
|
15047
15210
|
this.collectImports(ast, filePath);
|
|
15211
|
+
const aliasesBeforeFile = new Set(Object.keys(this.schemaIdAliases));
|
|
15048
15212
|
this.collectAllExportedDefinitions(ast, filePath);
|
|
15049
15213
|
collectTopLevelDefinitionNames(ast).forEach((name) => {
|
|
15050
15214
|
const indexedFiles = this.schemaDefinitionIndex[name];
|
|
@@ -15056,6 +15220,16 @@ var SchemaProcessor = class {
|
|
|
15056
15220
|
}
|
|
15057
15221
|
this.schemaDefinitionIndex[name] = [filePath];
|
|
15058
15222
|
});
|
|
15223
|
+
Object.entries(this.schemaIdAliases).forEach(([originalName, aliasName]) => {
|
|
15224
|
+
if (aliasesBeforeFile.has(originalName))
|
|
15225
|
+
return;
|
|
15226
|
+
if (!this.schemaDefinitionIndex[aliasName]) {
|
|
15227
|
+
this.schemaDefinitionIndex[aliasName] = [];
|
|
15228
|
+
}
|
|
15229
|
+
if (!this.schemaDefinitionIndex[aliasName].includes(filePath)) {
|
|
15230
|
+
this.schemaDefinitionIndex[aliasName].push(filePath);
|
|
15231
|
+
}
|
|
15232
|
+
});
|
|
15059
15233
|
}
|
|
15060
15234
|
getParsedSchemaFile(filePath) {
|
|
15061
15235
|
const cachedAst = this.fileASTCache.get(filePath);
|
|
@@ -15094,7 +15268,7 @@ var SchemaProcessor = class {
|
|
|
15094
15268
|
* Used when processing imported files to ensure all referenced types are available
|
|
15095
15269
|
*/
|
|
15096
15270
|
collectAllExportedDefinitions(ast, filePath) {
|
|
15097
|
-
collectAllExportedDefinitions(ast, this.typeDefinitions, filePath || this.currentFilePath);
|
|
15271
|
+
collectAllExportedDefinitions(ast, this.typeDefinitions, filePath || this.currentFilePath, this.schemaIdAliases);
|
|
15098
15272
|
}
|
|
15099
15273
|
collectTypeDefinitions(ast, schemaName, filePath) {
|
|
15100
15274
|
collectTypeDefinitions(ast, schemaName, this.typeDefinitions, filePath || this.currentFilePath);
|
|
@@ -15691,6 +15865,9 @@ var SchemaProcessor = class {
|
|
|
15691
15865
|
logger.debug(`Record<...> used with ${node.typeParameters?.params.length ?? 0} type parameters; expected 2`);
|
|
15692
15866
|
return { type: "object", additionalProperties: true };
|
|
15693
15867
|
}
|
|
15868
|
+
if ((!node.typeParameters || node.typeParameters.params.length === 0) && this.schemaIdAliases[typeName] && this.openapiDefinitions[this.schemaIdAliases[typeName]]) {
|
|
15869
|
+
return { $ref: `#/components/schemas/${this.schemaIdAliases[typeName]}` };
|
|
15870
|
+
}
|
|
15694
15871
|
const utilityType = resolveUtilityTypeReference(node, {
|
|
15695
15872
|
currentFilePath: this.currentFilePath,
|
|
15696
15873
|
contentType: this.contentType,
|
|
@@ -15866,7 +16043,9 @@ var SchemaProcessor = class {
|
|
|
15866
16043
|
};
|
|
15867
16044
|
}
|
|
15868
16045
|
if (t15.isTSTypeReference(node) && t15.isIdentifier(node.typeName)) {
|
|
15869
|
-
|
|
16046
|
+
const refName = node.typeName.name;
|
|
16047
|
+
const aliasedName = this.schemaIdAliases[refName] ?? refName;
|
|
16048
|
+
return { $ref: `#/components/schemas/${aliasedName}` };
|
|
15870
16049
|
}
|
|
15871
16050
|
logger.debug("Unrecognized TypeScript type node:", node);
|
|
15872
16051
|
return { type: "object" };
|
|
@@ -16007,7 +16186,8 @@ var SchemaProcessor = class {
|
|
|
16007
16186
|
if (this.schemaTypes.includes("zod") && this.zodSchemaConverter) {
|
|
16008
16187
|
return this.zodSchemaConverter.getSchemaReferenceName(baseTypeName, contentType);
|
|
16009
16188
|
}
|
|
16010
|
-
|
|
16189
|
+
const aliasedName = this.schemaIdAliases[baseTypeName] ?? baseTypeName;
|
|
16190
|
+
return aliasedName;
|
|
16011
16191
|
}
|
|
16012
16192
|
/**
|
|
16013
16193
|
* Parse and resolve a generic type from a string like "MyApiSuccessResponseBody<LLMSResponse>"
|