| … | … | @@ -7,10 +7,9 @@ |
| 7 | 7 | // - Timeline = merge all followed feeds by timestamp |
| 8 | 8 | // - Sparse replication = only followed users, not entire network |
| 9 | 9 | // |
| 10 | | // pear-runtime provides P2P OTA updates when running from a deployed install. |
| 10 | // pgh provides P2P OTA updates (content-addressed) when installed via pgh. |
| 11 | 11 | // |
| 12 | 12 | // Usage: bare index.js <command> [options] |
| 13 | | // pear run pear://KEY <command> [options] |
| 14 | 13 | |
| 15 | 14 | import Corestore from 'corestore' |
| 16 | 15 | import Hyperswarm from 'hyperswarm' |
| … | … | @@ -27,6 +26,7 @@ import fs from 'bare-fs' |
| 27 | 26 | import path from 'bare-path' |
| 28 | 27 | import process from 'bare-process' |
| 29 | 28 | import os from 'bare-os' |
| 29 | import subprocess from 'bare-subprocess' |
| 30 | 30 | import { ANProto } from './lib/anproto.js' |
| 31 | 31 | import { YAMLHelper } from './lib/yaml-helper.js' |
| 32 | 32 | |
| … | … | @@ -2052,29 +2052,42 @@ async function main() { |
| 2052 | 2052 | } |
| 2053 | 2053 | } |
| 2054 | 2054 | |
| 2055 | | // Initialize pear-runtime for P2P OTA updates (non-blocking) |
| 2056 | | async function initPearRuntime () { |
| 2055 | // Background OTA via pgh — content-addressed store, NO Hyperdrive/blobs. |
| 2056 | // `pgh app update <name>` resolves the latest release from package.json's |
| 2057 | // pgh.upgrade and ATOMICALLY materializes the new tree (next launch uses it). |
| 2058 | // Replaces the former pear-runtime Hyperdrive updater, which kept an unbounded |
| 2059 | // append-only blob corestore under the app storage dir. |
| 2060 | function startBackgroundUpdate () { |
| 2057 | 2061 | try { |
| 2058 | 2062 | const pkg = JSON.parse(fs.readFileSync(path.join(getAppDir(), 'package.json'), 'utf-8')) |
| 2059 | | if (!pkg.upgrade) return null |
| 2060 | | |
| 2061 | | const { default: PearRuntime } = await import('pear-runtime') |
| 2062 | | const dir = getStorageDir() |
| 2063 | | |
| 2064 | | const runtime = new PearRuntime({ dir, app: getAppDir(), version: pkg.version, upgrade: pkg.upgrade }) |
| 2065 | | runtime.on('updated', () => { |
| 2066 | | runtime.applyUpdate().catch(() => {}) |
| 2063 | const upgrade = pkg.pgh && pkg.pgh.upgrade |
| 2064 | if (!upgrade) return |
| 2065 | const appName = (pkg.pgh && pkg.pgh.bin) || pkg.name || 'wirecore' |
| 2066 | // Resolve the pgh CLI: prefer ~/.local/bin/pgh, else the store bare+entry. |
| 2067 | let argv = null |
| 2068 | const launcher = path.join(os.homedir(), '.local', 'bin', 'pgh') |
| 2069 | if (fs.existsSync(launcher)) argv = [launcher] |
| 2070 | else { |
| 2071 | const storeRoot = process.env.PGH_STORE_ROOT || path.join(os.homedir(), '.local', 'share', 'store') |
| 2072 | const bareBin = path.join(storeRoot, 'apps', 'pgh', 'runtime', 'bare') |
| 2073 | const entry = path.join(storeRoot, 'apps', 'pgh', 'bin', 'pgh.bare.js') |
| 2074 | if (fs.existsSync(bareBin) && fs.existsSync(entry)) argv = [bareBin, entry] |
| 2075 | } |
| 2076 | if (!argv) return |
| 2077 | // Detached + best-effort: never blocks the command. |
| 2078 | const proc = subprocess.spawn(argv[0], [...argv.slice(1), 'app', 'update', appName], { |
| 2079 | stdio: 'ignore', |
| 2080 | detached: true |
| 2067 | 2081 | }) |
| 2068 | | return runtime |
| 2069 | | } catch { |
| 2070 | | return null |
| 2071 | | } |
| 2082 | proc.on('error', () => {}) |
| 2083 | if (proc.unref) proc.unref() |
| 2084 | } catch {} |
| 2072 | 2085 | } |
| 2073 | 2086 | |
| 2074 | 2087 | // Run main |
| 2075 | | let runtimeRef = null |
| 2076 | | if (!isPear) { |
| 2077 | | runtimeRef = initPearRuntime() |
| 2088 | const _argv = typeof Bare !== 'undefined' ? Bare.argv : process.argv |
| 2089 | if (!isPear && !_argv.includes('--no-updates')) { |
| 2090 | startBackgroundUpdate() |
| 2078 | 2091 | } |
| 2079 | 2092 | |
| 2080 | 2093 | main().catch(err => { |