@moccona/apicodegen 0.0.8 → 0.0.10
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/bin/cli.cjs +12 -13
- package/npm/index.cjs +671 -787
- package/npm/index.cjs.map +1 -1
- package/npm/index.d.cts +30 -6
- package/npm/index.d.cts.map +1 -1
- package/npm/index.d.mts +30 -6
- package/npm/index.d.mts.map +1 -1
- package/npm/index.mjs +671 -787
- package/npm/index.mjs.map +1 -1
- package/npm/vite/index.d.mts.map +1 -1
- package/npm/vite/index.mjs +433 -558
- package/npm/vite/index.mjs.map +1 -1
- package/package.json +1 -1
package/npm/vite/index.mjs
CHANGED
|
@@ -240,29 +240,6 @@ var ApicodegenError = class ApicodegenError extends Error {
|
|
|
240
240
|
}
|
|
241
241
|
};
|
|
242
242
|
/**
|
|
243
|
-
* ANSI color codes for terminal output
|
|
244
|
-
*/
|
|
245
|
-
const Colors = {
|
|
246
|
-
reset: "\x1B[0m",
|
|
247
|
-
bold: "\x1B[1m",
|
|
248
|
-
red: "\x1B[31m",
|
|
249
|
-
green: "\x1B[32m",
|
|
250
|
-
yellow: "\x1B[33m",
|
|
251
|
-
blue: "\x1B[34m",
|
|
252
|
-
cyan: "\x1B[36m",
|
|
253
|
-
gray: "\x1B[90m",
|
|
254
|
-
brightRed: "\x1B[91m",
|
|
255
|
-
brightGreen: "\x1B[92m"
|
|
256
|
-
};
|
|
257
|
-
/**
|
|
258
|
-
* Format error for CLI output
|
|
259
|
-
*/
|
|
260
|
-
function formatError(error, verbose = false) {
|
|
261
|
-
if (error instanceof ApicodegenError) return error.toString(verbose);
|
|
262
|
-
if (error instanceof Error) return `${Colors.red}${Colors.bold}Error${Colors.reset}: ${error.message}${verbose && error.stack ? `\n\n${Colors.gray}${error.stack}${Colors.reset}` : ""}`;
|
|
263
|
-
return `${Colors.red}${Colors.bold}Error${Colors.reset}: ${String(error)}`;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
243
|
* Create error with common patterns
|
|
267
244
|
*/
|
|
268
245
|
const createErrors = {
|
|
@@ -399,6 +376,68 @@ function isApicodegenError(error) {
|
|
|
399
376
|
return error instanceof ApicodegenError;
|
|
400
377
|
}
|
|
401
378
|
//#endregion
|
|
379
|
+
//#region src/core/logger.ts
|
|
380
|
+
const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
|
|
381
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`;
|
|
382
|
+
const red = (s) => `\x1b[31m${s}\x1b[0m`;
|
|
383
|
+
const blue = (s) => `\x1b[34m${s}\x1b[0m`;
|
|
384
|
+
const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
|
|
385
|
+
const magenta = (s) => `\x1b[35m${s}\x1b[0m`;
|
|
386
|
+
const gray = (s) => `\x1b[90m${s}\x1b[0m`;
|
|
387
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
388
|
+
const logger$1 = {
|
|
389
|
+
success(msg) {
|
|
390
|
+
console.log(`${green("✓")} ${msg}`);
|
|
391
|
+
},
|
|
392
|
+
error(err, verbose = false) {
|
|
393
|
+
if (isApicodegenError(err)) console.error(`${red("✗")} ${err.toString(verbose)}`);
|
|
394
|
+
else if (err instanceof Error) {
|
|
395
|
+
const msg = `Error: ${err.message}`;
|
|
396
|
+
console.error(`${red("✗")} ${msg}${verbose && err.stack ? `\n${gray(err.stack)}` : ""}`);
|
|
397
|
+
} else console.error(`${red("✗")} ${String(err)}`);
|
|
398
|
+
},
|
|
399
|
+
info(msg) {
|
|
400
|
+
console.log(`${blue("ℹ")} ${msg}`);
|
|
401
|
+
},
|
|
402
|
+
warn(msg) {
|
|
403
|
+
console.log(`${yellow("⚠")} ${msg}`);
|
|
404
|
+
},
|
|
405
|
+
loading(msg) {
|
|
406
|
+
console.log(`${yellow("🔄")} ${msg}`);
|
|
407
|
+
},
|
|
408
|
+
watching(msg) {
|
|
409
|
+
console.log(`${magenta("⟳")} ${msg}`);
|
|
410
|
+
},
|
|
411
|
+
fileChange(filePath) {
|
|
412
|
+
console.log(`${yellow("↓")} ${filePath}`);
|
|
413
|
+
},
|
|
414
|
+
fileAdd(filePath) {
|
|
415
|
+
console.log(`${green("+")} ${filePath}`);
|
|
416
|
+
},
|
|
417
|
+
shutdown() {
|
|
418
|
+
console.log(`\n${gray("👋 Shutting down...")}`);
|
|
419
|
+
},
|
|
420
|
+
divider(width = 50) {
|
|
421
|
+
console.log(`${bold(cyan("─".repeat(width)))}`);
|
|
422
|
+
},
|
|
423
|
+
heading(text, mode, width = 50) {
|
|
424
|
+
console.log(`${bold(cyan("─".repeat(width)))}`);
|
|
425
|
+
console.log(`${bold(cyan(text))}`);
|
|
426
|
+
console.log(`${gray("Mode:")} ${mode || "unknown"}`);
|
|
427
|
+
console.log(`${bold(cyan("─".repeat(width)))}`);
|
|
428
|
+
},
|
|
429
|
+
item(label, color = "green") {
|
|
430
|
+
const icon = color === "green" ? "✓" : color === "red" ? "✗" : "⚠";
|
|
431
|
+
console.log(`${color === "green" ? green(icon) : color === "red" ? red(icon) : yellow(icon)} ${label}`);
|
|
432
|
+
},
|
|
433
|
+
summary(stats) {
|
|
434
|
+
const { succeeded, failed, endpoints, schemas, duration } = stats;
|
|
435
|
+
const label = `API Code Gen - Complete (${succeeded} succeeded${failed > 0 ? `, ${failed} failed` : ""}, ${endpoints} endpoints, ${schemas} schemas, ${duration}ms)`;
|
|
436
|
+
if (failed === 0) console.log(`${green("✓")} ${label}`);
|
|
437
|
+
else console.log(`${yellow("⚠")} ${label}`);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
//#endregion
|
|
402
441
|
//#region src/core/base/Adaptor.ts
|
|
403
442
|
/**
|
|
404
443
|
* Base adapter for tool
|
|
@@ -572,7 +611,9 @@ var Base = class Base {
|
|
|
572
611
|
*/
|
|
573
612
|
static camelCase(text) {
|
|
574
613
|
text = text.trim();
|
|
575
|
-
|
|
614
|
+
const parts = text.split("_").filter(Boolean);
|
|
615
|
+
while (parts[0]?.match(/^\d/)) parts.shift();
|
|
616
|
+
return parts.map((t, index) => index === 0 ? t : Base.capitalize(t)).join("");
|
|
576
617
|
}
|
|
577
618
|
/**
|
|
578
619
|
* Converts a string to UpperCamelCase.
|
|
@@ -762,10 +803,19 @@ var Generator = class Generator {
|
|
|
762
803
|
return createPrinter().printFile(sourceFile);
|
|
763
804
|
}
|
|
764
805
|
static async write(code, filepath) {
|
|
806
|
+
const { mkdir } = await import("node:fs/promises");
|
|
807
|
+
const { dirname } = await import("node:path");
|
|
765
808
|
try {
|
|
809
|
+
await mkdir(dirname(filepath), { recursive: true });
|
|
766
810
|
await writeFile(filepath, code);
|
|
767
811
|
} catch (error) {
|
|
768
|
-
|
|
812
|
+
throw new ApicodegenError({
|
|
813
|
+
code: ErrorCodes.OUTPUT_DIR_MISSING,
|
|
814
|
+
message: "Failed to write generated code to output file",
|
|
815
|
+
location: filepath,
|
|
816
|
+
cause: error instanceof Error ? error : new Error(String(error)),
|
|
817
|
+
suggestions: ["Verify the output directory path is writable", "Check that the parent directory exists or can be created"]
|
|
818
|
+
});
|
|
769
819
|
}
|
|
770
820
|
}
|
|
771
821
|
/**
|
|
@@ -801,9 +851,12 @@ var Generator = class Generator {
|
|
|
801
851
|
static addComments(node, comments) {
|
|
802
852
|
if (!Array.isArray(comments) || comments.filter(Boolean).length === 0) return;
|
|
803
853
|
const formatComment = (comment) => {
|
|
804
|
-
|
|
854
|
+
if (comment.tag === "returns") return `* @returns {${comment.type}} ${comment.comment ?? ""}`;
|
|
855
|
+
if (comment.tag === "param") return comment.comment ? `* @param ${comment.paramName} - ${comment.comment}` : `* @param ${comment.paramName}`;
|
|
856
|
+
if (comment.tag) return `* @${comment.tag} ${comment.comment ?? ""}`;
|
|
857
|
+
return `* ${comment.comment}`;
|
|
805
858
|
};
|
|
806
|
-
const formattedComments =
|
|
859
|
+
const formattedComments = comments.map(formatComment).join("\n").trim() + "\n";
|
|
807
860
|
addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, formattedComments, true);
|
|
808
861
|
}
|
|
809
862
|
/**
|
|
@@ -820,6 +873,53 @@ var Generator = class Generator {
|
|
|
820
873
|
const nonArraySchema = schema;
|
|
821
874
|
return nonArraySchema.format === "blob" || nonArraySchema.format === "binary" || nonArraySchema.type === "file";
|
|
822
875
|
}
|
|
876
|
+
static schemaToTypeString(schema) {
|
|
877
|
+
if (schema.type === "array") {
|
|
878
|
+
const arraySchema = schema;
|
|
879
|
+
return arraySchema.items ? `${Generator.schemaToTypeString(arraySchema.items)}[]` : "unknown";
|
|
880
|
+
}
|
|
881
|
+
const singleSchema = schema;
|
|
882
|
+
if (schema.type === "string") return "string";
|
|
883
|
+
if (schema.type === "number" || schema.type === "integer") return "number";
|
|
884
|
+
if (schema.type === "boolean") return "boolean";
|
|
885
|
+
if (schema.type === "object" || schema.properties) return "object";
|
|
886
|
+
if (singleSchema.format === "binary" || singleSchema.type === "file") return "Blob";
|
|
887
|
+
if (singleSchema.format === "blob") return "Blob";
|
|
888
|
+
if (singleSchema.ref) return singleSchema.ref;
|
|
889
|
+
return "unknown";
|
|
890
|
+
}
|
|
891
|
+
static generateParamTags(parameters, requestBody) {
|
|
892
|
+
const tags = [];
|
|
893
|
+
for (const p of parameters) {
|
|
894
|
+
const paramName = Base.camelCase(Base.normalize(p.name));
|
|
895
|
+
let paramType = "unknown";
|
|
896
|
+
if (p.schema) paramType = Generator.schemaToTypeString(p.schema);
|
|
897
|
+
const isOptional = p.required === false;
|
|
898
|
+
tags.push({
|
|
899
|
+
tag: "param",
|
|
900
|
+
paramName,
|
|
901
|
+
type: `${paramType}${isOptional ? " | undefined" : ""}`,
|
|
902
|
+
comment: p.description ?? ""
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
if (requestBody?.schema && "properties" in requestBody.schema) {
|
|
906
|
+
const properties = requestBody.schema.properties;
|
|
907
|
+
const required = requestBody.schema.required;
|
|
908
|
+
const requiredArray = Array.isArray(required) ? required : [];
|
|
909
|
+
for (const [key, schema] of Object.entries(properties ?? {})) {
|
|
910
|
+
const paramName = `req.${key}`;
|
|
911
|
+
const paramType = Generator.schemaToTypeString(schema);
|
|
912
|
+
const isOptional = !requiredArray.includes(key);
|
|
913
|
+
tags.push({
|
|
914
|
+
tag: "param",
|
|
915
|
+
paramName,
|
|
916
|
+
type: `${paramType}${isOptional ? " | undefined" : ""}`,
|
|
917
|
+
comment: schema.description ?? ""
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return tags;
|
|
922
|
+
}
|
|
823
923
|
static toRequestBodyTypeNode(schema) {
|
|
824
924
|
return factory.createParameterDeclaration(void 0, void 0, factory.createIdentifier("req"), void 0, Generator.toTypeNode(schema));
|
|
825
925
|
}
|
|
@@ -898,8 +998,8 @@ var Generator = class Generator {
|
|
|
898
998
|
factory.createIdentifier("file"),
|
|
899
999
|
factory.createPropertyAccessExpression(factory.createAsExpression(factory.createIdentifier("file"), factory.createTypeReferenceNode(factory.createIdentifier("File"), void 0)), factory.createIdentifier("name"))
|
|
900
1000
|
]))])));
|
|
901
|
-
else if (schemaByKey.required) statements.push(factory.createExpressionStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("fd"), factory.createIdentifier("append")), void 0, [factory.createStringLiteral(key), schemaByKey.type === "string" ? factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key)) : factory.createCallExpression(factory.createIdentifier("String"), void 0, [factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key))])])));
|
|
902
|
-
else statements.push(factory.createExpressionStatement(factory.createBinaryExpression(factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key)), factory.createToken(SyntaxKind.AmpersandAmpersandToken), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("fd"), factory.createIdentifier("append")), void 0, [factory.createStringLiteral(key), schemaByKey.type === "string" ? factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key)) : factory.createCallExpression(factory.createIdentifier("String"), void 0, [factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key))])]))));
|
|
1001
|
+
else if (schemaByKey.required) statements.push(factory.createExpressionStatement(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("fd"), factory.createIdentifier("append")), void 0, [factory.createStringLiteral(key), schemaByKey.type === "string" || Generator.isBinarySchema(schemaByKey) || schemaByKey.isRef ? factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key)) : schemaByKey.type === "array" || schemaByKey.type === "object" ? factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("JSON"), factory.createIdentifier("stringify")), void 0, [factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key))]) : factory.createCallExpression(factory.createIdentifier("String"), void 0, [factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key))])])));
|
|
1002
|
+
else statements.push(factory.createExpressionStatement(factory.createBinaryExpression(factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key)), factory.createToken(SyntaxKind.AmpersandAmpersandToken), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("fd"), factory.createIdentifier("append")), void 0, [factory.createStringLiteral(key), schemaByKey.type === "string" || Generator.isBinarySchema(schemaByKey) || schemaByKey.isRef ? factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key)) : schemaByKey.type === "array" || schemaByKey.type === "object" ? factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("JSON"), factory.createIdentifier("stringify")), void 0, [factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key))]) : factory.createCallExpression(factory.createIdentifier("String"), void 0, [factory.createElementAccessExpression(factory.createIdentifier("req"), factory.createStringLiteral(key))])]))));
|
|
903
1003
|
});
|
|
904
1004
|
return statements;
|
|
905
1005
|
}
|
|
@@ -911,7 +1011,7 @@ var Generator = class Generator {
|
|
|
911
1011
|
const parametersShouldNotPutInFormData = parameters.filter((p) => !parametersShouldPutInFormData.includes(p));
|
|
912
1012
|
const isRequestBodyContainsBinary = requestBody?.schema && "properties" in requestBody.schema && Object.values(requestBody.schema?.properties ?? {}).some((p) => Generator.isBinarySchema(p));
|
|
913
1013
|
const hasBinaryInParameters = parameters.some((p) => p?.schema && Generator.isBinarySchema(p.schema));
|
|
914
|
-
const shouldPutParametersOrBodyInFormData = isFormDataRequest
|
|
1014
|
+
const shouldPutParametersOrBodyInFormData = !!isFormDataRequest && (isRequestBodyBinary || hasBinaryInParameters || isRequestBodyContainsBinary || parametersShouldPutInFormData.length > 0);
|
|
915
1015
|
return factory.createBlock([...shouldPutParametersOrBodyInFormData ? Generator.toFormDataStatement(parametersShouldPutInFormData, requestBody?.schema) : [], ...adapter.client(uri, method, parametersShouldNotPutInFormData, requestBody, response, adapter, shouldPutParametersOrBodyInFormData, shouldParseResponseToJSON)]);
|
|
916
1016
|
}
|
|
917
1017
|
static schemaToStatemets(parsedDoc, adaptor, options) {
|
|
@@ -938,10 +1038,11 @@ var Generator = class Generator {
|
|
|
938
1038
|
const shouldAddExtraMethodNameSuffix = requestBody.length > 1;
|
|
939
1039
|
for (const req of requestBody) {
|
|
940
1040
|
const statement = factory.createFunctionDeclaration([factory.createModifier(SyntaxKind.ExportKeyword), factory.createModifier(SyntaxKind.AsyncKeyword)], void 0, Base.pathToFnName(uri, method, operationId) + (shouldAddExtraMethodNameSuffix ? Base.capitalize(req.type.split("/")[1]) : ""), void 0, [...parameters.length > 0 ? Generator.toDeclarationNodes(parameters) : [], ...req?.schema ? [Generator.toRequestBodyTypeNode(req.schema)] : []].filter(Boolean), void 0, Generator.bodyBlock(options.baseURL + uri, method, parameters, req, responses[0], adaptor));
|
|
1041
|
+
const mergedDescription = [description, summary].filter(Boolean).join(". ");
|
|
941
1042
|
Generator.addComments(statement, [
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1043
|
+
mergedDescription && { comment: mergedDescription },
|
|
1044
|
+
deprecated && { tag: "deprecated" },
|
|
1045
|
+
...Generator.generateParamTags(parameters, req)
|
|
945
1046
|
].filter(Boolean));
|
|
946
1047
|
statements.push(statement);
|
|
947
1048
|
}
|
|
@@ -1051,12 +1152,12 @@ var FetchAdapter = class extends Adapter {
|
|
|
1051
1152
|
}
|
|
1052
1153
|
};
|
|
1053
1154
|
//#endregion
|
|
1054
|
-
//#region src/openapi/
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1155
|
+
//#region src/openapi/VersionedProvider.ts
|
|
1156
|
+
/**
|
|
1157
|
+
* Abstract base class. Subclasses implement the four container accessors
|
|
1158
|
+
* and a version tag. The shared logic lives here.
|
|
1159
|
+
*/
|
|
1160
|
+
var VersionedProvider = class {
|
|
1060
1161
|
/**
|
|
1061
1162
|
* Resolves a path $ref to the actual path object.
|
|
1062
1163
|
*/
|
|
@@ -1068,281 +1169,37 @@ var V2 = class {
|
|
|
1068
1169
|
* Is array schema.
|
|
1069
1170
|
*/
|
|
1070
1171
|
isOpenAPIArraySchema(schema) {
|
|
1071
|
-
return typeof schema === "object" && schema.type === "array";
|
|
1172
|
+
return typeof schema === "object" && schema !== null && schema.type === "array";
|
|
1072
1173
|
}
|
|
1073
1174
|
/**
|
|
1074
|
-
* OpenAPI schema to base schema.
|
|
1175
|
+
* OpenAPI schema to base schema. Override for version-specific quirks
|
|
1176
|
+
* (V3_1 throws on missing ref; V3 returns `{ type: 'unknown' }`).
|
|
1075
1177
|
*/
|
|
1076
1178
|
getSchemaByRef(schema, reserveRef = false, enums = [], upLevelSchemaKey = "") {
|
|
1077
1179
|
let refName = "";
|
|
1078
1180
|
if (Base.isRef(schema)) {
|
|
1079
|
-
refName =
|
|
1181
|
+
refName = this.formatRefName(Base.ref2name(schema.$ref));
|
|
1080
1182
|
if (reserveRef) return { type: upLevelSchemaKey + refName };
|
|
1081
|
-
|
|
1082
|
-
|
|
1183
|
+
const resolvedSchema = this.getSchemaContainer()?.[Base.ref2name(schema.$ref, this.doc)];
|
|
1184
|
+
if (!resolvedSchema) return { type: "unknown" };
|
|
1185
|
+
schema = resolvedSchema;
|
|
1083
1186
|
}
|
|
1084
1187
|
return this.toBaseSchema(schema, enums, "", upLevelSchemaKey + refName);
|
|
1085
1188
|
}
|
|
1086
1189
|
/**
|
|
1087
|
-
*
|
|
1088
|
-
|
|
1089
|
-
toBaseSchema(schema, enums = [], schemaKey = "", upLevelSchemaKey = "") {
|
|
1090
|
-
if (!schema) return { type: "unknown" };
|
|
1091
|
-
if (Base.isRef(schema)) return this.getSchemaByRef(schema, true);
|
|
1092
|
-
if (this.isOpenAPIArraySchema(schema)) {
|
|
1093
|
-
const { type, description, items, required } = schema;
|
|
1094
|
-
return {
|
|
1095
|
-
type,
|
|
1096
|
-
required: !!required,
|
|
1097
|
-
description,
|
|
1098
|
-
items: this.toBaseSchema(items, enums, schemaKey, upLevelSchemaKey)
|
|
1099
|
-
};
|
|
1100
|
-
} else {
|
|
1101
|
-
const { required = [], allOf, anyOf, description, enum: enum_, format, oneOf, properties = {} } = schema;
|
|
1102
|
-
let { type } = schema;
|
|
1103
|
-
if (enum_ && type !== "boolean") {
|
|
1104
|
-
const enumObject = {
|
|
1105
|
-
name: Base.upperCamelCase(Base.normalize(upLevelSchemaKey)) + Base.upperCamelCase(Base.normalize(schemaKey)),
|
|
1106
|
-
enum: [...new Set(enum_)]
|
|
1107
|
-
};
|
|
1108
|
-
const sameObject = Base.findSameSchema(enumObject, enums);
|
|
1109
|
-
if (!sameObject && Base.isValidEnumType(schema)) enums.push(enumObject);
|
|
1110
|
-
return {
|
|
1111
|
-
type: sameObject ? sameObject.name : Base.isBooleanEnum(schema) ? "boolean" : enumObject.name,
|
|
1112
|
-
required,
|
|
1113
|
-
description
|
|
1114
|
-
};
|
|
1115
|
-
}
|
|
1116
|
-
if (type === void 0 && Object.keys(properties).length > 0) type = "object";
|
|
1117
|
-
return {
|
|
1118
|
-
type,
|
|
1119
|
-
required,
|
|
1120
|
-
description,
|
|
1121
|
-
enum: enum_,
|
|
1122
|
-
format,
|
|
1123
|
-
allOf: allOf?.map((s) => Base.isRef(s) ? {
|
|
1124
|
-
...s,
|
|
1125
|
-
ref: s.$ref,
|
|
1126
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1127
|
-
} : this.toBaseSchema(s, enums)),
|
|
1128
|
-
anyOf: anyOf?.map((s) => Base.isRef(s) ? {
|
|
1129
|
-
...s,
|
|
1130
|
-
ref: s.$ref,
|
|
1131
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1132
|
-
} : this.toBaseSchema(s, enums)),
|
|
1133
|
-
oneOf: oneOf?.map((s) => Base.isRef(s) ? {
|
|
1134
|
-
...s,
|
|
1135
|
-
ref: s.$ref,
|
|
1136
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1137
|
-
} : this.toBaseSchema(s, enums)),
|
|
1138
|
-
properties: Object.keys(properties).reduce((acc, p) => {
|
|
1139
|
-
const propSchema = properties[p];
|
|
1140
|
-
return {
|
|
1141
|
-
...acc,
|
|
1142
|
-
[p]: Base.isRef(propSchema) ? { type: Base.capitalize(Base.ref2name(propSchema.$ref, this.doc)) } : this.toBaseSchema(propSchema, enums, p, upLevelSchemaKey)
|
|
1143
|
-
};
|
|
1144
|
-
}, {})
|
|
1145
|
-
};
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
/**
|
|
1149
|
-
* OpenAPI parameter to base parameter.
|
|
1150
|
-
*/
|
|
1151
|
-
getParameterByRef(parameter, enums = [], upLevelSchemaKey = "") {
|
|
1152
|
-
if (Base.isRef(parameter)) {
|
|
1153
|
-
const refName = Base.ref2name(parameter.$ref, this.doc);
|
|
1154
|
-
const resolved = this.doc.parameters?.[refName];
|
|
1155
|
-
if (!resolved) throw new Error(`Parameter reference not found: ${parameter.$ref}`);
|
|
1156
|
-
parameter = resolved;
|
|
1157
|
-
}
|
|
1158
|
-
const p = parameter;
|
|
1159
|
-
const { name, required, description, type, items, enum: enum_, properties, schema } = p;
|
|
1160
|
-
if (enum_) {
|
|
1161
|
-
const type = Base.upperCamelCase(Base.normalize(upLevelSchemaKey)) + Base.upperCamelCase(Base.normalize(name));
|
|
1162
|
-
const enumSchema = {
|
|
1163
|
-
name: type,
|
|
1164
|
-
enum: [...new Set(enum_)]
|
|
1165
|
-
};
|
|
1166
|
-
const sameEnum = Base.findSameSchema(enumSchema, enums);
|
|
1167
|
-
if (!sameEnum && Base.isValidEnumType({
|
|
1168
|
-
type,
|
|
1169
|
-
enum: enum_
|
|
1170
|
-
})) enums.push(enumSchema);
|
|
1171
|
-
return {
|
|
1172
|
-
name,
|
|
1173
|
-
required,
|
|
1174
|
-
description,
|
|
1175
|
-
in: p.in,
|
|
1176
|
-
schema: { type: sameEnum?.name ?? type }
|
|
1177
|
-
};
|
|
1178
|
-
}
|
|
1179
|
-
if (items) return {
|
|
1180
|
-
name,
|
|
1181
|
-
required,
|
|
1182
|
-
description,
|
|
1183
|
-
in: p.in,
|
|
1184
|
-
schema: {
|
|
1185
|
-
type,
|
|
1186
|
-
items
|
|
1187
|
-
}
|
|
1188
|
-
};
|
|
1189
|
-
if (schema && Base.isRef(schema)) return {
|
|
1190
|
-
name,
|
|
1191
|
-
required,
|
|
1192
|
-
description,
|
|
1193
|
-
in: p.in,
|
|
1194
|
-
schema: { type: Base.capitalize(Base.ref2name(schema.$ref)) }
|
|
1195
|
-
};
|
|
1196
|
-
return {
|
|
1197
|
-
name,
|
|
1198
|
-
required,
|
|
1199
|
-
description,
|
|
1200
|
-
in: p.in,
|
|
1201
|
-
schema: {
|
|
1202
|
-
type,
|
|
1203
|
-
properties
|
|
1204
|
-
}
|
|
1205
|
-
};
|
|
1206
|
-
}
|
|
1207
|
-
/**
|
|
1208
|
-
* OpenAPI schema to base response
|
|
1209
|
-
*/
|
|
1210
|
-
getResponseByRef(schema) {
|
|
1211
|
-
if (Base.isRef(schema)) schema = this.doc.responses[Base.ref2name(schema.$ref, this.doc)];
|
|
1212
|
-
const { schema: responseSchema } = schema;
|
|
1213
|
-
return [{
|
|
1214
|
-
type: "application/json",
|
|
1215
|
-
schema: responseSchema && this.getSchemaByRef(responseSchema, true)
|
|
1216
|
-
}];
|
|
1217
|
-
}
|
|
1218
|
-
init() {
|
|
1219
|
-
const { definitions = {}, responses = {}, paths = {} } = this.doc;
|
|
1220
|
-
const enums = [];
|
|
1221
|
-
const definitions_ = Object.keys(definitions).reduce((acc, key) => {
|
|
1222
|
-
const schema = definitions[key];
|
|
1223
|
-
return {
|
|
1224
|
-
...acc,
|
|
1225
|
-
[key]: this.getSchemaByRef(schema, false, enums, key)
|
|
1226
|
-
};
|
|
1227
|
-
}, {});
|
|
1228
|
-
const responses_ = Object.keys(responses).reduce((acc, key) => {
|
|
1229
|
-
const response = responses[key];
|
|
1230
|
-
return {
|
|
1231
|
-
...acc,
|
|
1232
|
-
[key]: this.getResponseByRef(response)
|
|
1233
|
-
};
|
|
1234
|
-
}, {});
|
|
1235
|
-
const apis = Object.keys(paths).reduce((acc, path) => {
|
|
1236
|
-
let pathObject = paths[path] ?? {};
|
|
1237
|
-
if (pathObject.$ref) {
|
|
1238
|
-
const resolved = this.resolvePathRef(pathObject.$ref);
|
|
1239
|
-
if (resolved) pathObject = resolved;
|
|
1240
|
-
}
|
|
1241
|
-
const { parameters = [] } = pathObject;
|
|
1242
|
-
const methodApis = [];
|
|
1243
|
-
Object.values(HttpMethods).forEach((method) => {
|
|
1244
|
-
const methodObject = pathObject[method];
|
|
1245
|
-
if (methodObject) {
|
|
1246
|
-
const { deprecated, operationId, summary: summary_, description: description_, responses = {} } = methodObject;
|
|
1247
|
-
const { parameters: parameters_ = [] } = methodObject;
|
|
1248
|
-
const baseParameters = [...parameters, ...parameters_].map((parameter) => this.getParameterByRef(parameter, enums));
|
|
1249
|
-
const uniqueParameterName = [...new Set(baseParameters.map((p) => p.name))];
|
|
1250
|
-
if (Object.keys(responses).length === 0) Object.assign(responses, { 200: { description: "Successful response" } });
|
|
1251
|
-
const inBody = baseParameters.filter((p) => p.in === "body" || p.in === "formData");
|
|
1252
|
-
const notInBody = baseParameters.filter((p) => p.in !== "body" && p.in !== "formData");
|
|
1253
|
-
const httpCodes = Object.keys(responses);
|
|
1254
|
-
for (const code of httpCodes) if (code in responses) {
|
|
1255
|
-
const response = responses[code];
|
|
1256
|
-
const responseSchema = this.getResponseByRef(response);
|
|
1257
|
-
const inBodyOnlyHasBody = inBody && inBody.length === 1 && inBody[0].in === "body" && inBody[0].name === "body";
|
|
1258
|
-
methodApis.push({
|
|
1259
|
-
method,
|
|
1260
|
-
operationId,
|
|
1261
|
-
summary: summary_,
|
|
1262
|
-
deprecated,
|
|
1263
|
-
description: description_,
|
|
1264
|
-
parameters: uniqueParameterName.map((name) => notInBody.find((p) => p.name === name)).filter(Boolean),
|
|
1265
|
-
responses: responseSchema,
|
|
1266
|
-
requestBody: inBody.length > 0 ? inBodyOnlyHasBody ? [{
|
|
1267
|
-
type: "application/json",
|
|
1268
|
-
schema: inBody[0].schema
|
|
1269
|
-
}] : [{
|
|
1270
|
-
type: "application/json",
|
|
1271
|
-
schema: {
|
|
1272
|
-
type: "object",
|
|
1273
|
-
properties: inBody.reduce((a, p) => {
|
|
1274
|
-
return {
|
|
1275
|
-
...a,
|
|
1276
|
-
[p.name]: {
|
|
1277
|
-
type: p.schema?.type ?? "unknown",
|
|
1278
|
-
required: p.schema?.required,
|
|
1279
|
-
items: p.schema?.items,
|
|
1280
|
-
description: p.schema?.description
|
|
1281
|
-
}
|
|
1282
|
-
};
|
|
1283
|
-
}, {})
|
|
1284
|
-
}
|
|
1285
|
-
}] : void 0
|
|
1286
|
-
});
|
|
1287
|
-
break;
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
});
|
|
1291
|
-
return {
|
|
1292
|
-
...acc,
|
|
1293
|
-
[path]: methodApis
|
|
1294
|
-
};
|
|
1295
|
-
}, {});
|
|
1296
|
-
return {
|
|
1297
|
-
enums: Base.uniqueEnums(enums),
|
|
1298
|
-
schemas: definitions_,
|
|
1299
|
-
responses: responses_,
|
|
1300
|
-
parameters: {},
|
|
1301
|
-
requestBodies: {},
|
|
1302
|
-
apis
|
|
1303
|
-
};
|
|
1304
|
-
}
|
|
1305
|
-
};
|
|
1306
|
-
//#endregion
|
|
1307
|
-
//#region src/openapi/V3.ts
|
|
1308
|
-
var V3 = class {
|
|
1309
|
-
doc;
|
|
1310
|
-
constructor(doc) {
|
|
1311
|
-
this.doc = doc;
|
|
1312
|
-
}
|
|
1313
|
-
/**
|
|
1314
|
-
* Resolves a path $ref to the actual path object.
|
|
1315
|
-
*/
|
|
1316
|
-
resolvePathRef($ref) {
|
|
1317
|
-
const refName = Base.ref2name($ref, this.doc);
|
|
1318
|
-
return this.doc.paths?.[refName];
|
|
1319
|
-
}
|
|
1320
|
-
/**
|
|
1321
|
-
* Is array schema.
|
|
1322
|
-
*/
|
|
1323
|
-
isOpenAPIArraySchema(schema) {
|
|
1324
|
-
return typeof schema === "object" && schema.type === "array";
|
|
1325
|
-
}
|
|
1326
|
-
/**
|
|
1327
|
-
* OpenAPI schema to base schema.
|
|
1190
|
+
* Format a ref name for the schema's `type` field.
|
|
1191
|
+
* V3 uses `capitalize`; V3_1 uses `upperCamelCase` (preserved for compat).
|
|
1328
1192
|
*/
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
if (Base.isRef(schema)) {
|
|
1332
|
-
refName = Base.capitalize(Base.ref2name(schema.$ref));
|
|
1333
|
-
if (reserveRef) return { type: upLevelSchemaKey + refName };
|
|
1334
|
-
const resolvedSchema = this.doc.components?.schemas?.[Base.ref2name(schema.$ref, this.doc)];
|
|
1335
|
-
if (!resolvedSchema) return { type: "unknown" };
|
|
1336
|
-
schema = resolvedSchema;
|
|
1337
|
-
}
|
|
1338
|
-
return this.toBaseSchema(schema, enums, "", upLevelSchemaKey + refName);
|
|
1193
|
+
formatRefName(name) {
|
|
1194
|
+
return Base.capitalize(name);
|
|
1339
1195
|
}
|
|
1340
1196
|
/**
|
|
1341
|
-
* OpenAPI parameter to base parameter.
|
|
1197
|
+
* OpenAPI parameter to base parameter. Override in V2 — its parameter
|
|
1198
|
+
* shape is structurally different (top-level `items`/`properties`/`enum`).
|
|
1342
1199
|
*/
|
|
1343
1200
|
getParameterByRef(schema, enums = [], upLevelSchemaKey = "") {
|
|
1344
1201
|
if (Base.isRef(schema)) {
|
|
1345
|
-
const resolvedSchema = this.
|
|
1202
|
+
const resolvedSchema = this.getParameterContainer()?.[Base.ref2name(schema.$ref, this.doc)];
|
|
1346
1203
|
if (!resolvedSchema) return {
|
|
1347
1204
|
name: "unknown",
|
|
1348
1205
|
in: "query"
|
|
@@ -1373,37 +1230,38 @@ var V3 = class {
|
|
|
1373
1230
|
description,
|
|
1374
1231
|
deprecated,
|
|
1375
1232
|
in: schema.in,
|
|
1376
|
-
schema: schema.schema
|
|
1233
|
+
schema: schema.schema ? this.getSchemaByRef(schema.schema, false, enums, upLevelSchemaKey + Base.capitalize(name)) : void 0
|
|
1377
1234
|
};
|
|
1378
1235
|
}
|
|
1379
1236
|
/**
|
|
1380
|
-
* OpenAPI schema to base response
|
|
1237
|
+
* OpenAPI schema to base response. Override in V2 (its response shape
|
|
1238
|
+
* lacks the `content` wrapper).
|
|
1381
1239
|
*/
|
|
1382
1240
|
getResponseByRef(schema) {
|
|
1383
1241
|
if (Base.isRef(schema)) {
|
|
1384
|
-
const resolvedSchema = this.
|
|
1242
|
+
const resolvedSchema = this.getResponseContainer()?.[Base.ref2name(schema.$ref, this.doc)];
|
|
1385
1243
|
if (!resolvedSchema) return [];
|
|
1386
1244
|
schema = resolvedSchema;
|
|
1387
1245
|
}
|
|
1388
1246
|
const { content = {} } = schema;
|
|
1389
1247
|
return Object.keys(content).map((c) => ({
|
|
1390
1248
|
type: c,
|
|
1391
|
-
schema: content[c].schema
|
|
1249
|
+
schema: content[c].schema ? this.getSchemaByRef(content[c].schema, true) : void 0
|
|
1392
1250
|
}));
|
|
1393
1251
|
}
|
|
1394
1252
|
/**
|
|
1395
|
-
* OpenAPI schema to requestBody.
|
|
1253
|
+
* OpenAPI schema to requestBody. V2 has no requestBody concept.
|
|
1396
1254
|
*/
|
|
1397
1255
|
getRequestBodyByRef(schema, enums = []) {
|
|
1398
1256
|
if (Base.isRef(schema)) {
|
|
1399
|
-
const resolvedSchema = this.
|
|
1257
|
+
const resolvedSchema = this.getRequestBodyContainer()?.[Base.ref2name(schema.$ref, this.doc)];
|
|
1400
1258
|
if (!resolvedSchema) return [];
|
|
1401
1259
|
schema = resolvedSchema;
|
|
1402
1260
|
}
|
|
1403
1261
|
const { content = {} } = schema;
|
|
1404
1262
|
return Object.keys(content).map((c) => ({
|
|
1405
1263
|
type: c,
|
|
1406
|
-
schema: content[c].schema
|
|
1264
|
+
schema: content[c].schema ? this.getSchemaByRef(content[c].schema, false, enums) : void 0
|
|
1407
1265
|
}));
|
|
1408
1266
|
}
|
|
1409
1267
|
/**
|
|
@@ -1414,89 +1272,98 @@ var V3 = class {
|
|
|
1414
1272
|
if (Base.isRef(schema)) return this.getSchemaByRef(schema, true);
|
|
1415
1273
|
if (this.isOpenAPIArraySchema(schema)) {
|
|
1416
1274
|
const { type, description, items, required } = schema;
|
|
1275
|
+
const itemsSchema = items ? this.toBaseSchema(items, enums, schemaKey, upLevelSchemaKey) : { type: "unknown" };
|
|
1417
1276
|
return {
|
|
1418
1277
|
type,
|
|
1419
1278
|
required: !!required,
|
|
1420
1279
|
description,
|
|
1421
|
-
items:
|
|
1280
|
+
items: itemsSchema
|
|
1422
1281
|
};
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
return {
|
|
1434
|
-
type: sameObject ? sameObject.name : Base.isBooleanEnum(schema) ? "boolean" : enumObject.name,
|
|
1435
|
-
required,
|
|
1436
|
-
description,
|
|
1437
|
-
deprecated
|
|
1438
|
-
};
|
|
1439
|
-
}
|
|
1440
|
-
if (type === void 0 && Object.keys(properties).length > 0) type = "object";
|
|
1282
|
+
}
|
|
1283
|
+
const { required = [], allOf, anyOf, description, deprecated, enum: enum_, format, oneOf, properties = {} } = schema;
|
|
1284
|
+
let { type } = schema;
|
|
1285
|
+
if (enum_ && type !== "boolean") {
|
|
1286
|
+
const enumObject = {
|
|
1287
|
+
name: Base.upperCamelCase(Base.normalize(upLevelSchemaKey)) + Base.upperCamelCase(Base.normalize(schemaKey)),
|
|
1288
|
+
enum: [...new Set(enum_)]
|
|
1289
|
+
};
|
|
1290
|
+
const sameObject = Base.findSameSchema(enumObject, enums);
|
|
1291
|
+
if (!sameObject && Base.isValidEnumType(schema)) enums.push(enumObject);
|
|
1441
1292
|
return {
|
|
1442
|
-
type,
|
|
1293
|
+
type: sameObject ? sameObject.name : Base.isBooleanEnum(schema) ? "boolean" : enumObject.name,
|
|
1443
1294
|
required,
|
|
1444
1295
|
description,
|
|
1445
|
-
deprecated
|
|
1446
|
-
enum: enum_,
|
|
1447
|
-
format,
|
|
1448
|
-
allOf: allOf?.map((s) => Base.isRef(s) ? {
|
|
1449
|
-
...s,
|
|
1450
|
-
ref: s.$ref,
|
|
1451
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1452
|
-
} : this.toBaseSchema(s, enums)),
|
|
1453
|
-
anyOf: anyOf?.map((s) => Base.isRef(s) ? {
|
|
1454
|
-
...s,
|
|
1455
|
-
ref: s.$ref,
|
|
1456
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1457
|
-
} : this.toBaseSchema(s, enums)),
|
|
1458
|
-
oneOf: oneOf?.map((s) => Base.isRef(s) ? {
|
|
1459
|
-
...s,
|
|
1460
|
-
ref: s.$ref,
|
|
1461
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1462
|
-
} : this.toBaseSchema(s, enums)),
|
|
1463
|
-
properties: Object.keys(properties).reduce((acc, p) => {
|
|
1464
|
-
const propSchema = properties[p];
|
|
1465
|
-
return {
|
|
1466
|
-
...acc,
|
|
1467
|
-
[p]: Base.isRef(propSchema) ? { type: Base.capitalize(Base.ref2name(propSchema.$ref, this.doc)) } : this.toBaseSchema(propSchema, enums, p, upLevelSchemaKey)
|
|
1468
|
-
};
|
|
1469
|
-
}, {})
|
|
1296
|
+
deprecated
|
|
1470
1297
|
};
|
|
1471
1298
|
}
|
|
1299
|
+
if (type === void 0 && Object.keys(properties).length > 0) type = "object";
|
|
1300
|
+
return {
|
|
1301
|
+
type,
|
|
1302
|
+
required,
|
|
1303
|
+
description,
|
|
1304
|
+
deprecated,
|
|
1305
|
+
enum: enum_,
|
|
1306
|
+
format,
|
|
1307
|
+
allOf: allOf?.map((s) => Base.isRef(s) ? {
|
|
1308
|
+
...s,
|
|
1309
|
+
ref: s.$ref,
|
|
1310
|
+
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1311
|
+
} : this.toBaseSchema(s, enums)),
|
|
1312
|
+
anyOf: anyOf?.map((s) => Base.isRef(s) ? {
|
|
1313
|
+
...s,
|
|
1314
|
+
ref: s.$ref,
|
|
1315
|
+
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1316
|
+
} : this.toBaseSchema(s, enums)),
|
|
1317
|
+
oneOf: oneOf?.map((s) => Base.isRef(s) ? {
|
|
1318
|
+
...s,
|
|
1319
|
+
ref: s.$ref,
|
|
1320
|
+
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1321
|
+
} : this.toBaseSchema(s, enums)),
|
|
1322
|
+
properties: Object.keys(properties).reduce((acc, p) => {
|
|
1323
|
+
const propSchema = properties[p];
|
|
1324
|
+
return {
|
|
1325
|
+
...acc,
|
|
1326
|
+
[p]: Base.isRef(propSchema) ? {
|
|
1327
|
+
type: Base.capitalize(Base.ref2name(propSchema.$ref, this.doc)),
|
|
1328
|
+
isRef: true
|
|
1329
|
+
} : this.toBaseSchema(propSchema, enums, p, upLevelSchemaKey)
|
|
1330
|
+
};
|
|
1331
|
+
}, {})
|
|
1332
|
+
};
|
|
1472
1333
|
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Run the parsing pipeline and return a ProviderInitResult.
|
|
1336
|
+
*/
|
|
1473
1337
|
init() {
|
|
1474
|
-
const {
|
|
1338
|
+
const { paths = {} } = this.doc;
|
|
1475
1339
|
const enums = [];
|
|
1476
|
-
const
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1340
|
+
const schemaContainer = this.getSchemaContainer() ?? {};
|
|
1341
|
+
const parameterContainer = this.getParameterContainer() ?? {};
|
|
1342
|
+
const responseContainer = this.getResponseContainer() ?? {};
|
|
1343
|
+
const requestBodyContainer = this.getRequestBodyContainer() ?? {};
|
|
1344
|
+
const schemas_ = Object.keys(schemaContainer).reduce((acc, key) => {
|
|
1345
|
+
const schema = schemaContainer[key];
|
|
1479
1346
|
return {
|
|
1480
1347
|
...acc,
|
|
1481
1348
|
[key]: this.getSchemaByRef(schema, false, enums, key)
|
|
1482
1349
|
};
|
|
1483
1350
|
}, {});
|
|
1484
|
-
const parameters_ = Object.keys(
|
|
1485
|
-
const parameter =
|
|
1351
|
+
const parameters_ = Object.keys(parameterContainer).reduce((acc, key) => {
|
|
1352
|
+
const parameter = parameterContainer[key];
|
|
1486
1353
|
return {
|
|
1487
1354
|
...acc,
|
|
1488
1355
|
[key]: this.getParameterByRef(parameter, enums, key)
|
|
1489
1356
|
};
|
|
1490
1357
|
}, {});
|
|
1491
|
-
const responses_ = Object.keys(
|
|
1492
|
-
const response =
|
|
1358
|
+
const responses_ = Object.keys(responseContainer).reduce((acc, key) => {
|
|
1359
|
+
const response = responseContainer[key];
|
|
1493
1360
|
return {
|
|
1494
1361
|
...acc,
|
|
1495
1362
|
[key]: this.getResponseByRef(response)
|
|
1496
1363
|
};
|
|
1497
1364
|
}, {});
|
|
1498
|
-
const requestBodies_ = Object.keys(
|
|
1499
|
-
const requestBody =
|
|
1365
|
+
const requestBodies_ = Object.keys(requestBodyContainer).reduce((acc, key) => {
|
|
1366
|
+
const requestBody = requestBodyContainer[key];
|
|
1500
1367
|
return {
|
|
1501
1368
|
...acc,
|
|
1502
1369
|
[key]: this.getRequestBodyByRef(requestBody, enums)
|
|
@@ -1513,15 +1380,16 @@ var V3 = class {
|
|
|
1513
1380
|
Object.values(HttpMethods).forEach((method) => {
|
|
1514
1381
|
const methodObject = pathObject[method];
|
|
1515
1382
|
if (methodObject) {
|
|
1516
|
-
const { deprecated, operationId, responses
|
|
1383
|
+
const { deprecated, operationId, responses, summary: summary_, description: description_, requestBody = { content: {} } } = methodObject;
|
|
1384
|
+
const responsesClone = responses ? { ...responses } : {};
|
|
1517
1385
|
const { parameters: parameters_ = [] } = methodObject;
|
|
1518
1386
|
const baseParameters = [...parameters, ...parameters_].map((parameter) => this.getParameterByRef(parameter, enums));
|
|
1519
1387
|
const baseRequestBody = this.getRequestBodyByRef(requestBody, enums);
|
|
1520
1388
|
const uniqueParameterName = [...new Set(baseParameters.map((p) => p.name))];
|
|
1521
|
-
if (Object.keys(
|
|
1522
|
-
const httpCodes = Object.keys(
|
|
1523
|
-
for (const code of httpCodes) if (code in
|
|
1524
|
-
const response =
|
|
1389
|
+
if (Object.keys(responsesClone).length === 0) responsesClone[200] = { description: "Successful response" };
|
|
1390
|
+
const httpCodes = Object.keys(responsesClone);
|
|
1391
|
+
for (const code of httpCodes) if (code in responsesClone) {
|
|
1392
|
+
const response = responsesClone[code];
|
|
1525
1393
|
const responseSchema = this.getResponseByRef(response);
|
|
1526
1394
|
methodApis.push({
|
|
1527
1395
|
method,
|
|
@@ -1553,243 +1421,248 @@ var V3 = class {
|
|
|
1553
1421
|
}
|
|
1554
1422
|
};
|
|
1555
1423
|
//#endregion
|
|
1556
|
-
//#region src/openapi/
|
|
1557
|
-
var
|
|
1424
|
+
//#region src/openapi/V2.ts
|
|
1425
|
+
var V2 = class extends VersionedProvider {
|
|
1558
1426
|
doc;
|
|
1427
|
+
version = "v2";
|
|
1559
1428
|
constructor(doc) {
|
|
1429
|
+
super();
|
|
1560
1430
|
this.doc = doc;
|
|
1561
1431
|
}
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
*/
|
|
1565
|
-
resolvePathRef($ref) {
|
|
1566
|
-
const refName = Base.ref2name($ref, this.doc);
|
|
1567
|
-
return this.doc.paths?.[refName];
|
|
1432
|
+
getSchemaContainer() {
|
|
1433
|
+
return this.doc.definitions;
|
|
1568
1434
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
*/
|
|
1572
|
-
isOpenAPIArraySchema(schema) {
|
|
1573
|
-
return typeof schema === "object" && schema.type === "array";
|
|
1435
|
+
getParameterContainer() {
|
|
1436
|
+
return this.doc.parameters;
|
|
1574
1437
|
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
*/
|
|
1578
|
-
getSchemaByRef(schema, reserveRef = false, enums = [], upLevelSchemaKey = "") {
|
|
1579
|
-
let refName = "";
|
|
1580
|
-
if (Base.isRef(schema)) {
|
|
1581
|
-
refName = Base.upperCamelCase(Base.ref2name(schema.$ref));
|
|
1582
|
-
if (reserveRef) return { type: upLevelSchemaKey + refName };
|
|
1583
|
-
if (!this.doc.components) this.doc.components = { schemas: {} };
|
|
1584
|
-
const resolvedSchema = this.doc.components.schemas?.[Base.ref2name(schema.$ref, this.doc)];
|
|
1585
|
-
if (!resolvedSchema) throw new Error(`Schema reference not found: ${refName}`);
|
|
1586
|
-
schema = resolvedSchema;
|
|
1587
|
-
}
|
|
1588
|
-
return this.toBaseSchema(schema, enums, "", upLevelSchemaKey + refName);
|
|
1438
|
+
getResponseContainer() {
|
|
1439
|
+
return this.doc.responses;
|
|
1589
1440
|
}
|
|
1441
|
+
getRequestBodyContainer() {}
|
|
1590
1442
|
/**
|
|
1591
|
-
*
|
|
1443
|
+
* V2 parameter shape differs from V3: top-level `items`/`properties`/`enum`
|
|
1444
|
+
* rather than nested under `schema`. Override accordingly.
|
|
1592
1445
|
*/
|
|
1593
|
-
getParameterByRef(
|
|
1594
|
-
if (Base.isRef(
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1446
|
+
getParameterByRef(parameter, enums = [], upLevelSchemaKey = "") {
|
|
1447
|
+
if (Base.isRef(parameter)) {
|
|
1448
|
+
const refName = Base.ref2name(parameter.$ref, this.doc);
|
|
1449
|
+
const resolved = this.doc.parameters?.[refName];
|
|
1450
|
+
if (!resolved) throw new Error(`Parameter reference not found: ${parameter.$ref}`);
|
|
1451
|
+
parameter = resolved;
|
|
1452
|
+
}
|
|
1453
|
+
const p = parameter;
|
|
1454
|
+
const { name, required, description, type, items, enum: enum_, properties, schema } = p;
|
|
1455
|
+
if (enum_) {
|
|
1456
|
+
const enumType = Base.upperCamelCase(Base.normalize(upLevelSchemaKey)) + Base.upperCamelCase(Base.normalize(name));
|
|
1598
1457
|
const enumSchema = {
|
|
1599
|
-
name:
|
|
1600
|
-
enum: [...new Set(
|
|
1458
|
+
name: enumType,
|
|
1459
|
+
enum: [...new Set(enum_)]
|
|
1601
1460
|
};
|
|
1602
1461
|
const sameEnum = Base.findSameSchema(enumSchema, enums);
|
|
1603
|
-
if (!sameEnum && Base.isValidEnumType(
|
|
1462
|
+
if (!sameEnum && Base.isValidEnumType({
|
|
1463
|
+
type: enumType,
|
|
1464
|
+
enum: enum_
|
|
1465
|
+
})) enums.push(enumSchema);
|
|
1604
1466
|
return {
|
|
1605
1467
|
name,
|
|
1606
1468
|
required,
|
|
1607
1469
|
description,
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
schema: { type: sameEnum?.name ?? type }
|
|
1470
|
+
in: p.in,
|
|
1471
|
+
schema: { type: sameEnum?.name ?? enumType }
|
|
1611
1472
|
};
|
|
1612
1473
|
}
|
|
1474
|
+
if (items) return {
|
|
1475
|
+
name,
|
|
1476
|
+
required,
|
|
1477
|
+
description,
|
|
1478
|
+
in: p.in,
|
|
1479
|
+
schema: {
|
|
1480
|
+
type,
|
|
1481
|
+
items
|
|
1482
|
+
}
|
|
1483
|
+
};
|
|
1484
|
+
if (schema && Base.isRef(schema)) return {
|
|
1485
|
+
name,
|
|
1486
|
+
required,
|
|
1487
|
+
description,
|
|
1488
|
+
in: p.in,
|
|
1489
|
+
schema: { type: Base.capitalize(Base.ref2name(schema.$ref)) }
|
|
1490
|
+
};
|
|
1613
1491
|
return {
|
|
1614
1492
|
name,
|
|
1615
1493
|
required,
|
|
1616
1494
|
description,
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1495
|
+
in: p.in,
|
|
1496
|
+
schema: {
|
|
1497
|
+
type,
|
|
1498
|
+
properties
|
|
1499
|
+
}
|
|
1620
1500
|
};
|
|
1621
1501
|
}
|
|
1622
1502
|
/**
|
|
1623
|
-
*
|
|
1503
|
+
* V2 response shape: a `schema` field directly, not `content`. V2 always
|
|
1504
|
+
* emits JSON.
|
|
1624
1505
|
*/
|
|
1625
1506
|
getResponseByRef(schema) {
|
|
1626
|
-
if (Base.isRef(schema)) schema = this.doc.
|
|
1627
|
-
const {
|
|
1628
|
-
return
|
|
1629
|
-
type:
|
|
1630
|
-
schema:
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
/**
|
|
1634
|
-
* OpenAPI schema to requestBody.
|
|
1635
|
-
*/
|
|
1636
|
-
getRequestBodyByRef(schema, enums = []) {
|
|
1637
|
-
if (Base.isRef(schema)) schema = this.doc.components?.requestBodies?.[Base.ref2name(schema.$ref, this.doc)];
|
|
1638
|
-
const { content = {} } = schema;
|
|
1639
|
-
return Object.keys(content).map((c) => ({
|
|
1640
|
-
type: c,
|
|
1641
|
-
schema: content[c].schema && this.getSchemaByRef(content[c].schema, true, enums)
|
|
1642
|
-
}));
|
|
1507
|
+
if (Base.isRef(schema)) schema = this.doc.responses[Base.ref2name(schema.$ref, this.doc)];
|
|
1508
|
+
const { schema: responseSchema } = schema;
|
|
1509
|
+
return [{
|
|
1510
|
+
type: "application/json",
|
|
1511
|
+
schema: responseSchema ? this.getSchemaByRef(responseSchema, true) : void 0
|
|
1512
|
+
}];
|
|
1643
1513
|
}
|
|
1644
1514
|
/**
|
|
1645
|
-
*
|
|
1515
|
+
* V2 has no `requestBody` concept; parameters with `in: body` or
|
|
1516
|
+
* `in: formData` are split out and turned into a synthetic requestBody
|
|
1517
|
+
* here. A single body param named `body` is used directly; otherwise
|
|
1518
|
+
* the body / formData params are wrapped in a synthetic object.
|
|
1646
1519
|
*/
|
|
1647
|
-
toBaseSchema(schema, enums = [], schemaKey = "", upLevelSchemaKey = "") {
|
|
1648
|
-
if (!schema) return { type: "unknown" };
|
|
1649
|
-
if (Base.isRef(schema)) return this.getSchemaByRef(schema, true);
|
|
1650
|
-
if (this.isOpenAPIArraySchema(schema)) {
|
|
1651
|
-
const { type, description, items, required } = schema;
|
|
1652
|
-
return {
|
|
1653
|
-
type,
|
|
1654
|
-
required: !!required,
|
|
1655
|
-
description,
|
|
1656
|
-
items: this.toBaseSchema(items, enums, schemaKey, upLevelSchemaKey)
|
|
1657
|
-
};
|
|
1658
|
-
} else {
|
|
1659
|
-
const { required = [], allOf, anyOf, description, deprecated, enum: enum_, format, oneOf, properties = {} } = schema;
|
|
1660
|
-
let { type } = schema;
|
|
1661
|
-
if (enum_ && type !== "boolean") {
|
|
1662
|
-
const enumObject = {
|
|
1663
|
-
name: Base.upperCamelCase(Base.normalize(upLevelSchemaKey)) + Base.upperCamelCase(Base.normalize(schemaKey)),
|
|
1664
|
-
enum: [...new Set(enum_)]
|
|
1665
|
-
};
|
|
1666
|
-
const sameObject = Base.findSameSchema(enumObject, enums);
|
|
1667
|
-
if (!sameObject && Base.isValidEnumType(schema)) enums.push(enumObject);
|
|
1668
|
-
return {
|
|
1669
|
-
type: sameObject ? sameObject.name : Base.isBooleanEnum(schema) ? "boolean" : enumObject.name,
|
|
1670
|
-
required,
|
|
1671
|
-
description,
|
|
1672
|
-
deprecated
|
|
1673
|
-
};
|
|
1674
|
-
}
|
|
1675
|
-
if (type === void 0 && Object.keys(properties).length > 0) type = "object";
|
|
1676
|
-
return {
|
|
1677
|
-
type,
|
|
1678
|
-
required,
|
|
1679
|
-
description,
|
|
1680
|
-
deprecated,
|
|
1681
|
-
enum: enum_,
|
|
1682
|
-
format,
|
|
1683
|
-
allOf: allOf?.map((s) => Base.isRef(s) ? {
|
|
1684
|
-
...s,
|
|
1685
|
-
ref: s.$ref,
|
|
1686
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1687
|
-
} : this.toBaseSchema(s, enums)),
|
|
1688
|
-
anyOf: anyOf?.map((s) => Base.isRef(s) ? {
|
|
1689
|
-
...s,
|
|
1690
|
-
ref: s.$ref,
|
|
1691
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1692
|
-
} : this.toBaseSchema(s, enums)),
|
|
1693
|
-
oneOf: oneOf?.map((s) => Base.isRef(s) ? {
|
|
1694
|
-
...s,
|
|
1695
|
-
ref: s.$ref,
|
|
1696
|
-
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1697
|
-
} : this.toBaseSchema(s, enums)),
|
|
1698
|
-
properties: Object.keys(properties).reduce((acc, p) => {
|
|
1699
|
-
const propSchema = properties[p];
|
|
1700
|
-
return {
|
|
1701
|
-
...acc,
|
|
1702
|
-
[p]: Base.isRef(propSchema) ? { type: Base.capitalize(Base.ref2name(propSchema.$ref, this.doc)) } : this.toBaseSchema(propSchema, enums, p, upLevelSchemaKey)
|
|
1703
|
-
};
|
|
1704
|
-
}, {})
|
|
1705
|
-
};
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1708
1520
|
init() {
|
|
1709
|
-
const {
|
|
1521
|
+
const { paths = {} } = this.doc;
|
|
1710
1522
|
const enums = [];
|
|
1711
|
-
const
|
|
1712
|
-
const
|
|
1713
|
-
|
|
1523
|
+
const schemaContainer = this.getSchemaContainer() ?? {};
|
|
1524
|
+
const parameterContainer = this.getParameterContainer() ?? {};
|
|
1525
|
+
const responseContainer = this.getResponseContainer() ?? {};
|
|
1526
|
+
const schemas_ = Object.keys(schemaContainer).reduce((acc, key) => {
|
|
1527
|
+
const schema = schemaContainer[key];
|
|
1714
1528
|
return {
|
|
1715
1529
|
...acc,
|
|
1716
1530
|
[key]: this.getSchemaByRef(schema, false, enums, key)
|
|
1717
1531
|
};
|
|
1718
1532
|
}, {});
|
|
1719
|
-
const parameters_ = Object.keys(
|
|
1720
|
-
const parameter =
|
|
1533
|
+
const parameters_ = Object.keys(parameterContainer).reduce((acc, key) => {
|
|
1534
|
+
const parameter = parameterContainer[key];
|
|
1721
1535
|
return {
|
|
1722
1536
|
...acc,
|
|
1723
1537
|
[key]: this.getParameterByRef(parameter, enums, key)
|
|
1724
1538
|
};
|
|
1725
1539
|
}, {});
|
|
1726
|
-
const responses_ = Object.keys(
|
|
1727
|
-
const response =
|
|
1540
|
+
const responses_ = Object.keys(responseContainer).reduce((acc, key) => {
|
|
1541
|
+
const response = responseContainer[key];
|
|
1728
1542
|
return {
|
|
1729
1543
|
...acc,
|
|
1730
1544
|
[key]: this.getResponseByRef(response)
|
|
1731
1545
|
};
|
|
1732
1546
|
}, {});
|
|
1733
|
-
const
|
|
1734
|
-
|
|
1735
|
-
return {
|
|
1736
|
-
...acc,
|
|
1737
|
-
[key]: this.getRequestBodyByRef(requestBody, enums)
|
|
1738
|
-
};
|
|
1739
|
-
}, {});
|
|
1740
|
-
const apis = Object.keys(paths).reduce((acc, path) => {
|
|
1547
|
+
const apis = {};
|
|
1548
|
+
for (const path of Object.keys(paths)) {
|
|
1741
1549
|
let pathObject = paths[path] ?? {};
|
|
1742
1550
|
if (pathObject.$ref) {
|
|
1743
1551
|
const resolved = this.resolvePathRef(pathObject.$ref);
|
|
1744
1552
|
if (resolved) pathObject = resolved;
|
|
1745
1553
|
}
|
|
1746
|
-
const { parameters = []
|
|
1554
|
+
const { parameters = [] } = pathObject;
|
|
1747
1555
|
const methodApis = [];
|
|
1748
1556
|
Object.values(HttpMethods).forEach((method) => {
|
|
1749
1557
|
const methodObject = pathObject[method];
|
|
1750
|
-
if (methodObject)
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1558
|
+
if (!methodObject) return;
|
|
1559
|
+
const { deprecated, operationId, summary: summary_, description: description_, responses } = methodObject;
|
|
1560
|
+
const { parameters: parameters_ = [] } = methodObject;
|
|
1561
|
+
const baseParameters = [...parameters, ...parameters_].map((p) => this.getParameterByRef(p, enums));
|
|
1562
|
+
const uniqueParameterName = [...new Set(baseParameters.map((p) => p.name))];
|
|
1563
|
+
const responsesClone = responses ? { ...responses } : {};
|
|
1564
|
+
if (Object.keys(responsesClone).length === 0) responsesClone[200] = { description: "Successful response" };
|
|
1565
|
+
const inBody = baseParameters.filter((p) => p.in === "body" || p.in === "formData");
|
|
1566
|
+
const notInBody = baseParameters.filter((p) => p.in !== "body" && p.in !== "formData");
|
|
1567
|
+
const httpCodes = Object.keys(responsesClone);
|
|
1568
|
+
for (const code of httpCodes) if (code in responsesClone) {
|
|
1569
|
+
const response = responsesClone[code];
|
|
1570
|
+
const responseSchema = this.getResponseByRef(response);
|
|
1571
|
+
const inBodyOnlyHasBody = inBody.length === 1 && inBody[0].in === "body" && inBody[0].name === "body";
|
|
1572
|
+
methodApis.push({
|
|
1573
|
+
method,
|
|
1574
|
+
operationId,
|
|
1575
|
+
summary: summary_,
|
|
1576
|
+
deprecated,
|
|
1577
|
+
description: description_,
|
|
1578
|
+
parameters: uniqueParameterName.map((name) => notInBody.find((p) => p.name === name)).filter((p) => p !== void 0),
|
|
1579
|
+
responses: responseSchema,
|
|
1580
|
+
requestBody: inBody.length > 0 ? inBodyOnlyHasBody ? [{
|
|
1581
|
+
type: "application/json",
|
|
1582
|
+
schema: inBody[0].schema
|
|
1583
|
+
}] : [{
|
|
1584
|
+
type: "application/json",
|
|
1585
|
+
schema: {
|
|
1586
|
+
type: "object",
|
|
1587
|
+
properties: inBody.reduce((a, p) => {
|
|
1588
|
+
return {
|
|
1589
|
+
...a,
|
|
1590
|
+
[p.name]: {
|
|
1591
|
+
type: p.schema?.type ?? "unknown",
|
|
1592
|
+
required: p.schema?.required,
|
|
1593
|
+
items: p.schema?.items,
|
|
1594
|
+
description: p.schema?.description
|
|
1595
|
+
}
|
|
1596
|
+
};
|
|
1597
|
+
}, {})
|
|
1598
|
+
}
|
|
1599
|
+
}] : void 0
|
|
1600
|
+
});
|
|
1601
|
+
break;
|
|
1773
1602
|
}
|
|
1774
1603
|
});
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
[path]: methodApis
|
|
1778
|
-
};
|
|
1779
|
-
}, {});
|
|
1604
|
+
apis[path] = methodApis;
|
|
1605
|
+
}
|
|
1780
1606
|
return {
|
|
1781
1607
|
enums: Base.uniqueEnums(enums),
|
|
1782
1608
|
schemas: schemas_,
|
|
1783
1609
|
responses: responses_,
|
|
1784
1610
|
parameters: parameters_,
|
|
1785
|
-
requestBodies:
|
|
1611
|
+
requestBodies: {},
|
|
1786
1612
|
apis
|
|
1787
1613
|
};
|
|
1788
1614
|
}
|
|
1789
1615
|
};
|
|
1790
1616
|
//#endregion
|
|
1617
|
+
//#region src/openapi/V3.ts
|
|
1618
|
+
var V3 = class extends VersionedProvider {
|
|
1619
|
+
doc;
|
|
1620
|
+
version = "v3";
|
|
1621
|
+
constructor(doc) {
|
|
1622
|
+
super();
|
|
1623
|
+
this.doc = doc;
|
|
1624
|
+
}
|
|
1625
|
+
getSchemaContainer() {
|
|
1626
|
+
return this.doc.components?.schemas;
|
|
1627
|
+
}
|
|
1628
|
+
getParameterContainer() {
|
|
1629
|
+
return this.doc.components?.parameters;
|
|
1630
|
+
}
|
|
1631
|
+
getResponseContainer() {
|
|
1632
|
+
return this.doc.components?.responses;
|
|
1633
|
+
}
|
|
1634
|
+
getRequestBodyContainer() {
|
|
1635
|
+
return this.doc.components?.requestBodies;
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
//#endregion
|
|
1639
|
+
//#region src/openapi/V3_1.ts
|
|
1640
|
+
var V3_1 = class extends VersionedProvider {
|
|
1641
|
+
doc;
|
|
1642
|
+
version = "v3_1";
|
|
1643
|
+
constructor(doc) {
|
|
1644
|
+
super();
|
|
1645
|
+
this.doc = doc;
|
|
1646
|
+
}
|
|
1647
|
+
formatRefName(name) {
|
|
1648
|
+
return Base.upperCamelCase(name);
|
|
1649
|
+
}
|
|
1650
|
+
getSchemaContainer() {
|
|
1651
|
+
return this.doc.components?.schemas;
|
|
1652
|
+
}
|
|
1653
|
+
getParameterContainer() {
|
|
1654
|
+
return this.doc.components?.parameters;
|
|
1655
|
+
}
|
|
1656
|
+
getResponseContainer() {
|
|
1657
|
+
return this.doc.components?.responses;
|
|
1658
|
+
}
|
|
1659
|
+
getRequestBodyContainer() {
|
|
1660
|
+
return this.doc.components?.requestBodies;
|
|
1661
|
+
}
|
|
1662
|
+
};
|
|
1663
|
+
//#endregion
|
|
1791
1664
|
//#region src/openapi/index.ts
|
|
1792
|
-
const logger
|
|
1665
|
+
const logger = createScopedLogger("OpenAPI");
|
|
1793
1666
|
function getDocVersion(doc) {
|
|
1794
1667
|
switch ((doc.openapi || doc.swagger).slice(0, 3)) {
|
|
1795
1668
|
case "3.1": return "v3_1";
|
|
@@ -1801,7 +1674,7 @@ function getDocVersion(doc) {
|
|
|
1801
1674
|
var OpenAPIProvider = class extends Provider {
|
|
1802
1675
|
parse(doc) {
|
|
1803
1676
|
const version = getDocVersion(doc);
|
|
1804
|
-
logger
|
|
1677
|
+
logger.debug(`openapi version ${version}`);
|
|
1805
1678
|
switch (version) {
|
|
1806
1679
|
case "v2": return new V2(doc).init();
|
|
1807
1680
|
case "v3": return new V3(doc).init();
|
|
@@ -1819,9 +1692,9 @@ function getAdaptor(type) {
|
|
|
1819
1692
|
async function codeGen(initOptions) {
|
|
1820
1693
|
const startTime = Date.now();
|
|
1821
1694
|
const { verbose } = initOptions;
|
|
1822
|
-
if (verbose) logger
|
|
1823
|
-
else logger
|
|
1824
|
-
logger
|
|
1695
|
+
if (verbose) logger.setLevel("debug");
|
|
1696
|
+
else logger.setLevel("info");
|
|
1697
|
+
logger.info(`Fetch document from ${initOptions.docURL}`);
|
|
1825
1698
|
const { enums, schemas, parameters, responses, requestBodies, apis } = new OpenAPIProvider(initOptions, await Base.fetchDoc(initOptions.docURL, initOptions.requestOptions));
|
|
1826
1699
|
const adaptor = getAdaptor(initOptions.adaptor ?? "fetch");
|
|
1827
1700
|
const code = await Generator.genCode({
|
|
@@ -1846,7 +1719,7 @@ async function codeGen(initOptions) {
|
|
|
1846
1719
|
//#endregion
|
|
1847
1720
|
//#region src/vite-plugin/index.ts
|
|
1848
1721
|
const PLUGIN_NAME = "api-code-gen";
|
|
1849
|
-
const
|
|
1722
|
+
const pluginLogger = createScopedLogger("api-code-gen");
|
|
1850
1723
|
/**
|
|
1851
1724
|
* Run TypeScript type checking on generated file
|
|
1852
1725
|
*/
|
|
@@ -1875,7 +1748,7 @@ async function validateSpecPath(specPath) {
|
|
|
1875
1748
|
async function generateForOption(option) {
|
|
1876
1749
|
const { name, typeCheck = true, verbose, ...restOptions } = option;
|
|
1877
1750
|
try {
|
|
1878
|
-
|
|
1751
|
+
logger$1.info(`Generating ${name}...`);
|
|
1879
1752
|
const config = await loadConfig({
|
|
1880
1753
|
name,
|
|
1881
1754
|
cliOptions: {
|
|
@@ -1899,8 +1772,8 @@ async function generateForOption(option) {
|
|
|
1899
1772
|
if (typeCheck && config.output) {
|
|
1900
1773
|
const typeErrors = await runTypeCheck(config.output);
|
|
1901
1774
|
if (typeErrors.length > 0) {
|
|
1902
|
-
|
|
1903
|
-
if (verbose) for (const error of typeErrors)
|
|
1775
|
+
pluginLogger.warn(`Type check failed for ${config.output}`);
|
|
1776
|
+
if (verbose) for (const error of typeErrors) pluginLogger.warn(` ${error}`);
|
|
1904
1777
|
}
|
|
1905
1778
|
}
|
|
1906
1779
|
return {
|
|
@@ -1941,45 +1814,47 @@ async function generateForOption(option) {
|
|
|
1941
1814
|
*/
|
|
1942
1815
|
function apiCodeGenPlugin(options) {
|
|
1943
1816
|
if (!Array.isArray(options) || options.length === 0) {
|
|
1944
|
-
|
|
1817
|
+
pluginLogger.warn("No API configurations provided to apiCodeGenPlugin");
|
|
1945
1818
|
return { name: PLUGIN_NAME };
|
|
1946
1819
|
}
|
|
1947
1820
|
return {
|
|
1948
1821
|
name: PLUGIN_NAME,
|
|
1949
1822
|
async config(_config, env) {
|
|
1950
|
-
|
|
1951
|
-
console.log(`\x1b[1m\x1b[36mAPI Code Gen\x1b[0m`);
|
|
1952
|
-
console.log(`\x1b[90mMode:\x1b[0m ${env?.command || "unknown"}`);
|
|
1953
|
-
console.log(`\x1b[1m\x1b[36m${"─".repeat(50)}\x1b[0m`);
|
|
1823
|
+
logger$1.heading("API Code Gen", env?.command);
|
|
1954
1824
|
const results = await Promise.all(options.map(generateForOption));
|
|
1955
1825
|
const successCount = results.filter((r) => r.success).length;
|
|
1956
1826
|
const failCount = options.length - successCount;
|
|
1957
|
-
|
|
1827
|
+
logger$1.divider();
|
|
1958
1828
|
for (const result of results) if (result.success) {
|
|
1959
1829
|
const { name, output, stats } = result;
|
|
1960
|
-
if (stats)
|
|
1961
|
-
else
|
|
1830
|
+
if (stats) logger$1.item(`${name} → ${output} (${stats.endpoints} endpoints, ${stats.schemas} schemas) ${stats.duration}ms`, "green");
|
|
1831
|
+
else logger$1.item(`${name} → ${output || "N/A"}`, "green");
|
|
1962
1832
|
} else {
|
|
1963
1833
|
const { name, error } = result;
|
|
1964
1834
|
if (isApicodegenError(error)) {
|
|
1965
|
-
|
|
1966
|
-
|
|
1835
|
+
logger$1.item(name, "red");
|
|
1836
|
+
logger$1.error(error, true);
|
|
1967
1837
|
} else {
|
|
1968
1838
|
const wrapped = wrapError(error, {
|
|
1969
|
-
code:
|
|
1839
|
+
code: ErrorCodes.GENERATION_FAILED,
|
|
1970
1840
|
message: `Failed to generate API "${name}"`
|
|
1971
1841
|
});
|
|
1972
|
-
|
|
1973
|
-
|
|
1842
|
+
logger$1.item(name, "red");
|
|
1843
|
+
logger$1.error(wrapped, true);
|
|
1974
1844
|
}
|
|
1975
1845
|
}
|
|
1976
|
-
|
|
1846
|
+
logger$1.divider();
|
|
1977
1847
|
const totalDuration = results.reduce((sum, r) => sum + (r.stats?.duration || 0), 0);
|
|
1978
1848
|
const totalEndpoints = results.reduce((sum, r) => sum + (r.stats?.endpoints || 0), 0);
|
|
1979
1849
|
const totalSchemas = results.reduce((sum, r) => sum + (r.stats?.schemas || 0), 0);
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1850
|
+
logger$1.summary({
|
|
1851
|
+
succeeded: successCount,
|
|
1852
|
+
failed: failCount,
|
|
1853
|
+
endpoints: totalEndpoints,
|
|
1854
|
+
schemas: totalSchemas,
|
|
1855
|
+
duration: totalDuration
|
|
1856
|
+
});
|
|
1857
|
+
logger$1.divider();
|
|
1983
1858
|
return {};
|
|
1984
1859
|
}
|
|
1985
1860
|
};
|