// Stamp this build's version into a module the worklet can import.
//
// ⛔ WHY A GENERATED FILE. The packed bundle carries no readable package.json — measured: the name
// appears, no version string does — so a worklet has no way to say which build it is. Settings could
// show two tree hashes and nothing a person can compare against a release page, which is exactly the
// state that makes "is my update installed?" unanswerable from the device.
//
// ⚠ COMMITTED with whatever it last held, and regenerated by prebuild. A generated file that is not
// committed breaks a plain checkout on import; one that is never regenerated lies. Both are worse
// than a file that is occasionally one version stale in git and always correct in a build.
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..')
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'))
// ⛔ WHAT WENT IN, NOT JUST WHICH BUILD. Every sibling arrives as `file:../x`, so a bundle carries
// whatever was in that working tree at pack time — while the DESKTOP runs whatever was last
// published. Those two can drift by any amount and, until now, nothing recorded enough to notice:
// the stamp said 0.0.41 and nothing about which favela-surface was inside it.
//
// Measured 2026-09-15: desktop and phone happened to be identical (favela-surface 0.0.63, favela-peer
// 0.0.57) purely because of the order things were published that afternoon. A parity you cannot read
// off the device is a parity you are guessing at.
//
// ⚠ RESOLVED FROM THE SIBLING'S OWN package.json, never from the dependency RANGE — `file:../x` says
// nothing about the version and that is the whole problem. A sibling that cannot be read is recorded
// as null rather than omitted: "we could not tell" and "it is not there" are different answers.
const deps = {}
for (const [name, spec] of Object.entries(pkg.dependencies || {})) {
if (typeof spec !== 'string' || !spec.startsWith('file:')) continue
try {
const sib = JSON.parse(fs.readFileSync(path.join(root, spec.slice('file:'.length), 'package.json'), 'utf8'))
deps[name] = sib.version || null
} catch {
deps[name] = null
}
}
const out = `// GENERATED by scripts/gen-version.mjs — do not edit.
export const VERSION = ${JSON.stringify(pkg.version)}
export const BUILT_AT = ${Date.now()}
// The sibling versions THIS bundle was packed from — what a desktop compares against to see drift.
export const DEPS = ${JSON.stringify(deps, null, 2)}
export default { VERSION, BUILT_AT, DEPS }
`
fs.writeFileSync(path.join(root, 'lib', 'version.js'), out)
console.log('version ' + pkg.version + ' — ' + Object.entries(deps).map(([k, v]) => k + '@' + (v || '?')).join(' '))