Attempt 3

This commit is contained in:
Raven Scott
2026-04-22 19:17:59 -04:00
parent 1371a15314
commit 59af2a3dbf
@@ -340,20 +340,42 @@ export async function bareHolesailManagedSyncPersistedServerKey(ctx, env, id) {
}
/**
* Start one managed tunnel from the **current** `state.json` row for `id` (no normalize — uses disk as-is).
* Re-reads state immediately before `new Holesail` so `key` matches `~/.holesail/state.json`, including full `hs://…`.
* @param {Record<string, unknown>} ctx
* @param {Record<string, string | undefined>} env
* @param {string} id
* @param {Record<string, unknown>} entry
*/
async function startManagedInstance(ctx, env, id, entry) {
const norm = bareHolesailManagedNormalizeEntry(entry)
if (!norm.ok) throw new Error(norm.err)
if (!norm.entry.enabled) return
async function startManagedInstance(ctx, env, id) {
const { state } = await bareHolesailManagedReadState(ctx, env)
const raw = state.connections[id]
if (!raw || typeof raw !== 'object') return
const conn = /** @type {Record<string, unknown>} */ (raw)
const enabled =
conn.enabled === undefined || conn.enabled === null
? true
: bareHolesailEnvTruthy(conn.enabled)
if (!enabled) return
const server = bareHolesailEnvTruthy(conn.server)
const client = bareHolesailEnvTruthy(conn.client)
if (server === client) {
logLine(ctx, `managed: skip ${id}: set exactly one of server or client`)
return
}
const keyStr = String(conn.key ?? '').trim()
if (client && !keyStr) {
logLine(ctx, `managed: skip ${id}: client requires key`)
return
}
if (managedInstances.has(id)) {
const persisted = String(norm.entry.key ?? '').trim()
if (norm.entry.server && persisted) {
if (server && keyStr) {
const live = bareHolesailManagedRuntimeUrl(id).trim()
if (bareHolesailManagedPersistedUrlMatchesLive(persisted, live)) return
if (bareHolesailManagedPersistedUrlMatchesLive(keyStr, live)) return
await stopManagedInstance(ctx, id)
} else {
return
@@ -361,7 +383,7 @@ async function startManagedInstance(ctx, env, id, entry) {
}
const Holesail = await loadHolesailConstructor(ctx)
const conn = norm.entry
/** @type {number | boolean} */
let logLevel = 1
if (conn.log !== undefined && conn.log !== null && conn.log !== '') {
@@ -370,24 +392,26 @@ async function startManagedInstance(ctx, env, id, entry) {
logLevel = Number.parseInt(String(conn.log), 10)
else logLevel = bareHolesailEnvTruthy(conn.log)
}
/** Fields mirror `state.json` connection rows; `enabled` stays on the row only (not passed to holesail). */
/** Same shape as reading `connections[id]` from `state.json`; `enabled` is not passed upstream. */
/** @type {Record<string, unknown>} */
const cfg = {
server: conn.server,
client: conn.client,
server,
client,
port: conn.port,
host: conn.host,
key: conn.key,
log: logLevel
}
if (conn.secure !== undefined && conn.secure !== null && String(conn.secure) !== '')
cfg.secure = bareHolesailEnvTruthy(conn.secure)
if (conn.udp !== undefined && conn.udp !== null && String(conn.udp) !== '')
cfg.udp = bareHolesailEnvTruthy(conn.udp)
if (keyStr) cfg.key = keyStr
const hs = new Holesail(cfg)
await hs.ready()
managedInstances.set(id, { hs, entry: norm.entry })
if (norm.entry.server) {
managedInstances.set(id, { hs, entry: { ...conn } })
if (server) {
try {
await bareHolesailManagedSyncPersistedServerKey(ctx, env, id)
} catch (e) {
@@ -426,23 +450,18 @@ async function stopManagedInstance(ctx, id) {
export async function bareHolesailManagedStartService(ctx, env) {
if (managedServiceRunning) return
const { state } = await bareHolesailManagedReadState(ctx, env)
managedServiceRunning = true
for (const [id, raw] of Object.entries(state.connections)) {
const { state } = await bareHolesailManagedReadState(ctx, env)
const idsSorted = Object.keys(state.connections).sort()
for (const id of idsSorted) {
const idOk = bareHolesailManagedValidateId(id)
if (!idOk.ok) {
logLine(ctx, `managed: skip invalid id ${id}: ${idOk.err}`)
continue
}
const norm = bareHolesailManagedNormalizeEntry(raw)
if (!norm.ok) {
logLine(ctx, `managed: skip ${id}: ${norm.err}`)
continue
}
if (!norm.entry.enabled) continue
try {
await startManagedInstance(ctx, env, idOk.id, norm.entry)
await startManagedInstance(ctx, env, idOk.id)
} catch (e) {
const msg = (e && /** @type {{ message?: string }} */ (e).message) || String(e)
logLine(ctx, `managed: start ${id} failed: ${msg}`)
@@ -543,19 +562,15 @@ export async function bareHolesailManagedStartOne(ctx, env, id) {
if (!idOk.ok) throw new Error(idOk.err)
const { state } = await bareHolesailManagedReadState(ctx, env)
const raw = state.connections[idOk.id]
if (!raw) throw new Error(`holesail: unknown connection ${idOk.id}`)
const norm = bareHolesailManagedNormalizeEntry(raw)
if (!norm.ok) throw new Error(norm.err)
if (!norm.entry.enabled) throw new Error(`holesail: ${idOk.id} is disabled`)
await startManagedInstance(ctx, env, idOk.id, norm.entry)
if (norm.entry.server) {
try {
await bareHolesailManagedSyncPersistedServerKey(ctx, env, idOk.id)
} catch (e) {
const msg = (e && /** @type {{ message?: string }} */ (e).message) || String(e)
logLine(ctx, `managed: persist key ${idOk.id} (startOne): ${msg}`)
}
}
if (!raw || typeof raw !== 'object')
throw new Error(`holesail: unknown connection ${idOk.id}`)
const row = /** @type {Record<string, unknown>} */ (raw)
const en =
row.enabled === undefined || row.enabled === null
? true
: bareHolesailEnvTruthy(row.enabled)
if (!en) throw new Error(`holesail: ${idOk.id} is disabled`)
await startManagedInstance(ctx, env, idOk.id)
}
/**