Browse Source

thin out the logging

master
Silberengel 1 month ago
parent
commit
1424c8e7c9
  1. 14
      src/lib/modules/comments/CommentThread.svelte
  2. 4
      src/lib/modules/discussions/DiscussionList.svelte
  3. 4
      src/lib/modules/discussions/DiscussionView.svelte
  4. 8
      src/lib/modules/feed/FeedPage.svelte
  5. 69
      src/lib/modules/profiles/ProfilePage.svelte
  6. 2
      src/lib/services/cache/cache-manager.ts
  7. 6
      src/lib/services/cache/deletion-tracker.ts
  8. 10
      src/lib/services/cache/draft-store.ts
  9. 14
      src/lib/services/cache/event-cache.ts
  10. 10
      src/lib/services/cache/indexeddb-store.ts
  11. 6
      src/lib/services/cache/markdown-cache.ts
  12. 6
      src/lib/services/cache/profile-cache.ts
  13. 8
      src/lib/services/cache/rss-cache.ts
  14. 53
      src/lib/services/nostr/nostr-client.ts
  15. 23
      src/routes/bookmarks/+page.svelte
  16. 22
      src/routes/cache/+page.svelte
  17. 4
      src/routes/discussions/+page.svelte
  18. 6
      src/routes/event/[id]/+page.svelte
  19. 6
      src/routes/find/+page.svelte
  20. 30
      src/routes/highlights/+page.svelte
  21. 6
      src/routes/lists/+page.svelte
  22. 8
      src/routes/relay/+page.svelte
  23. 19
      src/routes/replaceable/[d_tag]/+page.svelte
  24. 4
      src/routes/repos/+page.svelte
  25. 62
      src/routes/repos/[naddr]/+page.svelte
  26. 10
      src/routes/rss/+page.svelte
  27. 2
      src/routes/topics/+page.svelte

14
src/lib/modules/comments/CommentThread.svelte

@ -79,7 +79,7 @@
return loadComments(); return loadComments();
}).catch((error) => { }).catch((error) => {
if (isMounted) { // Only log if still mounted if (isMounted) { // Only log if still mounted
console.error('Error initializing nostrClient in CommentThread:', error); // Failed to initialize client
} }
// Still try to load comments even if initialization fails // Still try to load comments even if initialization fails
if (isMounted) { if (isMounted) {
@ -321,7 +321,7 @@
loading = true; // Only show loading if no cache loading = true; // Only show loading if no cache
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached comments:', error); // Cache error (non-critical)
loading = true; // Show loading if cache check fails loading = true; // Show loading if cache check fails
} }
@ -417,12 +417,12 @@
fetchNestedReplies().then(() => { fetchNestedReplies().then(() => {
subscribeToNestedReplies(); subscribeToNestedReplies();
}).catch((error) => { }).catch((error) => {
console.error('Error fetching nested replies:', error); // Failed to fetch nested replies
subscribeToNestedReplies(); subscribeToNestedReplies();
}); });
} catch (error) { } catch (error) {
console.error('Error loading comments:', error); // Failed to load comments
loading = false; loading = false;
} }
} }
@ -475,7 +475,7 @@
activeFetchPromises.add(subscriptionPromise); activeFetchPromises.add(subscriptionPromise);
subscriptionPromise.catch(error => { subscriptionPromise.catch(error => {
if (isMounted) { // Only log if still mounted if (isMounted) { // Only log if still mounted
console.error('Error subscribing to nested replies:', error); // Failed to subscribe to replies
} }
nestedSubscriptionActive = false; nestedSubscriptionActive = false;
}).finally(() => { }).finally(() => {
@ -729,13 +729,13 @@
// This subscription will handle all future updates for nested replies // This subscription will handle all future updates for nested replies
subscribeToNestedReplies(); subscribeToNestedReplies();
}).catch((error) => { }).catch((error) => {
console.error('Error fetching nested replies:', error); // Failed to fetch nested replies
// Still set up subscription even if fetch fails // Still set up subscription even if fetch fails
subscribeToNestedReplies(); subscribeToNestedReplies();
}); });
} catch (error) { } catch (error) {
console.error('Error reloading comments:', error); // Failed to reload comments
} finally { } finally {
loading = false; loading = false;
} }

4
src/lib/modules/discussions/DiscussionList.svelte

@ -151,7 +151,7 @@
} }
} }
} catch (error) { } catch (error) {
console.error('Error loading cached threads:', error); // Cache error (non-critical)
} }
} }
@ -397,7 +397,7 @@
} }
} }
} catch (error) { } catch (error) {
console.error('Error loading thread data:', error); // Failed to load threads
threadsMap = new Map(); threadsMap = new Map();
voteCountsReady = false; voteCountsReady = false;
} finally { } finally {

4
src/lib/modules/discussions/DiscussionView.svelte

@ -105,7 +105,7 @@
loading = true; // Only show loading if no cache loading = true; // Only show loading if no cache
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached event:', error); // Cache error (non-critical)
loading = true; // Show loading if cache check fails loading = true; // Show loading if cache check fails
} }
@ -122,7 +122,7 @@
rootEvent = await findRootEvent(event); rootEvent = await findRootEvent(event);
} }
} catch (error) { } catch (error) {
console.error('Error loading thread:', error); // Failed to load thread
} finally { } finally {
loading = false; loading = false;
} }

8
src/lib/modules/feed/FeedPage.svelte

@ -58,7 +58,7 @@
Virtualizer = module.Virtualizer; Virtualizer = module.Virtualizer;
return Virtualizer; return Virtualizer;
} catch (error) { } catch (error) {
console.error('Failed to load virtual scrolling:', error); // Virtual scrolling initialization failed
return null; return null;
} finally { } finally {
virtualizerLoading = false; virtualizerLoading = false;
@ -212,7 +212,7 @@
// Batch fetch referenced events for paginated events too // Batch fetch referenced events for paginated events too
await batchFetchReferencedEvents(filtered); await batchFetchReferencedEvents(filtered);
} catch (error) { } catch (error) {
console.error('Error loading older events:', error); // Failed to load older events
} finally { } finally {
loadingMore = false; loadingMore = false;
} }
@ -328,7 +328,7 @@
await batchFetchReferencedEvents(allEvents); await batchFetchReferencedEvents(allEvents);
} }
} catch (error) { } catch (error) {
console.error('Error loading feed:', error); // Failed to load feed
if (!events.length) { if (!events.length) {
relayError = 'Failed to load feed.'; relayError = 'Failed to load feed.';
} }
@ -476,7 +476,7 @@
preloadedReferencedEvents = merged; preloadedReferencedEvents = merged;
} }
} catch (error) { } catch (error) {
console.debug('[FeedPage] Error batch fetching referenced events:', error); // Failed to fetch referenced events (non-critical)
// Don't block on errors - components will fetch individually if needed // Don't block on errors - components will fetch individually if needed
} }
} }

69
src/lib/modules/profiles/ProfilePage.svelte

@ -121,7 +121,7 @@
await loadWallComments(profileEvent.id); await loadWallComments(profileEvent.id);
} }
} catch (error) { } catch (error) {
console.error('Error loading profile event:', error); // Failed to load profile
} }
} }
@ -147,7 +147,7 @@
loadingWall = true; // Only show loading if no cache loadingWall = true; // Only show loading if no cache
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached wall comments:', error); // Cache error is non-critical
loadingWall = true; // Show loading if cache check fails loadingWall = true; // Show loading if cache check fails
} }
@ -199,7 +199,7 @@
}) })
.sort((a, b) => b.created_at - a.created_at); .sort((a, b) => b.created_at - a.created_at);
} catch (error) { } catch (error) {
console.error('Error loading wall comments:', error); // Failed to load wall comments
if (isMounted) { if (isMounted) {
wallComments = []; wallComments = [];
} }
@ -267,7 +267,7 @@
// Sort by created_at descending // Sort by created_at descending
pins = pinnedEvents.sort((a, b) => b.created_at - a.created_at); pins = pinnedEvents.sort((a, b) => b.created_at - a.created_at);
} catch (error) { } catch (error) {
console.error('Error loading pins:', error); // Failed to load pins
pins = []; pins = [];
} }
} }
@ -326,7 +326,7 @@
loadingBookmarks = false; // Show cached content immediately loadingBookmarks = false; // Show cached content immediately
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached bookmarks:', error); // Cache error is non-critical
} }
// Stream fresh data from relays (progressive enhancement) // Stream fresh data from relays (progressive enhancement)
@ -388,7 +388,7 @@
} }
} }
} catch (error) { } catch (error) {
console.error('Error loading bookmarks:', error); // Failed to load bookmarks
if (isMounted) { if (isMounted) {
bookmarks = []; bookmarks = [];
} }
@ -454,7 +454,7 @@
.sort((a, b) => b.created_at - a.created_at) .sort((a, b) => b.created_at - a.created_at)
.slice(0, 100); // Limit to 100 most recent .slice(0, 100); // Limit to 100 most recent
} catch (error) { } catch (error) {
console.error('Error loading notifications:', error); // Failed to load notifications
notifications = []; notifications = [];
} }
} }
@ -525,7 +525,7 @@
}) })
.sort((a, b) => b.created_at - a.created_at); .sort((a, b) => b.created_at - a.created_at);
} catch (error) { } catch (error) {
console.debug('Error loading interactions with me:', error); // Cache error is non-critical
interactionsWithMe = []; interactionsWithMe = [];
} }
} }
@ -579,7 +579,7 @@
} }
} }
} catch (error) { } catch (error) {
console.error('Error decoding bech32:', error); // Invalid bech32 format
return null; return null;
} }
} }
@ -606,63 +606,43 @@
* Uses caching like jumble to avoid repeated lookups * Uses caching like jumble to avoid repeated lookups
*/ */
async function validateNIP05(nip05: string, expectedPubkey: string) { async function validateNIP05(nip05: string, expectedPubkey: string) {
console.log(`[NIP-05] Starting validation for ${nip05} with pubkey ${expectedPubkey.substring(0, 8)}...`); // Check cache first
// Check cache first (like jumble does)
const cacheKey = `${nip05}:${expectedPubkey}`; const cacheKey = `${nip05}:${expectedPubkey}`;
if (nip05ValidationCache.has(cacheKey)) { if (nip05ValidationCache.has(cacheKey)) {
const cachedResult = nip05ValidationCache.get(cacheKey)!; nip05Validations[nip05] = nip05ValidationCache.get(cacheKey)!;
console.log(`[NIP-05] Cache hit for ${nip05}: ${cachedResult}`);
nip05Validations[nip05] = cachedResult;
return; return;
} }
// Mark as checking
console.log(`[NIP-05] Cache miss, fetching for ${nip05}`);
nip05Validations[nip05] = null; nip05Validations[nip05] = null;
try { try {
// Parse NIP-05: format is "local@domain.com"
const [localPart, domain] = nip05.split('@'); const [localPart, domain] = nip05.split('@');
if (!localPart || !domain) { if (!localPart || !domain) {
console.log(`[NIP-05] Invalid format for ${nip05}`);
nip05Validations[nip05] = false; nip05Validations[nip05] = false;
nip05ValidationCache.set(cacheKey, false); nip05ValidationCache.set(cacheKey, false);
return; return;
} }
// Build URL using URL constructor (like jumble)
const url = getNIP05WellKnownUrl(nip05); const url = getNIP05WellKnownUrl(nip05);
if (!url) { if (!url) {
console.log(`[NIP-05] Failed to build URL for ${nip05}`);
nip05Validations[nip05] = false; nip05Validations[nip05] = false;
nip05ValidationCache.set(cacheKey, false); nip05ValidationCache.set(cacheKey, false);
return; return;
} }
console.log(`[NIP-05] Fetching ${url}`);
// Add timeout to prevent hanging
const controller = new AbortController(); const controller = new AbortController();
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => controller.abort(), 5000);
console.log(`[NIP-05] Timeout reached for ${nip05}`);
controller.abort();
}, 5000); // 5 second timeout
try { try {
const response = await fetch(url, { const response = await fetch(url, {
method: 'GET', method: 'GET',
headers: { headers: { 'Accept': 'application/json' },
'Accept': 'application/json'
},
signal: controller.signal signal: controller.signal
}); });
clearTimeout(timeoutId); clearTimeout(timeoutId);
console.log(`[NIP-05] Response status for ${nip05}: ${response.status}`);
if (!response.ok) { if (!response.ok) {
console.log(`[NIP-05] Response not OK for ${nip05}: ${response.status}`);
nip05Validations[nip05] = false; nip05Validations[nip05] = false;
nip05ValidationCache.set(cacheKey, false); nip05ValidationCache.set(cacheKey, false);
return; return;
@ -671,50 +651,39 @@
let data; let data;
try { try {
data = await response.json(); data = await response.json();
console.log(`[NIP-05] Parsed JSON for ${nip05}:`, data); } catch {
} catch (jsonError) {
console.error(`[NIP-05] Failed to parse JSON for ${nip05}:`, jsonError);
nip05Validations[nip05] = false; nip05Validations[nip05] = false;
nip05ValidationCache.set(cacheKey, false); nip05ValidationCache.set(cacheKey, false);
return; return;
} }
// Check if the response contains the expected pubkey
// NIP-05 format: { "names": { "local": "hex-pubkey" } }
const verifiedPubkey = data.names?.[localPart]; const verifiedPubkey = data.names?.[localPart];
const isValid = verifiedPubkey && typeof verifiedPubkey === 'string' const isValid = verifiedPubkey && typeof verifiedPubkey === 'string'
? verifiedPubkey.toLowerCase() === expectedPubkey.toLowerCase() ? verifiedPubkey.toLowerCase() === expectedPubkey.toLowerCase()
: false; : false;
console.log(`[NIP-05] Validation result for ${nip05}: ${isValid} (verified: ${verifiedPubkey}, expected: ${expectedPubkey.substring(0, 8)}...)`);
nip05Validations[nip05] = isValid; nip05Validations[nip05] = isValid;
nip05ValidationCache.set(cacheKey, isValid); nip05ValidationCache.set(cacheKey, isValid);
} catch (fetchError) { } catch (fetchError) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
// Check if it was aborted due to timeout
if (fetchError instanceof Error && fetchError.name === 'AbortError') { if (fetchError instanceof Error && fetchError.name === 'AbortError') {
console.log(`[NIP-05] Timeout/abort for ${nip05}`);
nip05Validations[nip05] = false; nip05Validations[nip05] = false;
nip05ValidationCache.set(cacheKey, false); nip05ValidationCache.set(cacheKey, false);
} else { } else {
console.error(`[NIP-05] Fetch error for ${nip05}:`, fetchError); throw fetchError;
throw fetchError; // Re-throw other errors
} }
} }
} catch (error) { } catch (error) {
console.error(`[NIP-05] Error validating ${nip05}:`, error);
nip05Validations[nip05] = false; nip05Validations[nip05] = false;
nip05ValidationCache.set(cacheKey, false); nip05ValidationCache.set(cacheKey, false);
} }
console.log(`[NIP-05] Validation complete for ${nip05}`);
} }
async function loadProfile() { async function loadProfile() {
if (!isMounted) return; if (!isMounted) return;
const param = $page.params.pubkey; const param = $page.params.pubkey;
if (!param) { if (!param) {
console.warn('No pubkey parameter provided to ProfilePage'); // Invalid route parameter
loading = false; loading = false;
profile = null; profile = null;
currentLoadPubkey = null; currentLoadPubkey = null;
@ -724,7 +693,7 @@
// Decode the parameter to hex pubkey // Decode the parameter to hex pubkey
const pubkey = decodePubkey(param); const pubkey = decodePubkey(param);
if (!pubkey) { if (!pubkey) {
console.warn('Invalid pubkey format:', param); // Invalid pubkey format
loading = false; loading = false;
profile = null; profile = null;
currentLoadPubkey = null; currentLoadPubkey = null;
@ -778,7 +747,7 @@
if (profileData?.nip05 && profileData.nip05.length > 0) { if (profileData?.nip05 && profileData.nip05.length > 0) {
for (const nip05 of profileData.nip05) { for (const nip05 of profileData.nip05) {
validateNIP05(nip05, pubkey).catch(err => { validateNIP05(nip05, pubkey).catch(err => {
console.error('[NIP-05] Unhandled validation error:', nip05, err); // NIP-05 validation failed
// Ensure state is set even on unhandled errors // Ensure state is set even on unhandled errors
nip05Validations[nip05] = false; nip05Validations[nip05] = false;
const cacheKey = `${nip05}:${pubkey}`; const cacheKey = `${nip05}:${pubkey}`;
@ -819,7 +788,7 @@
} catch (error) { } catch (error) {
// Only update state if this load wasn't aborted // Only update state if this load wasn't aborted
if (!abortController.signal.aborted && currentLoadPubkey === pubkey) { if (!abortController.signal.aborted && currentLoadPubkey === pubkey) {
console.error('Error loading profile:', error); // Failed to load profile
loading = false; loading = false;
profile = null; profile = null;
} }

2
src/lib/services/cache/cache-manager.ts vendored

@ -90,7 +90,7 @@ export async function getCacheStats(): Promise<CacheStats> {
} }
// If we get here, all retries failed // If we get here, all retries failed
console.error('Error getting cache stats (all retries failed):', lastError); // Failed to get cache stats after retries
// Return empty stats on error // Return empty stats on error
return { return {
totalEvents: 0, totalEvents: 0,

6
src/lib/services/cache/deletion-tracker.ts vendored

@ -36,7 +36,7 @@ async function getDeletedEventIdsFromCache(): Promise<Set<string>> {
} }
} }
} catch (error) { } catch (error) {
console.debug('Error getting deleted event IDs from cache:', error); // Cache read failed (non-critical)
} }
return deletedSet; return deletedSet;
@ -50,7 +50,7 @@ export async function isEventDeleted(eventId: string): Promise<boolean> {
const deletedIds = await getDeletedEventIdsFromCache(); const deletedIds = await getDeletedEventIdsFromCache();
return deletedIds.has(eventId); return deletedIds.has(eventId);
} catch (error) { } catch (error) {
console.debug('Error checking if event is deleted:', error); // Cache read failed (non-critical)
return false; return false;
} }
} }
@ -65,7 +65,7 @@ export async function getDeletedEventIds(eventIds: string[]): Promise<Set<string
// Return intersection of requested IDs and deleted IDs // Return intersection of requested IDs and deleted IDs
return new Set(eventIds.filter(id => deletedIds.has(id))); return new Set(eventIds.filter(id => deletedIds.has(id)));
} catch (error) { } catch (error) {
console.debug('Error checking deleted events:', error); // Cache read failed (non-critical)
return new Set<string>(); return new Set<string>();
} }
} }

10
src/lib/services/cache/draft-store.ts vendored

@ -29,7 +29,7 @@ export async function saveDraft(
}; };
await db.put('drafts', draft); await db.put('drafts', draft);
} catch (error) { } catch (error) {
console.warn('Error saving draft to IndexedDB:', error); // Draft save failed (non-critical)
} }
} }
@ -42,7 +42,7 @@ export async function getDraft(id: string): Promise<DraftData | null> {
const draft = await db.get('drafts', id); const draft = await db.get('drafts', id);
return (draft as DraftData) || null; return (draft as DraftData) || null;
} catch (error) { } catch (error) {
console.warn('Error reading draft from IndexedDB:', error); // Draft read failed (non-critical)
return null; return null;
} }
} }
@ -55,7 +55,7 @@ export async function deleteDraft(id: string): Promise<void> {
const db = await getDB(); const db = await getDB();
await db.delete('drafts', id); await db.delete('drafts', id);
} catch (error) { } catch (error) {
console.warn('Error deleting draft from IndexedDB:', error); // Draft delete failed (non-critical)
} }
} }
@ -75,7 +75,7 @@ export async function listDrafts(): Promise<DraftData[]> {
await tx.done; await tx.done;
return drafts; return drafts;
} catch (error) { } catch (error) {
console.warn('Error listing drafts from IndexedDB:', error); // Draft list failed (non-critical)
return []; return [];
} }
} }
@ -88,6 +88,6 @@ export async function clearAllDrafts(): Promise<void> {
const db = await getDB(); const db = await getDB();
await db.clear('drafts'); await db.clear('drafts');
} catch (error) { } catch (error) {
console.warn('Error clearing all drafts:', error); // Draft clear failed (non-critical)
} }
} }

14
src/lib/services/cache/event-cache.ts vendored

@ -27,7 +27,7 @@ export async function cacheEvent(event: NostrEvent): Promise<void> {
}; };
await db.put('events', cached); await db.put('events', cached);
} catch (error) { } catch (error) {
console.debug('Error caching event:', error); // Cache write failed (non-critical)
// Don't throw - caching failures shouldn't break the app // Don't throw - caching failures shouldn't break the app
} }
} }
@ -64,7 +64,7 @@ export async function cacheEvents(events: NostrEvent[]): Promise<void> {
// Wait for transaction to complete // Wait for transaction to complete
await tx.done; await tx.done;
} catch (error) { } catch (error) {
console.debug('Error caching events:', error); // Cache write failed (non-critical)
// Don't throw - caching failures shouldn't break the app // Don't throw - caching failures shouldn't break the app
} }
} }
@ -77,7 +77,7 @@ export async function getEvent(id: string): Promise<CachedEvent | undefined> {
const db = await getDB(); const db = await getDB();
return await db.get('events', id); return await db.get('events', id);
} catch (error) { } catch (error) {
console.debug('Error getting event from cache:', error); // Cache read failed (non-critical)
return undefined; return undefined;
} }
} }
@ -101,7 +101,7 @@ export async function getEventsByKind(kind: number, limit?: number): Promise<Cac
const sorted = events.sort((a, b) => b.created_at - a.created_at); const sorted = events.sort((a, b) => b.created_at - a.created_at);
return limit ? sorted.slice(0, limit) : sorted; return limit ? sorted.slice(0, limit) : sorted;
} catch (error) { } catch (error) {
console.debug('Error getting events by kind from cache:', error); // Cache read failed (non-critical)
return []; return [];
} }
} }
@ -125,7 +125,7 @@ export async function getEventsByPubkey(pubkey: string, limit?: number): Promise
const sorted = events.sort((a, b) => b.created_at - a.created_at); const sorted = events.sort((a, b) => b.created_at - a.created_at);
return limit ? sorted.slice(0, limit) : sorted; return limit ? sorted.slice(0, limit) : sorted;
} catch (error) { } catch (error) {
console.debug('Error getting events by pubkey from cache:', error); // Cache read failed (non-critical)
return []; return [];
} }
} }
@ -171,7 +171,7 @@ export async function getRecentCachedEvents(kinds: number[], maxAge: number = 15
try { try {
return await kindIndex.getAll(kind); return await kindIndex.getAll(kind);
} catch (error) { } catch (error) {
console.debug(`Error getting events for kind ${kind}:`, error); // Cache read failed for kind (non-critical)
return []; return [];
} }
}); });
@ -193,7 +193,7 @@ export async function getRecentCachedEvents(kinds: number[], maxAge: number = 15
const sorted = results.sort((a, b) => b.created_at - a.created_at); const sorted = results.sort((a, b) => b.created_at - a.created_at);
return sorted.slice(0, limit); return sorted.slice(0, limit);
} catch (error) { } catch (error) {
console.debug('Error getting recent cached events:', error); // Cache read failed (non-critical)
return []; return [];
} }
} }

10
src/lib/services/cache/indexeddb-store.ts vendored

@ -107,7 +107,7 @@ export async function getDB(): Promise<IDBPDatabase<DatabaseSchema>> {
} }
}, },
blocked() { blocked() {
console.warn('IndexedDB is blocked - another tab may have it open'); // IndexedDB blocked (another tab may have it open)
}, },
blocking() { blocking() {
// Close connection if another tab wants to upgrade // Close connection if another tab wants to upgrade
@ -128,7 +128,7 @@ export async function getDB(): Promise<IDBPDatabase<DatabaseSchema>> {
!dbInstance.objectStoreNames.contains('rss') || !dbInstance.objectStoreNames.contains('rss') ||
!dbInstance.objectStoreNames.contains('markdown')) { !dbInstance.objectStoreNames.contains('markdown')) {
// Database is corrupted - close and delete it, then recreate // Database is corrupted - close and delete it, then recreate
console.warn('Database missing required stores, recreating...'); // Database schema outdated, recreating
dbInstance.close(); dbInstance.close();
dbInstance = null; dbInstance = null;
@ -138,7 +138,7 @@ export async function getDB(): Promise<IDBPDatabase<DatabaseSchema>> {
deleteReq.onsuccess = () => resolve(); deleteReq.onsuccess = () => resolve();
deleteReq.onerror = () => reject(deleteReq.error); deleteReq.onerror = () => reject(deleteReq.error);
deleteReq.onblocked = () => { deleteReq.onblocked = () => {
console.warn('Database deletion blocked - another tab may have it open'); // Database deletion blocked (another tab may have it open)
resolve(); // Continue anyway resolve(); // Continue anyway
}; };
}); });
@ -164,7 +164,7 @@ export async function getDB(): Promise<IDBPDatabase<DatabaseSchema>> {
markdownStore.createIndex('cached_at', 'cached_at', { unique: false }); markdownStore.createIndex('cached_at', 'cached_at', { unique: false });
}, },
blocked() { blocked() {
console.warn('IndexedDB is blocked - another tab may have it open'); // IndexedDB blocked (another tab may have it open)
}, },
blocking() { blocking() {
if (dbInstance) { if (dbInstance) {
@ -177,7 +177,7 @@ export async function getDB(): Promise<IDBPDatabase<DatabaseSchema>> {
return dbInstance; return dbInstance;
} catch (error) { } catch (error) {
console.error('Failed to open IndexedDB:', error); // Failed to open IndexedDB
// Reset instance so we can retry // Reset instance so we can retry
dbInstance = null; dbInstance = null;
throw error; throw error;

6
src/lib/services/cache/markdown-cache.ts vendored

@ -42,7 +42,7 @@ export async function getCachedMarkdown(content: string): Promise<string | null>
return null; return null;
} catch (error) { } catch (error) {
console.debug('Error getting cached markdown:', error); // Cache read failed (non-critical)
return null; return null;
} }
} }
@ -61,7 +61,7 @@ export async function cacheMarkdown(content: string, rendered: string): Promise<
}; };
await db.put('markdown', cached); await db.put('markdown', cached);
} catch (error) { } catch (error) {
console.debug('Error caching markdown:', error); // Cache write failed (non-critical)
// Don't throw - caching failures shouldn't break the app // Don't throw - caching failures shouldn't break the app
} }
} }
@ -83,6 +83,6 @@ export async function clearOldMarkdownCache(olderThan: number): Promise<void> {
await tx.done; await tx.done;
} catch (error) { } catch (error) {
console.debug('Error clearing old markdown cache:', error); // Cache cleanup failed (non-critical)
} }
} }

6
src/lib/services/cache/profile-cache.ts vendored

@ -26,7 +26,7 @@ export async function cacheProfile(event: NostrEvent): Promise<void> {
}; };
await db.put('profiles', cached); await db.put('profiles', cached);
} catch (error) { } catch (error) {
console.debug('Error caching profile:', error); // Cache write failed (non-critical)
// Don't throw - caching failures shouldn't break the app // Don't throw - caching failures shouldn't break the app
} }
} }
@ -39,7 +39,7 @@ export async function getProfile(pubkey: string): Promise<CachedProfile | undefi
const db = await getDB(); const db = await getDB();
return await db.get('profiles', pubkey); return await db.get('profiles', pubkey);
} catch (error) { } catch (error) {
console.debug('Error getting profile from cache:', error); // Cache read failed (non-critical)
return undefined; return undefined;
} }
} }
@ -63,7 +63,7 @@ export async function getProfiles(pubkeys: string[]): Promise<Map<string, Cached
await tx.done; await tx.done;
return profiles; return profiles;
} catch (error) { } catch (error) {
console.debug('Error getting profiles from cache:', error); // Cache read failed (non-critical)
return new Map(); return new Map();
} }
} }

8
src/lib/services/cache/rss-cache.ts vendored

@ -37,7 +37,7 @@ export async function cacheRSSFeed(feedUrl: string, items: RSSItem[]): Promise<v
}; };
await db.put('rss', cached); await db.put('rss', cached);
} catch (error) { } catch (error) {
console.debug('Error caching RSS feed:', error); // Cache write failed (non-critical)
// Don't throw - caching failures shouldn't break the app // Don't throw - caching failures shouldn't break the app
} }
} }
@ -70,7 +70,7 @@ export async function getCachedRSSFeed(feedUrl: string): Promise<RSSItem[] | nul
return items; return items;
} catch (error) { } catch (error) {
console.debug('Error getting cached RSS feed:', error); // Cache read failed (non-critical)
return null; return null;
} }
} }
@ -103,7 +103,7 @@ export async function getAllCachedRSSFeeds(): Promise<Map<string, RSSItem[]>> {
return result; return result;
} catch (error) { } catch (error) {
console.debug('Error getting all cached RSS feeds:', error); // Cache read failed (non-critical)
return new Map(); return new Map();
} }
} }
@ -126,7 +126,7 @@ export async function clearExpiredRSSCaches(): Promise<void> {
await db.delete('rss', cached.feedUrl); await db.delete('rss', cached.feedUrl);
} }
} catch (error) { } catch (error) {
console.debug('Error clearing expired RSS caches:', error); // Cache cleanup failed (non-critical)
// Don't throw - cleanup failures shouldn't break the app // Don't throw - cleanup failures shouldn't break the app
} }
} }

53
src/lib/services/nostr/nostr-client.ts

@ -149,9 +149,7 @@ class NostrClient {
const stats = memoryManager.getStats(); const stats = memoryManager.getStats();
if (stats.totalSizeMB > 50) { if (stats.totalSizeMB > 50) {
const cleanedIds = memoryManager.cleanupOldEvents(25 * 1024 * 1024); const cleanedIds = memoryManager.cleanupOldEvents(25 * 1024 * 1024);
if (cleanedIds.length > 0) { // Memory cleanup completed
console.debug(`[nostr-client] Periodic cleanup: removed ${cleanedIds.length} tracked events (${stats.totalSizeMB.toFixed(2)}MB -> target 25MB)`);
}
} }
}, 30000); // Every 30 seconds }, 30000); // Every 30 seconds
} }
@ -184,9 +182,7 @@ class NostrClient {
} }
} }
if (toRemove.length > 0) { // Subscription cleanup completed
console.debug(`[nostr-client] Cleaned up ${toRemove.length} inactive subscriptions`);
}
}, 10000); // Check every 10 seconds }, 10000); // Check every 10 seconds
} }
@ -203,7 +199,7 @@ class NostrClient {
// Check if user is logged in // Check if user is logged in
const session = sessionManager.getSession(); const session = sessionManager.getSession();
if (!session) { if (!session) {
console.debug(`[nostr-client] Cannot authenticate with ${url}: user not logged in`); // User not logged in, cannot authenticate
return false; return false;
} }
@ -230,7 +226,6 @@ class NostrClient {
}); });
this.authenticatedRelays.add(url); this.authenticatedRelays.add(url);
console.debug(`[nostr-client] Successfully authenticated with relay: ${url}`);
return true; return true;
} }
} catch (error) { } catch (error) {
@ -243,7 +238,7 @@ class NostrClient {
.replace(/password/gi, '[password]') .replace(/password/gi, '[password]')
.replace(/nsec/gi, '[nsec]') .replace(/nsec/gi, '[nsec]')
.replace(/ncryptsec/gi, '[ncryptsec]'); .replace(/ncryptsec/gi, '[ncryptsec]');
console.warn(`[nostr-client] Failed to authenticate with relay ${url}:`, safeMessage); // Authentication failed (non-critical)
} }
return false; return false;
} }
@ -335,11 +330,11 @@ class NostrClient {
if (failureCount >= this.PERMANENT_FAILURE_THRESHOLD) { if (failureCount >= this.PERMANENT_FAILURE_THRESHOLD) {
// Only log once when threshold is reached // Only log once when threshold is reached
if (failureCount === this.PERMANENT_FAILURE_THRESHOLD) { if (failureCount === this.PERMANENT_FAILURE_THRESHOLD) {
console.warn(`[nostr-client] Relay ${url} has failed ${failureCount} times, will be skipped for this session`); // Relay temporarily disabled due to failures
} }
} else if (failureCount === 10) { } else if (failureCount === 10) {
// Log once at 10 failures as a warning // Log once at 10 failures as a warning
console.warn(`[nostr-client] Relay ${url} has failed ${failureCount} times, will stop retrying after ${this.PERMANENT_FAILURE_THRESHOLD} failures`); // Relay approaching permanent failure threshold
} }
// Don't throw - allow graceful degradation like jumble does // Don't throw - allow graceful degradation like jumble does
// The caller can check if relay was added by checking this.relays.has(url) // The caller can check if relay was added by checking this.relays.has(url)
@ -378,7 +373,7 @@ class NostrClient {
try { try {
const ws = (relay as any).ws; const ws = (relay as any).ws;
if (ws && (ws.readyState === WebSocket.CLOSED || ws.readyState === WebSocket.CLOSING)) { if (ws && (ws.readyState === WebSocket.CLOSED || ws.readyState === WebSocket.CLOSING)) {
console.debug(`[nostr-client] Relay ${relayUrl} WebSocket is closed, removing from active relays`); // Relay connection closed
this.relays.delete(relayUrl); this.relays.delete(relayUrl);
this.authenticatedRelays.delete(relayUrl); this.authenticatedRelays.delete(relayUrl);
return false; return false;
@ -402,7 +397,7 @@ class NostrClient {
await this.addRelay(url); await this.addRelay(url);
// Check if relay was actually added // Check if relay was actually added
if (!this.relays.has(url)) { if (!this.relays.has(url)) {
console.debug(`[nostr-client] Failed to connect to relay ${url}, skipping gracefully`); // Connection failed, skipping relay
return null; return null;
} }
} }
@ -443,7 +438,7 @@ class NostrClient {
const sorted = allEvents.sort((a, b) => b.created_at - a.created_at); const sorted = allEvents.sort((a, b) => b.created_at - a.created_at);
return sorted.slice(0, targetLimit); return sorted.slice(0, targetLimit);
} catch (error) { } catch (error) {
console.debug('Error getting events by kind from cache:', error); // Cache error (non-critical)
return []; return [];
} }
} }
@ -467,7 +462,7 @@ class NostrClient {
const sorted = allEvents.sort((a, b) => b.created_at - a.created_at); const sorted = allEvents.sort((a, b) => b.created_at - a.created_at);
return sorted.slice(0, targetLimit); return sorted.slice(0, targetLimit);
} catch (error) { } catch (error) {
console.debug('Error getting events by pubkey from cache:', error); // Cache error (non-critical)
return []; return [];
} }
} }
@ -546,7 +541,7 @@ class NostrClient {
await tx.done; await tx.done;
candidateEvents = events; candidateEvents = events;
} catch (dbError) { } catch (dbError) {
console.error('[nostr-client] Error querying IndexedDB for recent events:', dbError); // IndexedDB query failed (non-critical)
candidateEvents = []; candidateEvents = [];
} }
} }
@ -619,7 +614,7 @@ class NostrClient {
} }
} catch (error) { } catch (error) {
// Continue with other filters // Continue with other filters
console.error('[nostr-client] Error querying cache for filter:', error, filter); // Cache query failed (non-critical)
} }
} }
@ -632,12 +627,12 @@ class NostrClient {
// Only log cache queries when significant filtering happens or large result sets // Only log cache queries when significant filtering happens or large result sets
// This reduces noise from background cache enhancement queries // This reduces noise from background cache enhancement queries
if (filtered.length > 10 || (filtered.length > 0 && limited.length > filtered.length * 3)) { if (filtered.length > 10 || (filtered.length > 0 && limited.length > filtered.length * 3)) {
console.debug(`[nostr-client] Cache query: ${limited.length} events before filter, ${filtered.length} after filter`); // Cache query completed
} }
return filtered; return filtered;
} catch (error) { } catch (error) {
console.error('[nostr-client] Error getting cached events:', error); // Cache error (non-critical)
return []; return [];
} }
} }
@ -689,7 +684,7 @@ class NostrClient {
// Check if it's a closed connection error // Check if it's a closed connection error
const errorMessage = error instanceof Error ? error.message : String(error); const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('SendingOnClosedConnection') || errorMessage.includes('closed connection')) { if (errorMessage.includes('SendingOnClosedConnection') || errorMessage.includes('closed connection')) {
console.debug(`[nostr-client] Relay ${url} connection closed during publish, removing from active relays`); // Relay closed during publish
this.relays.delete(url); this.relays.delete(url);
this.authenticatedRelays.delete(url); this.authenticatedRelays.delete(url);
} }
@ -813,7 +808,7 @@ class NostrClient {
// Handle errors - setupSubscription already handles closed connection errors // Handle errors - setupSubscription already handles closed connection errors
const errorMessage = error instanceof Error ? error.message : String(error); const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('SendingOnClosedConnection') || errorMessage.includes('closed connection')) { if (errorMessage.includes('SendingOnClosedConnection') || errorMessage.includes('closed connection')) {
console.debug(`[nostr-client] Relay ${url} connection closed, removing from active relays`); // Relay connection closed
this.relays.delete(url); this.relays.delete(url);
this.authenticatedRelays.delete(url); this.authenticatedRelays.delete(url);
} }
@ -835,7 +830,7 @@ class NostrClient {
// Check relay status before setting up subscription // Check relay status before setting up subscription
if (!this.checkAndCleanupRelay(url)) { if (!this.checkAndCleanupRelay(url)) {
console.debug(`[nostr-client] Relay ${url} is closed, skipping subscription setup`); // Relay closed, skipping subscription
return; return;
} }
@ -846,7 +841,7 @@ class NostrClient {
const startSub = () => { const startSub = () => {
// Check relay status again before subscribing // Check relay status again before subscribing
if (!client.checkAndCleanupRelay(url)) { if (!client.checkAndCleanupRelay(url)) {
console.debug(`[nostr-client] Relay ${url} closed before subscription, aborting`); // Relay closed before subscription
return; return;
} }
@ -898,7 +893,7 @@ class NostrClient {
// Handle SendingOnClosedConnection and other errors // Handle SendingOnClosedConnection and other errors
const errorMessage = error instanceof Error ? error.message : String(error); const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('SendingOnClosedConnection') || errorMessage.includes('closed connection')) { if (errorMessage.includes('SendingOnClosedConnection') || errorMessage.includes('closed connection')) {
console.debug(`[nostr-client] Relay ${url} connection closed during subscription setup, removing from active relays`); // Relay closed during subscription setup
this.relays.delete(url); this.relays.delete(url);
this.authenticatedRelays.delete(url); this.authenticatedRelays.delete(url);
} }
@ -1022,7 +1017,7 @@ class NostrClient {
// Simple timeout - single timeout per fetch // Simple timeout - single timeout per fetch
timeoutId = setTimeout(() => { timeoutId = setTimeout(() => {
if (!resolved) { if (!resolved) {
console.debug(`[nostr-client] Timeout reached for ${relayUrl}`); // Request timeout
finish(); finish();
} }
}, timeout); }, timeout);
@ -1113,7 +1108,7 @@ class NostrClient {
for (const id of cleanedIds) { for (const id of cleanedIds) {
events.delete(id); events.delete(id);
} }
console.warn(`[nostr-client] Memory cleanup: removed ${cleanedIds.length} events from Map (${stats.totalSizeMB.toFixed(2)}MB -> target 25MB)`); // Memory cleanup completed
} }
} }
@ -1171,13 +1166,13 @@ class NostrClient {
startSub(); // Retry subscription after authentication startSub(); // Retry subscription after authentication
} }
} else { } else {
console.debug(`[nostr-client] Authentication failed for ${relayUrl} after 0-event EOSE`); // Authentication failed (expected for some relays)
finish(); finish();
} }
}) })
.catch((error) => { .catch((error) => {
authInProgress = false; authInProgress = false;
console.debug(`[nostr-client] Authentication error for ${relayUrl} after 0-event EOSE:`, error); // Authentication error (non-critical)
finish(); finish();
}); });
return; // Don't finish yet, wait for auth return; // Don't finish yet, wait for auth
@ -1208,7 +1203,7 @@ class NostrClient {
startSub(); startSub();
} }
} else { } else {
console.debug(`[nostr-client] Authentication failed for ${relayUrl}`); // Authentication failed (non-critical)
finish(); finish();
} }
}) })

23
src/routes/bookmarks/+page.svelte

@ -130,7 +130,6 @@
} }
} }
console.log(`[Bookmarks] Found ${bookmarkMap.size} unique bookmarked event IDs from ${fetchedBookmarkLists.length} bookmark lists`);
// 2. Fetch highlight events (kind 9802) - limit 100 // 2. Fetch highlight events (kind 9802) - limit 100
// Use profile read relays for highlights (they might be on different relays) // Use profile read relays for highlights (they might be on different relays)
@ -148,7 +147,6 @@
} }
); );
console.log(`[Bookmarks] Found ${highlightEvents.length} highlight events from ${allRelaysForHighlights.length} relays`);
// For highlights, we store the highlight event itself, mapped by source event ID // For highlights, we store the highlight event itself, mapped by source event ID
// sourceEventId -> highlight event // sourceEventId -> highlight event
@ -185,14 +183,9 @@
// Store highlights without refs to display them directly // Store highlights without refs to display them directly
highlightsWithoutRefs.push({ highlight, authorPubkey: highlight.pubkey }); highlightsWithoutRefs.push({ highlight, authorPubkey: highlight.pubkey });
// Log a sample of highlights without refs for debugging // Log a sample of highlights without refs for debugging
if (highlightsWithNoRefs <= 3) {
console.debug(`[Bookmarks] Highlight ${highlight.id.substring(0, 16)}... has no e-tag or a-tag. Tags:`, highlight.tags.map(t => t[0]).join(', '));
}
} }
} }
console.log(`[Bookmarks] Found ${highlightBySourceEvent.size} e-tag references and ${aTagHighlights.size} a-tag references`);
console.log(`[Bookmarks] Highlights breakdown: ${highlightsWithETags} with e-tags, ${highlightsWithATags} with a-tags only, ${highlightsWithNoRefs} with no event references`);
// Second pass: fetch events for a-tags in batches (grouped by kind+pubkey+d-tag) // Second pass: fetch events for a-tags in batches (grouped by kind+pubkey+d-tag)
if (aTagHighlights.size > 0) { if (aTagHighlights.size > 0) {
@ -312,16 +305,14 @@
} }
} }
console.log(`[Bookmarks] Resolved ${eventToATag.size} events from ${aTagGroups.size} a-tag groups`);
} catch (err) { } catch (err) {
console.error('[Bookmarks] Error fetching events for a-tags:', err); // Non-critical: a-tag resolution failed
} }
} }
} }
// Get source event IDs for highlights (to fetch them for sorting/display) // Get source event IDs for highlights (to fetch them for sorting/display)
const highlightSourceEventIds = Array.from(highlightBySourceEvent.keys()); const highlightSourceEventIds = Array.from(highlightBySourceEvent.keys());
console.log(`[Bookmarks] Total extracted ${highlightSourceEventIds.length} source event IDs from ${highlightEvents.length} highlight events`);
// Combine all event IDs (bookmarks + highlight source events) // Combine all event IDs (bookmarks + highlight source events)
const allEventIds = new Set([...bookmarkMap.keys(), ...highlightSourceEventIds]); const allEventIds = new Set([...bookmarkMap.keys(), ...highlightSourceEventIds]);
@ -334,21 +325,16 @@
// Limit to maxTotalItems // Limit to maxTotalItems
const eventIds = Array.from(allEventIds).slice(0, maxTotalItems); const eventIds = Array.from(allEventIds).slice(0, maxTotalItems);
if (allEventIds.size > maxTotalItems) { if (allEventIds.size > maxTotalItems) {
console.log(`[Bookmarks] Limiting to ${maxTotalItems} items (found ${allEventIds.size})`);
} }
// Fetch the actual events - batch to avoid relay limits (use smaller batch size to avoid "arr too big" errors) // Fetch the actual events - batch to avoid relay limits (use smaller batch size to avoid "arr too big" errors)
const batchSize = 100; // Reduced from 500 to avoid relay limits const batchSize = 100; // Reduced from 500 to avoid relay limits
const allFetchedEvents: NostrEvent[] = []; const allFetchedEvents: NostrEvent[] = [];
console.log(`[Bookmarks] Fetching ${eventIds.length} events in batches of ${batchSize}`);
for (let i = 0; i < eventIds.length; i += batchSize) { for (let i = 0; i < eventIds.length; i += batchSize) {
const batch = eventIds.slice(i, i + batchSize); const batch = eventIds.slice(i, i + batchSize);
const filters = [{ ids: batch }]; const filters = [{ ids: batch }];
console.log(`[Bookmarks] Fetching batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(eventIds.length / batchSize)} (${batch.length} events)`);
const batchEvents = await nostrClient.fetchEvents( const batchEvents = await nostrClient.fetchEvents(
filters, filters,
relays, relays,
@ -359,11 +345,8 @@
} }
); );
console.log(`[Bookmarks] Batch ${Math.floor(i / batchSize) + 1} returned ${batchEvents.length} events`);
allFetchedEvents.push(...batchEvents); allFetchedEvents.push(...batchEvents);
} }
console.log(`[Bookmarks] Total fetched: ${allFetchedEvents.length} events`);
// Track which highlights we've already added (to avoid duplicates) // Track which highlights we've already added (to avoid duplicates)
const addedHighlightIds = new Set<string>(); const addedHighlightIds = new Set<string>();
@ -442,12 +425,12 @@
timeout: config.standardTimeout timeout: config.standardTimeout
} }
).catch(err => { ).catch(err => {
console.debug('[Bookmarks] Error pre-fetching profiles:', err); // Profile pre-fetch failed (non-critical)
// Don't block on profile fetch errors // Don't block on profile fetch errors
}); });
} }
} catch (err) { } catch (err) {
console.error('Error loading bookmarks and highlights:', err); // Failed to load bookmarks
error = err instanceof Error ? err.message : 'Failed to load bookmarks and highlights'; error = err instanceof Error ? err.message : 'Failed to load bookmarks and highlights';
} finally { } finally {
loading = false; loading = false;

22
src/routes/cache/+page.svelte vendored

@ -46,7 +46,7 @@
try { try {
stats = await getCacheStats(); stats = await getCacheStats();
} catch (error) { } catch (error) {
console.error('Error loading cache stats:', error); // Failed to load cache stats
} }
} }
@ -78,7 +78,7 @@
hasMore = newEvents.length === PAGE_SIZE; hasMore = newEvents.length === PAGE_SIZE;
offset = events.length; offset = events.length;
} catch (error) { } catch (error) {
console.error('Error loading events:', error); // Failed to load events
} finally { } finally {
loadingMore = false; loadingMore = false;
loading = false; loading = false;
@ -102,7 +102,7 @@
expandedEvents.delete(id); expandedEvents.delete(id);
await loadStats(); await loadStats();
} catch (error) { } catch (error) {
console.error('Error deleting event:', error); // Failed to delete event
alert('Failed to delete event'); alert('Failed to delete event');
} finally { } finally {
deletingEventId = null; deletingEventId = null;
@ -122,7 +122,7 @@
await loadEvents(true); await loadEvents(true);
alert('Cache cleared successfully'); alert('Cache cleared successfully');
} catch (error) { } catch (error) {
console.error('Error clearing cache:', error); // Failed to clear cache
alert('Failed to clear cache'); alert('Failed to clear cache');
} }
} }
@ -142,7 +142,7 @@
await loadEvents(true); await loadEvents(true);
alert(`Deleted ${deleted} events`); alert(`Deleted ${deleted} events`);
} catch (error) { } catch (error) {
console.error('Error clearing cache by kind:', error); // Failed to clear cache by kind
alert('Failed to clear cache'); alert('Failed to clear cache');
} }
} }
@ -162,7 +162,7 @@
await loadEvents(true); await loadEvents(true);
alert(`Deleted ${deleted} events`); alert(`Deleted ${deleted} events`);
} catch (error) { } catch (error) {
console.error('Error clearing cache by date:', error); // Failed to clear cache by date
alert('Failed to clear cache'); alert('Failed to clear cache');
} }
} }
@ -182,7 +182,7 @@
await loadEvents(true); await loadEvents(true);
alert(`Deleted ${deleted} events`); alert(`Deleted ${deleted} events`);
} catch (error) { } catch (error) {
console.error('Error clearing cache by kinds:', error); // Failed to clear cache by kinds
alert('Failed to clear cache'); alert('Failed to clear cache');
} }
} }
@ -202,7 +202,7 @@
await navigator.clipboard.writeText(json); await navigator.clipboard.writeText(json);
// Could show a toast notification here // Could show a toast notification here
} catch (error) { } catch (error) {
console.error('Error copying to clipboard:', error); // Failed to copy to clipboard
alert('Failed to copy to clipboard'); alert('Failed to copy to clipboard');
} }
} }
@ -411,20 +411,20 @@
} }
if (retries === 0 && lastError) { if (retries === 0 && lastError) {
console.error('Error reloading stats after delete (all retries failed):', lastError); // Failed to reload stats after delete
// Don't show error to user - stats will update on next manual refresh // Don't show error to user - stats will update on next manual refresh
} }
alert(`Delete request published to ${result.success.length} relay(s) and event removed from cache`); alert(`Delete request published to ${result.success.length} relay(s) and event removed from cache`);
} catch (deleteError) { } catch (deleteError) {
console.error('Error deleting from cache:', deleteError); // Failed to delete from cache
alert(`Delete request published to ${result.success.length} relay(s), but failed to remove from cache: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`); alert(`Delete request published to ${result.success.length} relay(s), but failed to remove from cache: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
} }
} else { } else {
alert('Failed to publish delete request'); alert('Failed to publish delete request');
} }
} catch (error) { } catch (error) {
console.error('Error publishing delete request:', error); // Failed to publish delete request
alert('Failed to publish delete request'); alert('Failed to publish delete request');
} finally { } finally {
deletingEventId = null; deletingEventId = null;

4
src/routes/discussions/+page.svelte

@ -30,7 +30,9 @@
} }
onMount(() => { onMount(() => {
nostrClient.initialize().catch(console.error); nostrClient.initialize().catch(() => {
// Client initialization failed
});
}); });
</script> </script>

6
src/routes/event/[id]/+page.svelte

@ -75,13 +75,13 @@
if (events.length > 0) { if (events.length > 0) {
return events[0].id; return events[0].id;
} else { } else {
console.warn('Event not found for naddr:', param); // Event not found for naddr
return null; return null;
} }
} }
} }
} catch (error) { } catch (error) {
console.error('Error decoding bech32:', error); // Invalid bech32 format
return null; return null;
} }
} }
@ -121,7 +121,7 @@
error = 'Event not found or invalid format'; error = 'Event not found or invalid format';
} }
} catch (err) { } catch (err) {
console.error('Error loading event:', err); // Failed to load event
error = 'Failed to load event'; error = 'Failed to load event';
} finally { } finally {
loading = false; loading = false;

6
src/routes/find/+page.svelte

@ -461,7 +461,7 @@
searching = false; searching = false;
} catch (error) { } catch (error) {
console.error('Error searching with filters:', error); // Search failed
searching = false; searching = false;
searchResults = { events: [], profiles: [], relays: [] }; searchResults = { events: [], profiles: [], relays: [] };
} }
@ -506,7 +506,7 @@
} }
} catch (error) { } catch (error) {
// Not a valid bech32, continue with text search // Not a valid bech32, continue with text search
console.debug('Error decoding bech32:', error); // Invalid bech32 format
} }
} }
@ -644,7 +644,7 @@
searching = false; searching = false;
} catch (error) { } catch (error) {
console.error('Error searching with combined filters:', error); // Search failed
searching = false; searching = false;
searchResults = { events: [], profiles: [], relays: [] }; searchResults = { events: [], profiles: [], relays: [] };
} }

30
src/routes/highlights/+page.svelte

@ -110,8 +110,8 @@
loading = true; // Only show loading if no cache loading = true; // Only show loading if no cache
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached highlights:', error); // Cache error is non-critical, continue with relay fetch
loading = true; // Show loading if cache check fails loading = true;
} }
error = null; error = null;
@ -150,8 +150,6 @@
await processHighlightEvents(highlightEvents); await processHighlightEvents(highlightEvents);
} }
console.log(`[Highlights] Found ${highlightEvents.length} highlight events from ${allRelaysForHighlights.length} relays`);
// For highlights, we store the highlight event itself, mapped by source event ID // For highlights, we store the highlight event itself, mapped by source event ID
const highlightBySourceEvent = new Map<string, { highlight: NostrEvent; authorPubkey: string }>(); const highlightBySourceEvent = new Map<string, { highlight: NostrEvent; authorPubkey: string }>();
const aTagHighlights = new Map<string, { highlight: NostrEvent; pubkey: string }>(); const aTagHighlights = new Map<string, { highlight: NostrEvent; pubkey: string }>();
@ -184,14 +182,9 @@
if (!hasRef) { if (!hasRef) {
highlightsWithNoRefs++; highlightsWithNoRefs++;
highlightsWithoutRefs.push({ highlight, authorPubkey: highlight.pubkey }); highlightsWithoutRefs.push({ highlight, authorPubkey: highlight.pubkey });
if (highlightsWithNoRefs <= 3) {
console.debug(`[Highlights] Highlight ${highlight.id.substring(0, 16)}... has no e-tag or a-tag. Tags:`, highlight.tags.map(t => t[0]).join(', '));
}
} }
} }
console.log(`[Highlights] Found ${highlightBySourceEvent.size} e-tag references and ${aTagHighlights.size} a-tag references`);
console.log(`[Highlights] Highlights breakdown: ${highlightsWithETags} with e-tags, ${highlightsWithATags} with a-tags only, ${highlightsWithNoRefs} with no event references`);
// Second pass: fetch events for a-tags in batches (grouped by kind+pubkey+d-tag) // Second pass: fetch events for a-tags in batches (grouped by kind+pubkey+d-tag)
if (aTagHighlights.size > 0) { if (aTagHighlights.size > 0) {
@ -307,35 +300,26 @@
} }
} }
console.log(`[Highlights] Resolved ${eventToATag.size} events from ${aTagGroups.size} a-tag groups`);
} catch (err) { } catch (err) {
console.error('[Highlights] Error fetching events for a-tags:', err); // Non-critical: a-tag resolution failed, continue with e-tags only
} }
} }
} }
// Get source event IDs for highlights (to fetch them for sorting/display) // Get source event IDs for highlights (to fetch them for sorting/display)
const highlightSourceEventIds = Array.from(highlightBySourceEvent.keys()); const highlightSourceEventIds = Array.from(highlightBySourceEvent.keys());
console.log(`[Highlights] Total extracted ${highlightSourceEventIds.length} source event IDs from ${highlightEvents.length} highlight events`);
// Limit to maxTotalItems // Limit to maxTotalItems
const eventIds = highlightSourceEventIds.slice(0, maxTotalItems); const eventIds = highlightSourceEventIds.slice(0, maxTotalItems);
if (highlightSourceEventIds.length > maxTotalItems) {
console.log(`[Highlights] Limiting to ${maxTotalItems} items (found ${highlightSourceEventIds.length})`);
}
// Fetch the actual events - batch to avoid relay limits // Fetch the actual events - batch to avoid relay limits
const batchSize = 100; const batchSize = 100;
const allFetchedEvents: NostrEvent[] = []; const allFetchedEvents: NostrEvent[] = [];
console.log(`[Highlights] Fetching ${eventIds.length} events in batches of ${batchSize}`);
for (let i = 0; i < eventIds.length; i += batchSize) { for (let i = 0; i < eventIds.length; i += batchSize) {
const batch = eventIds.slice(i, i + batchSize); const batch = eventIds.slice(i, i + batchSize);
const filters = [{ ids: batch }]; const filters = [{ ids: batch }];
console.log(`[Highlights] Fetching batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(eventIds.length / batchSize)} (${batch.length} events)`);
const batchEvents = await nostrClient.fetchEvents( const batchEvents = await nostrClient.fetchEvents(
filters, filters,
relays, relays,
@ -346,11 +330,8 @@
} }
); );
console.log(`[Highlights] Batch ${Math.floor(i / batchSize) + 1} returned ${batchEvents.length} events`);
allFetchedEvents.push(...batchEvents); allFetchedEvents.push(...batchEvents);
} }
console.log(`[Highlights] Total fetched: ${allFetchedEvents.length} events`);
// Track which highlights we've already added (to avoid duplicates) // Track which highlights we've already added (to avoid duplicates)
const addedHighlightIds = new Set<string>(); const addedHighlightIds = new Set<string>();
@ -417,12 +398,11 @@
priority: 'low', priority: 'low',
timeout: config.standardTimeout timeout: config.standardTimeout
} }
).catch(err => { ).catch(() => {
console.debug('[Highlights] Error pre-fetching profiles:', err); // Non-critical: profile pre-fetch failed
}); });
} }
} catch (err) { } catch (err) {
console.error('Error loading highlights:', err);
error = err instanceof Error ? err.message : 'Failed to load highlights'; error = err instanceof Error ? err.message : 'Failed to load highlights';
} finally { } finally {
loading = false; loading = false;

6
src/routes/lists/+page.svelte

@ -125,7 +125,7 @@
await loadListEvents(lists[0]); await loadListEvents(lists[0]);
} }
} catch (error) { } catch (error) {
console.error('Error loading lists:', error); // Failed to load lists
} finally { } finally {
loading = false; loading = false;
} }
@ -154,7 +154,7 @@
loadingEvents = true; // Only show loading if no cache loadingEvents = true; // Only show loading if no cache
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached list events:', error); // Cache error (non-critical)
loadingEvents = true; // Show loading if cache check fails loadingEvents = true; // Show loading if cache check fails
} }
@ -199,7 +199,7 @@
// Final merge of any remaining events // Final merge of any remaining events
mergeEvents(fetchedEvents); mergeEvents(fetchedEvents);
} catch (error) { } catch (error) {
console.error('Error loading list events:', error); // Failed to load list events
events = []; events = [];
} finally { } finally {
loadingEvents = false; loadingEvents = false;

8
src/routes/relay/+page.svelte

@ -85,7 +85,7 @@
// Load favorite relays if user is logged in (non-blocking - show page immediately) // Load favorite relays if user is logged in (non-blocking - show page immediately)
loadFavoriteRelays().catch(err => { loadFavoriteRelays().catch(err => {
console.debug('Error loading favorite relays in background:', err); // Background fetch failed (non-critical)
}); });
loading = false; loading = false;
@ -149,7 +149,7 @@
processFavoriteRelayEvent(cachedFavoriteEvent); processFavoriteRelayEvent(cachedFavoriteEvent);
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached favorite relays:', error); // Cache error (non-critical)
} }
try { try {
@ -178,7 +178,7 @@
// Process the event (update favorite relays with fresh data) // Process the event (update favorite relays with fresh data)
processFavoriteRelayEvent(latestEvent); processFavoriteRelayEvent(latestEvent);
} catch (err) { } catch (err) {
console.error('Error loading favorite relays:', err); // Failed to load favorite relays
// Don't clear favoriteRelays if we have cached data // Don't clear favoriteRelays if we have cached data
if (favoriteRelays.length === 0) { if (favoriteRelays.length === 0) {
favoriteRelays = []; favoriteRelays = [];
@ -232,7 +232,7 @@
try { try {
await sessionManager.restoreSession(); await sessionManager.restoreSession();
} catch (error) { } catch (error) {
console.error('Failed to restore session in relay page:', error); // Session restore failed
} }
} }
await loadRelays(); await loadRelays();

19
src/routes/replaceable/[d_tag]/+page.svelte

@ -50,11 +50,10 @@
}); });
if (matching.length > 0) { if (matching.length > 0) {
allEvents.push(...matching); allEvents.push(...matching);
console.log(`[Replaceable] Found ${matching.length} cached events with d-tag "${dTag}" for kind ${kind}`);
} }
} }
} catch (cacheError) { } catch (cacheError) {
console.warn('[Replaceable] Error checking cache:', cacheError); // Cache error (non-critical)
} }
// First, try to decode as naddr (if the d-tag is actually an naddr) // First, try to decode as naddr (if the d-tag is actually an naddr)
@ -64,10 +63,9 @@
const decoded = nip19.decode(dTag); const decoded = nip19.decode(dTag);
if (decoded.type === 'naddr' && decoded.data && typeof decoded.data === 'object' && 'kind' in decoded.data && 'pubkey' in decoded.data) { if (decoded.type === 'naddr' && decoded.data && typeof decoded.data === 'object' && 'kind' in decoded.data && 'pubkey' in decoded.data) {
decodedNaddr = decoded.data as { kind: number; pubkey: string; identifier?: string; relays?: string[] }; decodedNaddr = decoded.data as { kind: number; pubkey: string; identifier?: string; relays?: string[] };
console.log('[Replaceable] Decoded naddr:', decodedNaddr);
} }
} catch (e) { } catch (e) {
console.log('[Replaceable] Not an naddr, treating as d-tag:', e); // Not an naddr, treating as d-tag
} }
} }
@ -104,7 +102,6 @@
// If not an naddr or naddr lookup failed, search by d-tag // If not an naddr or naddr lookup failed, search by d-tag
// Focus on parameterized replaceable events (30000-39999) first since they commonly use d-tags // Focus on parameterized replaceable events (30000-39999) first since they commonly use d-tags
console.log('[Replaceable] Searching for events with d-tag:', dTag);
// Query parameterized replaceable range (30000-39999) - these are most likely to have d-tags // Query parameterized replaceable range (30000-39999) - these are most likely to have d-tags
// Use smaller batches to avoid relay limits // Use smaller batches to avoid relay limits
@ -122,9 +119,8 @@
{ useCache: true, cacheResults: true, timeout: 10000 } { useCache: true, cacheResults: true, timeout: 10000 }
); );
allEvents.push(...batchEvents); allEvents.push(...batchEvents);
console.log(`[Replaceable] Found ${batchEvents.length} events in kind range ${start}-${Math.min(start + BATCH_SIZE - 1, 39999)}`);
} catch (e) { } catch (e) {
console.warn(`[Replaceable] Failed to query kind range ${start}-${Math.min(start + BATCH_SIZE - 1, 39999)}:`, e); // Query failed for kind range (non-critical)
} }
} }
@ -150,7 +146,6 @@
// Query additional relays if we found any // Query additional relays if we found any
if (additionalRelays.size > 0) { if (additionalRelays.size > 0) {
const additionalRelaysArray = Array.from(additionalRelays); const additionalRelaysArray = Array.from(additionalRelays);
console.log(`[Replaceable] Querying ${additionalRelaysArray.length} additional relays from event hints:`, additionalRelaysArray);
// Query parameterized replaceable range on additional relays // Query parameterized replaceable range on additional relays
for (let start = 30000; start < 40000; start += BATCH_SIZE) { for (let start = 30000; start < 40000; start += BATCH_SIZE) {
@ -166,15 +161,13 @@
{ useCache: true, cacheResults: true, timeout: 10000 } { useCache: true, cacheResults: true, timeout: 10000 }
); );
allEvents.push(...batchEvents); allEvents.push(...batchEvents);
console.log(`[Replaceable] Found ${batchEvents.length} additional events from hint relays in kind range ${start}-${Math.min(start + BATCH_SIZE - 1, 39999)}`);
} catch (e) { } catch (e) {
console.warn(`[Replaceable] Failed to query hint relays for kind range ${start}-${Math.min(start + BATCH_SIZE - 1, 39999)}:`, e); // Query failed for hint relays (non-critical)
} }
} }
} }
if (allEvents.length > 0) { if (allEvents.length > 0) {
console.log(`[Replaceable] Found ${allEvents.length} events total (including cache and hint relays)`);
} }
// Also check common replaceable kinds that might have d-tags // Also check common replaceable kinds that might have d-tags
@ -185,7 +178,6 @@
{ useCache: true, cacheResults: true } { useCache: true, cacheResults: true }
); );
allEvents.push(...commonEvents); allEvents.push(...commonEvents);
console.log(`[Replaceable] Found ${commonEvents.length} events in common replaceable kinds`);
// For replaceable events, get the newest version of each (by pubkey and kind) // For replaceable events, get the newest version of each (by pubkey and kind)
// For parameterized replaceable, get newest by (pubkey, kind, d-tag) // For parameterized replaceable, get newest by (pubkey, kind, d-tag)
@ -207,13 +199,12 @@
// Sort by created_at descending // Sort by created_at descending
events = Array.from(eventsByKey.values()).sort((a, b) => b.created_at - a.created_at); events = Array.from(eventsByKey.values()).sort((a, b) => b.created_at - a.created_at);
console.log(`[Replaceable] Total unique events found: ${events.length}`);
if (events.length === 0 && !error) { if (events.length === 0 && !error) {
error = `No replaceable events found with d-tag "${dTag}". The event might not be on the queried relays, or the d-tag might be incorrect.`; error = `No replaceable events found with d-tag "${dTag}". The event might not be on the queried relays, or the d-tag might be incorrect.`;
} }
} catch (err) { } catch (err) {
console.error('Error loading replaceable events:', err); // Failed to load replaceable events
error = err instanceof Error ? err.message : 'Failed to load replaceable events'; error = err instanceof Error ? err.message : 'Failed to load replaceable events';
events = []; events = [];
} finally { } finally {

4
src/routes/repos/+page.svelte

@ -63,7 +63,7 @@
} }
} }
} catch (error) { } catch (error) {
console.error('Error loading cached repos:', error); // Cache error (non-critical)
} }
} }
@ -135,7 +135,7 @@
// Sort by created_at descending // Sort by created_at descending
repos = Array.from(reposByKey.values()).sort((a, b) => b.created_at - a.created_at); repos = Array.from(reposByKey.values()).sort((a, b) => b.created_at - a.created_at);
} catch (error) { } catch (error) {
console.error('Error loading repos:', error); // Failed to load repos
repos = []; repos = [];
} finally { } finally {
loading = false; loading = false;

62
src/routes/repos/[naddr]/+page.svelte

@ -74,29 +74,25 @@
gitRepoFetchAttempted = true; // Mark as attempted immediately to prevent re-triggering gitRepoFetchAttempted = true; // Mark as attempted immediately to prevent re-triggering
try { try {
const gitUrls = extractGitUrls(repoEvent); const gitUrls = extractGitUrls(repoEvent);
console.log('Git URLs found:', gitUrls);
if (gitUrls.length > 0) { if (gitUrls.length > 0) {
// Try each URL until one works // Try each URL until one works
for (const url of gitUrls) { for (const url of gitUrls) {
try { try {
console.log('Attempting to fetch git repo from:', url);
const repo = await fetchGitRepo(url); const repo = await fetchGitRepo(url);
if (repo) { if (repo) {
gitRepo = repo; gitRepo = repo;
console.log('Git repo loaded:', repo.name);
break; // Success, stop trying other URLs break; // Success, stop trying other URLs
} }
} catch (error) { } catch (error) {
console.warn('Failed to fetch git repo from', url, error); // Failed to fetch git repo
// Continue to next URL // Continue to next URL
} }
} }
} else { } else {
console.log('No git URLs found in repo event');
} }
} catch (error) { } catch (error) {
console.error('Error loading git repo:', error); // Failed to load git repo
} finally { } finally {
loadingGitRepo = false; loadingGitRepo = false;
} }
@ -142,18 +138,18 @@
loadIssues(), loadIssues(),
loadDocumentation() loadDocumentation()
]).catch(err => { ]).catch(err => {
console.error('Error loading repo data from cache:', err); // Cache error (non-critical)
}); });
} }
} catch (error) { } catch (error) {
console.error('Error loading cached repo:', error); // Cache error (non-critical)
} }
} }
async function loadRepo() { async function loadRepo() {
if (!naddr || loadingRepo) { if (!naddr || loadingRepo) {
if (!naddr) { if (!naddr) {
console.warn('No naddr parameter provided'); // Missing naddr parameter
} }
if (!repoEvent) { if (!repoEvent) {
loading = false; loading = false;
@ -174,7 +170,7 @@
try { try {
decoded = nip19.decode(naddr); decoded = nip19.decode(naddr);
} catch (decodeError) { } catch (decodeError) {
console.error('Failed to decode naddr:', decodeError); // Invalid naddr format
if (!hasCachedData) { if (!hasCachedData) {
loading = false; loading = false;
} }
@ -182,7 +178,7 @@
} }
if (decoded.type !== 'naddr') { if (decoded.type !== 'naddr') {
console.error('Invalid naddr type:', decoded.type); // Invalid naddr type
if (!hasCachedData) { if (!hasCachedData) {
loading = false; loading = false;
} }
@ -194,7 +190,6 @@
const pubkey = naddrData.pubkey; const pubkey = naddrData.pubkey;
const dTag = naddrData.identifier || ''; const dTag = naddrData.identifier || '';
console.log('Loading repo:', { kind, pubkey, dTag });
// Fetch the repo announcement event // Fetch the repo announcement event
// Merge naddr relays with standard profile relays (naddr relays are additional hints, not replacements) // Merge naddr relays with standard profile relays (naddr relays are additional hints, not replacements)
@ -202,7 +197,6 @@
const naddrRelays = naddrData.relays || []; const naddrRelays = naddrData.relays || [];
const relays = [...new Set([...standardRelays, ...naddrRelays])]; // Deduplicate const relays = [...new Set([...standardRelays, ...naddrRelays])]; // Deduplicate
console.log('Using relays:', relays);
// Step 1: Fetch the repo event by ID (using kind, author, and d-tag) // Step 1: Fetch the repo event by ID (using kind, author, and d-tag)
const events = await nostrClient.fetchEvents( const events = await nostrClient.fetchEvents(
@ -211,14 +205,12 @@
{ useCache: true, cacheResults: true } { useCache: true, cacheResults: true }
); );
console.log('Fetched events:', events.length);
if (events.length > 0) { if (events.length > 0) {
const newRepoEvent = events[0]; const newRepoEvent = events[0];
// Only update if it's actually different (prevents unnecessary re-renders) // Only update if it's actually different (prevents unnecessary re-renders)
if (!repoEvent || repoEvent.id !== newRepoEvent.id) { if (!repoEvent || repoEvent.id !== newRepoEvent.id) {
repoEvent = newRepoEvent; repoEvent = newRepoEvent;
console.log('Repo event loaded:', repoEvent.id);
} }
// Don't fetch git repo here - wait until user clicks on repository tab // Don't fetch git repo here - wait until user clicks on repository tab
@ -232,13 +224,13 @@
]); ]);
} }
} else { } else {
console.warn('No repo event found for naddr:', naddr); // Repo event not found
if (!hasCachedData) { if (!hasCachedData) {
loading = false; loading = false;
} }
} }
} catch (error) { } catch (error) {
console.error('Error loading repo:', error); // Failed to load repo
if (!hasCachedData) { if (!hasCachedData) {
loading = false; loading = false;
} }
@ -290,7 +282,6 @@
const uniqueIssues = Array.from(new Map(issueEvents.map(e => [e.id, e])).values()); const uniqueIssues = Array.from(new Map(issueEvents.map(e => [e.id, e])).values());
issues = uniqueIssues.sort((a, b) => b.created_at - a.created_at); issues = uniqueIssues.sort((a, b) => b.created_at - a.created_at);
console.log(`Loaded ${issues.length} issues for repo ${repoEvent.id}`);
// Batch load statuses, comments, and profiles // Batch load statuses, comments, and profiles
await Promise.all([ await Promise.all([
@ -299,7 +290,7 @@
loadAllProfiles() loadAllProfiles()
]); ]);
} catch (error) { } catch (error) {
console.error('Error loading issues:', error); // Failed to load issues
} }
} }
@ -322,7 +313,6 @@
{ useCache: true, cacheResults: true } { useCache: true, cacheResults: true }
); );
console.log(`Loaded ${statuses.length} status events for ${issueIds.length} issues`);
// Get the latest status for each issue (statuses are replaceable per pubkey) // Get the latest status for each issue (statuses are replaceable per pubkey)
// For each issue, get the latest status from each pubkey, then take the most recent overall // For each issue, get the latest status from each pubkey, then take the most recent overall
@ -362,19 +352,12 @@
} }
if (latestStatus) { if (latestStatus) {
statusMap.set(issueId, latestStatus); statusMap.set(issueId, latestStatus);
const statusValue = getStatusFromKind(latestStatus.kind);
console.log(`Issue ${issueId.slice(0, 8)}... status:`, {
statusEvent: latestStatus.id.slice(0, 8) + '...',
kind: latestStatus.kind,
statusValue: statusValue,
allTags: latestStatus.tags.map(t => `${t[0]}:${t[1] || ''}${t[2] ? ':' + t[2] : ''}`).join(', ')
});
} }
} }
issueStatuses = statusMap; issueStatuses = statusMap;
} catch (error) { } catch (error) {
console.error('Error loading issue statuses:', error); // Failed to load issue statuses
} }
} }
@ -445,7 +428,7 @@
alert('Failed to publish status change. Please try again.'); alert('Failed to publish status change. Please try again.');
} }
} catch (error) { } catch (error) {
console.error('Error changing issue status:', error); // Failed to change issue status
alert('Error changing issue status: ' + (error instanceof Error ? error.message : String(error))); alert('Error changing issue status: ' + (error instanceof Error ? error.message : String(error)));
} finally { } finally {
changingStatus.set(issueId, false); changingStatus.set(issueId, false);
@ -552,9 +535,8 @@
} }
issueComments = commentsMap; issueComments = commentsMap;
console.log(`Loaded ${comments.length} comments for ${issueIds.length} issues`);
} catch (error) { } catch (error) {
console.error('Error loading issue comments:', error); // Failed to load issue comments
} }
} }
@ -590,15 +572,13 @@
} }
const uniquePubkeys = Array.from(pubkeys); const uniquePubkeys = Array.from(pubkeys);
console.log(`Batch fetching ${uniquePubkeys.length} profiles`);
// Batch fetch all profiles at once // Batch fetch all profiles at once
const relays = relayManager.getProfileReadRelays(); const relays = relayManager.getProfileReadRelays();
await fetchProfiles(uniquePubkeys, relays); await fetchProfiles(uniquePubkeys, relays);
console.log(`Pre-fetched ${uniquePubkeys.length} profiles`);
} catch (error) { } catch (error) {
console.error('Error loading profiles:', error); // Failed to load profiles
// Don't throw - profile loading is best effort // Don't throw - profile loading is best effort
} }
} }
@ -629,7 +609,7 @@
try { try {
const decoded = nip19.decode(doc.naddr); const decoded = nip19.decode(doc.naddr);
if (decoded.type !== 'naddr') { if (decoded.type !== 'naddr') {
console.warn('Documentation value is not a valid naddr:', doc.naddr); // Invalid documentation naddr format
continue; continue;
} }
@ -638,7 +618,7 @@
pubkey = naddrData.pubkey; pubkey = naddrData.pubkey;
dTag = naddrData.identifier || ''; dTag = naddrData.identifier || '';
} catch (decodeError) { } catch (decodeError) {
console.warn('Failed to decode documentation naddr:', doc.naddr, decodeError); // Failed to decode documentation naddr
continue; continue;
} }
} }
@ -659,13 +639,13 @@
docMap.set(doc.naddr, events[0]); docMap.set(doc.naddr, events[0]);
} }
} catch (error) { } catch (error) {
console.warn('Failed to load documentation:', doc.naddr, error); // Failed to load documentation
} }
} }
documentationEvents = docMap; documentationEvents = docMap;
} catch (error) { } catch (error) {
console.error('Error loading documentation:', error); // Failed to load documentation
} }
} }
@ -695,7 +675,7 @@
return gitRepo?.name || 'Repository'; return gitRepo?.name || 'Repository';
} catch (error) { } catch (error) {
console.error('Error in getRepoName:', error); // Failed to get repo name
return 'Repository'; return 'Repository';
} }
} }
@ -722,7 +702,7 @@
return gitRepo?.description || ''; return gitRepo?.description || '';
} catch (error) { } catch (error) {
console.error('Error in getRepoDescription:', error); // Failed to get repo description
return ''; return '';
} }
} }
@ -789,7 +769,7 @@
}); });
return { naddr, relay, kind, pubkey, dTag }; return { naddr, relay, kind, pubkey, dTag };
} catch (error) { } catch (error) {
console.warn('Failed to encode naddr from documentation tag:', docValue, error); // Failed to encode naddr
return { naddr: docValue, relay, kind, pubkey, dTag }; return { naddr: docValue, relay, kind, pubkey, dTag };
} }
} }

10
src/routes/rss/+page.svelte

@ -107,7 +107,7 @@
loading = true; // Only show loading if no cache loading = true; // Only show loading if no cache
} }
} catch (error) { } catch (error) {
console.debug('Error loading cached RSS event:', error); // Cache error (non-critical)
loading = true; // Show loading if cache check fails loading = true; // Show loading if cache check fails
} }
@ -135,7 +135,7 @@
} }
} }
} catch (error) { } catch (error) {
console.error('Error checking RSS event:', error); // Failed to load RSS event
} finally { } finally {
loading = false; loading = false;
} }
@ -198,9 +198,7 @@
} catch (error) { } catch (error) {
// Only log non-CORS errors to avoid console spam // Only log non-CORS errors to avoid console spam
const errorMessage = error instanceof Error ? error.message : 'Failed to fetch feed'; const errorMessage = error instanceof Error ? error.message : 'Failed to fetch feed';
if (!errorMessage.includes('CORS') && !errorMessage.includes('Cross-Origin') && !errorMessage.includes('timeout')) { // Feed fetch failed (errors logged only for non-CORS/timeout issues)
console.error(`Error fetching RSS feed ${feedUrl}:`, error);
}
feedErrors.set(feedUrl, errorMessage); feedErrors.set(feedUrl, errorMessage);
return { feedUrl, items: [] }; return { feedUrl, items: [] };
} }
@ -233,7 +231,7 @@
feedsLoaded = true; feedsLoaded = true;
} catch (error) { } catch (error) {
console.error('Error loading RSS feeds:', error); // Failed to load RSS feeds
} finally { } finally {
loadingFeeds = false; loadingFeeds = false;
} }

2
src/routes/topics/+page.svelte

@ -157,7 +157,7 @@
updateVisibleTopics(); updateVisibleTopics();
hasMore = allTopics.length > renderedCount; hasMore = allTopics.length > renderedCount;
} catch (error) { } catch (error) {
console.error('Error loading topics:', error); // Failed to load topics
allTopics = []; allTopics = [];
visibleTopics = []; visibleTopics = [];
} finally { } finally {

Loading…
Cancel
Save