120 lines
3.4 KiB
TypeScript
120 lines
3.4 KiB
TypeScript
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<string, string> = {
|
|
'Аутентификация': 'authentication',
|
|
'Карта компетенций: аналитика': 'competence-map-analytics',
|
|
'Мониторинг': 'monitoring',
|
|
'Пользователь': 'user',
|
|
'Управление пользователями': 'user-management',
|
|
}
|
|
|
|
const parseOpenApiSpec = (rawSpec: string) => {
|
|
try {
|
|
return JSON.parse(rawSpec) as Record<string, unknown>
|
|
} 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<string, unknown>
|
|
}
|
|
}
|
|
|
|
const loadOpenApiTarget = () => {
|
|
const rawSpec = readFileSync(OPENAPI_FILE_PATH, 'utf8')
|
|
const parsedSpec = parseOpenApiSpec(rawSpec)
|
|
const { specification } = upgrade(parsedSpec)
|
|
const target = specification as Record<string, unknown>
|
|
const paths = target.paths
|
|
|
|
if (paths && typeof paths === 'object') {
|
|
for (const pathItem of Object.values(paths as Record<string, unknown>)) {
|
|
if (!pathItem || typeof pathItem !== 'object') {
|
|
continue
|
|
}
|
|
|
|
for (const operation of Object.values(pathItem as Record<string, unknown>)) {
|
|
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
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|