@alova/wormhole
Version:
More modern openAPI generating solution for alova.js
264 lines (263 loc) • 10.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseResponse = parseResponse;
exports.parseRequestBody = parseRequestBody;
exports.parseParameters = parseParameters;
exports.transformApiMethods = transformApiMethods;
exports.apiMethod2ApiDescriptor = apiMethod2ApiDescriptor;
exports.apiDescriptor2apiMethod = apiDescriptor2apiMethod;
const lodash_1 = require("lodash");
const loader_1 = require("../../../core/loader");
const utils_1 = require("../../../utils");
function getTsStr(originObj, options) {
const { document, preText = '', config, schemasMap } = options;
return loader_1.schemaLoader.transform(originObj, {
document,
deep: false,
noEnum: true,
commentType: 'doc',
preText,
defaultRequire: config.defaultRequire,
async onReference(ast) {
if (ast.keyName && schemasMap && !schemasMap.has(ast.keyName)) {
const result = await loader_1.astLoader.transformTsStr(ast, {
shallowDeep: true,
commentType: 'doc',
noEnum: true,
format: true,
export: true,
});
schemasMap.set(ast.keyName, result);
}
},
});
}
async function parseResponse(responses, document, config, schemasMap) {
const successKey = (0, utils_1.getResponseSuccessKey)(responses);
const responseInfo = responses?.[successKey];
if (!responseInfo) {
return {
responseName: 'unknown',
responseComment: 'unknown',
};
}
const responseObject = (0, utils_1.isReferenceObject)(responseInfo)
? (0, utils_1.findBy$ref)(responseInfo.$ref, document)
: responseInfo;
const key = getContentKey(responseObject.content, config.responseMediaType);
const responseSchema = responseObject?.content?.[key]?.schema ?? {};
const responseName = await getTsStr(responseSchema, {
document,
config,
schemasMap,
});
return {
responseName,
responseComment: await loader_1.schemaLoader.transform(responseSchema, {
document,
deep: true,
preText: '* ',
defaultRequire: config.defaultRequire,
}),
};
}
async function parseRequestBody(requestBody, document, config, schemasMap) {
if (!requestBody) {
return {
requestName: '',
requestComment: '',
};
}
const requestBodyObject = (0, utils_1.isReferenceObject)(requestBody)
? (0, utils_1.findBy$ref)(requestBody.$ref, document)
: requestBody;
const key = getContentKey(requestBodyObject.content, config.bodyMediaType);
const requestBodySchema = requestBodyObject?.content?.[key]?.schema ?? {};
const requestName = await getTsStr(requestBodySchema, { document, config, schemasMap });
return {
requestName,
requestComment: await loader_1.schemaLoader.transform(requestBodySchema, {
document,
deep: true,
preText: '* ',
defaultRequire: config.defaultRequire,
}),
};
}
function getContentKey(content = {}, requireKey = 'application/json') {
let key = Object.keys(content)[0] || requireKey;
if (content[requireKey]) {
key = requireKey;
}
return key;
}
async function parseParameters(parameters, document, config, schemasMap) {
const pathParametersSchema = {
type: 'object',
};
const queryParametersSchema = {
type: 'object',
};
const parseParameter = (parameter, parameters) => {
if (!parameters.properties) {
parameters.properties = {};
}
if (!parameters.required) {
parameters.required = [];
}
if (parameter.required) {
parameters.required.push(parameter.name);
}
parameters.properties[parameter.name] = {
...parameter.schema,
description: parameter.description || '',
deprecated: !!parameter.deprecated,
};
};
const parseParametersSchema = async (parameters) => {
let parametersStr = '';
let parametersComment = '';
if (Object.keys(parameters.properties ?? {}).length) {
parametersStr = await getTsStr(parameters, {
document,
config,
schemasMap,
});
parametersComment = await loader_1.schemaLoader.transform(parameters, {
document,
deep: true,
preText: '* ',
defaultRequire: config.defaultRequire,
});
}
return [parametersStr, parametersComment];
};
for (const refParameter of parameters || []) {
const parameter = (0, utils_1.parseReference)(refParameter, document);
if (parameter.in === 'path') {
parseParameter(parameter, pathParametersSchema);
}
else if (parameter.in === 'query') {
parseParameter(parameter, queryParametersSchema);
}
}
const [pathParameters, pathParametersComment] = await parseParametersSchema(pathParametersSchema);
const [queryParameters, queryParametersComment] = await parseParametersSchema(queryParametersSchema);
return {
pathParameters,
queryParameters,
pathParametersComment,
queryParametersComment,
};
}
async function transformApiMethods(apiMethod, options) {
const { handleApi } = options.config;
if (!handleApi || typeof handleApi !== 'function') {
return apiMethod;
}
const { apiDescriptor, apiInfo } = apiMethod2ApiDescriptor(apiMethod, options);
let newApiDescriptor = (0, lodash_1.cloneDeep)(apiDescriptor);
try {
newApiDescriptor = handleApi(newApiDescriptor);
}
catch { }
// TODO:插件处理handleApi
if (!newApiDescriptor) {
return null;
}
const newApiMethod = apiDescriptor2apiMethod(newApiDescriptor, {
oldApiInfo: apiInfo,
operationObject: apiMethod.operationObject,
});
newApiMethod.operationObject = (0, utils_1.mergeObject)(apiMethod.operationObject, newApiMethod.operationObject, options.document, options.map);
return newApiMethod;
}
function apiMethod2ApiDescriptor(apiMethod, options) {
const { url, method } = apiMethod;
const { document, config } = options;
const operationObject = (0, lodash_1.cloneDeep)(apiMethod.operationObject);
const { requestBody, responses, parameters } = operationObject;
const apiDescriptor = {
...operationObject,
requestBody: {},
responses: {},
parameters: [],
url,
method,
};
const successKey = (0, utils_1.getResponseSuccessKey)(responses);
const responseSuccess = responses?.[successKey];
let requestBodyObject = requestBody;
let responseObject = responseSuccess;
let requestKey = 'application/json';
let responseKey = 'application/json';
if (parameters) {
apiDescriptor.parameters = [];
parameters.forEach((parameter) => {
apiDescriptor.parameters?.push((0, utils_1.removeAll$ref)(parameter, document));
});
}
if (requestBody) {
requestBodyObject = (0, utils_1.parseReference)(requestBody, document, true);
requestKey = getContentKey(requestBodyObject.content, config.bodyMediaType);
apiDescriptor.requestBody = (0, utils_1.removeAll$ref)(requestBodyObject.content?.[requestKey].schema ?? {}, document);
}
if (responseSuccess) {
responseObject = (0, utils_1.parseReference)(responseSuccess, document, true);
responseKey = getContentKey(responseObject.content, config.responseMediaType);
apiDescriptor.responses = (0, utils_1.removeAll$ref)(responseObject.content?.[responseKey].schema ?? {}, document);
}
return {
apiDescriptor,
apiInfo: {
successKey,
requestKey,
responseKey,
requestBody: requestBodyObject,
response: responseObject,
hasResponse: !!responseSuccess,
hasRequestBody: !!requestBody,
hasParameters: !!parameters,
},
};
}
function apiDescriptor2apiMethod(apiDescriptor, options) {
const apiDescriptorValue = (0, lodash_1.cloneDeep)(apiDescriptor);
const operationObject = (0, lodash_1.cloneDeep)(options.operationObject);
const { url, method } = apiDescriptorValue;
const { successKey, requestKey, responseKey, hasResponse, hasParameters, hasRequestBody, requestBody, response } = options.oldApiInfo;
if (!(0, lodash_1.isEmpty)(apiDescriptorValue.requestBody) || hasRequestBody) {
operationObject.requestBody = requestBody || { content: {} };
const { content } = operationObject.requestBody;
if (!content[requestKey]) {
content[requestKey] = {};
}
content[requestKey].schema = apiDescriptorValue.requestBody;
}
if (!(0, lodash_1.isEmpty)(apiDescriptorValue.responses) || hasResponse) {
if (!operationObject.responses) {
operationObject.responses = {};
}
operationObject.responses[successKey] = response || { content: {} };
if (!operationObject.responses[successKey].content) {
operationObject.responses[successKey].content = {};
}
const { content } = operationObject.responses[successKey];
if (!content[responseKey]) {
content[responseKey] = {};
}
content[responseKey].schema = apiDescriptorValue.responses;
}
if (!(0, lodash_1.isEmpty)(apiDescriptorValue.parameters) || hasParameters) {
operationObject.parameters = apiDescriptorValue.parameters;
}
delete apiDescriptorValue.requestBody;
delete apiDescriptorValue.responses;
delete apiDescriptorValue.parameters;
Object.assign(operationObject, apiDescriptorValue);
return {
url,
method,
operationObject,
};
}