Fix Holesail in Bare standalone via static import
Release rolling / release (push) Successful in 8m20s

createRequire(import.meta.url) could not resolve holesail inside the
packed app bundle even though holesail was embedded. Import holesail
statically so Bare resolution works; surface loadError in status banner.
This commit is contained in:
Raven Scott
2026-07-11 15:50:56 -04:00
parent 6bdb64b1fd
commit 06022e6e90
2 changed files with 25 additions and 6 deletions
+1 -1
View File
@@ -121,7 +121,7 @@ logger.banner([
? 'off (ENABLE_HOLESAIL=0)' ? 'off (ENABLE_HOLESAIL=0)'
: hs?.available : hs?.available
? `on · max ${hs.max} tunnels` ? `on · max ${hs.max} tunnels`
: 'on but package missing' : `on but package missing${hs?.loadError ? ` · ${String(hs.loadError).slice(0, 80)}` : ''}`
}`, }`,
`Swarm RPC: ${isSwarmEnabled() ? 'on' : 'off'} · Plugins: ${isPluginsEnabled() ? 'on' : 'off'}`, `Swarm RPC: ${isSwarmEnabled() ? 'on' : 'off'} · Plugins: ${isPluginsEnabled() ? 'on' : 'off'}`,
`Log: ${logger.format} · level ${['error', 'warn', 'info', 'debug'][logger.level] || 'info'}`, `Log: ${logger.format} · level ${['error', 'warn', 'info', 'debug'][logger.level] || 'info'}`,
+24 -5
View File
@@ -10,14 +10,15 @@
* @see https://github.com/holesail/holesail * @see https://github.com/holesail/holesail
* @see docs/HOLESAIL.md * @see docs/HOLESAIL.md
*/ */
import { createRequire } from 'module'
import { randomBytes } from 'crypto' import { randomBytes } from 'crypto'
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
// Static import so bare-pack embeds holesail and Bare resolves it at load time.
// Dynamic createRequire(import.meta.url) fails in standalone bundles (parent URL
// does not match pack resolutions → "package missing").
import HolesailModule from 'holesail'
import logger from '../utils/logger.js' import logger from '../utils/logger.js'
const require = createRequire(import.meta.url)
/** @typedef {{ /** @typedef {{
* id: string, * id: string,
* name: string, * name: string,
@@ -95,10 +96,21 @@ function loadHolesail() {
if (HolesailCtor) return HolesailCtor if (HolesailCtor) return HolesailCtor
if (holesailLoadError) throw holesailLoadError if (holesailLoadError) throw holesailLoadError
try { try {
HolesailCtor = require('holesail') // CJS interop: module.exports = class Holesail → default under ESM
const mod = HolesailModule?.default ?? HolesailModule
if (typeof mod !== 'function') {
throw new Error(
`holesail export is not a constructor (got ${typeof mod})`
)
}
HolesailCtor = mod
return HolesailCtor return HolesailCtor
} catch (err) { } catch (err) {
holesailLoadError = err holesailLoadError = err
logger.error('Failed to load holesail package', {
error: err?.message || String(err),
stack: err?.stack,
})
throw err throw err
} }
} }
@@ -489,13 +501,20 @@ async function safeClose(instance) {
} }
export function holesailStatus() { export function holesailStatus() {
const available = isHolesailAvailable()
return { return {
enabled: isHolesailEnabled(), enabled: isHolesailEnabled(),
available: isHolesailAvailable(), available,
active: tunnels.size, active: tunnels.size,
max: MAX_TUNNELS, max: MAX_TUNNELS,
allowedHosts: [...allowedTunnelHosts()], allowedHosts: [...allowedTunnelHosts()],
persistPath: persistPath(), persistPath: persistPath(),
/** Present when available === false — helps diagnose bare packing / load issues */
loadError: available
? null
: holesailLoadError?.message || holesailLoadError
? String(holesailLoadError)
: 'unknown',
} }
} }