import fs from 'node:fs'; import path from 'node:path'; import { randomBytes } from 'node:crypto'; import { spawnSync } from 'node:child_process'; import { root } from './server.mjs'; const envPath = path.join(root, '.env'); const command = process.argv[2] || 'up'; if (!['up', 'status', 'stop'].includes(command)) throw new Error('Use db.mjs up | status | stop'); function addLocalValue(key, value) { if (process.env[key]) return; const contents = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : ''; // An explicit existing setting is owned by the user, even if left empty. if (new RegExp(`^${key}=`, 'm').test(contents)) throw new Error(`${key} is empty in .env; complete the local database configuration.`); fs.appendFileSync(envPath, `${contents && !contents.endsWith('\n') ? '\n' : ''}${key}=${value}\n`, { mode: 0o600 }); process.env[key] = value; } if (command === 'up') { addLocalValue('ASSISTANT_POSTGRES_PASSWORD', randomBytes(32).toString('hex')); addLocalValue('ASSISTANT_POSTGRES_PORT', '55432'); const base = `postgresql://assistant:${encodeURIComponent(process.env.ASSISTANT_POSTGRES_PASSWORD)}@127.0.0.1:${process.env.ASSISTANT_POSTGRES_PORT}`; addLocalValue('ASSISTANT_DATABASE_URL', `${base}/assistant_learning`); addLocalValue('ASSISTANT_DATABASE_SCHEMA', 'assistant_learning'); addLocalValue('ASSISTANT_RETRIEVAL_DATABASE_URL', `${base}/assistant_retrieval`); addLocalValue('ASSISTANT_TEST_DATABASE_URL', `${base}/assistant_learning_test`); addLocalValue('ASSISTANT_BROWSER_CHANNEL', process.platform === 'win32' ? 'msedge' : 'chromium'); } const args = ['compose', '--progress', 'quiet', '--project-directory', root, '--file', path.join(root, 'compose.yaml')]; args.push(...(command === 'up' ? ['up', '-d', '--wait', '--wait-timeout', '120'] : command === 'stop' ? ['stop'] : ['ps'])); const result = spawnSync('docker', args, { cwd: root, env: process.env, stdio: 'inherit', windowsHide: true }); if (result.error) throw new Error('Docker CLI is unavailable; install and start Docker Desktop.'); process.exitCode = result.status ?? 1; if (process.exitCode === 0 && command === 'up') console.log('Assistant PostgreSQL is ready. Local connection settings are saved in the ignored .env file.');