next-openapi-gen 0.6.6 → 0.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/schema-processor.js +76 -4
- package/package.json +1 -1
|
@@ -16,6 +16,7 @@ export class SchemaProcessor {
|
|
|
16
16
|
processingTypes = new Set();
|
|
17
17
|
zodSchemaConverter;
|
|
18
18
|
schemaType;
|
|
19
|
+
isResolvingPickOmitBase = false;
|
|
19
20
|
constructor(schemaDir, schemaType = "typescript") {
|
|
20
21
|
this.schemaDir = path.resolve(schemaDir);
|
|
21
22
|
this.schemaType = schemaType;
|
|
@@ -166,10 +167,21 @@ export class SchemaProcessor {
|
|
|
166
167
|
const enumValues = this.processEnum(typeNode);
|
|
167
168
|
return enumValues;
|
|
168
169
|
}
|
|
169
|
-
if (t.isTSTypeLiteral(typeNode) || t.isTSInterfaceBody(typeNode)) {
|
|
170
|
+
if (t.isTSTypeLiteral(typeNode) || t.isTSInterfaceBody(typeNode) || t.isTSInterfaceDeclaration(typeNode)) {
|
|
170
171
|
const properties = {};
|
|
171
|
-
|
|
172
|
-
|
|
172
|
+
// Handle interface extends clause
|
|
173
|
+
if (t.isTSInterfaceDeclaration(typeNode) && typeNode.extends && typeNode.extends.length > 0) {
|
|
174
|
+
typeNode.extends.forEach((extendedType) => {
|
|
175
|
+
const extendedSchema = this.resolveTSNodeType(extendedType);
|
|
176
|
+
if (extendedSchema.properties) {
|
|
177
|
+
Object.assign(properties, extendedSchema.properties);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
// Get members from interface declaration body or direct members
|
|
182
|
+
const members = t.isTSInterfaceDeclaration(typeNode) ? typeNode.body.body : typeNode.members;
|
|
183
|
+
if (members) {
|
|
184
|
+
(members || []).forEach((member) => {
|
|
173
185
|
if (t.isTSPropertySignature(member) && t.isIdentifier(member.key)) {
|
|
174
186
|
const propName = member.key.name;
|
|
175
187
|
const options = this.getPropertyOptions(member);
|
|
@@ -192,6 +204,9 @@ export class SchemaProcessor {
|
|
|
192
204
|
if (t.isTSUnionType(typeNode)) {
|
|
193
205
|
return this.resolveTSNodeType(typeNode);
|
|
194
206
|
}
|
|
207
|
+
if (t.isTSTypeReference(typeNode)) {
|
|
208
|
+
return this.resolveTSNodeType(typeNode);
|
|
209
|
+
}
|
|
195
210
|
return {};
|
|
196
211
|
}
|
|
197
212
|
finally {
|
|
@@ -250,6 +265,18 @@ export class SchemaProcessor {
|
|
|
250
265
|
};
|
|
251
266
|
}
|
|
252
267
|
}
|
|
268
|
+
// Handle TSExpressionWithTypeArguments (used in interface extends)
|
|
269
|
+
if (t.isTSExpressionWithTypeArguments(node)) {
|
|
270
|
+
if (t.isIdentifier(node.expression)) {
|
|
271
|
+
// Convert to TSTypeReference-like structure for processing
|
|
272
|
+
const syntheticNode = {
|
|
273
|
+
type: 'TSTypeReference',
|
|
274
|
+
typeName: node.expression,
|
|
275
|
+
typeParameters: node.typeParameters
|
|
276
|
+
};
|
|
277
|
+
return this.resolveTSNodeType(syntheticNode);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
253
280
|
if (t.isTSTypeReference(node) && t.isIdentifier(node.typeName)) {
|
|
254
281
|
const typeName = node.typeName.name;
|
|
255
282
|
// Special handling for built-in types
|
|
@@ -284,6 +311,34 @@ export class SchemaProcessor {
|
|
|
284
311
|
}
|
|
285
312
|
}
|
|
286
313
|
if (typeName === "Pick" || typeName === "Omit") {
|
|
314
|
+
if (node.typeParameters && node.typeParameters.params.length > 1) {
|
|
315
|
+
const baseTypeParam = node.typeParameters.params[0];
|
|
316
|
+
const keysParam = node.typeParameters.params[1];
|
|
317
|
+
// Resolve base type without adding it to schema definitions
|
|
318
|
+
this.isResolvingPickOmitBase = true;
|
|
319
|
+
const baseType = this.resolveTSNodeType(baseTypeParam);
|
|
320
|
+
this.isResolvingPickOmitBase = false;
|
|
321
|
+
if (baseType.properties) {
|
|
322
|
+
const properties = {};
|
|
323
|
+
const keyNames = this.extractKeysFromLiteralType(keysParam);
|
|
324
|
+
if (typeName === "Pick") {
|
|
325
|
+
keyNames.forEach(key => {
|
|
326
|
+
if (baseType.properties[key]) {
|
|
327
|
+
properties[key] = baseType.properties[key];
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
else { // Omit
|
|
332
|
+
Object.entries(baseType.properties).forEach(([key, value]) => {
|
|
333
|
+
if (!keyNames.includes(key)) {
|
|
334
|
+
properties[key] = value;
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
return { type: "object", properties };
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Fallback to just the base type if we can't process properly
|
|
287
342
|
if (node.typeParameters && node.typeParameters.params.length > 0) {
|
|
288
343
|
return this.resolveTSNodeType(node.typeParameters.params[0]);
|
|
289
344
|
}
|
|
@@ -413,7 +468,9 @@ export class SchemaProcessor {
|
|
|
413
468
|
// Reset the set of processed types before each schema processing
|
|
414
469
|
this.processingTypes.clear();
|
|
415
470
|
const definition = this.resolveType(schemaName);
|
|
416
|
-
this.
|
|
471
|
+
if (!this.isResolvingPickOmitBase) {
|
|
472
|
+
this.openapiDefinitions[schemaName] = definition;
|
|
473
|
+
}
|
|
417
474
|
this.processSchemaTracker[`${filePath}-${schemaName}`] = true;
|
|
418
475
|
return definition;
|
|
419
476
|
}
|
|
@@ -447,6 +504,21 @@ export class SchemaProcessor {
|
|
|
447
504
|
});
|
|
448
505
|
return enumSchema;
|
|
449
506
|
}
|
|
507
|
+
extractKeysFromLiteralType(node) {
|
|
508
|
+
if (t.isTSLiteralType(node) && t.isStringLiteral(node.literal)) {
|
|
509
|
+
return [node.literal.value];
|
|
510
|
+
}
|
|
511
|
+
if (t.isTSUnionType(node)) {
|
|
512
|
+
const keys = [];
|
|
513
|
+
node.types.forEach((type) => {
|
|
514
|
+
if (t.isTSLiteralType(type) && t.isStringLiteral(type.literal)) {
|
|
515
|
+
keys.push(type.literal.value);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
return keys;
|
|
519
|
+
}
|
|
520
|
+
return [];
|
|
521
|
+
}
|
|
450
522
|
getPropertyOptions(node) {
|
|
451
523
|
const isOptional = !!node.optional; // check if property is optional
|
|
452
524
|
let description = null;
|
package/package.json
CHANGED