Skip to content

Instantly share code, notes, and snippets.

@vltansky
Last active August 4, 2023 08:01
Show Gist options
  • Save vltansky/99eeea21ac795eebbf0ce239f2b9450b to your computer and use it in GitHub Desktop.
Save vltansky/99eeea21ac795eebbf0ce239f2b9450b to your computer and use it in GitHub Desktop.
Zodios generate api from jsons
import SwaggerParser from '@apidevtools/swagger-parser';
import { ESLint } from 'eslint';
import { promises as fs } from 'fs';
import camelCase from 'lodash/camelCase';
import { generateZodClientFromOpenAPI } from 'openapi-zod-client';
import type { OpenAPIObject } from 'openapi3-ts';
import path from 'path';
import { Options, format, resolveConfig } from 'prettier';
const BASE_FOLDER = 'libs/shared/zodios/src';
const ORIGINAL_URL_TO_REPLACE_PREFIX = 'local.dev/v1/corp/';
const SWAGGER_JSON_LOCATION = path.join(__dirname, `../${BASE_FOLDER}/swaggers/`);
async function generateApi() {
const swaggerFiles = await fs.readdir(SWAGGER_JSON_LOCATION);
const prettierConfig = await resolveConfig('./');
// create or replace api folder inside zodios folder
await fs.mkdir(`${SWAGGER_JSON_LOCATION}/../api`, { recursive: true });
await Promise.all(
swaggerFiles.map(async (file, index) => {
if (!file.endsWith('.json')) return;
const currentFile = path.join(SWAGGER_JSON_LOCATION, file);
const swaggerData = (await SwaggerParser.parse(currentFile)) as OpenAPIObject;
const serverUrl =
swaggerData.servers
?.find((v) => v?.url?.includes('v1/corp'))
?.url?.split(ORIGINAL_URL_TO_REPLACE_PREFIX)?.[1] ?? '';
Object.keys(swaggerData.paths).forEach((originalPath) => {
let newPath: string = originalPath.includes(serverUrl)
? originalPath
: (serverUrl !== '' ? '/' : '') + serverUrl + originalPath;
// find all the varaibles in path e.g /some-path/{id}/dsadas/{ok}
const variables = originalPath.match(/{(.*?)}/g);
// replace all the variables with camel case, remove the curly braces and add colon
if (variables) {
variables.forEach((variable) => {
const newVariable = camelCase(variable.replace(/{/g, '').replace(/}/g, ''));
newPath = newPath.replace(variable, `:${newVariable}`);
});
}
swaggerData.paths['uiapiproxy' + newPath] = swaggerData.paths[originalPath];
delete swaggerData.paths[originalPath];
});
createFile(file, swaggerData, prettierConfig, 'axiosClient');
})
);
}
async function createFile(
file: string,
swaggerData: OpenAPIObject,
prettierConfig: Options | null,
axiosInstance: string
) {
const fileName = file.replace('.json', '');
const distPath = `${BASE_FOLDER}/api/${fileName}.ts`;
const res = await generateZodClientFromOpenAPI({
openApiDoc: swaggerData,
prettierConfig,
disableWriteToFile: true,
options: {
withAlias: true,
},
});
const camelCasedFileName = camelCase(fileName);
const variableName = camelCasedFileName + 'ApiClient';
const fileContent = `/* eslint-disable */
import { ${axiosInstance} } from '@/shared/axios';
import { ApiOf } from '@zodios/core';
import { ZodiosHooks } from '@zodios/react';
${res.replace(
'export const api = new Zodios(endpoints);',
`export const ${variableName} = new Zodios(endpoints, {
axiosInstance: ${axiosInstance},
validate: false,
});
export type zodiosApi = ApiOf<typeof ${variableName}>;
export const ${camelCasedFileName}Hooks = new ZodiosHooks('api', ${variableName});
`
)}`;
await fs.writeFile(distPath, format(fileContent, { ...prettierConfig, parser: 'typescript' }));
// eslint fix the file
const eslint = new ESLint({ fix: true });
const results = await eslint.lintText(fileContent, { filePath: distPath });
await ESLint.outputFixes(results);
}
generateApi();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment