first commit
This commit is contained in:
45
apps/backend/src/config/database.ts
Normal file
45
apps/backend/src/config/database.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { env } from './env.js';
|
||||
import { logger } from './logger.js';
|
||||
|
||||
export async function connectToDatabase(): Promise<void> {
|
||||
if (!env.MONGODB_URI) {
|
||||
logger.warn('Skipping MongoDB connection: MONGODB_URI is not set.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const connectionUri = env.MONGODB_URI;
|
||||
const options: mongoose.ConnectOptions = {};
|
||||
|
||||
if (env.MONGODB_DB) {
|
||||
options.dbName = env.MONGODB_DB;
|
||||
}
|
||||
|
||||
if (env.MONGODB_USER && env.MONGODB_PASS) {
|
||||
options.auth = {
|
||||
username: env.MONGODB_USER,
|
||||
password: env.MONGODB_PASS
|
||||
};
|
||||
options.authMechanism = 'SCRAM-SHA-256';
|
||||
}
|
||||
|
||||
if (env.MONGODB_AUTH_SOURCE) {
|
||||
options.authSource = env.MONGODB_AUTH_SOURCE;
|
||||
}
|
||||
|
||||
logger.info({ uri: connectionUri, db: options.dbName, authSource: options.authSource }, 'Attempting MongoDB connection');
|
||||
await mongoose.connect(connectionUri, options);
|
||||
logger.info('MongoDB connected');
|
||||
} catch (error) {
|
||||
logger.error({ error }, 'Failed to connect to MongoDB');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function disconnectFromDatabase(): Promise<void> {
|
||||
if (mongoose.connection.readyState !== 0) {
|
||||
await mongoose.disconnect();
|
||||
logger.info('MongoDB disconnected');
|
||||
}
|
||||
}
|
||||
45
apps/backend/src/config/env.ts
Normal file
45
apps/backend/src/config/env.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const DEFAULT_NOTIFICATION_PACKAGES = [
|
||||
'com.eg.android.AlipayGphone',
|
||||
'com.tencent.mm',
|
||||
'com.tencent.mobileqq',
|
||||
'com.google.android.gms',
|
||||
'com.android.mms'
|
||||
];
|
||||
|
||||
const envSchema = z
|
||||
.object({
|
||||
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
|
||||
PORT: z.coerce.number().default(3000),
|
||||
HOST: z.string().default('0.0.0.0'),
|
||||
MONGODB_URI: z.string().url().optional(),
|
||||
MONGODB_DB: z.string().optional(),
|
||||
MONGODB_USER: z.string().optional(),
|
||||
MONGODB_PASS: z.string().optional(),
|
||||
MONGODB_AUTH_SOURCE: z.string().optional(),
|
||||
JWT_SECRET: z.string().min(10).default('change-me-in-prod'),
|
||||
JWT_REFRESH_SECRET: z.string().min(10).optional(),
|
||||
NOTIFICATION_WEBHOOK_SECRET: z.string().min(10).optional(),
|
||||
NOTIFICATION_ALLOWED_PACKAGES: z.string().optional(),
|
||||
GEMINI_API_KEY: z.string().optional(),
|
||||
OCR_PROJECT_ID: z.string().optional(),
|
||||
FILE_STORAGE_BUCKET: z.string().optional()
|
||||
})
|
||||
.transform((values) => ({
|
||||
...values,
|
||||
isProduction: values.NODE_ENV === 'production',
|
||||
notificationPackageWhitelist: values.NOTIFICATION_ALLOWED_PACKAGES
|
||||
? values.NOTIFICATION_ALLOWED_PACKAGES.split(',').map((pkg) => pkg.trim()).filter(Boolean)
|
||||
: DEFAULT_NOTIFICATION_PACKAGES
|
||||
}));
|
||||
|
||||
const parsed = envSchema.safeParse(process.env);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error('❌ Invalid environment variables:', parsed.error.flatten().fieldErrors);
|
||||
throw new Error('Invalid environment configuration.');
|
||||
}
|
||||
|
||||
export const env = parsed.data;
|
||||
export type Env = typeof env;
|
||||
17
apps/backend/src/config/logger.ts
Normal file
17
apps/backend/src/config/logger.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import pino from 'pino';
|
||||
|
||||
const level = process.env.LOG_LEVEL ?? (process.env.NODE_ENV === 'production' ? 'info' : 'debug');
|
||||
|
||||
export const logger = pino({
|
||||
level,
|
||||
transport:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? undefined
|
||||
: {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
translateTime: 'SYS:standard',
|
||||
ignore: 'pid,hostname'
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user