krona-staff/src/app.ts

25 lines
2.2 KiB
TypeScript

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('<!doctype html><html lang="ru"><meta charset="utf-8"><title>Krona Staff</title><body><main><h1>Krona Staff</h1><p>Архитектурная основа модуля. Предметные функции ожидают требований владельца.</p><nav><a href="/openapi.json">OpenAPI</a> · <a href="/live">Live</a> · <a href="/ready">Ready</a> · <a href="/version">Version</a></nav></main></body></html>'));
app.addHook('onClose', async () => database.close());
return app;
}