Files
hermes-agent/apps/desktop/scripts/ensure-rolldown-binding.mjs
teknium1 3dcf0d49ad fix(install): let Rolldown name the missing binding; repair on every OS
The first cut derived the package from `binding-${platform}-${arch}` with an
exact-suffix match, which never matches Windows (`-msvc`) or Linux
(`-gnu`/`-musl`) names, so the repair only ever worked on macOS and
install.sh had to gate it there. Rolldown's own loader already resolves
platform, arch and libc and prints the exact `@rolldown/binding-*` it wanted
in its error chain; parse that instead and drop the gate. Also spawn npm
through a shell on Windows (Node refuses to spawn npm.cmd directly) and trim
the tests to the two invariants (no-op when it loads; installs exactly what
the loader asked for, then re-probes).
2026-09-17 00:25:57 -07:00

72 lines
2.5 KiB
JavaScript

import { existsSync, readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { spawnSync } from 'node:child_process'
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', '..')
// Rolldown's loader already resolves platform, arch and libc; when the native
// package is absent, its load-error chain names the exact `@rolldown/binding-*`
// it wanted, followed by the wasm fallback it also tried. Reuse that verdict
// instead of re-deriving it from `process.platform` (Windows bindings carry a
// `-msvc` suffix, Linux ones `-gnu`/`-musl`).
export function missingRolldownBinding(stderr) {
const names = [...String(stderr ?? '').matchAll(/@rolldown\/binding-[a-z0-9-]+/g)].map(m => m[0])
return names.find(name => !name.includes('wasm32')) ?? null
}
function probeRolldown(root) {
return spawnSync(process.execPath, ['--input-type=module', '--eval', "await import('rolldown')"], {
cwd: root,
encoding: 'utf8'
})
}
function installBinding(root, spec) {
// npm.cmd needs a shell on Windows (Node refuses to spawn .cmd directly).
return spawnSync('npm', ['install', '--no-save', '--package-lock=false', '--include=optional', spec], {
cwd: root,
stdio: 'inherit',
shell: process.platform === 'win32'
})
}
function installedRolldownVersion(root) {
const packagePath = [
join(root, 'node_modules', 'rolldown', 'package.json'),
join(root, 'apps', 'desktop', 'node_modules', 'rolldown', 'package.json')
].find(existsSync)
return packagePath ? JSON.parse(readFileSync(packagePath, 'utf8')).version : null
}
export function ensureRolldownBinding({
root = rootDir,
probe = probeRolldown,
install = installBinding,
rolldownVersion = installedRolldownVersion
} = {}) {
const initial = probe(root)
if (initial.status === 0) return true
const name = missingRolldownBinding(initial.stderr)
const version = rolldownVersion(root)
if (!name || !version) {
console.error(initial.stderr?.trim() || 'Rolldown could not load.')
return false
}
console.warn(`Rolldown could not load; installing ${name}@${version}...`)
if (install(root, `${name}@${version}`).status !== 0) return false
const repaired = probe(root)
if (repaired.status !== 0) {
console.error(repaired.stderr?.trim() || `Rolldown still cannot load after installing ${name}.`)
return false
}
return true
}
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
process.exitCode = ensureRolldownBinding() ? 0 : 1
}