import { execFileSync } from 'child_process'; const BW = 'bw'; const ORG_ID = '4bd75130-b4d3-48d4-a4cb-e52b70295a51'; const AI_COLLECTION = '5be27a82-8475-4c38-96b2-fa94ec8c957b'; let _session = null; function bwEnv() { const env = { ...process.env }; for (const k of ['HTTPS_PROXY','HTTP_PROXY','ALL_PROXY','https_proxy','http_proxy','all_proxy']) delete env[k]; env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; return env; } function run(args, input) { return execFileSync(BW, args, { env: bwEnv(), encoding: 'utf8', input, stdio: input ? ['pipe','pipe','pipe'] : ['ignore','pipe','pipe'], }).trim(); } export async function initVaultwarden() { const email = process.env.BW_EMAIL || 'allogn@gmail.com'; const password = process.env.BW_PASSWORD; // Data dir is mounted from host — server already configured, skip bw config server let status = 'unauthenticated'; try { status = JSON.parse(run(['status'])).status; } catch {} if (status === 'unauthenticated') { run(['login', email, password, '--raw']); } _session = run(['unlock', password, '--raw']); run(['sync', '--session', _session]); console.log('Vaultwarden: ready'); } function session() { if (!_session) throw new Error('Vaultwarden not initialized'); return _session; } export function vwGetPassword(name) { return run(['get', 'password', name, '--session', session()]); } export function vwGetItem(name) { return JSON.parse(run(['get', 'item', name, '--session', session()])); } export function vwListItems(search) { const args = ['list', 'items', '--session', session()]; if (search) args.push('--search', search); return JSON.parse(run(args)); } export function vwListOrgItems(search) { const args = ['list', 'items', '--organizationid', ORG_ID, '--session', session()]; if (search) args.push('--search', search); return JSON.parse(run(args)); } export function vwCreateLogin({ name, username, password, url, notes }) { const item = { organizationId: ORG_ID, collectionIds: [AI_COLLECTION], folderId: null, type: 1, name, notes: notes || null, favorite: false, login: { username: username || null, password, uris: url ? [{ match: null, uri: url }] : [], }, }; const encoded = run(['encode'], JSON.stringify(item)); return JSON.parse(run(['create', 'item', encoded, '--session', session()])); } export function vwUpdatePassword(nameOrId, newPassword) { let item; try { item = JSON.parse(run(['get', 'item', nameOrId, '--session', session()])); } catch { const items = vwListOrgItems(nameOrId); item = items.find(i => i.name === nameOrId); if (!item) throw new Error(`Item not found: ${nameOrId}`); } item.login.password = newPassword; const encoded = run(['encode'], JSON.stringify(item)); return JSON.parse(run(['edit', 'item', item.id, encoded, '--session', session()])); }