import Fastify from 'fastify'; import helmet from '@fastify/helmet'; import sensible from '@fastify/sensible'; import swagger from '@fastify/swagger'; import type { AppConfig } from './config.js'; import { Database } from './infrastructure/database.js'; import { newUlid } from './core/ids.js'; export interface BuildAppOptions { config: AppConfig; database?: Database } export async function buildApp({ config, database = new Database(config.DATABASE_URL) }: BuildAppOptions) { const app = Fastify({ logger: { level: config.LOG_LEVEL }, genReqId: (request) => request.headers['x-correlation-id']?.toString() ?? newUlid() }); await app.register(helmet); await app.register(sensible); await app.register(swagger, { openapi: { info: { title: 'Krona Staff API', version: '0.1.0' }, servers: [{ url: '/api/v1/staff' }] } }); app.get('/live', { schema: { tags: ['Operations'], response: { 200: { type: 'object', required: ['status'], properties: { status: { type: 'string', const: 'ok' } } } } } }, async () => ({ status: 'ok' })); app.get('/ready', { schema: { tags: ['Operations'], response: { 200: { type: 'object', required: ['status'], properties: { status: { type: 'string', const: 'ready' } } } } } }, async () => { await database.ping(); return { status: 'ready' }; }); app.get('/version', { schema: { tags: ['Operations'], response: { 200: { type: 'object', required: ['name', 'version', 'mode'], properties: { name: { type: 'string' }, version: { type: 'string' }, mode: { type: 'string' } } } } } }, async () => ({ name: 'krona-staff', version: '0.1.0', mode: config.STAFF_RUNTIME_MODE })); app.get('/openapi.json', async () => app.swagger()); app.get('/', async (_request, reply) => reply.type('text/html').send('Krona Staff

Krona Staff

Архитектурная основа модуля. Предметные функции ожидают требований владельца.

')); app.addHook('onClose', async () => database.close()); return app; }