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