Require only bare-* modules under Bare for Holesail control
CI / test (push) Successful in 10m3s

Stop falling back to Node builtin names (process/crypto/…) which
bare-module cannot resolve. Detect Bare via globalThis.Bare and drop
bare-process (use global pid instead).
This commit is contained in:
2026-07-10 23:22:10 -04:00
parent aa48876d75
commit f732cab26c
+43 -36
View File
@@ -1,40 +1,40 @@
/**
* Bare/Node control plane for local Holesail client sessions.
* Runs in the pear-electron Bare entry (index.js), where require.addon works.
* The UI renderer talks to this over http://127.0.0.1:<port> (never loads bare-tcp itself).
* The UI renderer talks to this over http://127.0.0.1:<port>.
*
* Uses Bare modules under Pear (via package.json "imports" bare conditions and
* which-runtime dual-load). Do not require bare Node built-ins alone on Bare.
* Under Bare: require ONLY bare-* packages (never Node builtin names like
* 'process' / 'crypto' — bare-module has no Node core builtins).
* Under Node: require Node core (bare-* native addons need Bare's require.addon).
*/
'use strict'
const { isBare } = require('which-runtime')
const isBare = typeof globalThis.Bare !== 'undefined'
// Prefer package.json imports maps; dual-load as fallback for older resolvers.
function load (bareName, nodeName) {
if (isBare) {
try {
return require(bareName)
} catch {
return require(nodeName)
}
}
try {
return require(nodeName)
} catch {
return require(bareName)
}
}
const http = load('bare-http1', 'http')
const fs = load('bare-fs', 'fs')
const path = load('bare-path', 'path')
const crypto = load('bare-crypto', 'crypto')
const net = load('bare-net', 'net')
const process = load('bare-process', 'process')
// Strict split — no cross-fallback (Bare cannot load 'process', Node cannot load bare-abort addons).
const http = isBare ? require('bare-http1') : require('http')
const fs = isBare ? require('bare-fs') : require('fs')
const path = isBare ? require('bare-path') : require('path')
const crypto = isBare ? require('bare-crypto') : require('crypto')
const net = isBare ? require('bare-net') : require('net')
const b4a = require('b4a')
const Holesail = require('holesail')
// Avoid bare-process / Node 'process' entirely
function getPid() {
try {
if (typeof globalThis.process?.pid === 'number') return globalThis.process.pid
} catch {
// ignore
}
try {
if (typeof globalThis.Bare?.pid === 'number') return globalThis.Bare.pid
} catch {
// ignore
}
return 0
}
/** @type {Map<string, { instance: any, localPort: number, host: string, url: string, info: object }>} */
const localClients = new Map()
@@ -74,7 +74,6 @@ async function connect(urlOrKey, opts = {}) {
log: false,
})
// Race ready against a timeout so the UI never hangs forever
const readyMs = Number(opts.readyTimeoutMs) || 45000
await Promise.race([
instance.ready(),
@@ -159,6 +158,12 @@ function sendJson(res, status, body) {
res.end(raw)
}
function makeToken() {
// bare-crypto and Node crypto both expose randomBytes
const bytes = crypto.randomBytes(16)
return b4a.toString(bytes, 'hex')
}
/**
* @param {{
* statePath?: string,
@@ -168,12 +173,11 @@ function sendJson(res, status, body) {
* }} [opts]
*/
async function start(opts = {}) {
const token = opts.token || crypto.randomBytes(16).toString('hex')
const token = opts.token || makeToken()
const host = opts.host || '127.0.0.1'
const pid = process.pid
const pid = getPid()
const server = http.createServer(async (req, res) => {
// CORS preflight (UI fetch from pear-bridge origin)
if (req.method === 'OPTIONS') {
res.statusCode = 204
res.setHeader('Access-Control-Allow-Origin', '*')
@@ -184,16 +188,19 @@ async function start(opts = {}) {
}
try {
// bare-url / WHATWG URL
const url = new URL(req.url || '/', `http://${host}`)
const pathname = url.pathname
if (pathname === '/health' && req.method === 'GET') {
sendJson(res, 200, { ok: true, service: 'holesail-local', clients: localClients.size })
sendJson(res, 200, {
ok: true,
service: 'holesail-local',
clients: localClients.size,
bare: isBare,
})
return
}
// All mutating / privileged routes need the token
if (pathname !== '/health') {
const hdr = req.headers['x-peardock-token']
const q = url.searchParams.get('token')
@@ -245,7 +252,7 @@ async function start(opts = {}) {
const addr = server.address()
const port = typeof addr === 'object' && addr ? addr.port : 0
const baseUrl = `http://${host}:${port}`
const meta = { port, host, token, baseUrl, pid }
const meta = { port, host, token, baseUrl, pid, bare: isBare }
if (opts.statePath) {
try {
@@ -262,9 +269,9 @@ async function start(opts = {}) {
...meta,
server,
async close() {
for (const url of [...localClients.keys()]) {
for (const u of [...localClients.keys()]) {
try {
await disconnect(url)
await disconnect(u)
} catch {
// ignore
}