/** * rFeeds Automerge document schemas. * * Granularity: one Automerge document per space. * DocId format: {space}:rfeeds:data */ import type { DocSchema } from '../../shared/local-first/document'; // ── Feed source ── export interface FeedSource { id: string; url: string; name: string; color: string; enabled: boolean; lastFetchedAt: number; lastError: string | null; itemCount: number; intervalMs: number; // default 300_000 (5 min) addedBy: string; // DID of who added it addedAt: number; } // ── Imported feed item ── export interface FeedItem { id: string; sourceId: string; guid: string; title: string; url: string; summary: string; // 500 chars max, HTML stripped author: string; publishedAt: number; importedAt: number; reshared: boolean; // included in outbound Atom feed } // ── Manual post ── export interface ManualPost { id: string; content: string; authorDid: string; authorName: string; createdAt: number; updatedAt: number; } // ── Activity cache (Phase 2) ── export interface ActivityCacheEntry { id: string; // deterministic: `${moduleId}:${space}:${itemId}` moduleId: string; // 'rcal' | 'rtasks' | 'rdocs' | etc itemType: string; // 'event' | 'task' | 'note' | 'thread' | 'file' | etc title: string; summary: string; // 280 char max url: string; // e.g. https://demo.rspace.online/rcal author: string; publishedAt: number; reshared: boolean; syncedAt: number; } export interface ActivityModuleConfig { enabled: boolean; label: string; color: string; } // ── User feed profiles (Phase 2) ── export interface UserFeedProfile { did: string; displayName: string; bio: string; publishModules: string[]; // which moduleIds appear in personal feed createdAt: number; updatedAt: number; } // ── Settings ── export interface FeedsSettings { feedTitle: string; feedDescription: string; activityModules: Record; } // ── Document root ── export interface FeedsDoc { meta: { module: string; collection: string; version: number; spaceSlug: string; createdAt: number; }; sources: Record; items: Record; posts: Record; activityCache: Record; userProfiles: Record; settings: FeedsSettings; } // ── Schema registration ── export const feedsSchema: DocSchema = { module: 'rfeeds', collection: 'data', version: 2, init: (): FeedsDoc => ({ meta: { module: 'rfeeds', collection: 'data', version: 2, spaceSlug: '', createdAt: Date.now(), }, sources: {}, items: {}, posts: {}, activityCache: {}, userProfiles: {}, settings: { feedTitle: '', feedDescription: '', activityModules: {}, }, }), migrate: (doc: any): any => { if (!doc.activityCache) doc.activityCache = {}; if (!doc.userProfiles) doc.userProfiles = {}; if (!doc.settings.activityModules) doc.settings.activityModules = {}; if (doc.meta) doc.meta.version = 2; return doc; }, }; // ── Helpers ── export function feedsDocId(space: string) { return `${space}:rfeeds:data` as const; } /** Max items retained per source */ export const MAX_ITEMS_PER_SOURCE = 200; /** Max activity cache entries */ export const MAX_ACTIVITY_CACHE = 500; /** Default sync interval */ export const DEFAULT_SYNC_INTERVAL_MS = 5 * 60 * 1000;