diff --git a/app/server.ts b/app/server.ts index 0c291b41..650b4837 100644 --- a/app/server.ts +++ b/app/server.ts @@ -1,24 +1,16 @@ -import * as schema from "./server/db/schema"; -import { setSchema, runDbMigrations } from "./server/db/db"; -import { startup } from "./server/modules/lifecycle/startup"; import { logger } from "./server/utils/logger"; import { shutdown } from "./server/modules/lifecycle/shutdown"; import { runCLI } from "./server/cli"; -import { runMigrations } from "./server/modules/lifecycle/migrations"; +import { bootstrapApplication } from "./server/modules/lifecycle/bootstrap"; import { createStartHandler, defaultStreamHandler, defineHandlerCallback } from "@tanstack/react-start/server"; import { createServerEntry } from "@tanstack/react-start/server-entry"; -setSchema(schema); - const cliRun = await runCLI(Bun.argv); if (cliRun) { process.exit(0); } -runDbMigrations(); - -await runMigrations(); -await startup(); +await bootstrapApplication(); const customHandler = defineHandlerCallback((ctx) => { return defaultStreamHandler(ctx); diff --git a/app/server/modules/lifecycle/bootstrap.ts b/app/server/modules/lifecycle/bootstrap.ts new file mode 100644 index 00000000..529b4cc8 --- /dev/null +++ b/app/server/modules/lifecycle/bootstrap.ts @@ -0,0 +1,26 @@ +import * as schema from "../../db/schema"; +import { runDbMigrations, setSchema } from "../../db/db"; +import { runMigrations } from "./migrations"; +import { startup } from "./startup"; + +let bootstrapPromise: Promise | undefined; + +const runBootstrap = async () => { + setSchema(schema); + runDbMigrations(); + await runMigrations(); + await startup(); +}; + +export const bootstrapApplication = async () => { + if (!bootstrapPromise) { + bootstrapPromise = runBootstrap(); + } + + try { + await bootstrapPromise; + } catch (err) { + bootstrapPromise = undefined; + throw err; + } +}; diff --git a/app/server/plugins/bootstrap.ts b/app/server/plugins/bootstrap.ts new file mode 100644 index 00000000..b07b1df5 --- /dev/null +++ b/app/server/plugins/bootstrap.ts @@ -0,0 +1,11 @@ +import { definePlugin } from "nitro"; +import { bootstrapApplication } from "../modules/lifecycle/bootstrap"; +import { logger } from "../utils/logger"; +import { toMessage } from "../utils/errors"; + +export default definePlugin(() => { + void bootstrapApplication().catch((err) => { + logger.error(`Bootstrap failed: ${toMessage(err)}`); + process.exit(1); + }); +}); diff --git a/vite.config.ts b/vite.config.ts index 6abc6502..e4e0a2de 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -14,7 +14,10 @@ export default defineConfig({ routesDirectory: "routes", }, }), - nitro({ preset: "bun" }), + nitro({ + preset: "bun", + plugins: ["./app/server/plugins/bootstrap.ts"], + }), viteReact({ babel: { plugins: ["babel-plugin-react-compiler"],