diff --git a/js/adminListStore.js b/js/adminListStore.js index afed1d2f..15e07323 100644 --- a/js/adminListStore.js +++ b/js/adminListStore.js @@ -9,6 +9,7 @@ import { ADMIN_COMMUNITY_BLACKLIST_PREFIX, isDevMode, } from "./config.js"; +import { SHORT_TIMEOUT_MS } from "./constants.js"; import { getRegisteredNostrClient, requestDefaultExtensionPermissions, @@ -549,22 +550,42 @@ async function fetchLatestListEvent(filter, contextLabel = "admin-list") { } let events = []; - if (pubkey) { - events = await nostrClient.fetchListIncrementally({ - kind, - pubkey, - dTag, - relayUrls: relays - }); - } else { + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => { + reject(createError("timeout", "Request timed out")); + }, SHORT_TIMEOUT_MS); + }); + + try { + if (pubkey) { + events = await Promise.race([ + nostrClient.fetchListIncrementally({ + kind, + pubkey, + dTag, + relayUrls: relays, + }), + timeoutPromise, + ]); + } else { // Fallback for non-specific queries const normalizedFilter = { kinds: [kind], - limit: 50 + limit: 50, }; if (dTag) normalizedFilter["#d"] = [dTag]; if (filter.authors) normalizedFilter.authors = filter.authors; - events = await nostrClient.pool.list(relays, [normalizedFilter]); + events = await Promise.race([ + nostrClient.pool.list(relays, [normalizedFilter]), + timeoutPromise, + ]); + } + } catch (error) { + devLogger.warn( + `[adminListStore] Fetch failed for ${contextLabel}:`, + error, + ); + throw error; } if (!events || !events.length) { diff --git a/tests/admin-list-store.test.mjs b/tests/admin-list-store.test.mjs index 5cb39353..c8f8beb4 100644 --- a/tests/admin-list-store.test.mjs +++ b/tests/admin-list-store.test.mjs @@ -3,6 +3,8 @@ import "./test-helpers/setup-localstorage.mjs"; import assert from "node:assert/strict"; +globalThis.__BITVID_DEV_MODE_OVERRIDE__ = true; + if (typeof globalThis.window === "undefined") { globalThis.window = {}; }