diff --git a/docker-compose.yml b/docker-compose.yml index 3509315..34c139d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,6 @@ services: app: - build: - context: . - dockerfile: Dockerfile - image: dndextended:latest + build: . container_name: dndextended-app restart: unless-stopped ports: diff --git a/src/lib/mongodb.ts b/src/lib/mongodb.ts index 800c694..58af9f6 100644 --- a/src/lib/mongodb.ts +++ b/src/lib/mongodb.ts @@ -1,23 +1,42 @@ import { MongoClient } from "mongodb"; -const uri = process.env.MONGODB_URI!; -const options = {}; +/** + * Lazy MongoClient promise. We don't touch `process.env.MONGODB_URI` at module + * import time so `next build` / page-data collection doesn't crash when the env + * isn't populated (e.g. inside a Docker build with no runtime env). + */ -let client: MongoClient; -let clientPromise: Promise; - -if (process.env.NODE_ENV === "development") { - const globalWithMongo = global as typeof globalThis & { - _mongoClientPromise?: Promise; - }; - if (!globalWithMongo._mongoClientPromise) { - client = new MongoClient(uri, options); - globalWithMongo._mongoClientPromise = client.connect(); - } - clientPromise = globalWithMongo._mongoClientPromise; -} else { - client = new MongoClient(uri, options); - clientPromise = client.connect(); +declare global { + var _mongoClientPromise: Promise | undefined; } +function createClientPromise(): Promise { + const uri = process.env.MONGODB_URI; + if (!uri) { + throw new Error("MONGODB_URI is not set"); + } + const client = new MongoClient(uri, {}); + return client.connect(); +} + +function getClientPromise(): Promise { + if (process.env.NODE_ENV === "development") { + if (!globalThis._mongoClientPromise) { + globalThis._mongoClientPromise = createClientPromise(); + } + return globalThis._mongoClientPromise; + } + if (!globalThis._mongoClientPromise) { + globalThis._mongoClientPromise = createClientPromise(); + } + return globalThis._mongoClientPromise; +} + +const clientPromise: Promise = { + then: (onFulfilled, onRejected) => getClientPromise().then(onFulfilled, onRejected), + catch: (onRejected) => getClientPromise().catch(onRejected), + finally: (onFinally) => getClientPromise().finally(onFinally), + [Symbol.toStringTag]: "Promise", +} as Promise; + export default clientPromise;