Files
chad/server/server.ts

114 lines
2.7 KiB
TypeScript

import type { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import FastifyAutoLoad from '@fastify/autoload'
import FastifyCookie from '@fastify/cookie'
import FastifyCors from '@fastify/cors'
import FastifyMultipart from '@fastify/multipart'
import FastifySensible from '@fastify/sensible'
import FastifySwagger from '@fastify/swagger'
import FastifyApiReference from '@scalar/fastify-api-reference'
import Fastify from 'fastify'
import { Prisma } from './prisma/generated-client/client.ts'
import { ErrorReplySchema } from './schemas/common.ts'
import 'dotenv/config'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const fastify = Fastify({
logger: true,
}).withTypeProvider<TypeBoxTypeProvider>()
fastify.register(FastifySensible)
fastify.setErrorHandler((error, request, reply) => {
if (error instanceof Prisma.PrismaClientValidationError) {
reply.notAcceptable()
return
}
if (error.statusCode) {
reply.getHttpError(error.statusCode, error.message)
return
}
reply.badRequest(error.message)
})
fastify.register(FastifySwagger, {
openapi: {
info: {
version: '1.0.0',
title: 'Chad API',
},
},
transform: ({ schema, url }) => {
if (!url.startsWith('/chad'))
return { schema, url }
const transformedSchema: typeof schema = schema ?? {}
const responseSchema: any = transformedSchema.response ?? {}
responseSchema['4xx'] ??= ErrorReplySchema
responseSchema['5xx'] ??= ErrorReplySchema
transformedSchema.response = responseSchema
return { schema: transformedSchema, url }
},
})
fastify.register(FastifyApiReference, {
routePrefix: '/reference',
configuration: {
showOperationId: true,
showDeveloperTools: 'never',
pageTitle: 'Chad API',
customCss: `
.scalar-mcp-layer,
.agent-button-container,
.t-doc__sidebar > div > button:last-child {
display: none !important;
}
`,
},
})
fastify.register(FastifyCors, {
origin: [
'http://localhost:3000',
'http://tauri.localhost',
'https://koptilnya.xyz',
'https://chad.koptilnya.xyz',
],
methods: ['PATCH', 'PUT', 'OPTIONS', 'GET', 'POST', 'DELETE'],
credentials: true,
})
fastify.register(FastifyCookie)
fastify.register(FastifyMultipart)
fastify.register(FastifyAutoLoad, {
dir: join(__dirname, 'plugins'),
})
fastify.register(FastifyAutoLoad, {
dir: join(__dirname, 'routes'),
options: { prefix: 'chad' },
})
;(async () => {
const port = process.env.PORT ? Number(process.env.PORT) : 4000
try {
await fastify.listen({ port, host: '0.0.0.0' })
}
catch (err) {
fastify.log.error(err)
process.exit(1)
}
})()