#!/usr/bin/env node /** * Resolve the Pear link for a workspace package (stage / release). * * Pear CLI v2.5+ requires pear:// (not channel names). * * Resolution order: * 1. BARE_OS_SEEDER_PEAR_LINK / BARE_OS_BOOTER_PEAR_LINK (always wins) * 2. If BARE_OS_PEAR_USE_PUBLISHED_LINK=1 (seeder): package.json pear.link, then pear.stageLink * 3. /.pear-stage-link (writable local; gitignored) * 4. package.json pear.stageLink * 5. package.json pear.link (booter default; seeder fallback) * * Usage: node scripts/resolve-pear-link.mjs */ import { readFileSync, existsSync } from 'node:fs' import path from 'node:path' const pkgDir = path.resolve(process.argv[2] ?? '') if (!pkgDir) { console.error('usage: resolve-pear-link.mjs ') process.exit(1) } const ENV_BY_PKG = { 'bare-os-seeder': 'BARE_OS_SEEDER_PEAR_LINK', 'bare-os-booter': 'BARE_OS_BOOTER_PEAR_LINK' } const LOCAL_LINK_FILE = '.pear-stage-link' const pkgJsonPath = path.join(pkgDir, 'package.json') let pkgJson try { pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8')) } catch (err) { console.error(`Could not read ${pkgJsonPath}: ${err.message}`) process.exit(1) } const name = pkgJson.pear?.name ?? pkgJson.name const envKey = ENV_BY_PKG[name] const fromEnv = envKey ? process.env[envKey]?.trim() : undefined const localPath = path.join(pkgDir, LOCAL_LINK_FILE) const fromLocal = existsSync(localPath) ? readFileSync(localPath, 'utf8').trim() : undefined const fromStageLink = pkgJson.pear?.stageLink?.trim() const fromPublishedLink = pkgJson.pear?.link?.trim() const usePublished = process.env.BARE_OS_PEAR_USE_PUBLISHED_LINK === '1' || process.env.BARE_OS_PEAR_USE_PUBLISHED_LINK === 'true' let link = '' if (fromEnv) { link = fromEnv } else if (name === 'bare-os-booter') { link = fromLocal ?? fromStageLink ?? fromPublishedLink ?? '' } else if (usePublished) { link = fromPublishedLink ?? fromStageLink ?? fromLocal ?? '' } else { link = fromLocal ?? fromStageLink ?? fromPublishedLink ?? '' } if (!link) { const publishedHint = name === 'bare-os-seeder' ? `Production seeder link (pear.link) is read-only on most hosts.\n` + ` node scripts/bootstrap-pear-stage-link.mjs ${pkgDir}\n` + ` Or set ${envKey}.\n` + ` Maintainer host only: BARE_OS_PEAR_USE_PUBLISHED_LINK=1` : `Set ${envKey} or add "pear": { "link": "pear://…" } to ${pkgJsonPath}.` console.error(`Missing Pear link for ${name ?? pkgDir}.\n${publishedHint}`) process.exit(1) } if (!/^pear:\/\/[a-z0-9]+$/i.test(link)) { console.error(`Invalid Pear link (expected pear://): ${link}`) process.exit(1) } process.stdout.write(`${link}\n`)