From a69f0da702976260c5781ae58757d138ab7ed82d Mon Sep 17 00:00:00 2001 From: Silberengel Date: Fri, 15 May 2026 22:17:03 +0200 Subject: [PATCH] bug-fixes --- src/lib/link.ts | 5 ++-- src/lib/profile-search-query.ts | 7 ++---- src/lib/pubkey.ts | 3 ++- .../client-replaceable-events.service.ts | 24 ++++++++++++++----- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/lib/link.ts b/src/lib/link.ts index 3d80de04..eb009652 100644 --- a/src/lib/link.ts +++ b/src/lib/link.ts @@ -87,8 +87,9 @@ export const toNoteList = ({ return `${path}?${query.toString()}` } export const toProfile = (userId: string) => { - if (userId.startsWith('npub') || userId.startsWith('nprofile')) return `/users/${userId}` - const npub = nip19.npubEncode(userId) + const t = userId.trim().replace(/^nostr:/i, '').trim() + if (t.startsWith('npub') || t.startsWith('nprofile')) return `/users/${t}` + const npub = nip19.npubEncode(t) return `/users/${npub}` } export const toProfileList = ({ search, domain }: { search?: string; domain?: string }) => { diff --git a/src/lib/profile-search-query.ts b/src/lib/profile-search-query.ts index 116ddabf..16a02fab 100644 --- a/src/lib/profile-search-query.ts +++ b/src/lib/profile-search-query.ts @@ -7,13 +7,10 @@ const HEX_PUBKEY = /^[0-9a-f]{64}$/i * profile fetch and IndexedDB kind-0 matching. NIP-50 text search does not match bech32 npubs. */ export function decodeProfileSearchQueryToPubkeyHex(raw: string): string | undefined { - const q = raw.trim() + const q = raw.trim().replace(/^nostr:/i, '').trim() if (!q) return undefined if (HEX_PUBKEY.test(q)) return q.toLowerCase() - let bech = q - if (q.toLowerCase().startsWith('nostr:')) { - bech = q.slice(6).trim() - } + const bech = q try { const { type, data } = nip19.decode(bech) if (type === 'npub' && typeof data === 'string') return data.toLowerCase() diff --git a/src/lib/pubkey.ts b/src/lib/pubkey.ts index adb5499a..f8536782 100644 --- a/src/lib/pubkey.ts +++ b/src/lib/pubkey.ts @@ -49,7 +49,8 @@ export function pubkeyToNpub(pubkey: string) { } export function userIdToPubkey(userId: string) { - const trimmed = userId.trim() + /** NIP-21 `nostr:` URI — must strip before bech32 / hex branches (otherwise we miss `npub1` / hex). */ + const trimmed = userId.trim().replace(/^nostr:/i, '').trim() if (!trimmed) return '' if (trimmed.startsWith('npub1') || trimmed.startsWith('nprofile1')) { diff --git a/src/services/client-replaceable-events.service.ts b/src/services/client-replaceable-events.service.ts index f6ce0b98..6367817d 100644 --- a/src/services/client-replaceable-events.service.ts +++ b/src/services/client-replaceable-events.service.ts @@ -359,15 +359,21 @@ export class ReplaceableEventService { 'replaceableEventFromBigRelaysDataloader.loadMany' ) } catch (err) { + // Never throw: a DataLoader/relay error would abort the whole feed profile batch and skip IDB + // hydration in {@link fetchProfilesForPubkeysBody}. Degrade like timeout — gaps fill from IDB/session below. if (isPromiseTimeoutError(err)) { logger.warn('[ReplaceableEventService] Profile batch network load timed out', { missingCount: stillMissing.length, kind }) - newEvents = stillMissing.map(() => undefined) } else { - throw err + logger.warn('[ReplaceableEventService] Profile batch network load failed', { + missingCount: stillMissing.length, + kind, + error: err instanceof Error ? err.message : String(err) + }) } + newEvents = stillMissing.map(() => undefined) } newEvents.forEach((event, idx) => { if (event && !(event instanceof Error)) { @@ -1060,10 +1066,16 @@ export class ReplaceableEventService { 'fetchProfilesForPubkeys' ) } catch (err) { - if (!isPromiseTimeoutError(err)) throw err - logger.warn('[ReplaceableEventService] fetchProfilesForPubkeys exceeded wall timeout', { - pubkeyCount: deduped.length - }) + if (isPromiseTimeoutError(err)) { + logger.warn('[ReplaceableEventService] fetchProfilesForPubkeys exceeded wall timeout', { + pubkeyCount: deduped.length + }) + } else { + logger.warn('[ReplaceableEventService] fetchProfilesForPubkeys failed; using session / IndexedDB only', { + pubkeyCount: deduped.length, + error: err instanceof Error ? err.message : String(err) + }) + } return this.fetchProfilesForPubkeysLocalFallback(deduped) } }