/** * Seeder / host script logging: levels + optional NDJSON lines on stderr for tooling. * Avoids scattering raw console.log without structure. */ /** * @param {Record | null | undefined} env */ function wantJson(env) { const v = String(env?.BARE_OS_SEED_LOG_FORMAT ?? '').trim().toLowerCase() return v === 'json' || v === 'ndjson' } /** * @param {Record | undefined} detail */ function formatDetailForText(detail) { if (!detail || typeof detail !== 'object') return '' const parts = [] for (const [k, v] of Object.entries(detail)) { if (v === undefined) continue const s = v !== null && typeof v === 'object' ? JSON.stringify(v) : String(v) parts.push(`${k}=${s}`) } return parts.length ? ` — ${parts.join(', ')}` : '' } /** * @param {'info'|'warn'|'error'} level * @param {string} message * @param {Record} [detail] */ export function seedLog(level, message, detail = undefined) { const env = globalThis.process?.env const err = globalThis.process?.stderr if (wantJson(env) && err && typeof err.write === 'function') { err.write( `${JSON.stringify({ type: 'bare_os_seeder', level, message: String(message), detail: detail && typeof detail === 'object' ? detail : undefined, ts: Date.now() })}\n` ) return } const line = `[bare-os-seeder] ${level}: ${message}` + formatDetailForText(detail) if (level === 'error') { if (typeof console.error === 'function') console.error(line) else if (err && typeof err.write === 'function') err.write(`${line}\n`) return } if (level === 'warn') { if (typeof console.warn === 'function') console.warn(line) else if (err && typeof err.write === 'function') err.write(`${line}\n`) return } if (typeof console.log === 'function') console.log(line) else if (err && typeof err.write === 'function') err.write(`${line}\n`) }