WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: include theme and themePolicy collections in backfill

Themes and theme policies were handled by the firehose but omitted from
FORUM_OWNED_COLLECTIONS and COLLECTION_HANDLER_MAP, so a backfill after
restart would never replay them from the PDS — causing 404s when the web
app tried to resolve a theme URI that existed on the PDS but not in the DB.

+23 -11
+19 -11
apps/appview/src/lib/__tests__/backfill-manager.test.ts
··· 306 306 handleMembershipCreate: vi.fn().mockResolvedValue(true), 307 307 handlePostCreate: vi.fn().mockResolvedValue(true), 308 308 handleModActionCreate: vi.fn().mockResolvedValue(true), 309 + handleThemeCreate: vi.fn().mockResolvedValue(true), 310 + handleThemePolicyCreate: vi.fn().mockResolvedValue(true), 309 311 } as unknown as Indexer; 310 312 }); 311 313 ··· 458 460 }); 459 461 460 462 it("CatchUp: syncs user-owned collections and aggregates counts", async () => { 461 - // Phase 1 (5 FORUM_OWNED_COLLECTIONS) must return empty so its records don't 463 + // Phase 1 (7 FORUM_OWNED_COLLECTIONS) must return empty so its records don't 462 464 // pollute the count. Phase 2: 2 users × 2 USER_OWNED_COLLECTIONS × 1 record = 4. 463 465 const emptyPage = { data: { records: [], cursor: undefined } }; 464 466 const recordPage = { ··· 473 475 }; 474 476 475 477 const mockListRecords = vi.fn() 476 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.forum (Phase 1 call 1) 477 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.category (Phase 1 call 2) 478 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.board (Phase 1 call 3) 479 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.role (Phase 1 call 4) 480 - .mockResolvedValueOnce(emptyPage) // space.atbb.modAction (Phase 1 call 5) 478 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.forum (Phase 1 call 1) 479 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.category (Phase 1 call 2) 480 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.board (Phase 1 call 3) 481 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.role (Phase 1 call 4) 482 + .mockResolvedValueOnce(emptyPage) // space.atbb.modAction (Phase 1 call 5) 483 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.theme (Phase 1 call 6) 484 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.themePolicy (Phase 1 call 7) 481 485 .mockResolvedValue(recordPage); // all Phase 2 user collection calls 482 486 483 487 mockDb = { ··· 524 528 const emptyPage = { data: { records: [], cursor: undefined } }; 525 529 526 530 const mockListRecords = vi.fn() 527 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.forum (Phase 1 call 1) 528 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.category (Phase 1 call 2) 529 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.board (Phase 1 call 3) 530 - .mockResolvedValueOnce(emptyPage) // space.atbb.forum.role (Phase 1 call 4) 531 - .mockResolvedValueOnce(emptyPage) // space.atbb.modAction (Phase 1 call 5) 531 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.forum (Phase 1 call 1) 532 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.category (Phase 1 call 2) 533 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.board (Phase 1 call 3) 534 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.role (Phase 1 call 4) 535 + .mockResolvedValueOnce(emptyPage) // space.atbb.modAction (Phase 1 call 5) 536 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.theme (Phase 1 call 6) 537 + .mockResolvedValueOnce(emptyPage) // space.atbb.forum.themePolicy (Phase 1 call 7) 532 538 // user1: both collections succeed, 1 record each 533 539 .mockResolvedValueOnce({ data: { records: [{ 534 540 uri: "at://did:plc:user1/space.atbb.membership/self", ··· 682 688 handleMembershipCreate: vi.fn().mockResolvedValue(true), 683 689 handlePostCreate: vi.fn().mockResolvedValue(true), 684 690 handleModActionCreate: vi.fn().mockResolvedValue(true), 691 + handleThemeCreate: vi.fn().mockResolvedValue(true), 692 + handleThemePolicyCreate: vi.fn().mockResolvedValue(true), 685 693 } as unknown as Indexer; 686 694 }); 687 695
+4
apps/appview/src/lib/backfill-manager.ts
··· 19 19 "space.atbb.forum.board", 20 20 "space.atbb.forum.role", 21 21 "space.atbb.modAction", 22 + "space.atbb.forum.theme", 23 + "space.atbb.forum.themePolicy", 22 24 ] as const; 23 25 24 26 export const USER_OWNED_COLLECTIONS = [ ··· 34 36 "space.atbb.forum.role": "handleRoleCreate", 35 37 "space.atbb.membership": "handleMembershipCreate", 36 38 "space.atbb.modAction": "handleModActionCreate", 39 + "space.atbb.forum.theme": "handleThemeCreate", 40 + "space.atbb.forum.themePolicy": "handleThemePolicyCreate", 37 41 }; 38 42 39 43 export enum BackfillStatus {