This commit is contained in:
Raven Scott
2026-04-02 22:04:58 -04:00
parent c3b3dc188e
commit 9efede0dc8
16 changed files with 380 additions and 43 deletions
+23 -12
View File
@@ -5,29 +5,37 @@ import safetyCatch from 'safety-catch'
import Hyperdrive from 'hyperdrive'
import Corestore from 'corestore'
import path from 'path'
import { fileURLToPath } from 'url'
import { topicKey, parseMbr } from 'bare-os-protocol'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const repoRoot = path.join(__dirname, '..', '..')
import { SwarmDisk } from './lib/swarm-disk.js'
import { runKernelFromSource, runBinCommand } from './lib/kernel-runner.js'
import {
packageRootDir,
defaultBootCorestorePath,
defaultLocalSeedCorestorePath
} from './lib/paths.js'
const _pkg = packageRootDir(import.meta.url)
function bootStorePath() {
return process.env.BARE_OS_BOOT_STORE || path.join(repoRoot, 'data', 'corestore-booter')
return defaultBootCorestorePath(_pkg, import.meta.url)
}
async function createReadLine() {
if (process.env.BARE_OS_SKIP_REPL === '1') {
if (globalThis.process?.env?.BARE_OS_SKIP_REPL === '1') {
return async () => null
}
try {
const { createInterface } = await import('node:readline')
const stdin = globalThis.process?.stdin
const stdout = globalThis.process?.stdout
if (!stdin || !stdout) {
return async () => null
}
return (prompt) =>
new Promise((resolve) => {
const rl = createInterface({
input: process.stdin,
output: process.stdout
input: stdin,
output: stdout
})
rl.question(prompt, (line) => {
rl.close()
@@ -119,8 +127,7 @@ async function bootFromPeers(disk, store, swarm) {
}
async function bootLocal(disk, store, swarm) {
const seedPath =
process.env.BARE_OS_LOCAL_SEED || path.join(repoRoot, 'data', 'corestore-seeder')
const seedPath = defaultLocalSeedCorestorePath(_pkg, import.meta.url)
console.log('Local boot from', seedPath)
const seedStore = new Corestore(seedPath)
disk.drive = new Hyperdrive(seedStore)
@@ -153,7 +160,7 @@ async function main() {
swarm.join(topic)
const maxWait = Number(process.env.BARE_OS_PEER_WAIT_MS || 8000)
const maxWait = Number(globalThis.process?.env?.BARE_OS_PEER_WAIT_MS || 8000)
let waited = 0
while (disk.peers.size === 0 && waited < maxWait) {
await new Promise((r) => setTimeout(r, 500))
@@ -184,4 +191,8 @@ async function main() {
}
}
main().catch(safetyCatch)
main().catch((err) => {
console.error('bare-os-booter failed:', err?.message ?? err)
if (err?.stack) console.error(err.stack)
safetyCatch(err)
})
+65
View File
@@ -0,0 +1,65 @@
import path from 'path'
import { statSync } from 'fs'
import { fileURLToPath } from 'node:url'
import os from 'bare-os'
function cwd() {
if (typeof globalThis.process?.cwd === 'function')
return globalThis.process.cwd()
return os.cwd()
}
function env(name) {
return globalThis.process?.env?.[name]
}
/** Booter has no `kernel/`; use `package.json` to detect the staged app root. */
function stagedAppRootHeuristic(root) {
try {
return statSync(path.join(root, 'package.json')).isFile()
} catch {
return false
}
}
export function packageRootDir(metaUrl) {
const href = String(metaUrl)
if (href.startsWith('file:')) {
return path.dirname(fileURLToPath(href))
}
const rti = globalThis.Pear?.constructor?.RTI?.mount
const swap = globalThis.Pear?.config?.swapDir
const seen = new Set()
const candidates = []
for (const c of [rti, swap, cwd()].filter(Boolean)) {
const p = path.resolve(String(c))
if (!seen.has(p)) {
seen.add(p)
candidates.push(p)
}
}
for (const root of candidates) {
if (stagedAppRootHeuristic(root)) return root
}
return candidates[0] ?? cwd()
}
export function defaultBootCorestorePath(pkgRoot, metaUrl) {
const override = env('BARE_OS_BOOT_STORE')
if (override) return override
const href = String(metaUrl)
const dataRoot = href.startsWith('file:')
? path.join(pkgRoot, '..', '..', 'data')
: path.join(pkgRoot, 'data')
return path.join(dataRoot, 'corestore-booter')
}
export function defaultLocalSeedCorestorePath(pkgRoot, metaUrl) {
const override = env('BARE_OS_LOCAL_SEED')
if (override) return override
const href = String(metaUrl)
const dataRoot = href.startsWith('file:')
? path.join(pkgRoot, '..', '..', 'data')
: path.join(pkgRoot, 'data')
return path.join(dataRoot, 'corestore-seeder')
}
+1
View File
@@ -0,0 +1 @@
../../node_modules
+12 -1
View File
@@ -10,6 +10,7 @@
"test": "brittle-node test.js"
},
"dependencies": {
"bare-os": "^3.8.7",
"bare-os-protocol": "*",
"b4a": "^1.6.7",
"compact-encoding": "^2.18.0",
@@ -34,11 +35,17 @@
"coverage",
".DS_Store",
"node_modules/.bin",
"node_modules/.package-lock.json"
"node_modules/.package-lock.json",
"test.js",
".test-data"
]
}
},
"imports": {
"fs": {
"bare": "bare-fs",
"default": "node:fs"
},
"path": {
"bare": "bare-path",
"default": "node:path"
@@ -46,6 +53,10 @@
"url": {
"bare": "bare-url",
"default": "node:url"
},
"node:url": {
"bare": "bare-url",
"default": "node:url"
}
}
}
+13 -8
View File
@@ -6,19 +6,22 @@ import Hyperdrive from 'hyperdrive'
import Corestore from 'corestore'
import { readdir, readFile, stat } from 'fs/promises'
import path from 'path'
import { fileURLToPath } from 'url'
import {
topicKey,
buildMbr,
setupSeedChannel,
BLOCK_SIZE
} from 'bare-os-protocol'
import {
packageRootDir,
defaultKernelRoot,
defaultSeedCorestorePath
} from './lib/paths.js'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const repoRoot = path.join(__dirname, '..', '..')
const _pkg = packageRootDir(import.meta.url)
function corestorePath() {
return process.env.BARE_OS_SEED_STORE || path.join(repoRoot, 'data', 'corestore-seeder')
return defaultSeedCorestorePath(_pkg, import.meta.url)
}
/** @param {import('hyperdrive').default} drive */
@@ -62,9 +65,7 @@ async function main() {
console.clear?.()
console.log('--- bare-os-seeder (Hyperdrive + MBR) ---')
const kernelRoot = process.env.BARE_OS_KERNEL_ROOT
? path.resolve(process.env.BARE_OS_KERNEL_ROOT)
: path.join(repoRoot, 'kernel')
const kernelRoot = defaultKernelRoot(_pkg, import.meta.url)
const store = new Corestore(corestorePath())
const drive = new Hyperdrive(store)
@@ -98,4 +99,8 @@ async function main() {
console.log('(Kernel read directly into Hyperdrive.) Corestore:', corestorePath())
}
main().catch(safetyCatch)
main().catch((err) => {
console.error('bare-os-seeder failed:', err?.message ?? err)
if (err?.stack) console.error(err.stack)
safetyCatch(err)
})
+4
View File
@@ -0,0 +1,4 @@
// Drive path: /bin/echo — print arguments (kernel invokes run(argv))
async function run(ctx, argv) {
ctx.console.log(argv.slice(1).join(' '))
}
+3
View File
@@ -0,0 +1,3 @@
async function run(ctx, _argv) {
ctx.console.log('Commands: help, echo <text>, exit')
}
@@ -0,0 +1,3 @@
NAME="BareOS"
VERSION="0.1.0"
VARIANT="hyperdrive-only"
+20
View File
@@ -0,0 +1,20 @@
/**
* Hyperdrive-resident kernel (staged as /boot/init.js).
* Loaded by the booter with an injected ctx object (trusted replication source).
*/
async function start(ctx) {
const { console, drive, readLine, execLine, b4a } = ctx
const rel = await drive.get('/etc/os-release')
if (rel) console.log(b4a.toString(rel))
console.log('Bare operating system — commands: help, echo, exit')
while (true) {
const line = await readLine('bare-os> ')
if (line == null) break
const t = line.trim()
if (t === '' || t === 'exit') {
if (t === 'exit') break
continue
}
await execLine(t)
}
}
+67
View File
@@ -0,0 +1,67 @@
import path from 'path'
import { statSync } from 'fs'
import { fileURLToPath } from 'node:url'
import os from 'bare-os'
function cwd() {
if (typeof globalThis.process?.cwd === 'function')
return globalThis.process.cwd()
return os.cwd()
}
function env(name) {
return globalThis.process?.env?.[name]
}
function kernelDirPresent(root) {
try {
return statSync(path.join(root, 'kernel')).isDirectory()
} catch {
return false
}
}
/**
* Directory containing this package (index.js, kernel/, …).
* Under `pear run`, `import.meta.url` is pear: — Pear may set `RTI.mount` and/or `swapDir`
* to different paths; prefer the first candidate that actually contains `kernel/` (see pear-rti).
*/
export function packageRootDir(metaUrl) {
const href = String(metaUrl)
if (href.startsWith('file:')) {
return path.dirname(fileURLToPath(href))
}
const rti = globalThis.Pear?.constructor?.RTI?.mount
const swap = globalThis.Pear?.config?.swapDir
const seen = new Set()
const candidates = []
for (const c of [rti, swap, cwd()].filter(Boolean)) {
const p = path.resolve(String(c))
if (!seen.has(p)) {
seen.add(p)
candidates.push(p)
}
}
for (const root of candidates) {
if (kernelDirPresent(root)) return root
}
return candidates[0] ?? cwd()
}
/** Default kernel tree: vendored `kernel/` next to the app (works for pear: and file:). */
export function defaultKernelRoot(pkgRoot, metaUrl) {
const override = env('BARE_OS_KERNEL_ROOT')
if (override) return path.resolve(override)
return path.join(pkgRoot, 'kernel')
}
/** Corestore directory for the seeder (host cache, not Hyperdrive OS state). */
export function defaultSeedCorestorePath(pkgRoot, metaUrl) {
const override = env('BARE_OS_SEED_STORE')
if (override) return override
const href = String(metaUrl)
const dataRoot = href.startsWith('file:')
? path.join(pkgRoot, '..', '..', 'data')
: path.join(pkgRoot, 'data')
return path.join(dataRoot, 'corestore-seeder')
}
+1
View File
@@ -0,0 +1 @@
../../node_modules
+5
View File
@@ -9,6 +9,7 @@
"dev": "bare index.js"
},
"dependencies": {
"bare-os": "^3.8.7",
"bare-os-protocol": "*",
"b4a": "^1.6.7",
"compact-encoding": "^2.18.0",
@@ -50,6 +51,10 @@
"url": {
"bare": "bare-url",
"default": "node:url"
},
"node:url": {
"bare": "bare-url",
"default": "node:url"
}
}
}