87 lines
2.2 KiB
TypeScript
87 lines
2.2 KiB
TypeScript
import { OpenAPIHandler } from '@orpc/openapi/fetch'
|
|
import { OpenAPIReferencePlugin } from '@orpc/openapi/plugins'
|
|
import { ORPCError, onError, ValidationError } from '@orpc/server'
|
|
import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'
|
|
import { createFileRoute } from '@tanstack/react-router'
|
|
import { z } from 'zod'
|
|
import { name, version } from '@/../package.json'
|
|
import { router } from '@/server/api/routers'
|
|
|
|
const handler = new OpenAPIHandler(router, {
|
|
plugins: [
|
|
new OpenAPIReferencePlugin({
|
|
docsProvider: 'scalar',
|
|
schemaConverters: [new ZodToJsonSchemaConverter()],
|
|
specGenerateOptions: {
|
|
info: {
|
|
title: name,
|
|
version,
|
|
},
|
|
// components: {
|
|
// securitySchemes: {
|
|
// bearerAuth: {
|
|
// type: 'http',
|
|
// scheme: 'bearer',
|
|
// },
|
|
// },
|
|
// },
|
|
},
|
|
docsPath: '/docs',
|
|
specPath: '/spec.json',
|
|
}),
|
|
],
|
|
interceptors: [
|
|
onError((error) => {
|
|
console.error(error)
|
|
}),
|
|
],
|
|
clientInterceptors: [
|
|
onError((error) => {
|
|
if (
|
|
error instanceof ORPCError &&
|
|
error.code === 'BAD_REQUEST' &&
|
|
error.cause instanceof ValidationError
|
|
) {
|
|
// If you only use Zod you can safely cast to ZodIssue[]
|
|
const zodError = new z.ZodError(
|
|
error.cause.issues as z.core.$ZodIssue[],
|
|
)
|
|
|
|
throw new ORPCError('INPUT_VALIDATION_FAILED', {
|
|
status: 422,
|
|
message: z.prettifyError(zodError),
|
|
data: z.flattenError(zodError),
|
|
cause: error.cause,
|
|
})
|
|
}
|
|
|
|
if (
|
|
error instanceof ORPCError &&
|
|
error.code === 'INTERNAL_SERVER_ERROR' &&
|
|
error.cause instanceof ValidationError
|
|
) {
|
|
throw new ORPCError('OUTPUT_VALIDATION_FAILED', {
|
|
cause: error.cause,
|
|
})
|
|
}
|
|
}),
|
|
],
|
|
})
|
|
|
|
export const Route = createFileRoute('/api/$')({
|
|
server: {
|
|
handlers: {
|
|
ANY: async ({ request }) => {
|
|
const { response } = await handler.handle(request, {
|
|
prefix: '/api',
|
|
context: {
|
|
headers: request.headers,
|
|
},
|
|
})
|
|
|
|
return response ?? new Response('Not Found', { status: 404 })
|
|
},
|
|
},
|
|
},
|
|
})
|