217ee25bfc68097bff1259592c5450882588ebb1f39c2254eb68d6ec991680cc.json raw
1 {"ast":null,"code":"import _asyncToGenerator from \"/home/mleku/src/orly.dev/next/signer/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\";\nimport { SimplePool } from 'nostr-tools/pool';\nimport { FALLBACK_PROFILE_RELAYS } from '../../constants/fallback-relays';\nimport * as i0 from \"@angular/core\";\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours\nconst FETCH_TIMEOUT_MS = 10000; // 10 seconds\nconst STORAGE_KEY = 'relayListCache';\nexport let RelayListService = /*#__PURE__*/(() => {\n class RelayListService {\n #cache = {};\n #pool = null;\n #fetchPromises = new Map();\n #initialized = false;\n #initPromise = null;\n /**\n * Initialize the service by loading cache from session storage\n */\n initialize() {\n var _this = this;\n return _asyncToGenerator(function* () {\n if (_this.#initialized) {\n return;\n }\n if (_this.#initPromise) {\n return _this.#initPromise;\n }\n _this.#initPromise = _this.#loadCacheFromStorage();\n yield _this.#initPromise;\n _this.#initialized = true;\n })();\n }\n /**\n * Load cache from browser session storage\n */\n #loadCacheFromStorage() {\n var _this2 = this;\n return _asyncToGenerator(function* () {\n try {\n if (typeof chrome !== 'undefined' && chrome.storage?.session) {\n const result = yield chrome.storage.session.get(STORAGE_KEY);\n if (result[STORAGE_KEY]) {\n _this2.#cache = result[STORAGE_KEY];\n _this2.#pruneStaleCache();\n }\n }\n } catch (error) {\n console.error('Failed to load relay list cache from storage:', error);\n }\n })();\n }\n /**\n * Save cache to browser session storage\n */\n #saveCacheToStorage() {\n var _this3 = this;\n return _asyncToGenerator(function* () {\n try {\n if (typeof chrome !== 'undefined' && chrome.storage?.session) {\n yield chrome.storage.session.set({\n [STORAGE_KEY]: _this3.#cache\n });\n }\n } catch (error) {\n console.error('Failed to save relay list cache to storage:', error);\n }\n })();\n }\n /**\n * Remove stale entries from cache\n */\n #pruneStaleCache() {\n const now = Date.now();\n for (const pubkey of Object.keys(this.#cache)) {\n if (now - this.#cache[pubkey].fetchedAt > CACHE_TTL_MS) {\n delete this.#cache[pubkey];\n }\n }\n }\n /**\n * Get the SimplePool instance, creating it if necessary\n */\n #getPool() {\n if (!this.#pool) {\n this.#pool = new SimplePool();\n }\n return this.#pool;\n }\n /**\n * Get cached relay list for a pubkey\n */\n getCachedRelayList(pubkey) {\n const cached = this.#cache[pubkey];\n if (!cached) {\n return null;\n }\n if (Date.now() - cached.fetchedAt > CACHE_TTL_MS) {\n delete this.#cache[pubkey];\n return null;\n }\n return cached.relays;\n }\n /**\n * Fetch NIP-65 relay list for a single pubkey\n */\n fetchRelayList(pubkey) {\n var _this4 = this;\n return _asyncToGenerator(function* () {\n yield _this4.initialize();\n // Check cache first\n const cached = _this4.getCachedRelayList(pubkey);\n if (cached) {\n return cached;\n }\n // Check if already fetching\n const existingPromise = _this4.#fetchPromises.get(pubkey);\n if (existingPromise) {\n return existingPromise;\n }\n // Start new fetch\n const fetchPromise = _this4.#doFetchRelayList(pubkey);\n _this4.#fetchPromises.set(pubkey, fetchPromise);\n try {\n const result = yield fetchPromise;\n return result;\n } finally {\n _this4.#fetchPromises.delete(pubkey);\n }\n })();\n }\n /**\n * Internal method to fetch a single relay list\n */\n #doFetchRelayList(pubkey) {\n var _this5 = this;\n return _asyncToGenerator(function* () {\n const pool = _this5.#getPool();\n try {\n const events = yield _this5.#queryWithTimeout(pool, FALLBACK_PROFILE_RELAYS, [{\n kinds: [10002],\n authors: [pubkey]\n }], FETCH_TIMEOUT_MS);\n if (events.length === 0) {\n return [];\n }\n // Get the most recent event (kind 10002 is replaceable)\n const latestEvent = events.reduce((latest, event) => event.created_at > latest.created_at ? event : latest);\n // Parse relay tags\n const relays = [];\n for (const tag of latestEvent.tags) {\n if (tag[0] === 'r' && tag[1]) {\n const url = tag[1];\n const marker = tag[2]; // Optional: \"read\" or \"write\"\n let read = true;\n let write = true;\n if (marker === 'read') {\n write = false;\n } else if (marker === 'write') {\n read = false;\n }\n // No marker means both read and write\n relays.push({\n url,\n read,\n write\n });\n }\n }\n // Cache the result\n _this5.#cache[pubkey] = {\n pubkey,\n relays,\n fetchedAt: Date.now()\n };\n yield _this5.#saveCacheToStorage();\n return relays;\n } catch (error) {\n console.error(`Failed to fetch relay list for ${pubkey}:`, error);\n return [];\n }\n })();\n }\n /**\n * Query relays with a timeout\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #queryWithTimeout(pool, relays, filters, timeoutMs) {\n return _asyncToGenerator(function* () {\n return new Promise(resolve => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const events = [];\n let settled = false;\n const timeout = setTimeout(() => {\n if (!settled) {\n settled = true;\n resolve(events);\n }\n }, timeoutMs);\n const sub = pool.subscribeMany(relays, filters, {\n onevent(event) {\n events.push(event);\n },\n oneose() {\n if (!settled) {\n settled = true;\n clearTimeout(timeout);\n sub.close();\n resolve(events);\n }\n }\n });\n });\n })();\n }\n /**\n * Clear the cache\n */\n clearCache() {\n var _this6 = this;\n return _asyncToGenerator(function* () {\n _this6.#cache = {};\n yield _this6.#saveCacheToStorage();\n })();\n }\n /**\n * Clear cache for a specific pubkey\n */\n clearCacheForPubkey(pubkey) {\n var _this7 = this;\n return _asyncToGenerator(function* () {\n delete _this7.#cache[pubkey];\n yield _this7.#saveCacheToStorage();\n })();\n }\n static ɵfac = function RelayListService_Factory(__ngFactoryType__) {\n return new (__ngFactoryType__ || RelayListService)();\n };\n static ɵprov = /*@__PURE__*/i0.ɵɵdefineInjectable({\n token: RelayListService,\n factory: RelayListService.ɵfac,\n providedIn: 'root'\n });\n }\n return RelayListService;\n})();","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}