diff --git a/apps/cli/templates/backend/server/elysia/src/index.ts.hbs b/apps/cli/templates/backend/server/elysia/src/index.ts.hbs index 21b1fef05..324fad646 100644 --- a/apps/cli/templates/backend/server/elysia/src/index.ts.hbs +++ b/apps/cli/templates/backend/server/elysia/src/index.ts.hbs @@ -25,6 +25,7 @@ import { createContext } from "./lib/context"; {{#if (eq auth "better-auth")}} import { auth } from "./lib/auth"; {{/if}} +import { checkDatabaseHealth } from "./lib/health"; {{#if (eq api "orpc")}} const rpcHandler = new RPCHandler(appRouter, { @@ -111,7 +112,11 @@ const app = new Elysia() return result.toUIMessageStreamResponse(); }) {{/if}} - .get("/", () => "OK") + .get("/", async ({ set }) => { + const health = await checkDatabaseHealth(); + if (health.error) set.status = 500; + return health; + }) .listen(3000, () => { console.log("Server is running on http://localhost:3000"); }); diff --git a/apps/cli/templates/backend/server/express/src/index.ts.hbs b/apps/cli/templates/backend/server/express/src/index.ts.hbs index 43cfa74f4..e3be030c2 100644 --- a/apps/cli/templates/backend/server/express/src/index.ts.hbs +++ b/apps/cli/templates/backend/server/express/src/index.ts.hbs @@ -25,6 +25,7 @@ import { google } from "@ai-sdk/google"; import { auth } from "./lib/auth"; import { toNodeHandler } from "better-auth/node"; {{/if}} +import { checkDatabaseHealth } from "./lib/health"; const app = express(); @@ -112,8 +113,10 @@ app.post("/ai", async (req, res) => { }); {{/if}} -app.get("/", (_req, res) => { - res.status(200).send("OK"); +app.get("/", async (_req, res) => { + const health = await checkDatabaseHealth(); + const status = health.error ? 500 : 200; + res.status(status).json(health); }); const port = process.env.PORT || 3000; diff --git a/apps/cli/templates/backend/server/fastify/src/index.ts.hbs b/apps/cli/templates/backend/server/fastify/src/index.ts.hbs index 79c88c19f..eca09f52e 100644 --- a/apps/cli/templates/backend/server/fastify/src/index.ts.hbs +++ b/apps/cli/templates/backend/server/fastify/src/index.ts.hbs @@ -30,6 +30,7 @@ import { google } from "@ai-sdk/google"; {{#if (eq auth "better-auth")}} import { auth } from "./lib/auth"; {{/if}} +import { checkDatabaseHealth } from "./lib/health"; const baseCorsConfig = { origin: process.env.CORS_ORIGIN || "", @@ -169,8 +170,12 @@ fastify.post('/ai', async function (request) { }); {{/if}} -fastify.get('/', async () => { - return 'OK'; +fastify.get('/', async (request, reply) => { + const health = await checkDatabaseHealth(); + if (health.error) { + reply.status(500); + } + return health; }); fastify.listen({ port: 3000 }, (err) => { diff --git a/apps/cli/templates/backend/server/hono/src/index.ts.hbs b/apps/cli/templates/backend/server/hono/src/index.ts.hbs index a5392a8d7..70aa32881 100644 --- a/apps/cli/templates/backend/server/hono/src/index.ts.hbs +++ b/apps/cli/templates/backend/server/hono/src/index.ts.hbs @@ -21,6 +21,7 @@ import { appRouter } from "./routers/index"; {{#if (eq auth "better-auth")}} import { auth } from "./lib/auth"; {{/if}} +import { checkDatabaseHealth } from "./lib/health"; import { Hono } from "hono"; import { cors } from "hono/cors"; import { logger } from "hono/logger"; @@ -145,8 +146,10 @@ app.post("/ai", async (c) => { }); {{/if}} -app.get("/", (c) => { - return c.text("OK"); +app.get("/", async (c) => { + const health = await checkDatabaseHealth(); + const status = health.error ? 500 : 200; + return c.json(health, status); }); {{#if (eq runtime "node")}} diff --git a/apps/cli/templates/backend/server/next/src/app/route.ts b/apps/cli/templates/backend/server/next/src/app/route.ts index bed4f46b8..883c7b934 100644 --- a/apps/cli/templates/backend/server/next/src/app/route.ts +++ b/apps/cli/templates/backend/server/next/src/app/route.ts @@ -1,5 +1,8 @@ import { NextResponse } from "next/server"; +import { checkDatabaseHealth } from "../lib/health"; export async function GET() { - return NextResponse.json({ message: "OK" }); + const health = await checkDatabaseHealth(); + const status = health.error ? 500 : 200; + return NextResponse.json(health, { status }); } diff --git a/apps/cli/templates/backend/server/next/src/lib/health.ts.hbs b/apps/cli/templates/backend/server/next/src/lib/health.ts.hbs new file mode 100644 index 000000000..48e7ee177 --- /dev/null +++ b/apps/cli/templates/backend/server/next/src/lib/health.ts.hbs @@ -0,0 +1,41 @@ +{{#if orm}} +{{#if (eq orm "drizzle")}} +import { db } from "../../db"; +{{/if}} +{{#if (eq orm "prisma")}} +import prisma from "../../db"; +{{/if}} +{{#if (eq orm "mongoose")}} +import { client } from "../../db"; +{{/if}} + +export async function checkDatabaseHealth(): Promise<{ status: string; database: string; error?: string }> { + try { + {{#if (eq orm "drizzle")}} + {{#if (eq database "sqlite")}} + await db.get("SELECT 1"); + {{else if (eq database "postgres")}} + await db.execute("SELECT 1"); + {{else if (eq database "mysql")}} + await db.execute("SELECT 1"); + {{/if}} + {{else if (eq orm "prisma")}} + await prisma.$queryRaw`SELECT 1`; + {{else if (eq orm "mongoose")}} + await client.admin().ping(); + {{/if}} + return { status: "OK", database: "connected" }; + } catch (error) { + console.error("Database connection error:", error); + return { + status: "OK", + database: "disconnected", + error: error instanceof Error ? error.message : String(error) + }; + } +} +{{else}} +export async function checkDatabaseHealth(): Promise<{ status: string; database: string }> { + return { status: "OK", database: "none" }; +} +{{/if}} \ No newline at end of file diff --git a/apps/cli/templates/backend/server/server-base/src/lib/health.ts.hbs b/apps/cli/templates/backend/server/server-base/src/lib/health.ts.hbs new file mode 100644 index 000000000..046dc59d9 --- /dev/null +++ b/apps/cli/templates/backend/server/server-base/src/lib/health.ts.hbs @@ -0,0 +1,41 @@ +{{#if orm}} +{{#if (eq orm "drizzle")}} +import { db } from "../db"; +{{/if}} +{{#if (eq orm "prisma")}} +import prisma from "../db"; +{{/if}} +{{#if (eq orm "mongoose")}} +import { client } from "../db"; +{{/if}} + +export async function checkDatabaseHealth(): Promise<{ status: string; database: string; error?: string }> { + try { + {{#if (eq orm "drizzle")}} + {{#if (eq database "sqlite")}} + await db.get("SELECT 1"); + {{else if (eq database "postgres")}} + await db.execute("SELECT 1"); + {{else if (eq database "mysql")}} + await db.execute("SELECT 1"); + {{/if}} + {{else if (eq orm "prisma")}} + await prisma.$queryRaw`SELECT 1`; + {{else if (eq orm "mongoose")}} + await client.admin().ping(); + {{/if}} + return { status: "OK", database: "connected" }; + } catch (error) { + console.error("Database connection error:", error); + return { + status: "OK", + database: "disconnected", + error: error instanceof Error ? error.message : String(error) + }; + } +} +{{else}} +export async function checkDatabaseHealth(): Promise<{ status: string; database: string }> { + return { status: "OK", database: "none" }; +} +{{/if}} \ No newline at end of file