UNPKG

@infinite-debugger/swagger-to-ts

Version:

swagger-to-ts is a powerful library that allows you to generate TypeScript code from Swagger documentation or OpenAPI specifications. It simplifies the process of integrating API definitions into your TypeScript projects, saving you time and effort.

552 lines (542 loc) 44.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAPIFunctionsCodeConfiguration = exports.getAPIAdapterCode = void 0; const lodash_1 = require("lodash"); const models_1 = require("../models"); const SchemaGenerator_1 = require("./SchemaGenerator"); const Utils_1 = require("./Utils"); //#region API adapter code generator const getAPIAdapterCode = () => { return ` import { getAPIAdapter } from '@infinite-debugger/axios-api-adapter'; export { IAPIAdapterConfiguration, CANCELLED_API_REQUEST_MESSAGE, EXPIRED_SESSION_ERROR_MESSAGES, RequestOptions, ResponseProcessor, } from '@infinite-debugger/axios-api-adapter'; export const { APIAdapterConfiguration, RequestController, _delete, defaultRequestHeaders, get, logout, patch, patchDefaultRequestHeaders, post, put, } = getAPIAdapter({ id: 'api-client', }); `.trimIndent(); }; exports.getAPIAdapterCode = getAPIAdapterCode; //#endregion //#region API functions code generator const API_ADAPTER_PATH = `./Adapter`; const AXIOS_PATH = 'axios'; const getAPIFunctionsCodeConfiguration = ({ requestGroupings, tagToEntityLabelMappings, schemaToEntityMappings, modelsToValidationSchemaMappings, trimNullValuesFromResponses = true, localScopeName, }) => { return Object.keys(requestGroupings).reduce((accumulator, tag) => { const dataKeyVariableName = `${localScopeName !== 'Root' ? localScopeName.replace(/\s/g, '_').toUpperCase() + '_' : ''}${tagToEntityLabelMappings[tag].UPPER_CASE_ENTITIES}_DATA_KEY`; const imports = (0, lodash_1.cloneDeep)(requestGroupings[tag].imports); const exports = []; //#region Generate entity api endpoint paths const requestPathsOutputCode = requestGroupings[tag].requests .map(({ requestPath, requestPathName, pathParameters }) => { if (pathParameters?.length) { const parametersCode = pathParameters .reduce((accumulator, { name, schema }) => { accumulator.push(`${name}: ${(0, SchemaGenerator_1.getPrimitiveSchemaType)(schema)}`); return accumulator; }, []) .join(';\n'); const pathParamType = `TemplatePath`; (0, Utils_1.addModuleImport)({ imports, importName: pathParamType, importFilePath: models_1.PATHS_LIBRARY_PATH, }); return `export const ${requestPathName}: ${pathParamType}<{${parametersCode}}> = '${requestPath}';`; } return `export const ${requestPathName} = '${requestPath}';`; }) .join('\n'); //#endregion //#region Generate entity api request functions const outputCode = requestGroupings[tag].requests .map((requestConfig) => { const { method, operationName, requestPathName, operationDescription, summary, description, pathParameters, deprecated, headerParameters, headerParametersModelReference, queryParameters, queryParametersModelReference, requestBody, requestBodySchemaName, requestBodyType, requestBodyTypeDependentSchemaName, successResponseSchemas, } = requestConfig; const responseType = requestConfig['x-requestConfig']?.apiFunctionConfig?.responseType; const { jsDocCommentShortOverloadSnippet, jsDocCommentSnippet, apiFunctionParameters, apiFunctionDeclarationParameters, returnValueString, definedSchemaResponseType, } = (() => { const jsDocCommentShortOverloadLines = []; const jsDocCommentLines = []; if (description) { jsDocCommentLines.push(description, ''); } if (pathParameters?.length) { jsDocCommentLines.push(...pathParameters.map(({ name, description = '' }) => { return `@param ${name} ${description}`.trim(); })); } if (deprecated) { jsDocCommentLines.push('@deprecated'); } const definedSchemaResponseNames = (() => { if (successResponseSchemas && successResponseSchemas.length > 0) { return successResponseSchemas .map((successResponseSchema) => { const definedSchemaResponseName = (() => { if ('name' in successResponseSchema && modelsToValidationSchemaMappings[successResponseSchema.name]) { const { name: successResponseSchemaName } = successResponseSchema; return modelsToValidationSchemaMappings[successResponseSchemaName].name; } })(); if (definedSchemaResponseName) { return { modelName: definedSchemaResponseName, type: successResponseSchema.isArray ? `${definedSchemaResponseName}[]` : definedSchemaResponseName, }; } if ('type' in successResponseSchema && successResponseSchema.type) { return { type: successResponseSchema.isArray ? `${successResponseSchema.type}[]` : successResponseSchema.type, }; } }) .filter((modelNameAndType) => modelNameAndType); } })(); const definedSchemaResponseType = (() => { if (definedSchemaResponseNames?.length) { return [ ...new Set(definedSchemaResponseNames.map(({ type }) => { return type; })), ].join(' | '); } })(); if (definedSchemaResponseNames?.length) { definedSchemaResponseNames.forEach(({ modelName: definedSchemaResponseName }) => { if (definedSchemaResponseName) { (0, Utils_1.addModuleImport)({ imports, importName: definedSchemaResponseName, importFilePath: `../models/${tagToEntityLabelMappings[schemaToEntityMappings[definedSchemaResponseName]].PascalCaseEntities}`.trim(), }); } }); } //#region Base API function parameters code const baseAPIFunctionParameters = [ //#region Path parameters ...(() => { if (pathParameters?.length) { return pathParameters.map(({ name, schema }) => { return `${name}: ${(0, SchemaGenerator_1.getPrimitiveSchemaType)(schema)}`; }); } return []; })(), //#endregion //#region Request body parameters ...(() => { if (requestBody && (requestBodySchemaName || requestBodyType)) { jsDocCommentLines.push(`@param requestPayload ${requestBody.description || ''}`.trim()); if (requestBodySchemaName) { const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[requestBodySchemaName]].PascalCaseEntities}`.trim(); (0, Utils_1.addModuleImport)({ imports, importName: requestBodySchemaName, importFilePath: schemaSource, }); return [`requestPayload: ${requestBodySchemaName}`]; } if (requestBodyType) { if (requestBodyTypeDependentSchemaName) { const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[requestBodyTypeDependentSchemaName]].PascalCaseEntities}`.trim(); (0, Utils_1.addModuleImport)({ imports, importName: requestBodyTypeDependentSchemaName, importFilePath: schemaSource, }); } return [`requestPayload: ${requestBodyType}`]; } } return []; })(), //#endregion //#region Header parameters ...(() => { if (headerParametersModelReference && headerParameters && headerParameters.length > 0) { jsDocCommentLines.push(`@param headers`); const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[headerParametersModelReference]].PascalCaseEntities}`.trim(); (0, Utils_1.addModuleImport)({ imports, importName: headerParametersModelReference, importFilePath: schemaSource, }); return [`headers: ${headerParametersModelReference}`]; } return []; })(), //#endregion ]; //#endregion //#region API function declaration parameters code const apiFunctionDeclarationParameters = [ ...baseAPIFunctionParameters, //#region Query parameters ...(() => { if (queryParametersModelReference && queryParameters && queryParameters.length > 0) { // Check if query params are required if (queryParameters.filter(({ required }) => required).length > 0) { return [`queryParams: ${queryParametersModelReference}`]; } return [`queryParams?: ${queryParametersModelReference}`]; } return []; })(), //#endregion ]; //#endregion //#region API function parameters code const apiFunctionParameters = [ ...baseAPIFunctionParameters, //#region Query parameters ...(() => { if (queryParametersModelReference && queryParameters && queryParameters.length > 0) { jsDocCommentLines.push(`@param queryParams`); const schemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[queryParametersModelReference]].PascalCaseEntities}`.trim(); (0, Utils_1.addModuleImport)({ imports, importName: queryParametersModelReference, importFilePath: schemaSource, }); // Check if query params are required if (queryParameters.filter(({ required }) => required).length > 0) { return [`queryParams: ${queryParametersModelReference}`]; } return [`queryParams: ${queryParametersModelReference} = {}`]; } return []; })(), //#endregion ]; //#endregion jsDocCommentShortOverloadLines.push(...jsDocCommentLines); jsDocCommentLines.push(`@param options The request options.`); (0, Utils_1.addModuleImport)({ imports, importName: 'RequestOptions', importFilePath: API_ADAPTER_PATH, }); const returnValueString = (() => { if (successResponseSchemas && successResponseSchemas.length === 1) { const [successResponseSchema] = successResponseSchemas; if ('name' in successResponseSchema && modelsToValidationSchemaMappings[successResponseSchema.name]) { const { name: successResponseSchemaName, description, isArray, } = successResponseSchema; const successResponseValidationSchemaName = modelsToValidationSchemaMappings[successResponseSchemaName] .zodValidationSchemaName; const validationSchemaSource = `../models/${tagToEntityLabelMappings[schemaToEntityMappings[successResponseSchemaName]].PascalCaseEntities}`.trim(); (0, Utils_1.addModuleImport)({ imports, importName: successResponseValidationSchemaName, importFilePath: validationSchemaSource, }); jsDocCommentLines.push(`@returns ${description}`); jsDocCommentShortOverloadLines.push(`@returns ${description}`); if (isArray) { (0, Utils_1.addModuleImport)({ imports, importName: 'z', importFilePath: 'zod', }); if (trimNullValuesFromResponses) { (0, Utils_1.addModuleImport)({ imports, importName: 'removeNullValues', importFilePath: models_1.RMK_UTILS_LIBRARY_PATH, }); return `z.array(${successResponseValidationSchemaName}).parse(removeNullValues(response.data))`; } return `z.array(${successResponseValidationSchemaName}).parse(response.data)`; } if (trimNullValuesFromResponses) { (0, Utils_1.addModuleImport)({ imports, importName: 'removeNullValues', importFilePath: models_1.RMK_UTILS_LIBRARY_PATH, }); return `${successResponseValidationSchemaName}.parse(removeNullValues(response.data))`; } return `${successResponseValidationSchemaName}.parse(response.data)`; } } return 'response.data'; })(); return { jsDocCommentShortOverloadSnippet: (() => { if (jsDocCommentShortOverloadLines.length > 0) { const linesString = jsDocCommentShortOverloadLines .map((line) => { return line .split('\n') .map((lineSlice) => ` * ${lineSlice}`) .join('\n'); }) .join('\n'); return ` /** ${linesString} */ `.trimIndent(); } return ''; })(), jsDocCommentSnippet: (() => { if (jsDocCommentLines.length > 0) { const linesString = jsDocCommentLines .map((line) => { return line .split('\n') .map((lineSlice) => ` * ${lineSlice}`) .join('\n'); }) .join('\n'); return ` /** ${linesString} */ `.trimIndent(); } return ''; })(), apiFunctionParameters, apiFunctionDeclarationParameters, returnValueString, definedSchemaResponseType, }; })(); //#region API request URL code const interpolatedEndpointPathString = (() => { const interpolatedEndpointPathString = (() => { if (pathParameters?.length) { const interpolationFunctionName = 'getInterpolatedPath'; (0, Utils_1.addModuleImport)({ imports, importName: interpolationFunctionName, importFilePath: models_1.PATHS_LIBRARY_PATH, }); return ` ${interpolationFunctionName}(${requestPathName}, { ${pathParameters.map(({ name }) => name).join(',\n')} }) `; } return requestPathName; })(); if (queryParameters && queryParameters.length > 0) { const searchParamsFunctionName = 'addSearchParams'; (0, Utils_1.addModuleImport)({ imports, importName: searchParamsFunctionName, importFilePath: models_1.PATHS_LIBRARY_PATH, }); return ` ${searchParamsFunctionName}(${interpolatedEndpointPathString}, {...queryParams}, { arrayParamStyle: 'append' }) `.trimIndent(); } return interpolatedEndpointPathString; })(); //#endregion //#region API adapter request call code const httpActionName = (() => { if (method === 'delete') { return `_delete`; } return method; })(); (0, Utils_1.addModuleImport)({ imports, importName: httpActionName, importFilePath: API_ADAPTER_PATH, }); const isEnvironmentDefinedModel = Boolean(successResponseSchemas && successResponseSchemas.every((successResponseSchema) => { if ('name' in successResponseSchema) { return (successResponseSchema.name && models_1.ENVIRONMENT_DEFINED_MODELS.includes(successResponseSchema.name)); } return 'type' in successResponseSchema; })); const isBlobType = Boolean(successResponseSchemas && successResponseSchemas.every((successResponseSchema) => { if ('name' in successResponseSchema) { return (successResponseSchema.name && models_1.ENVIRONMENT_DEFINED_MODELS.includes(successResponseSchema.name)); } return ('type' in successResponseSchema && successResponseSchema.type === 'any'); })); const environmentDefinedResponseType = (() => { if (isEnvironmentDefinedModel && successResponseSchemas) { return `${successResponseSchemas .map((successResponseSchema) => { if ('name' in successResponseSchema) { return successResponseSchema.name; } if ('type' in successResponseSchema) { return successResponseSchema.type; } }) .join('|')}`; } })(); //#endregion const requestOptionsCode = [ `label: '${operationDescription}'`, ...(() => { if (headerParameters && headerParameters.length > 0) { return [`headers: { ...headers }`]; } return []; })(), ...(() => { if (requestBody) { return [`data: requestPayload`]; } return []; })(), ...(() => { if (method.match(/get/gi)) { return [`cacheId: ${dataKeyVariableName}`]; } return []; })(), ...(() => { if (responseType) { return [`responseType: '${responseType}'`]; } if (isEnvironmentDefinedModel && isBlobType) { return [`responseType: 'blob'`]; } return []; })(), '...rest', ].join(',\n'); exports.push(operationName); const dataType = definedSchemaResponseType || environmentDefinedResponseType || 'any'; const axiosResponseTypeCode = `Promise<AxiosResponse<${dataType}>>`; (0, Utils_1.addModuleImport)({ imports, importName: 'AxiosResponse', importFilePath: AXIOS_PATH, }); const axiosResponseFunctionParametersCode = [ ...apiFunctionDeclarationParameters, `options?: RequestOptions<${dataType}> & { unWrapResponse?: false; }`, ]; const dataResponseTypeCode = `Promise<${dataType}>`; const dataResponseFunctionParametersWithoudUnWrapResposeOptionCode = [ ...apiFunctionDeclarationParameters, `options?: RequestOptions<${dataType}> & { unWrapResponse?: undefined; }`, ]; const dataResponseFunctionParametersCode = [ ...apiFunctionDeclarationParameters, `options?: RequestOptions<${dataType}> & { unWrapResponse?: true; }`, ]; const requestOptionsParameterCode = `{ unWrapResponse = true, ...rest }: RequestOptions<${dataType}> & { unWrapResponse?: boolean; } = {}`; const apiFunctionImplementationParametersCode = [ ...apiFunctionParameters, requestOptionsParameterCode, ]; return ` //#region ${summary} ${jsDocCommentShortOverloadSnippet} export async function ${operationName} ( ${apiFunctionDeclarationParameters.join(', ')} ): ${dataResponseTypeCode}; ${jsDocCommentSnippet} export async function ${operationName} ( ${dataResponseFunctionParametersWithoudUnWrapResposeOptionCode} ): ${dataResponseTypeCode}; ${jsDocCommentSnippet} export async function ${operationName} ( ${axiosResponseFunctionParametersCode} ): ${axiosResponseTypeCode}; ${jsDocCommentSnippet} export async function ${operationName} ( ${dataResponseFunctionParametersCode} ): ${dataResponseTypeCode}; ${jsDocCommentSnippet} export async function ${operationName}(${apiFunctionImplementationParametersCode}) { if (rest.getStaleWhileRevalidate) { const baseGetStaleWhileRevalidate = rest.getStaleWhileRevalidate; rest.getStaleWhileRevalidate = (data) => { return baseGetStaleWhileRevalidate(${returnValueString.replace('response.data', 'data')} as any); }; } const response = await ${httpActionName}(${interpolatedEndpointPathString}, { ${requestOptionsCode} }); const data = ${returnValueString}; if (unWrapResponse) { return data; } return { ...response, data }; }; //#endregion `.trimIndent(); }) .join('\n\n'); //#endregion accumulator[tag] = { requestPathsOutputCode, outputCode, imports, dataKeyVariableName, exports, }; return accumulator; }, {}); }; exports.getAPIFunctionsCodeConfiguration = getAPIFunctionsCodeConfiguration; //#endregion //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQVBJRnVuY3Rpb25zQ29kZUdlbmVyYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvQVBJRnVuY3Rpb25zQ29kZUdlbmVyYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtQ0FBbUM7QUFFbkMsc0NBUW1CO0FBQ25CLHVEQUEyRDtBQUMzRCxtQ0FBMEM7QUFFMUMsb0NBQW9DO0FBQzdCLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxFQUFFO0lBQ3BDLE9BQU87Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qk4sQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUNqQixDQUFDLENBQUM7QUEzQlcsUUFBQSxpQkFBaUIscUJBMkI1QjtBQUNGLFlBQVk7QUFFWixzQ0FBc0M7QUFDdEMsTUFBTSxnQkFBZ0IsR0FBRyxXQUFXLENBQUM7QUFFckMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDO0FBb0NwQixNQUFNLGdDQUFnQyxHQUFHLENBQUMsRUFDL0MsZ0JBQWdCLEVBQ2hCLHdCQUF3QixFQUN4QixzQkFBc0IsRUFDdEIsZ0NBQWdDLEVBQ2hDLDJCQUEyQixHQUFHLElBQUksRUFDbEMsY0FBYyxHQUMrQixFQUFFLEVBQUU7SUFDakQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsTUFBTSxDQUN6QyxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUUsRUFBRTtRQUNuQixNQUFNLG1CQUFtQixHQUFHLEdBQzFCLGNBQWMsS0FBSyxNQUFNO1lBQ3ZCLENBQUMsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUUsR0FBRyxHQUFHO1lBQ3hELENBQUMsQ0FBQyxFQUNOLEdBQUcsd0JBQXdCLENBQUMsR0FBRyxDQUFDLENBQUMsbUJBQW1CLFdBQVcsQ0FBQztRQUNoRSxNQUFNLE9BQU8sR0FBRyxJQUFBLGtCQUFTLEVBQUMsZ0JBQWdCLENBQUMs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