Monorepo for Wisp.place. A static site hosting service built on top of the AT Protocol.
at main 2.5 kB view raw
1import { Agent } from '@atproto/api' 2import type { OAuthSession } from '@atproto/oauth-client-node' 3import { upsertSite } from './db' 4 5/** 6 * Sync sites from user's PDS into the database cache 7 * - Fetches all place.wisp.fs records from AT Protocol repo 8 * - Validates record structure 9 * - Backfills into sites table 10 */ 11export async function syncSitesFromPDS( 12 did: string, 13 session: OAuthSession 14): Promise<{ synced: number; errors: string[] }> { 15 console.log(`[Sync] Starting site sync for ${did}`) 16 17 const agent = new Agent((url, init) => session.fetchHandler(url, init)) 18 const errors: string[] = [] 19 let synced = 0 20 21 try { 22 // List all records in the place.wisp.fs collection 23 console.log('[Sync] Fetching place.wisp.fs records from PDS') 24 const records = await agent.com.atproto.repo.listRecords({ 25 repo: did, 26 collection: 'place.wisp.fs', 27 limit: 100 // Adjust if users might have more sites 28 }) 29 30 console.log(`[Sync] Found ${records.data.records.length} records`) 31 32 // Process each record 33 for (const record of records.data.records) { 34 try { 35 const { uri, value } = record 36 37 // Extract rkey from URI (at://did/collection/rkey) 38 const rkey = uri.split('/').pop() 39 if (!rkey) { 40 errors.push(`Invalid URI format: ${uri}`) 41 continue 42 } 43 44 // Validate record structure 45 if (!value || typeof value !== 'object') { 46 errors.push(`Invalid record value for ${rkey}`) 47 continue 48 } 49 50 const siteValue = value as any 51 52 // Check for required fields 53 if (siteValue.$type !== 'place.wisp.fs') { 54 errors.push( 55 `Invalid $type for ${rkey}: ${siteValue.$type}` 56 ) 57 continue 58 } 59 60 if (!siteValue.site || typeof siteValue.site !== 'string') { 61 errors.push(`Missing or invalid site name for ${rkey}`) 62 continue 63 } 64 65 // Upsert into database 66 const displayName = siteValue.site 67 await upsertSite(did, rkey, displayName) 68 69 console.log( 70 `[Sync] ✓ Synced site: ${displayName} (${rkey})` 71 ) 72 synced++ 73 } catch (err) { 74 const errorMsg = `Error processing record: ${err instanceof Error ? err.message : 'Unknown error'}` 75 console.error(`[Sync] ${errorMsg}`) 76 errors.push(errorMsg) 77 } 78 } 79 80 console.log( 81 `[Sync] Complete: ${synced} synced, ${errors.length} errors` 82 ) 83 return { synced, errors } 84 } catch (err) { 85 const errorMsg = `Failed to fetch records from PDS: ${err instanceof Error ? err.message : 'Unknown error'}` 86 console.error(`[Sync] ${errorMsg}`) 87 errors.push(errorMsg) 88 return { synced, errors } 89 } 90}