62 lines
1.6 KiB
TypeScript
62 lines
1.6 KiB
TypeScript
import { ORPCError, onError, ValidationError } from '@orpc/server'
|
|
import { RPCHandler } from '@orpc/server/fetch'
|
|
import { createFileRoute } from '@tanstack/react-router'
|
|
import { z } from 'zod'
|
|
import { router } from '@/server/api/routers'
|
|
|
|
const handler = new RPCHandler(router, {
|
|
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/rpc/$')({
|
|
server: {
|
|
handlers: {
|
|
ANY: async ({ request }) => {
|
|
const { response } = await handler.handle(request, {
|
|
prefix: '/api/rpc',
|
|
context: {
|
|
headers: request.headers,
|
|
},
|
|
})
|
|
|
|
return response ?? new Response('Not Found', { status: 404 })
|
|
},
|
|
},
|
|
},
|
|
})
|