import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { defineConfig } from 'orval' import { upgrade } from '@scalar/openapi-parser' const OPENAPI_FILE_PATH = resolve(process.cwd(), 'openapi.json') const tagNameMap: Record = { Аутентификация: 'authentication', 'Карта компетенций: аналитика': 'competence-map-analytics', 'Карта компетенций: карта связей': 'competence-map-association-map', Мониторинг: 'monitoring', Пользователь: 'user', 'Управление пользователями': 'user-management', } const parseOpenApiSpec = (rawSpec: string) => { try { return JSON.parse(rawSpec) as Record } catch (error) { if (!(error instanceof SyntaxError)) { throw error } const positionMatch = /position (\d+)/.exec(error.message) if (!positionMatch) { throw error } const firstDocument = rawSpec.slice(0, Number(positionMatch[1])).trimEnd() return JSON.parse(firstDocument) as Record } } const loadOpenApiTarget = () => { const rawSpec = readFileSync(OPENAPI_FILE_PATH, 'utf8') const parsedSpec = parseOpenApiSpec(rawSpec) const { specification } = upgrade(parsedSpec) const target = specification as Record const paths = target.paths if (paths && typeof paths === 'object') { for (const pathItem of Object.values(paths as Record)) { if (!pathItem || typeof pathItem !== 'object') { continue } for (const operation of Object.values(pathItem as Record)) { if (!operation || typeof operation !== 'object' || !('tags' in operation)) { continue } const operationWithTags = operation as { tags?: unknown } if (Array.isArray(operationWithTags.tags)) { operationWithTags.tags = operationWithTags.tags.map((tag) => typeof tag === 'string' ? (tagNameMap[tag] ?? normalizeOperationName(tag)) : tag, ) } } } } return target } const normalizeOperationName = (name: string) => name.replace(/[^A-Za-z0-9_$]/g, '_') export default defineConfig({ api: { input: { target: loadOpenApiTarget(), }, output: { mode: 'tags', target: './src/shared/api/generated-api/endpoints.ts', client: 'vue-query', mock: false, clean: true, override: { mutator: { path: './src/shared/api/axiosInstance.ts', name: 'customInstance', }, operationName: (operation, _route, verb) => { const name = normalizeOperationName(operation.operationId || '') const isMutation = ['post', 'put', 'patch', 'delete'].includes(verb.toLowerCase()) return isMutation ? `${name}Mutation` : name }, query: { useQuery: true, useMutation: true, signal: true, }, }, }, }, apiZod: { input: { target: loadOpenApiTarget(), }, output: { mode: 'tags', target: './src/shared/model/generated-zod/endpoints.zod.ts', client: 'zod', mock: false, clean: true, override: { operationName: (operation, _route, verb) => { const name = normalizeOperationName(operation.operationId || '') const isMutation = ['post', 'put', 'patch', 'delete'].includes(verb.toLowerCase()) return isMutation ? `${name}Mutation` : name }, }, }, }, })