a tool for shared writing and social publishing

filter out notifications with deleted resources

+98 -74
+98 -74
src/notifications.ts
··· 85 85 ) 86 86 .in("uri", commentUris); 87 87 88 - return commentNotifications.map((notification) => ({ 89 - id: notification.id, 90 - recipient: notification.recipient, 91 - created_at: notification.created_at, 92 - type: "comment" as const, 93 - comment_uri: notification.data.comment_uri, 94 - parentData: notification.data.parent_uri 95 - ? comments?.find((c) => c.uri === notification.data.parent_uri)! 96 - : undefined, 97 - commentData: comments?.find( 98 - (c) => c.uri === notification.data.comment_uri, 99 - )!, 100 - })); 88 + return commentNotifications 89 + .map((notification) => { 90 + const commentData = comments?.find((c) => c.uri === notification.data.comment_uri); 91 + if (!commentData) return null; 92 + return { 93 + id: notification.id, 94 + recipient: notification.recipient, 95 + created_at: notification.created_at, 96 + type: "comment" as const, 97 + comment_uri: notification.data.comment_uri, 98 + parentData: notification.data.parent_uri 99 + ? comments?.find((c) => c.uri === notification.data.parent_uri) 100 + : undefined, 101 + commentData, 102 + }; 103 + }) 104 + .filter((n) => n !== null); 101 105 } 102 106 103 107 export type HydratedSubscribeNotification = Awaited< ··· 125 129 .select("*, identities(bsky_profiles(*)), publications(*)") 126 130 .in("uri", subscriptionUris); 127 131 128 - return subscribeNotifications.map((notification) => ({ 129 - id: notification.id, 130 - recipient: notification.recipient, 131 - created_at: notification.created_at, 132 - type: "subscribe" as const, 133 - subscription_uri: notification.data.subscription_uri, 134 - subscriptionData: subscriptions?.find( 135 - (s) => s.uri === notification.data.subscription_uri, 136 - )!, 137 - })); 132 + return subscribeNotifications 133 + .map((notification) => { 134 + const subscriptionData = subscriptions?.find((s) => s.uri === notification.data.subscription_uri); 135 + if (!subscriptionData) return null; 136 + return { 137 + id: notification.id, 138 + recipient: notification.recipient, 139 + created_at: notification.created_at, 140 + type: "subscribe" as const, 141 + subscription_uri: notification.data.subscription_uri, 142 + subscriptionData, 143 + }; 144 + }) 145 + .filter((n) => n !== null); 138 146 } 139 147 140 148 export type HydratedQuoteNotification = Awaited< ··· 165 173 .select("*, documents_in_publications(publications(*))") 166 174 .in("uri", documentUris); 167 175 168 - return quoteNotifications.map((notification) => ({ 169 - id: notification.id, 170 - recipient: notification.recipient, 171 - created_at: notification.created_at, 172 - type: "quote" as const, 173 - bsky_post_uri: notification.data.bsky_post_uri, 174 - document_uri: notification.data.document_uri, 175 - bskyPost: bskyPosts?.find((p) => p.uri === notification.data.bsky_post_uri)!, 176 - document: documents?.find((d) => d.uri === notification.data.document_uri)!, 177 - })); 176 + return quoteNotifications 177 + .map((notification) => { 178 + const bskyPost = bskyPosts?.find((p) => p.uri === notification.data.bsky_post_uri); 179 + const document = documents?.find((d) => d.uri === notification.data.document_uri); 180 + if (!bskyPost || !document) return null; 181 + return { 182 + id: notification.id, 183 + recipient: notification.recipient, 184 + created_at: notification.created_at, 185 + type: "quote" as const, 186 + bsky_post_uri: notification.data.bsky_post_uri, 187 + document_uri: notification.data.document_uri, 188 + bskyPost, 189 + document, 190 + }; 191 + }) 192 + .filter((n) => n !== null); 178 193 } 179 194 180 195 export type HydratedMentionNotification = Awaited< ··· 242 257 : Promise.resolve({ data: [] }), 243 258 ]); 244 259 245 - return mentionNotifications.map((notification) => { 246 - const mentionedUri = notification.data.mention_type !== "did" 247 - ? (notification.data as Extract<ExtractNotificationType<"mention">, { mentioned_uri: string }>).mentioned_uri 248 - : undefined; 260 + return mentionNotifications 261 + .map((notification) => { 262 + const document = documents?.find((d) => d.uri === notification.data.document_uri); 263 + if (!document) return null; 249 264 250 - const documentCreatorDid = new AtUri(notification.data.document_uri).host; 251 - const documentCreatorHandle = didToHandleMap.get(documentCreatorDid) ?? null; 265 + const mentionedUri = notification.data.mention_type !== "did" 266 + ? (notification.data as Extract<ExtractNotificationType<"mention">, { mentioned_uri: string }>).mentioned_uri 267 + : undefined; 252 268 253 - return { 254 - id: notification.id, 255 - recipient: notification.recipient, 256 - created_at: notification.created_at, 257 - type: "mention" as const, 258 - document_uri: notification.data.document_uri, 259 - mention_type: notification.data.mention_type, 260 - mentioned_uri: mentionedUri, 261 - document: documents?.find((d) => d.uri === notification.data.document_uri)!, 262 - documentCreatorHandle, 263 - mentionedPublication: mentionedUri ? mentionedPublications?.find((p) => p.uri === mentionedUri) : undefined, 264 - mentionedDocument: mentionedUri ? mentionedDocuments?.find((d) => d.uri === mentionedUri) : undefined, 265 - }; 266 - }); 269 + const documentCreatorDid = new AtUri(notification.data.document_uri).host; 270 + const documentCreatorHandle = didToHandleMap.get(documentCreatorDid) ?? null; 271 + 272 + return { 273 + id: notification.id, 274 + recipient: notification.recipient, 275 + created_at: notification.created_at, 276 + type: "mention" as const, 277 + document_uri: notification.data.document_uri, 278 + mention_type: notification.data.mention_type, 279 + mentioned_uri: mentionedUri, 280 + document, 281 + documentCreatorHandle, 282 + mentionedPublication: mentionedUri ? mentionedPublications?.find((p) => p.uri === mentionedUri) : undefined, 283 + mentionedDocument: mentionedUri ? mentionedDocuments?.find((d) => d.uri === mentionedUri) : undefined, 284 + }; 285 + }) 286 + .filter((n) => n !== null); 267 287 } 268 288 269 289 export type HydratedCommentMentionNotification = Awaited< ··· 333 353 : Promise.resolve({ data: [] }), 334 354 ]); 335 355 336 - return commentMentionNotifications.map((notification) => { 337 - const mentionedUri = notification.data.mention_type !== "did" 338 - ? (notification.data as Extract<ExtractNotificationType<"comment_mention">, { mentioned_uri: string }>).mentioned_uri 339 - : undefined; 356 + return commentMentionNotifications 357 + .map((notification) => { 358 + const commentData = comments?.find((c) => c.uri === notification.data.comment_uri); 359 + if (!commentData) return null; 340 360 341 - const commenterDid = new AtUri(notification.data.comment_uri).host; 342 - const commenterHandle = didToHandleMap.get(commenterDid) ?? null; 343 - const commentData = comments?.find((c) => c.uri === notification.data.comment_uri); 361 + const mentionedUri = notification.data.mention_type !== "did" 362 + ? (notification.data as Extract<ExtractNotificationType<"comment_mention">, { mentioned_uri: string }>).mentioned_uri 363 + : undefined; 344 364 345 - return { 346 - id: notification.id, 347 - recipient: notification.recipient, 348 - created_at: notification.created_at, 349 - type: "comment_mention" as const, 350 - comment_uri: notification.data.comment_uri, 351 - mention_type: notification.data.mention_type, 352 - mentioned_uri: mentionedUri, 353 - commentData: commentData!, 354 - commenterHandle, 355 - mentionedPublication: mentionedUri ? mentionedPublications?.find((p) => p.uri === mentionedUri) : undefined, 356 - mentionedDocument: mentionedUri ? mentionedDocuments?.find((d) => d.uri === mentionedUri) : undefined, 357 - }; 358 - }); 365 + const commenterDid = new AtUri(notification.data.comment_uri).host; 366 + const commenterHandle = didToHandleMap.get(commenterDid) ?? null; 367 + 368 + return { 369 + id: notification.id, 370 + recipient: notification.recipient, 371 + created_at: notification.created_at, 372 + type: "comment_mention" as const, 373 + comment_uri: notification.data.comment_uri, 374 + mention_type: notification.data.mention_type, 375 + mentioned_uri: mentionedUri, 376 + commentData, 377 + commenterHandle, 378 + mentionedPublication: mentionedUri ? mentionedPublications?.find((p) => p.uri === mentionedUri) : undefined, 379 + mentionedDocument: mentionedUri ? mentionedDocuments?.find((d) => d.uri === mentionedUri) : undefined, 380 + }; 381 + }) 382 + .filter((n) => n !== null); 359 383 } 360 384 361 385 export async function pingIdentityToUpdateNotification(did: string) {