thinkpool-pair 0.7.266 → 0.7.267
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bridge.mjs +4 -1
- package/package.json +1 -1
- package/reap-terminal.mjs +18 -4
package/bridge.mjs
CHANGED
|
@@ -695,7 +695,10 @@ async function refreshOwnerPlan() {
|
|
|
695
695
|
// unit-tested reap-terminal.mjs. Fire-and-forget from endStructured — the module never
|
|
696
696
|
// throws (best-effort), so an unawaited promise can't reject.
|
|
697
697
|
function reapTerminalRow(id) {
|
|
698
|
-
return _reapTerminalRow({
|
|
698
|
+
return _reapTerminalRow({
|
|
699
|
+
id, token: codeAuthToken, supabaseUrl: SUPABASE_URL, anonKey: SUPABASE_ANON, shuttingDown,
|
|
700
|
+
onFailure: ({ error, status }) => process.stderr.write(`\n ⚠ terminal row reap failed (${String(id).slice(0, 8)}${status ? `, HTTP ${status}` : ''}): ${error || 'unknown error'}\n`),
|
|
701
|
+
})
|
|
699
702
|
}
|
|
700
703
|
// Auth: is the sender a PARTICIPANT of THIS room (owner OR granted OR joined)? Room mode
|
|
701
704
|
// serves the room, so RLS returns participants; we confirm the jwt's user is one of them.
|
package/package.json
CHANGED
package/reap-terminal.mjs
CHANGED
|
@@ -24,10 +24,14 @@
|
|
|
24
24
|
// the feature, not the leak.
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* @returns {Promise<{reaped: boolean, reason: 'ok'|'shutdown'|'anon'|'no-id'|'error', error?: string}>}
|
|
27
|
+
* @returns {Promise<{reaped: boolean, reason: 'ok'|'shutdown'|'anon'|'no-id'|'error', error?: string, status?: number}>}
|
|
28
28
|
* Never throws — best-effort; the client reap (#205) is the fallback.
|
|
29
29
|
*/
|
|
30
|
-
export async function reapTerminalRow ({ id, token, supabaseUrl, anonKey, shuttingDown = false, fetchImpl = fetch }) {
|
|
30
|
+
export async function reapTerminalRow ({ id, token, supabaseUrl, anonKey, shuttingDown = false, fetchImpl = fetch, onFailure } = {}) {
|
|
31
|
+
const fail = (outcome) => {
|
|
32
|
+
try { onFailure?.(outcome) } catch { /* observability must not break a close */ }
|
|
33
|
+
return outcome
|
|
34
|
+
}
|
|
31
35
|
if (shuttingDown) return { reaped: false, reason: 'shutdown' }
|
|
32
36
|
if (!token) return { reaped: false, reason: 'anon' }
|
|
33
37
|
if (!id) return { reaped: false, reason: 'no-id' }
|
|
@@ -36,12 +40,22 @@ export async function reapTerminalRow ({ id, token, supabaseUrl, anonKey, shutti
|
|
|
36
40
|
// terminal id IS the code_terminals PK (client/bridge-minted uuid). RLS scopes the
|
|
37
41
|
// delete to this bridge's sessions, so id alone is sufficient + idempotent (a fast
|
|
38
42
|
// client tab may have reaped first — 204 / 0 rows is fine).
|
|
39
|
-
await fetchImpl(`${supabaseUrl}/rest/v1/code_terminals?id=eq.${encodeURIComponent(id)}`, {
|
|
43
|
+
const response = await fetchImpl(`${supabaseUrl}/rest/v1/code_terminals?id=eq.${encodeURIComponent(id)}`, {
|
|
40
44
|
method: 'DELETE',
|
|
41
45
|
headers: { apikey: anonKey, Authorization: `Bearer ${token}` },
|
|
42
46
|
})
|
|
47
|
+
// fetch resolves for HTTP failures. A 401/500 did not reap the row and must
|
|
48
|
+
// stay visible to the fire-and-forget caller as a failed best-effort cleanup.
|
|
49
|
+
if (!response?.ok) {
|
|
50
|
+
return fail({
|
|
51
|
+
reaped: false,
|
|
52
|
+
reason: 'error',
|
|
53
|
+
error: `HTTP ${response?.status ?? 'unknown'}${response?.statusText ? ` ${response.statusText}` : ''}`,
|
|
54
|
+
status: response?.status,
|
|
55
|
+
})
|
|
56
|
+
}
|
|
43
57
|
return { reaped: true, reason: 'ok' }
|
|
44
58
|
} catch (e) {
|
|
45
|
-
return { reaped: false, reason: 'error', error: e?.message }
|
|
59
|
+
return fail({ reaped: false, reason: 'error', error: e?.message })
|
|
46
60
|
}
|
|
47
61
|
}
|