repositories.ts raw
1 import { Event } from 'nostr-tools'
2 import { Pubkey } from '../shared/value-objects/Pubkey'
3 import { Feed, FeedState } from './Feed'
4 import { TimelineQuery } from './TimelineQuery'
5
6 /**
7 * Repository for persisting Feed configuration
8 *
9 * The Feed aggregate represents user preferences for feed display,
10 * not the actual timeline events. This repository handles persistence
11 * of feed configuration state.
12 */
13 export interface FeedRepository {
14 /**
15 * Get the feed configuration for a user
16 * Returns null if no saved configuration exists
17 */
18 getByOwner(owner: Pubkey): Promise<Feed | null>
19
20 /**
21 * Save the current feed configuration
22 */
23 save(feed: Feed): Promise<void>
24
25 /**
26 * Delete saved feed configuration for a user
27 */
28 delete(owner: Pubkey): Promise<void>
29
30 /**
31 * Get the raw state for a user (for debugging/migration)
32 */
33 getState(owner: Pubkey): Promise<FeedState | null>
34 }
35
36 /**
37 * Result of a timeline query
38 */
39 export interface TimelineResult {
40 events: Event[]
41 eose: boolean
42 queryId: string
43 }
44
45 /**
46 * Subscription handle for timeline updates
47 */
48 export interface TimelineSubscription {
49 readonly queryId: string
50
51 /**
52 * Close this subscription
53 */
54 close(): void
55
56 /**
57 * Check if subscription is still active
58 */
59 isActive(): boolean
60 }
61
62 /**
63 * Callback for timeline event updates
64 */
65 export type TimelineEventCallback = (event: Event) => void
66
67 /**
68 * Callback for end-of-stored-events signal
69 */
70 export type TimelineEOSECallback = (queryId: string) => void
71
72 /**
73 * Repository for fetching timeline events
74 *
75 * This repository handles the query side - fetching events from relays
76 * based on timeline queries. It's responsible for relay communication
77 * but not event storage (that's handled by event caching infrastructure).
78 */
79 export interface TimelineRepository {
80 /**
81 * Subscribe to a timeline query
82 * Returns a subscription handle for management
83 */
84 subscribe(
85 query: TimelineQuery,
86 onEvent: TimelineEventCallback,
87 onEOSE?: TimelineEOSECallback
88 ): TimelineSubscription
89
90 /**
91 * Fetch events matching a query (one-shot)
92 * Waits for EOSE from all relays before returning
93 */
94 fetch(query: TimelineQuery): Promise<TimelineResult>
95
96 /**
97 * Fetch newer events than the most recent in the query
98 * Useful for refreshing a timeline
99 */
100 fetchNewer(query: TimelineQuery, since: number): Promise<TimelineResult>
101
102 /**
103 * Fetch older events for pagination
104 */
105 fetchOlder(query: TimelineQuery, until: number): Promise<TimelineResult>
106
107 /**
108 * Close all active subscriptions
109 */
110 closeAll(): void
111 }
112
113 /**
114 * Repository for accessing cached timeline events
115 *
116 * Separate from TimelineRepository to allow for different caching strategies
117 * and to keep the query/fetch concerns separate from storage.
118 */
119 export interface TimelineCacheRepository {
120 /**
121 * Get cached events for a query
122 * Returns events sorted by created_at descending
123 */
124 getEvents(queryKey: string, limit?: number): Promise<Event[]>
125
126 /**
127 * Store events in cache
128 */
129 storeEvents(queryKey: string, events: Event[]): Promise<void>
130
131 /**
132 * Get the most recent event timestamp for a query
133 * Used to determine the "since" for refresh queries
134 */
135 getMostRecentTimestamp(queryKey: string): Promise<number | null>
136
137 /**
138 * Get the oldest event timestamp for a query
139 * Used to determine the "until" for pagination queries
140 */
141 getOldestTimestamp(queryKey: string): Promise<number | null>
142
143 /**
144 * Clear cache for a specific query
145 */
146 clearCache(queryKey: string): Promise<void>
147
148 /**
149 * Clear all cached timeline data
150 */
151 clearAll(): Promise<void>
152
153 /**
154 * Merge new events with existing cache
155 * Handles deduplication and sorting
156 */
157 mergeEvents(queryKey: string, newEvents: Event[]): Promise<Event[]>
158 }
159
160 /**
161 * Repository for draft note storage
162 *
163 * Handles persistence of unsent notes for recovery.
164 */
165 export interface DraftRepository {
166 /**
167 * Save a draft note
168 */
169 save(draftId: string, content: string, metadata: DraftMetadata): Promise<void>
170
171 /**
172 * Get a specific draft
173 */
174 get(draftId: string): Promise<Draft | null>
175
176 /**
177 * Get all drafts for a user
178 */
179 getAll(owner: Pubkey): Promise<Draft[]>
180
181 /**
182 * Delete a draft
183 */
184 delete(draftId: string): Promise<void>
185
186 /**
187 * Clear all drafts for a user
188 */
189 clearAll(owner: Pubkey): Promise<void>
190 }
191
192 /**
193 * Metadata for a draft note
194 */
195 export interface DraftMetadata {
196 owner: Pubkey
197 createdAt: number
198 updatedAt: number
199 replyToEventId?: string
200 quoteEventId?: string
201 }
202
203 /**
204 * A saved draft note
205 */
206 export interface Draft {
207 id: string
208 content: string
209 metadata: DraftMetadata
210 }
211