a demonstration replicated social networking web app built with anproto wiredove.net/
social ed25519 protocols
at master 64 lines 1.8 kB view raw
1import { getFeedRow, parseOpenedTimestamp, upsertFeedRow } from './feed_row_cache.js' 2 3const normalizeTs = (entry) => { 4 if (!entry) { return 0 } 5 if (entry.ts) { 6 const parsed = Number.parseInt(entry.ts, 10) 7 if (Number.isFinite(parsed) && parsed > 0) { return parsed } 8 } 9 return parseOpenedTimestamp(entry.opened) 10} 11 12export class FeedStore { 13 constructor(src, options = {}) { 14 this.src = src 15 this.entries = new Map() 16 this.isActive = typeof options.isActive === 'function' ? options.isActive : () => true 17 this.since = 0 18 } 19 20 normalize(entry) { 21 if (!entry || !entry.hash) { return null } 22 const ts = normalizeTs(entry) 23 const cachedRow = entry.row || getFeedRow(entry.hash) 24 if (cachedRow) { 25 upsertFeedRow(cachedRow) 26 } 27 return { 28 hash: entry.hash, 29 opened: entry.opened || null, 30 ts, 31 row: cachedRow || null 32 } 33 } 34 35 async upsert(entry) { 36 if (!this.isActive()) { return false } 37 const normalized = this.normalize(entry) 38 if (!normalized || !normalized.ts) { return false } 39 const prev = this.entries.get(normalized.hash) 40 if (prev && prev.ts >= normalized.ts && prev.row && !normalized.row) { 41 normalized.row = prev.row 42 } 43 this.entries.set(normalized.hash, normalized) 44 this.since = Math.max(this.since, normalized.ts) 45 if (!this.isActive()) { return false } 46 await window.__feedEnqueue?.(this.src, normalized) 47 return true 48 } 49 50 async upsertMany(entries) { 51 if (!Array.isArray(entries) || !entries.length) { return 0 } 52 let count = 0 53 for (const entry of entries) { 54 if (!this.isActive()) { break } 55 const ok = await this.upsert(entry) 56 if (ok) { count += 1 } 57 } 58 return count 59 } 60 61 getSince() { 62 return this.since 63 } 64}