From 706dda5defacedff25cd01481fe15a883ac19344 Mon Sep 17 00:00:00 2001 From: artbiit Date: Tue, 21 Apr 2026 11:35:18 +0900 Subject: [PATCH] refactor: improve environment configuration resolution and centralize Prisma instance management --- apps/bot/scratch_debug_env.js | 10 ++++++++++ apps/bot/src/config/env.ts | 16 ++++++++++++++-- apps/bot/src/database/index.ts | 8 ++++++++ apps/bot/src/events/ready.ts | 3 ++- apps/bot/src/services/FishingService.ts | 12 ++++++++++++ packages/db/index.ts | 4 +++- 6 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 apps/bot/scratch_debug_env.js diff --git a/apps/bot/scratch_debug_env.js b/apps/bot/scratch_debug_env.js new file mode 100644 index 0000000..8c3850b --- /dev/null +++ b/apps/bot/scratch_debug_env.js @@ -0,0 +1,10 @@ +const path = require('path'); +console.log('CWD:', process.cwd()); +console.log('__dirname:', __dirname); +console.log('.env path:', path.resolve(process.cwd(), '.env')); +const fs = require('fs'); +console.log('.env exists in CWD?', fs.existsSync(path.resolve(process.cwd(), '.env'))); +console.log('.env exists in root?', fs.existsSync(path.resolve(process.cwd(), '../../.env'))); + +require('dotenv').config({ path: path.resolve(process.cwd(), '../../.env') }); +console.log('DATABASE_URL from ../../.env:', process.env.DATABASE_URL); diff --git a/apps/bot/src/config/env.ts b/apps/bot/src/config/env.ts index 046a3cf..57184a1 100644 --- a/apps/bot/src/config/env.ts +++ b/apps/bot/src/config/env.ts @@ -1,9 +1,21 @@ import { config } from 'dotenv'; +import { existsSync } from 'fs'; import { hostname } from 'os'; import { resolve } from 'path'; -// Prefer systemd/cron-set DOTENV_CONFIG_PATH; otherwise cwd .env (default dotenv behavior). -config({ path: process.env.DOTENV_CONFIG_PATH || resolve(process.cwd(), '.env') }); +const getEnvPath = () => { + if (process.env.DOTENV_CONFIG_PATH) return process.env.DOTENV_CONFIG_PATH; + + const localEnv = resolve(process.cwd(), '.env'); + if (existsSync(localEnv)) return localEnv; + + const rootEnv = resolve(process.cwd(), '../../.env'); + if (existsSync(rootEnv)) return rootEnv; + + return localEnv; +}; + +config({ path: getEnvPath() }); const generateInstanceId = () => { return process.env.INSTANCE_ID || hostname() || `kord-${Math.random().toString(36).substring(2, 7)}`; diff --git a/apps/bot/src/database/index.ts b/apps/bot/src/database/index.ts index 2bc929b..be52342 100644 --- a/apps/bot/src/database/index.ts +++ b/apps/bot/src/database/index.ts @@ -38,6 +38,11 @@ export const prisma = new PrismaClient({ }); export const connectDB = async () => { + if (!env.DATABASE_URL) { + logger.error('DATABASE_URL is not set. Please check your .env file.'); + process.exit(1); + } + try { // Adapter-based client connects when first used, // but we can test the pool connection here. @@ -46,6 +51,9 @@ export const connectDB = async () => { logger.info('Connected to PostgreSQL successfully via Driver Adapter.'); } catch (error) { logger.error('Failed to connect to PostgreSQL:', error); + if (error instanceof Error && error.message.includes('password')) { + logger.error('Database authentication failed. Please check your DATABASE_URL password.'); + } process.exit(1); } }; diff --git a/apps/bot/src/events/ready.ts b/apps/bot/src/events/ready.ts index ca5feeb..b137410 100644 --- a/apps/bot/src/events/ready.ts +++ b/apps/bot/src/events/ready.ts @@ -8,7 +8,8 @@ import { auditLogService } from '../services/AuditLogService'; import { env } from '../config/env'; -import { PrismaShardStatusRepository, prisma } from '@kord/db'; +import { PrismaShardStatusRepository } from '@kord/db'; +import { prisma } from '../database'; export default { name: Events.ClientReady, once: true, diff --git a/apps/bot/src/services/FishingService.ts b/apps/bot/src/services/FishingService.ts index 2cca4f8..f924f2f 100644 --- a/apps/bot/src/services/FishingService.ts +++ b/apps/bot/src/services/FishingService.ts @@ -787,6 +787,18 @@ export class FishingService { } private static resolveResourcePath(relativePath: string) { + // Current file: apps/bot/src/services/FishingService.ts + // 1:src/services, 2:src, 3:bot, 4:apps, 5:root + // After re-evaluating: + // apps/bot/src/services -> .. -> src -> .. -> bot -> .. -> apps -> .. -> root (Total 4 levels) + const rootPath = path.resolve(__dirname, '..', '..', '..', '..'); + const candidatePath = path.resolve(rootPath, relativePath); + + if (fs.existsSync(candidatePath)) { + return candidatePath; + } + + // Fallback to local if root doesn't have it (unlikely in this monorepo) return path.resolve(__dirname, '..', '..', relativePath); } diff --git a/packages/db/index.ts b/packages/db/index.ts index fa3ca67..267cc30 100644 --- a/packages/db/index.ts +++ b/packages/db/index.ts @@ -1,6 +1,8 @@ import { PrismaClient, ShardStatus } from '@prisma/client'; -export const prisma = new PrismaClient(); +// We no longer export a default prisma instance here to avoid initialization conflicts. +// Consumers should provide their own configured PrismaClient instance. +// export const prisma = new PrismaClient(); export * from '@prisma/client';