diff options
| -rw-r--r-- | packages/meshbay-client/src/main.js | 25 | ||||
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/index-dock.js | 10 |
2 files changed, 24 insertions, 11 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js index a2a7a86..f582b57 100644 --- a/packages/meshbay-client/src/main.js +++ b/packages/meshbay-client/src/main.js @@ -1269,11 +1269,11 @@ function registerBridge() { // // The renderer never sees the session token. It names an operation and this // process executes it — the same pattern as hub:fetch. The token is read - // from the daemon's data directory, cached for the lifetime of this process, - // and never exposed through the preload. + // from the daemon's data directory on every call and never exposed through + // the preload. Not cached: the daemon writes a new one each run and deletes + // it on stop, so a cached copy answered 401 after every node restart, and an + // operation asked before any page had called detect() had none at all. - let _nodeToken = null; - let _nodePort = 18000; let _nodePairingCode = null; function nodeConfigPath() { @@ -1305,16 +1305,20 @@ function registerBridge() { } } + function nodeEndpoint() { + const nc = readNodeConfig(); + const token = readNodeToken(nc ? nc.dataDir : meshbayDataDir()); + return token ? { token, port: nc ? nc.uiPort : 18000 } : null; + } + handle('node:detect', async () => { const nc = readNodeConfig(); if (!nc) return { detected: false, configured: false }; const token = readNodeToken(nc.dataDir); if (!token) return { detected: false, configured: true }; - _nodeToken = token; - _nodePort = nc.uiPort; try { const r = await fetch( - `http://127.0.0.1:${_nodePort}/api/status?t=${_nodeToken}`, + `http://127.0.0.1:${nc.uiPort}/api/status?t=${token}`, { signal: AbortSignal.timeout(3000) }); if (!r.ok) return { detected: false, configured: true }; const status = await r.json(); @@ -1889,8 +1893,6 @@ function registerBridge() { const READY = ['running', 'waiting_for_node_key', 'waiting_for_account', 'waiting_for_hub', 'starting']; if (!READY.includes(status.status)) return null; - _nodeToken = token; - _nodePort = port; return { pk_node_ed25519: status.pk_node_ed25519 || '', status: status.status, version: status.version || '' }; } catch { return null; } @@ -2235,10 +2237,11 @@ function registerBridge() { handle('node:op', async (_e, name, args) => { const op = Object.hasOwn(NODE_OPS, String(name)) ? NODE_OPS[String(name)] : null; if (!op) throw new Error(`Refused: unknown node operation ${String(name)}`); - if (!_nodeToken) throw new Error('Node not detected'); + const endpoint = nodeEndpoint(); + if (!endpoint) throw new Error('Node not detected'); const [method, apiPath, body] = await op(anObject(args)); const sep = apiPath.includes('?') ? '&' : '?'; - const url = `http://127.0.0.1:${_nodePort}${apiPath}${sep}t=${_nodeToken}`; + const url = `http://127.0.0.1:${endpoint.port}${apiPath}${sep}t=${endpoint.token}`; const init = { method }; if (body !== undefined && body !== null) { init.headers = { 'Content-Type': 'application/json' }; diff --git a/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js b/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js index 6730e60..6c89eb6 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js @@ -51,9 +51,18 @@ function useLoopbackActivity() { let stopped = false; let timer = null; let last = ''; + // Asked before the first operation and again after any failure: detect() + // answers "no node" as a value, where an operation on an absent node is a + // rejected IPC call that Electron prints to its terminal on every poll. + let present = false; const poll = async () => { let delay = IDLE_POLL_MS; try { + if (!present) { + const found = await platform.node.detect(); + if (!found || !found.detected) throw new Error('no node'); + present = true; + } const data = await platform.node.op('indexStatus'); const next = {}; for (const g of (data && data.groups) || []) next[g.group_id] = fromLoopback(g); @@ -64,6 +73,7 @@ function useLoopbackActivity() { if (!stopped && text !== last) { last = text; setLocal(next); } } catch { // No node on this machine, or one older than the route. + present = false; if (!stopped && last !== '{}') { last = '{}'; setLocal({}); } delay = ABSENT_POLL_MS; } |