#!/usr/bin/env bun // scripts/postinstall.ts // // Postinstall hook: after `bun install`, apply any pending schema migrations so // a freshly-installed gbrain is immediately usable. Wired via package.json // ("postinstall": "bun run scripts/postinstall.ts") as a real Bun script rather // than an inline `node -e` one-liner. // // Why a script file and not an inline command: // Embedding a program inside the package.json postinstall string lets the // lifecycle shell mangle it. Bun's Windows script-runner expands `\n` in the // hint string into a REAL newline before node sees it, producing // `SyntaxError: Invalid or unexpected token` and aborting the whole install. // `node` is also not guaranteed present under a Bun install (bun is the // guaranteed runtime), and `shell: win32` re-opens a quoting surface. A // checked-in .ts run by `bun run` sidesteps all three. // // Uses Bun APIs only — `which()` for Windows-aware PATH resolution (finds // gbrain.exe / gbrain.cmd) and an argv-array `Bun.spawnSync` (no shell, nothing // to quote). It NEVER fails the install: every path exits 0. import { which } from 'bun'; const HINT = '[gbrain] postinstall skipped. If installed via bun install -g github:...: ' + 'run `gbrain doctor` and `gbrain apply-migrations --yes` manually. ' + 'See https://github.com/garrytan/gbrain/issues/218'; // Windows-aware PATH resolution — finds gbrain, gbrain.exe or gbrain.cmd. const bin = which('gbrain'); if (!bin) { // Fresh clone / global install where gbrain isn't on PATH yet: skip cleanly. console.error(HINT); process.exit(0); } try { const r = Bun.spawnSync({ cmd: [bin, 'apply-migrations', '--yes', '--non-interactive'], stdout: 'inherit', stderr: 'inherit', }); if (r.exitCode !== 0) console.error(HINT); } catch { console.error(HINT); } process.exit(0); // never abort the install