UNPKG

@alova/wormhole

Version:

More modern openAPI generating solution for alova.js

264 lines (263 loc) 10.1 kB
"use strict"; 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, }; }