@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
JavaScript
;
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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