feat(api): integrate Prisma client with /db/health endpoint
- Add @ketopath/db and fastify-plugin to apps/api - prismaPlugin decorates the Fastify instance with prisma and disconnects on app close, with FastifyInstance type augmented in src/types/fastify.d.ts - DATABASE_URL is now required by env validation - New module modules/db with GET /db/health running SELECT 1 via Prisma - dev script switched to tsx --env-file=.env for env loading Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
d309d06970
commit
72d47da453
8 files changed
+40
-3
No files matched your search
@@ -6,5 +6,4 @@ LOG_LEVEL=info
|
|||||||
# CORS — origini consentite (separate da virgola)
|
# CORS — origini consentite (separate da virgola)
|
||||||
CORS_ORIGINS=http://localhost:3000
|
CORS_ORIGINS=http://localhost:3000
|
||||||
|
|
||||||
# Database (configurato in step successivo con Prisma)
|
DATABASE_URL=postgresql://luciano:luciano%40@localhost:5432/ketopath?schema=public
|
||||||
# DATABASE_URL=postgresql://user:password@localhost:5432/ketopath
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsx watch src/server.ts",
|
"dev": "tsx watch --env-file=.env src/server.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "node dist/server.js",
|
"start": "node dist/server.js",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
@@ -15,8 +15,10 @@
|
|||||||
"@fastify/helmet": "^11.1.1",
|
"@fastify/helmet": "^11.1.1",
|
||||||
"@fastify/rate-limit": "^9.1.0",
|
"@fastify/rate-limit": "^9.1.0",
|
||||||
"@fastify/sensible": "^5.6.0",
|
"@fastify/sensible": "^5.6.0",
|
||||||
|
"@ketopath/db": "workspace:*",
|
||||||
"@ketopath/shared": "workspace:*",
|
"@ketopath/shared": "workspace:*",
|
||||||
"fastify": "^4.28.1",
|
"fastify": "^4.28.1",
|
||||||
|
"fastify-plugin": "^4.5.1",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import sensible from '@fastify/sensible';
|
|||||||
import Fastify, { type FastifyInstance } from 'fastify';
|
import Fastify, { type FastifyInstance } from 'fastify';
|
||||||
|
|
||||||
import { env } from './config/env.js';
|
import { env } from './config/env.js';
|
||||||
|
import { dbRoutes } from './modules/db/db.routes.js';
|
||||||
import { healthRoutes } from './modules/health/health.routes.js';
|
import { healthRoutes } from './modules/health/health.routes.js';
|
||||||
|
import { prismaPlugin } from './plugins/prisma.js';
|
||||||
|
|
||||||
export async function buildApp(): Promise<FastifyInstance> {
|
export async function buildApp(): Promise<FastifyInstance> {
|
||||||
const app = Fastify({
|
const app = Fastify({
|
||||||
@@ -33,8 +35,10 @@ export async function buildApp(): Promise<FastifyInstance> {
|
|||||||
timeWindow: '1 minute',
|
timeWindow: '1 minute',
|
||||||
});
|
});
|
||||||
await app.register(sensible);
|
await app.register(sensible);
|
||||||
|
await app.register(prismaPlugin);
|
||||||
|
|
||||||
await app.register(healthRoutes);
|
await app.register(healthRoutes);
|
||||||
|
await app.register(dbRoutes);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@ const envSchema = z.object({
|
|||||||
.map((origin) => origin.trim())
|
.map((origin) => origin.trim())
|
||||||
.filter(Boolean),
|
.filter(Boolean),
|
||||||
),
|
),
|
||||||
|
DATABASE_URL: z.string().url(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type Env = z.infer<typeof envSchema>;
|
export type Env = z.infer<typeof envSchema>;
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import type { FastifyPluginAsync } from 'fastify';
|
||||||
|
|
||||||
|
export const dbRoutes: FastifyPluginAsync = async (fastify) => {
|
||||||
|
fastify.get('/db/health', async (_request, reply) => {
|
||||||
|
try {
|
||||||
|
await fastify.prisma.$queryRaw`SELECT 1`;
|
||||||
|
return { status: 'ok', database: 'reachable' };
|
||||||
|
} catch (err) {
|
||||||
|
fastify.log.error({ err }, 'database health check failed');
|
||||||
|
return reply.code(503).send({ status: 'error', database: 'unreachable' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { prisma } from '@ketopath/db';
|
||||||
|
import fp from 'fastify-plugin';
|
||||||
|
|
||||||
|
export const prismaPlugin = fp(async (app) => {
|
||||||
|
await prisma.$connect();
|
||||||
|
app.decorate('prisma', prisma);
|
||||||
|
|
||||||
|
app.addHook('onClose', async () => {
|
||||||
|
await prisma.$disconnect();
|
||||||
|
});
|
||||||
|
});
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
import type { prisma } from '@ketopath/db';
|
||||||
|
|
||||||
|
declare module 'fastify' {
|
||||||
|
interface FastifyInstance {
|
||||||
|
prisma: typeof prisma;
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
BIN
Binary file not shown.
Reference in new issue
Block a user