singularity-forge/scripts/postinstall.js

96 lines
3.6 KiB
JavaScript

#!/usr/bin/env node
import { exec as execCb } from 'child_process'
import { createRequire } from 'module'
import os from 'os'
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
const __dirname = dirname(fileURLToPath(import.meta.url))
const require = createRequire(import.meta.url)
const pkg = require(resolve(__dirname, '..', 'package.json'))
const cwd = resolve(__dirname, '..')
// ---------------------------------------------------------------------------
// Async exec helper — captures stdout+stderr, never inherits to terminal
// ---------------------------------------------------------------------------
function run(cmd, options = {}) {
return new Promise((resolve) => {
execCb(cmd, { cwd, ...options }, (error, stdout, stderr) => {
resolve({ ok: !error, stdout, stderr, error })
})
})
}
// ---------------------------------------------------------------------------
// Redirect stdout → stderr so npm always shows postinstall output.
// npm ≥7 suppresses stdout from lifecycle scripts by default; stderr is
// always forwarded. Clack writes to process.stdout, so we reroute it.
// ---------------------------------------------------------------------------
process.stdout.write = process.stderr.write.bind(process.stderr)
// ---------------------------------------------------------------------------
// Main — wrapped in async IIFE, with graceful fallback if clack fails
// ---------------------------------------------------------------------------
;(async () => {
let p, pc
try {
p = await import('@clack/prompts')
pc = (await import('picocolors')).default
} catch {
// Clack or picocolors unavailable — fall back to minimal output
process.stderr.write(`\n GSD v${pkg.version} installed.\n Run gsd to get started.\n\n`)
await run('npx patch-package')
const args = os.platform() === 'linux' ? '--with-deps' : ''
await run(`npx playwright install chromium ${args}`)
return
}
// --- Branded intro -------------------------------------------------------
p.intro(pc.bgCyan(pc.black(' gsd ')) + ' ' + pc.dim(`v${pkg.version}`))
const results = []
const s = p.spinner()
// --- Step 1: Apply patches -----------------------------------------------
s.start('Applying patches…')
const patchResult = await run('npx patch-package')
if (patchResult.ok) {
s.stop('Patches applied')
results.push({ label: 'Patches applied', ok: true })
} else {
s.stop(pc.yellow('Patches — skipped (non-fatal)'))
results.push({
label: 'Patches skipped — run ' + pc.cyan('npx patch-package') + ' manually',
ok: false,
})
}
// --- Step 2: Playwright browser ------------------------------------------
s.start('Setting up browser tools…')
const pwArgs = os.platform() === 'linux' ? ' --with-deps' : ''
const pwResult = await run(`npx playwright install chromium${pwArgs}`)
if (pwResult.ok) {
s.stop('Browser tools ready')
results.push({ label: 'Browser tools ready', ok: true })
} else {
s.stop(pc.yellow('Browser tools — skipped (non-fatal)'))
results.push({
label: 'Browser tools unavailable — run ' + pc.cyan('npx playwright install chromium'),
ok: false,
})
}
// --- Summary note --------------------------------------------------------
const lines = results.map(
(r) => (r.ok ? pc.green('✓') : pc.yellow('⚠')) + ' ' + r.label
)
lines.push('')
lines.push('Run ' + pc.cyan('gsd') + ' to get started.')
p.note(lines.join('\n'), 'Installed')
// --- Outro ---------------------------------------------------------------
p.outro(pc.green('Done!'))
})()