import { readFileSync, existsSync } from 'node:fs' import { resolve } from 'node:path' import { buildApp } from './app.js' import { loadConfig } from './config.js' import { registerShutdown } from './lib/shutdown.js' for (const path of [ resolve(import.meta.dirname, '../../../.env'), '.env', '../.env', ]) { if (!existsSync(path)) continue const content = readFileSync(path, 'utf-8') for (const line of content.split('\n')) { const trimmed = line.trim() if (!trimmed || trimmed.startsWith('#')) continue const eq = trimmed.indexOf('=') if (eq === -1) continue const key = trimmed.slice(0, eq).trim() let value = trimmed.slice(eq + 1).trim() if ( (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")) ) { value = value.slice(1, -1) } if (!(key in process.env)) process.env[key] = value } break } const config = loadConfig() // `node dist/server.js backup` — разовый онлайн-бэкап без запуска сервера // (для cron / `docker exec auth-portal node dist/server.js backup`). if (process.argv[2] === 'backup') { const { createDb, closeDb } = await import('@authportal/db') const { runBackup } = await import('./services/backup.js') const { sqlite } = createDb(config.databaseUrl) try { const res = await runBackup(sqlite, config) console.log(`backup ok: ${res.file} (removed ${res.removed.length} old)`) closeDb(sqlite) process.exit(0) } catch (err) { console.error('backup failed:', err) process.exit(1) } } const app = await buildApp({ config }) registerShutdown(app, { timeoutMs: config.shutdownTimeoutMs }) try { await app.listen({ port: config.serverPort, host: '0.0.0.0' }) app.log.info(`auth-portal listening on ${config.serverPort}`) } catch (err) { app.log.error(err) process.exit(1) }