Raven Scott
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Create a writable Pear link for local stage/release on this host.
|
||||
* Writes packages/<app>/.pear-stage-link (gitignored).
|
||||
*
|
||||
* Usage: node scripts/bootstrap-pear-stage-link.mjs <package-dir>
|
||||
*/
|
||||
|
||||
import { execSync } from 'node:child_process'
|
||||
import { writeFileSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
const pkgDir = path.resolve(process.argv[2] ?? '')
|
||||
if (!pkgDir) {
|
||||
console.error('usage: bootstrap-pear-stage-link.mjs <package-dir>')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
let out
|
||||
try {
|
||||
out = execSync('pear touch --json', {
|
||||
cwd: pkgDir,
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'inherit']
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(`pear touch failed: ${err.message}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
let link = null
|
||||
for (const line of out.trim().split('\n').filter(Boolean).reverse()) {
|
||||
try {
|
||||
const row = JSON.parse(line)
|
||||
link = row.data?.link ?? row.link ?? null
|
||||
if (link) break
|
||||
} catch {
|
||||
/* skip non-JSON lines (warnings) */
|
||||
}
|
||||
}
|
||||
|
||||
if (!link || !/^pear:\/\/[a-z0-9]+$/i.test(link)) {
|
||||
console.error('pear touch --json did not return a pear:// link')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const dest = path.join(pkgDir, '.pear-stage-link')
|
||||
writeFileSync(dest, `${link}\n`, 'utf8')
|
||||
console.error(`Wrote ${dest}`)
|
||||
process.stdout.write(`${link}\n`)
|
||||
@@ -59,11 +59,50 @@ const concreteClosureByPkgRel = new Map([
|
||||
function linkTo(src, dst) {
|
||||
mkdirSync(dirname(dst), { recursive: true })
|
||||
const abs = resolve(src)
|
||||
if (process.platform === 'win32') {
|
||||
symlinkSync(abs, dst, 'junction')
|
||||
} else {
|
||||
symlinkSync(relative(dirname(dst), abs), dst, 'dir')
|
||||
// Absolute targets avoid Pear stage rejecting relative links with many '..'.
|
||||
symlinkSync(abs, dst, process.platform === 'win32' ? 'junction' : 'dir')
|
||||
}
|
||||
|
||||
/** Collect npm package names (scoped + unscoped) reachable from a workspace package.json. */
|
||||
function dependencyClosure(pkgRoot, rootNm) {
|
||||
const seen = new Set()
|
||||
const queue = []
|
||||
const pkgJsonPath = join(pkgRoot, 'package.json')
|
||||
if (!existsSync(pkgJsonPath)) return seen
|
||||
|
||||
const rootPkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
|
||||
const forPearStage =
|
||||
process.env.BARE_OS_PEAR_NODE_MODULES === '1' ||
|
||||
process.env.BARE_OS_PEAR_NODE_MODULES === 'true'
|
||||
const seedSpecs = [...Object.keys(rootPkg.dependencies || {})]
|
||||
// bare-os-booter lists catalog bare-* packages under optionalDependencies; never mirror those.
|
||||
if (!forPearStage) {
|
||||
seedSpecs.push(...Object.keys(rootPkg.devDependencies || {}))
|
||||
}
|
||||
for (const spec of seedSpecs) queue.push(spec)
|
||||
|
||||
while (queue.length) {
|
||||
const spec = queue.shift()
|
||||
if (!spec || seen.has(spec)) continue
|
||||
seen.add(spec)
|
||||
|
||||
const pkgDir = packagePath(rootNm, spec)
|
||||
const depJsonPath = join(pkgDir, 'package.json')
|
||||
if (!existsSync(depJsonPath)) continue
|
||||
|
||||
let pkg
|
||||
try {
|
||||
pkg = JSON.parse(readFileSync(depJsonPath, 'utf8'))
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
const deps = {
|
||||
...(pkg.dependencies || {}),
|
||||
...(pkg.optionalDependencies || {})
|
||||
}
|
||||
for (const depName of Object.keys(deps)) queue.push(depName)
|
||||
}
|
||||
return seen
|
||||
}
|
||||
|
||||
function packagePath(nmRoot, spec) {
|
||||
@@ -87,6 +126,8 @@ if (existsSync(localNm)) {
|
||||
}
|
||||
mkdirSync(localNm, { recursive: true })
|
||||
|
||||
const needed = dependencyClosure(pkgRoot, rootNm)
|
||||
|
||||
for (const name of readdirSync(rootNm)) {
|
||||
if (name === '.bin' || name === '.package-lock.json' || name.startsWith('.'))
|
||||
continue
|
||||
@@ -100,6 +141,8 @@ for (const name of readdirSync(rootNm)) {
|
||||
if (name.startsWith('@') && st.isDirectory()) {
|
||||
for (const sub of readdirSync(srcPath)) {
|
||||
if (sub.startsWith('.')) continue
|
||||
const spec = `${name}/${sub}`
|
||||
if (!needed.has(spec)) continue
|
||||
const scopedSrc = join(srcPath, sub)
|
||||
try {
|
||||
if (!lstatSync(scopedSrc).isDirectory()) continue
|
||||
@@ -110,6 +153,7 @@ for (const name of readdirSync(rootNm)) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (!needed.has(name)) continue
|
||||
if (st.isDirectory() || st.isSymbolicLink()) {
|
||||
linkTo(srcPath, join(localNm, name))
|
||||
}
|
||||
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# Release + seed current package.json pear.link keys (after stage-release staged content).
|
||||
# Usage: scripts/finish-pear-setup.sh
|
||||
set -euo pipefail
|
||||
|
||||
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
rm -f "${HOME}/.config/pear/lock"
|
||||
|
||||
SEEDER_LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/packages/bare-os-seeder")"
|
||||
BOOTER_LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/packages/bare-os-booter")"
|
||||
|
||||
release() {
|
||||
local dir="$1"
|
||||
local link="$2"
|
||||
local name="$3"
|
||||
echo ""
|
||||
echo "Releasing $name ($link)…"
|
||||
(cd "$dir" && pear release "$link")
|
||||
}
|
||||
|
||||
seed() {
|
||||
local dir="$1"
|
||||
local link="$2"
|
||||
local name="$3"
|
||||
echo ""
|
||||
echo "Seeding $name ($link)…"
|
||||
(cd "$dir" && pear seed "$link" --no-ask --no-tty) || true
|
||||
}
|
||||
|
||||
release "$ROOT/packages/bare-os-seeder" "$SEEDER_LINK" bare-os-seeder
|
||||
release "$ROOT/packages/bare-os-booter" "$BOOTER_LINK" bare-os-booter
|
||||
seed "$ROOT/packages/bare-os-seeder" "$SEEDER_LINK" bare-os-seeder
|
||||
seed "$ROOT/packages/bare-os-booter" "$BOOTER_LINK" bare-os-booter
|
||||
|
||||
echo ""
|
||||
echo "Done."
|
||||
echo " Seeder: $SEEDER_LINK"
|
||||
echo " Booter: $BOOTER_LINK"
|
||||
echo ""
|
||||
echo "Run (wait ~10s for first log line):"
|
||||
echo " source scripts/pear-path.sh"
|
||||
echo " pear run $SEEDER_LINK --checkout=release"
|
||||
echo "Dev (from disk, recommended locally):"
|
||||
echo " npm run os:seeder"
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "pear-seed-bare-os-seeder",
|
||||
"cwd": ".",
|
||||
"script": "scripts/pm2-pear-seed.sh",
|
||||
"args": ["packages/bare-os-seeder"],
|
||||
"interpreter": "bash",
|
||||
"instances": 1,
|
||||
"exec_mode": "fork",
|
||||
"autorestart": true,
|
||||
"min_uptime": 10000,
|
||||
"max_restarts": 20,
|
||||
"restart_delay": 5000,
|
||||
"kill_timeout": 10000
|
||||
},
|
||||
{
|
||||
"name": "pear-seed-bare-os-booter",
|
||||
"cwd": ".",
|
||||
"script": "scripts/pm2-pear-seed.sh",
|
||||
"args": ["packages/bare-os-booter"],
|
||||
"interpreter": "bash",
|
||||
"instances": 1,
|
||||
"exec_mode": "fork",
|
||||
"autorestart": true,
|
||||
"min_uptime": 10000,
|
||||
"max_restarts": 20,
|
||||
"restart_delay": 5000,
|
||||
"kill_timeout": 10000
|
||||
},
|
||||
{
|
||||
"name": "bare-os-seeder",
|
||||
"cwd": ".",
|
||||
"script": "scripts/pm2-pear-run.sh",
|
||||
"args": ["packages/bare-os-seeder"],
|
||||
"interpreter": "bash",
|
||||
"instances": 1,
|
||||
"exec_mode": "fork",
|
||||
"autorestart": true,
|
||||
"min_uptime": 15000,
|
||||
"max_restarts": 20,
|
||||
"restart_delay": 8000,
|
||||
"kill_timeout": 15000
|
||||
},
|
||||
{
|
||||
"name": "bare-os-booter",
|
||||
"cwd": ".",
|
||||
"script": "scripts/pm2-pear-run.sh",
|
||||
"args": ["packages/bare-os-booter"],
|
||||
"interpreter": "bash",
|
||||
"instances": 1,
|
||||
"exec_mode": "fork",
|
||||
"autorestart": true,
|
||||
"min_uptime": 15000,
|
||||
"max_restarts": 20,
|
||||
"restart_delay": 8000,
|
||||
"kill_timeout": 15000
|
||||
}
|
||||
]
|
||||
}
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# PM2 helper: run a Bare OS Pear app (long-lived) using pear.link from package.json.
|
||||
# Usage: scripts/pm2-pear-run.sh packages/bare-os-seeder
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PKG_REL="${1:?package path required, e.g. packages/bare-os-seeder}"
|
||||
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
|
||||
|
||||
LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/$PKG_REL")"
|
||||
cd "$ROOT/$PKG_REL"
|
||||
echo "[pm2-pear-run] $(basename "$PKG_REL") → $LINK" >&2
|
||||
exec pear run "$LINK" --checkout=release
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# PM2 helper: seed a Bare OS Pear app using pear.link from package.json.
|
||||
# Usage: scripts/pm2-pear-seed.sh packages/bare-os-seeder
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PKG_REL="${1:?package path required, e.g. packages/bare-os-seeder}"
|
||||
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
|
||||
|
||||
LINK="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$ROOT/$PKG_REL")"
|
||||
if [[ -z "$LINK" || "$LINK" == "." ]]; then
|
||||
echo "[pm2-pear-seed] ERROR: invalid Pear link for $PKG_REL (got: ${LINK:-<empty>})" >&2
|
||||
exit 1
|
||||
fi
|
||||
cd "$ROOT/$PKG_REL"
|
||||
echo "[pm2-pear-seed] $(basename "$PKG_REL") → $LINK" >&2
|
||||
exec pear seed "$LINK" --no-ask --no-tty
|
||||
@@ -2,10 +2,10 @@
|
||||
"apps": [
|
||||
{
|
||||
"name": "pear-seed-bare-os-seeder",
|
||||
"cwd": "./packages/bare-os-seeder",
|
||||
"script": "pear",
|
||||
"args": ["seed", "--no-ask", "bare-os-seeder", "."],
|
||||
"interpreter": "none",
|
||||
"cwd": ".",
|
||||
"script": "scripts/pm2-pear-seed.sh",
|
||||
"args": ["packages/bare-os-seeder"],
|
||||
"interpreter": "bash",
|
||||
"instances": 1,
|
||||
"exec_mode": "fork",
|
||||
"autorestart": true,
|
||||
@@ -16,10 +16,10 @@
|
||||
},
|
||||
{
|
||||
"name": "pear-seed-bare-os-booter",
|
||||
"cwd": "./packages/bare-os-booter",
|
||||
"script": "pear",
|
||||
"args": ["seed", "--no-ask", "bare-os-booter", "."],
|
||||
"interpreter": "none",
|
||||
"cwd": ".",
|
||||
"script": "scripts/pm2-pear-seed.sh",
|
||||
"args": ["packages/bare-os-booter"],
|
||||
"interpreter": "bash",
|
||||
"instances": 1,
|
||||
"exec_mode": "fork",
|
||||
"autorestart": true,
|
||||
|
||||
Executable
+99
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fully remove Pear, reinstall from npm, mint new bare-os keys, stage, release, seed.
|
||||
#
|
||||
# Usage (from repo root): scripts/reinstall-pear-and-setup.sh
|
||||
#
|
||||
# Stops PM2 pear/os-seeder jobs, deletes ~/.config/pear, reinstalls `npm i -g pear`,
|
||||
# bootstraps the platform (`pear run pear://runtime`), then runs stage-release + seed.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
PEAR_HOME="${HOME}/.config/pear"
|
||||
BARE_OS_HOME="${BARE_OS_HOME:-$HOME/.bare-os}"
|
||||
|
||||
log() {
|
||||
printf '\n%s\n' "$*"
|
||||
}
|
||||
|
||||
stop_pm2_pear_jobs() {
|
||||
if ! command -v pm2 >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
log "Stopping PM2 processes that use Pear…"
|
||||
for name in os-seeder os-booter pear-seed-bare-os-seeder pear-seed-bare-os-booter; do
|
||||
pm2 delete "$name" 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
|
||||
kill_pear_sidecars() {
|
||||
log "Stopping Pear sidecar / pear-runtime processes…"
|
||||
pkill -f 'pear-runtime' 2>/dev/null || true
|
||||
pkill -f 'pear\.sock' 2>/dev/null || true
|
||||
rm -f "${PEAR_HOME}/lock"
|
||||
sleep 2
|
||||
}
|
||||
|
||||
uninstall_pear() {
|
||||
log "Removing Pear platform data (~/.config/pear, ~20GB+ if present)…"
|
||||
kill_pear_sidecars
|
||||
rm -rf "${PEAR_HOME}" "${HOME}/.pear"
|
||||
if command -v npm >/dev/null 2>&1; then
|
||||
npm uninstall -g pear 2>/dev/null || true
|
||||
fi
|
||||
# Remove nvm/global shim if present (reinstall recreates it)
|
||||
if [[ -n "${NVM_BIN:-}" && -f "${NVM_BIN}/pear" ]]; then
|
||||
rm -f "${NVM_BIN}/pear"
|
||||
fi
|
||||
if [[ -f "${HOME}/.nvm/versions/node/$(node -v 2>/dev/null | tr -d v)/bin/pear" ]]; then
|
||||
rm -f "${HOME}/.nvm/versions/node/"*/bin/pear 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
install_pear() {
|
||||
log "Installing Pear CLI (npm i -g pear)…"
|
||||
npm install -g pear
|
||||
export PATH="${PEAR_HOME}/bin:${PATH:-}"
|
||||
if [[ ! -x "${PEAR_HOME}/bin/pear" ]] && command -v pear >/dev/null 2>&1; then
|
||||
log "Bootstrapping Pear platform (first run)…"
|
||||
pear 2>&1 | head -20 || true
|
||||
log "Pear runtime is installed under ${PEAR_HOME}/bin"
|
||||
export PATH="${PEAR_HOME}/bin:${PATH:-}"
|
||||
fi
|
||||
if [[ ! -x "${PEAR_HOME}/bin/pear" ]] && ! command -v pear >/dev/null 2>&1; then
|
||||
echo "Pear binary not found after install. Add ${PEAR_HOME}/bin to PATH and run: pear run pear://runtime" >&2
|
||||
exit 1
|
||||
fi
|
||||
export PATH="${PEAR_HOME}/bin:${PATH:-}"
|
||||
log "Pear binary: $(command -v pear)"
|
||||
pear 2>&1 | head -15 || true
|
||||
}
|
||||
|
||||
write_path_snippet() {
|
||||
local snippet="${ROOT}/scripts/pear-path.sh"
|
||||
cat >"$snippet" <<EOF
|
||||
# Source before pear commands: . scripts/pear-path.sh
|
||||
export PATH="\${HOME}/.config/pear/bin:\${PATH}"
|
||||
EOF
|
||||
log "Wrote ${snippet} — run: source scripts/pear-path.sh"
|
||||
}
|
||||
|
||||
log "=== Pear reinstall + Bare OS stage/release ==="
|
||||
log "Repo: $ROOT"
|
||||
|
||||
stop_pm2_pear_jobs
|
||||
uninstall_pear
|
||||
install_pear
|
||||
write_path_snippet
|
||||
|
||||
export PATH="${PEAR_HOME}/bin:${PATH:-}"
|
||||
rm -rf "${BARE_OS_HOME}/corestore/seeder" "${BARE_OS_HOME}/corestore/booter"
|
||||
rm -f "${ROOT}/packages/bare-os-seeder/.pear-stage-link" "${ROOT}/packages/bare-os-booter/.pear-stage-link"
|
||||
|
||||
log "Minting keys, stage, release, seed…"
|
||||
"${ROOT}/scripts/reset-pear-apps.sh"
|
||||
|
||||
log "=== Complete ==="
|
||||
log "Add to shell profile: export PATH=\"\${HOME}/.config/pear/bin:\${PATH}\""
|
||||
log "Dev run: cd $ROOT && npm run os:seeder"
|
||||
log "Pear run: pear run \$(node scripts/resolve-pear-link.mjs packages/bare-os-seeder)"
|
||||
log "PM2 seed: pm2 start scripts/pm2-pear-seeders.ecosystem.json"
|
||||
Executable
+108
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env bash
|
||||
# Clear Pear + Bare OS host storage for bare-os-seeder and bare-os-booter,
|
||||
# mint new pear:// links, update package.json, then stage, release, and seed.
|
||||
#
|
||||
# Usage (from repo root): scripts/reset-pear-apps.sh
|
||||
# Env: BARE_OS_HOME — host data root (default: $HOME/.bare-os)
|
||||
set -euo pipefail
|
||||
|
||||
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SEEDER="$ROOT/packages/bare-os-seeder"
|
||||
BOOTER="$ROOT/packages/bare-os-booter"
|
||||
BARE_OS_HOME="${BARE_OS_HOME:-$HOME/.bare-os}"
|
||||
|
||||
log() {
|
||||
printf '\n%s\n' "$*"
|
||||
}
|
||||
|
||||
collect_pear_links() {
|
||||
node --input-type=module -e "
|
||||
import fs from 'fs'
|
||||
const pkgs = ['$SEEDER', '$BOOTER']
|
||||
const links = new Set()
|
||||
for (const pkg of pkgs) {
|
||||
const p = JSON.parse(fs.readFileSync(pkg + '/package.json', 'utf8'))
|
||||
if (p.pear?.link) links.add(p.pear.link)
|
||||
const local = pkg + '/.pear-stage-link'
|
||||
if (fs.existsSync(local)) links.add(fs.readFileSync(local, 'utf8').trim())
|
||||
}
|
||||
for (const l of links) if (l) console.log(l)
|
||||
"
|
||||
}
|
||||
|
||||
drop_pear_link() {
|
||||
local link="$1"
|
||||
log "Resetting Pear app storage: $link"
|
||||
rm -f "${HOME}/.config/pear/lock"
|
||||
printf 'RESET\n' | pear drop app "$link" 2>&1 || true
|
||||
}
|
||||
|
||||
touch_pear_link() {
|
||||
node "$ROOT/scripts/bootstrap-pear-stage-link.mjs" "$1" 2>/dev/null | tail -1
|
||||
}
|
||||
|
||||
verify_pear_link() {
|
||||
local link="$1"
|
||||
local label="$2"
|
||||
local tmp
|
||||
rm -f "${HOME}/.config/pear/lock"
|
||||
tmp="$(mktemp -d)"
|
||||
if timeout 90 pear dump "$link" "$tmp" --force >/dev/null 2>&1 && [[ -f "$tmp/index.js" ]]; then
|
||||
log "$label: staged bundle OK (index.js present at $link)"
|
||||
rm -rf "$tmp"
|
||||
return 0
|
||||
fi
|
||||
rm -rf "$tmp"
|
||||
log "WARN: could not verify $label via pear dump (link may still work with pear run --checkout=staged)"
|
||||
return 0
|
||||
}
|
||||
|
||||
log "Repo root: $ROOT"
|
||||
log "Pear PATH uses: ${PATH%%:*}"
|
||||
rm -f "${HOME}/.config/pear/lock"
|
||||
|
||||
while IFS= read -r link; do
|
||||
[[ -n "$link" ]] && drop_pear_link "$link"
|
||||
done < <(collect_pear_links)
|
||||
|
||||
rm -f "$SEEDER/.pear-stage-link" "$BOOTER/.pear-stage-link"
|
||||
|
||||
if [[ -d "$BARE_OS_HOME/corestore" ]]; then
|
||||
log "Removing Bare OS host corestores under $BARE_OS_HOME/corestore/{seeder,booter}"
|
||||
rm -rf "$BARE_OS_HOME/corestore/seeder" "$BARE_OS_HOME/corestore/booter"
|
||||
fi
|
||||
|
||||
log "Pear GC (cores)…"
|
||||
pear gc cores 2>&1 || true
|
||||
|
||||
log "Minting new Pear links (pear touch)…"
|
||||
SEEDER_LINK="$(touch_pear_link "$SEEDER")"
|
||||
BOOTER_LINK="$(touch_pear_link "$BOOTER")"
|
||||
log " seeder: $SEEDER_LINK"
|
||||
log " booter: $BOOTER_LINK"
|
||||
|
||||
node "$ROOT/scripts/set-pear-package-link.mjs" "$SEEDER" "$SEEDER_LINK"
|
||||
node "$ROOT/scripts/set-pear-package-link.mjs" "$BOOTER" "$BOOTER_LINK"
|
||||
|
||||
log "Stage, release, and seed (scripts/stage-release.sh + pear seed)…"
|
||||
unset BARE_OS_PEAR_USE_PUBLISHED_LINK
|
||||
unset BARE_OS_SEEDER_PEAR_LINK
|
||||
unset BARE_OS_BOOTER_PEAR_LINK
|
||||
rm -f "$SEEDER/.pear-stage-link" "$BOOTER/.pear-stage-link"
|
||||
"$ROOT/scripts/stage-release.sh"
|
||||
|
||||
log "Seeding $SEEDER_LINK …"
|
||||
(cd "$SEEDER" && pear seed "$SEEDER_LINK" --no-ask --no-tty) || true
|
||||
|
||||
log "Seeding $BOOTER_LINK …"
|
||||
(cd "$BOOTER" && pear seed "$BOOTER_LINK" --no-ask --no-tty) || true
|
||||
|
||||
verify_pear_link "$SEEDER_LINK" "bare-os-seeder"
|
||||
verify_pear_link "$BOOTER_LINK" "bare-os-booter"
|
||||
|
||||
log "Done."
|
||||
log " bare-os-seeder: $SEEDER_LINK"
|
||||
log " bare-os-booter: $BOOTER_LINK"
|
||||
log "Update docs/PEAR-RUN.md and any pear:// references in the repo with these keys."
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Resolve the Pear link for a workspace package (stage / release).
|
||||
*
|
||||
* Pear CLI v2.5+ requires pear://<key> (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. <package-dir>/.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 <package-dir>
|
||||
*/
|
||||
|
||||
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 <package-dir>')
|
||||
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://<key>): ${link}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
process.stdout.write(`${link}\n`)
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Set package.json pear.link for a workspace Pear app.
|
||||
* Usage: node scripts/set-pear-package-link.mjs <package-dir> <pear://link>
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
const pkgDir = path.resolve(process.argv[2] ?? '')
|
||||
const link = (process.argv[3] ?? '').trim()
|
||||
if (!pkgDir || !link) {
|
||||
console.error('usage: set-pear-package-link.mjs <package-dir> <pear://link>')
|
||||
process.exit(1)
|
||||
}
|
||||
if (!/^pear:\/\/[a-z0-9]+$/i.test(link)) {
|
||||
console.error(`Invalid link: ${link}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const pkgJsonPath = path.join(pkgDir, 'package.json')
|
||||
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
|
||||
pkgJson.pear = pkgJson.pear ?? {}
|
||||
pkgJson.pear.link = link
|
||||
writeFileSync(pkgJsonPath, `${JSON.stringify(pkgJson, null, 2)}\n`, 'utf8')
|
||||
console.log(`Updated ${pkgJsonPath} → ${link}`)
|
||||
@@ -3,6 +3,8 @@
|
||||
# Run from anywhere; resolves repo root from this script's location.
|
||||
set -euo pipefail
|
||||
|
||||
export PATH="${HOME}/.config/pear/bin:${PATH:-}"
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SEEDER="$ROOT/packages/bare-os-seeder"
|
||||
BOOTER="$ROOT/packages/bare-os-booter"
|
||||
@@ -29,7 +31,7 @@ prepare_pkg_for_pear() {
|
||||
local nm="$pkg/node_modules"
|
||||
local rel="${pkg#"$ROOT"/}"
|
||||
log "Mirroring root node_modules → $rel/node_modules (ensure-pear-node-modules)"
|
||||
(cd "$ROOT" && node scripts/ensure-pear-node-modules.mjs "$rel")
|
||||
(cd "$ROOT" && BARE_OS_PEAR_NODE_MODULES=1 node scripts/ensure-pear-node-modules.mjs "$rel")
|
||||
rm -rf "$nm/bare-os-protocol"
|
||||
log "Copying bare-os-protocol into $(basename "$pkg")/node_modules"
|
||||
cp -R "$PROTO" "$nm/bare-os-protocol"
|
||||
@@ -40,7 +42,22 @@ prepare_pkg_for_pear() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Pear CLI v2.5+ requires pear://<key>, not channel names (bare-os-seeder).
|
||||
resolve_pear_link() {
|
||||
local pkg="$1"
|
||||
local link
|
||||
link="$(node "$ROOT/scripts/resolve-pear-link.mjs" "$pkg" 2>/dev/null)" || true
|
||||
if [[ -n "$link" ]]; then
|
||||
printf '%s' "$link"
|
||||
return 0
|
||||
fi
|
||||
log "Bootstrapping Pear link for $(basename "$pkg")…"
|
||||
node "$ROOT/scripts/bootstrap-pear-stage-link.mjs" "$pkg" >/dev/null
|
||||
node "$ROOT/scripts/resolve-pear-link.mjs" "$pkg"
|
||||
}
|
||||
|
||||
log "Repo root: $ROOT"
|
||||
rm -f "${HOME}/.config/pear/lock"
|
||||
ensure_root_deps
|
||||
|
||||
log "Sync kernel/ -> packages/bare-os-seeder/kernel/"
|
||||
@@ -50,14 +67,21 @@ cp -R "$ROOT/kernel/." "$SEEDER/kernel/"
|
||||
prepare_pkg_for_pear "$SEEDER"
|
||||
prepare_pkg_for_pear "$BOOTER"
|
||||
|
||||
SEEDER_LINK="$(resolve_pear_link "$SEEDER")"
|
||||
BOOTER_LINK="$(resolve_pear_link "$BOOTER")"
|
||||
log "Pear links: seeder=$SEEDER_LINK booter=$BOOTER_LINK"
|
||||
|
||||
log "Staging bare-os-seeder…"
|
||||
(cd "$SEEDER" && pear stage bare-os-seeder --no-ask)
|
||||
(cd "$SEEDER" && pear stage "$SEEDER_LINK" --no-ask)
|
||||
log "Releasing bare-os-seeder…"
|
||||
(cd "$SEEDER" && pear release bare-os-seeder)
|
||||
(cd "$SEEDER" && pear release "$SEEDER_LINK")
|
||||
|
||||
log "Staging bare-os-booter…"
|
||||
(cd "$BOOTER" && pear stage bare-os-booter --no-ask)
|
||||
(cd "$BOOTER" && pear stage "$BOOTER_LINK" --no-ask)
|
||||
log "Releasing bare-os-booter…"
|
||||
(cd "$BOOTER" && pear release bare-os-booter)
|
||||
(cd "$BOOTER" && pear release "$BOOTER_LINK")
|
||||
|
||||
log "Done. Use pear stage … --json | tail -1 for verlink, or pear run pear://<key>"
|
||||
log "Done."
|
||||
log " bare-os-seeder: $SEEDER_LINK"
|
||||
log " bare-os-booter: $BOOTER_LINK"
|
||||
log " pear stage … --json | tail -1 for verlink, or pear run <link>"
|
||||
|
||||
Reference in New Issue
Block a user