diff --git a/pages/index.tsx b/pages/index.tsx index 8e2f52352..f63e0b7a8 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -31,11 +31,12 @@ export default function Landing() { const [parsedProducts, setParsedProducts] = useState([]); const [listingCount, setListingCount] = useState(null); const [sellerCount, setSellerCount] = useState(null); + const productEventsLength = productEventContext.productEvents.length; const signerContext = useContext(SignerContext); useEffect(() => { - fetch("/api/db/marketplace-stats") + fetch("/api/db/marketplace-stats", { cache: "no-store" }) .then((r) => r.json()) .then((data) => { if (typeof data.listingCount === "number") @@ -46,7 +47,7 @@ export default function Landing() { .catch((error) => { console.error("Failed to fetch marketplace stats:", error); }); - }, []); + }, [productEventsLength]); useEffect(() => { if (router.pathname === "/" && signerContext.isLoggedIn) { router.push("/marketplace"); diff --git a/utils/nostr/fetch-service.ts b/utils/nostr/fetch-service.ts index 254d0b37e..14fd1142e 100644 --- a/utils/nostr/fetch-service.ts +++ b/utils/nostr/fetch-service.ts @@ -45,6 +45,23 @@ function isHexString(value: string): boolean { return /^[0-9a-fA-F]{64}$/.test(value); } +function parseJsonSafely(input: unknown): T | null { + if (typeof input !== "string") { + return null; + } + + const trimmed = input.trim(); + if (!trimmed) { + return null; + } + + try { + return JSON.parse(trimmed) as T; + } catch { + return null; + } +} + export const fetchAllPosts = async ( nostr: NostrManager, relays: string[], @@ -443,22 +460,20 @@ export const fetchProfile = async ( } for (const [pubkey, event] of latestDbEvents.entries()) { - try { - const content = JSON.parse(event.content); - const profile: NipProfile = { - pubkey: event.pubkey, - created_at: event.created_at, - content, - nip05Verified: false, - }; - dbProfileMap.set(pubkey, profile); - updateProfileIfNewer(profile); - } catch (error) { - console.error( - `Failed to parse profile from DB: ${pubkey}`, - error - ); + const content = parseJsonSafely>(event.content); + if (!content) { + console.warn(`Skipping invalid profile JSON from DB: ${pubkey}`); + continue; } + + const profile: NipProfile = { + pubkey: event.pubkey, + created_at: event.created_at, + content, + nip05Verified: false, + }; + dbProfileMap.set(pubkey, profile); + updateProfileIfNewer(profile); } if (dbProfileMap.size > 0) { @@ -494,23 +509,23 @@ export const fetchProfile = async ( !existing || event.created_at > existing.created_at ) { - try { - const content = JSON.parse(event.content); - const profile: NipProfile = { - pubkey: event.pubkey, - created_at: event.created_at, - content, - nip05Verified: false, - }; - profileMap.set(event.pubkey, profile); - updatedProfiles.set(event.pubkey, profile); - updateProfileIfNewer(profile); - } catch (error) { - console.error( - `Failed parse profile for pubkey: ${event.pubkey}, ${event.content}`, - error + const content = parseJsonSafely>(event.content); + if (!content) { + console.warn( + `Skipping invalid profile JSON for pubkey: ${event.pubkey}` ); + continue; } + + const profile: NipProfile = { + pubkey: event.pubkey, + created_at: event.created_at, + content, + nip05Verified: false, + }; + profileMap.set(event.pubkey, profile); + updatedProfiles.set(event.pubkey, profile); + updateProfileIfNewer(profile); } }