Last active
August 4, 2023 08:01
-
-
Save vltansky/99eeea21ac795eebbf0ce239f2b9450b to your computer and use it in GitHub Desktop.
Zodios generate api from jsons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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