@mrkvon/ndk-cache-dexie 2.7.9-fix

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # cache-dexie
2
+
3
+ NDK cache adapter for [Dexie](https://dexie.org/). Dexie is a wrapper around IndexedDB, an in-browser database.
4
+
5
+ ## Usage
6
+
7
+ NDK will attempt to use the Dexie adapter to store users, events, and tags. The default behaviour is to always check the cache first and then hit relays, replacing older cached events as needed.
8
+
9
+ ### Install
10
+
11
+ ```
12
+ pnpm add @nostr-dev-kit/cache-dexie
13
+ ```
14
+
15
+ ### Add as a cache adapter
16
+
17
+ ```ts
18
+ import NDKCacheAdapterDexie from "@nostr-dev-kit/cache-dexie";
19
+
20
+ const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'your-db-name' });
21
+ const ndk = new NDK({cacheAdapter: dexieAdapter, ...other config options});
22
+ ```
23
+
24
+ 🚨 Because Dexie only exists client-side, this cache adapter will not work in pure node.js environments. You'll need to make sure that you're using the right cache adapter in the right place (e.g. Redis on the backend, Dexie on the frontend).
25
+
26
+ # License
27
+
28
+ MIT
@@ -0,0 +1,224 @@
1
+ import { NDKUserProfile, NDKRelayInformation, NDKEventId, NDKRawEvent, NDKCacheAdapter, NDKSubscription, NDKEvent, Hexpubkey, ProfilePointer, NDKLnUrlData, NDKFilter, NDKRelay, NDKCacheRelayInfo, CacheModuleDefinition, CacheModuleCollection } from '@nostr-dev-kit/ndk';
2
+ import Dexie, { Table } from 'dexie';
3
+ import { LRUCache } from 'typescript-lru-cache';
4
+
5
+ interface Profile extends NDKUserProfile {
6
+ pubkey: string;
7
+ cachedAt: number;
8
+ }
9
+ interface Event {
10
+ id: string;
11
+ pubkey: string;
12
+ kind: number;
13
+ createdAt: number;
14
+ relay?: string;
15
+ event: string;
16
+ sig?: string;
17
+ }
18
+ interface EventTag {
19
+ eventId: string;
20
+ tagValue: string;
21
+ }
22
+ interface Nip05 {
23
+ nip05: string;
24
+ profile: string | null;
25
+ fetchedAt: number;
26
+ }
27
+ interface Lnurl {
28
+ pubkey: string;
29
+ document: string | null;
30
+ fetchedAt: number;
31
+ }
32
+ interface RelayStatus {
33
+ url: string;
34
+ updatedAt: number;
35
+ lastConnectedAt?: number;
36
+ dontConnectBefore?: number;
37
+ consecutiveFailures?: number;
38
+ lastFailureAt?: number;
39
+ nip11?: {
40
+ data: NDKRelayInformation;
41
+ fetchedAt: number;
42
+ };
43
+ metadata?: Record<string, Record<string, unknown>>;
44
+ }
45
+ interface UnpublishedEvent {
46
+ id: NDKEventId;
47
+ event: NDKRawEvent;
48
+ relays: Record<WebSocket["url"], boolean>;
49
+ lastTryAt?: number;
50
+ }
51
+ interface EventRelay {
52
+ eventId: string;
53
+ relayUrl: string;
54
+ seenAt: number;
55
+ }
56
+ interface DecryptedEvent {
57
+ id: NDKEventId;
58
+ event: string;
59
+ }
60
+ declare class Database extends Dexie {
61
+ profiles: Table<Profile>;
62
+ events: Table<Event>;
63
+ eventTags: Table<EventTag>;
64
+ nip05: Table<Nip05>;
65
+ lnurl: Table<Lnurl>;
66
+ relayStatus: Table<RelayStatus>;
67
+ unpublishedEvents: Table<UnpublishedEvent>;
68
+ eventRelays: Table<EventRelay>;
69
+ decryptedEvents: Table<DecryptedEvent>;
70
+ constructor(name: string);
71
+ }
72
+ declare let db: Database;
73
+
74
+ interface CacheOptions<T> {
75
+ maxSize: number;
76
+ dump: (dirtyKeys: Set<string>, cache: LRUCache<string, T>) => Promise<void>;
77
+ debug: debug.IDebugger;
78
+ }
79
+ declare class CacheHandler<T> {
80
+ private cache?;
81
+ private dirtyKeys;
82
+ private options;
83
+ private debug;
84
+ indexes: Map<string | number, LRUCache<string | number, Set<string>>>;
85
+ isSet: boolean;
86
+ maxSize: number;
87
+ constructor(options: CacheOptions<T>);
88
+ getSet(key: string): Set<T> | null;
89
+ /**
90
+ * Get all entries that match the filter.
91
+ */
92
+ getAllWithFilter(filter: (key: string, val: T) => boolean): Map<string, T>;
93
+ get(key: string): T | null | undefined;
94
+ getWithFallback(key: string, table: Table): Promise<T | null | undefined>;
95
+ getManyWithFallback(keys: string[], table: Table): Promise<T[]>;
96
+ add<K>(key: string, value: K, dirty?: boolean): void;
97
+ set(key: string, value: T, dirty?: boolean): void;
98
+ size(): number;
99
+ delete(key: string): void;
100
+ private dump;
101
+ addIndex<_T>(attribute: string | number): void;
102
+ getFromIndex(index: string, key: string | number): Set<T>;
103
+ }
104
+
105
+ type EventTagCacheEntry = string;
106
+
107
+ type EventCacheEntry = Event;
108
+
109
+ type Nip05CacheEntry = {
110
+ profile: string | null;
111
+ fetchedAt: number;
112
+ };
113
+
114
+ type ZapperCacheEntry = {
115
+ document: string | null;
116
+ fetchedAt: number;
117
+ };
118
+
119
+ interface NDKCacheAdapterDexieOptions {
120
+ /**
121
+ * The name of the database to use
122
+ */
123
+ dbName?: string;
124
+ /**
125
+ * Debug instance to use for logging
126
+ */
127
+ debug?: debug.IDebugger;
128
+ /**
129
+ * Number of profiles to keep in an LRU cache
130
+ */
131
+ profileCacheSize?: number;
132
+ zapperCacheSize?: number;
133
+ nip05CacheSize?: number;
134
+ eventCacheSize?: number;
135
+ eventTagsCacheSize?: number;
136
+ /**
137
+ * Whether to store event signatures in the cache
138
+ * @default false
139
+ */
140
+ saveSig?: boolean;
141
+ }
142
+ declare class NDKCacheAdapterDexie implements NDKCacheAdapter {
143
+ debug: debug.Debugger;
144
+ locking: boolean;
145
+ ready: boolean;
146
+ profiles: CacheHandler<Profile>;
147
+ zappers: CacheHandler<ZapperCacheEntry>;
148
+ nip05s: CacheHandler<Nip05CacheEntry>;
149
+ events: CacheHandler<EventCacheEntry>;
150
+ eventTags: CacheHandler<EventTagCacheEntry>;
151
+ relayInfo: CacheHandler<RelayStatus>;
152
+ unpublishedEvents: CacheHandler<UnpublishedEvent>;
153
+ private warmedUp;
154
+ private warmUpPromise;
155
+ devMode: boolean;
156
+ private saveSig;
157
+ _onReady?: () => void;
158
+ private moduleManager;
159
+ constructor(opts?: NDKCacheAdapterDexieOptions);
160
+ onReady(callback: () => void): void;
161
+ query(subscription: NDKSubscription): Promise<NDKEvent[]>;
162
+ fetchProfile(pubkey: Hexpubkey): Promise<NDKUserProfile | null>;
163
+ fetchProfileSync(pubkey: Hexpubkey): NDKUserProfile | null;
164
+ getProfiles(filter: ((pubkey: Hexpubkey, profile: NDKUserProfile) => boolean) | {
165
+ field?: string;
166
+ fields?: string[];
167
+ contains: string;
168
+ }): Promise<Map<Hexpubkey, NDKUserProfile> | undefined>;
169
+ saveProfile(pubkey: Hexpubkey, profile: NDKUserProfile): void;
170
+ loadNip05(nip05: string, maxAgeForMissing?: number): Promise<ProfilePointer | null | "missing">;
171
+ saveNip05(nip05: string, profile: ProfilePointer | null): Promise<void>;
172
+ loadUsersLNURLDoc?(pubkey: Hexpubkey, maxAgeInSecs?: number, maxAgeForMissing?: number): Promise<NDKLnUrlData | null | "missing">;
173
+ saveUsersLNURLDoc(pubkey: Hexpubkey, doc: NDKLnUrlData | null): Promise<void>;
174
+ private processFilter;
175
+ deleteEventIds(eventIds: NDKEventId[]): Promise<void>;
176
+ addUnpublishedEvent: (event: NDKEvent, relays: string[]) => void;
177
+ getUnpublishedEvents: () => Promise<{
178
+ event: NDKEvent;
179
+ relays: WebSocket["url"][];
180
+ lastTryAt?: number;
181
+ }[]>;
182
+ discardUnpublishedEvent: (id: string) => Promise<void>;
183
+ setEvent(event: NDKEvent, _filters: NDKFilter[], relay?: NDKRelay): Promise<void>;
184
+ setEventDup(event: NDKEvent, relay: NDKRelay): void;
185
+ updateRelayStatus(url: string, info: NDKCacheRelayInfo): void;
186
+ getRelayStatus(url: string): NDKCacheRelayInfo | undefined;
187
+ /**
188
+ * Searches by authors
189
+ */
190
+ private byAuthors;
191
+ /**
192
+ * Searches by ids
193
+ */
194
+ private byIdsQuery;
195
+ /**
196
+ * Searches by NIP-33
197
+ */
198
+ private byNip33Query;
199
+ /**
200
+ * Searches by tags and optionally filters by tags
201
+ */
202
+ private byTags;
203
+ private byKinds;
204
+ /**
205
+ * Register a cache module with its schema and migrations
206
+ */
207
+ registerModule(module: CacheModuleDefinition): Promise<void>;
208
+ /**
209
+ * Get a collection from a registered module
210
+ */
211
+ getModuleCollection<T>(namespace: string, collection: string): Promise<CacheModuleCollection<T>>;
212
+ /**
213
+ * Get a decrypted event from the cache by its wrapper ID
214
+ */
215
+ getDecryptedEvent(wrapperId: NDKEventId): Promise<NDKEvent | null>;
216
+ /**
217
+ * Add a decrypted event to the cache
218
+ */
219
+ addDecryptedEvent(wrapperId: NDKEventId, decryptedEvent: NDKEvent): Promise<void>;
220
+ }
221
+ declare function foundEvents(subscription: NDKSubscription, events: Event[], filter?: NDKFilter): void;
222
+ declare function foundEvent(subscription: NDKSubscription, event: Event, relayUrl: WebSocket["url"] | undefined, filter?: NDKFilter): void;
223
+
224
+ export { type NDKCacheAdapterDexieOptions, db, NDKCacheAdapterDexie as default, foundEvent, foundEvents };
@@ -0,0 +1,224 @@
1
+ import { NDKUserProfile, NDKRelayInformation, NDKEventId, NDKRawEvent, NDKCacheAdapter, NDKSubscription, NDKEvent, Hexpubkey, ProfilePointer, NDKLnUrlData, NDKFilter, NDKRelay, NDKCacheRelayInfo, CacheModuleDefinition, CacheModuleCollection } from '@nostr-dev-kit/ndk';
2
+ import Dexie, { Table } from 'dexie';
3
+ import { LRUCache } from 'typescript-lru-cache';
4
+
5
+ interface Profile extends NDKUserProfile {
6
+ pubkey: string;
7
+ cachedAt: number;
8
+ }
9
+ interface Event {
10
+ id: string;
11
+ pubkey: string;
12
+ kind: number;
13
+ createdAt: number;
14
+ relay?: string;
15
+ event: string;
16
+ sig?: string;
17
+ }
18
+ interface EventTag {
19
+ eventId: string;
20
+ tagValue: string;
21
+ }
22
+ interface Nip05 {
23
+ nip05: string;
24
+ profile: string | null;
25
+ fetchedAt: number;
26
+ }
27
+ interface Lnurl {
28
+ pubkey: string;
29
+ document: string | null;
30
+ fetchedAt: number;
31
+ }
32
+ interface RelayStatus {
33
+ url: string;
34
+ updatedAt: number;
35
+ lastConnectedAt?: number;
36
+ dontConnectBefore?: number;
37
+ consecutiveFailures?: number;
38
+ lastFailureAt?: number;
39
+ nip11?: {
40
+ data: NDKRelayInformation;
41
+ fetchedAt: number;
42
+ };
43
+ metadata?: Record<string, Record<string, unknown>>;
44
+ }
45
+ interface UnpublishedEvent {
46
+ id: NDKEventId;
47
+ event: NDKRawEvent;
48
+ relays: Record<WebSocket["url"], boolean>;
49
+ lastTryAt?: number;
50
+ }
51
+ interface EventRelay {
52
+ eventId: string;
53
+ relayUrl: string;
54
+ seenAt: number;
55
+ }
56
+ interface DecryptedEvent {
57
+ id: NDKEventId;
58
+ event: string;
59
+ }
60
+ declare class Database extends Dexie {
61
+ profiles: Table<Profile>;
62
+ events: Table<Event>;
63
+ eventTags: Table<EventTag>;
64
+ nip05: Table<Nip05>;
65
+ lnurl: Table<Lnurl>;
66
+ relayStatus: Table<RelayStatus>;
67
+ unpublishedEvents: Table<UnpublishedEvent>;
68
+ eventRelays: Table<EventRelay>;
69
+ decryptedEvents: Table<DecryptedEvent>;
70
+ constructor(name: string);
71
+ }
72
+ declare let db: Database;
73
+
74
+ interface CacheOptions<T> {
75
+ maxSize: number;
76
+ dump: (dirtyKeys: Set<string>, cache: LRUCache<string, T>) => Promise<void>;
77
+ debug: debug.IDebugger;
78
+ }
79
+ declare class CacheHandler<T> {
80
+ private cache?;
81
+ private dirtyKeys;
82
+ private options;
83
+ private debug;
84
+ indexes: Map<string | number, LRUCache<string | number, Set<string>>>;
85
+ isSet: boolean;
86
+ maxSize: number;
87
+ constructor(options: CacheOptions<T>);
88
+ getSet(key: string): Set<T> | null;
89
+ /**
90
+ * Get all entries that match the filter.
91
+ */
92
+ getAllWithFilter(filter: (key: string, val: T) => boolean): Map<string, T>;
93
+ get(key: string): T | null | undefined;
94
+ getWithFallback(key: string, table: Table): Promise<T | null | undefined>;
95
+ getManyWithFallback(keys: string[], table: Table): Promise<T[]>;
96
+ add<K>(key: string, value: K, dirty?: boolean): void;
97
+ set(key: string, value: T, dirty?: boolean): void;
98
+ size(): number;
99
+ delete(key: string): void;
100
+ private dump;
101
+ addIndex<_T>(attribute: string | number): void;
102
+ getFromIndex(index: string, key: string | number): Set<T>;
103
+ }
104
+
105
+ type EventTagCacheEntry = string;
106
+
107
+ type EventCacheEntry = Event;
108
+
109
+ type Nip05CacheEntry = {
110
+ profile: string | null;
111
+ fetchedAt: number;
112
+ };
113
+
114
+ type ZapperCacheEntry = {
115
+ document: string | null;
116
+ fetchedAt: number;
117
+ };
118
+
119
+ interface NDKCacheAdapterDexieOptions {
120
+ /**
121
+ * The name of the database to use
122
+ */
123
+ dbName?: string;
124
+ /**
125
+ * Debug instance to use for logging
126
+ */
127
+ debug?: debug.IDebugger;
128
+ /**
129
+ * Number of profiles to keep in an LRU cache
130
+ */
131
+ profileCacheSize?: number;
132
+ zapperCacheSize?: number;
133
+ nip05CacheSize?: number;
134
+ eventCacheSize?: number;
135
+ eventTagsCacheSize?: number;
136
+ /**
137
+ * Whether to store event signatures in the cache
138
+ * @default false
139
+ */
140
+ saveSig?: boolean;
141
+ }
142
+ declare class NDKCacheAdapterDexie implements NDKCacheAdapter {
143
+ debug: debug.Debugger;
144
+ locking: boolean;
145
+ ready: boolean;
146
+ profiles: CacheHandler<Profile>;
147
+ zappers: CacheHandler<ZapperCacheEntry>;
148
+ nip05s: CacheHandler<Nip05CacheEntry>;
149
+ events: CacheHandler<EventCacheEntry>;
150
+ eventTags: CacheHandler<EventTagCacheEntry>;
151
+ relayInfo: CacheHandler<RelayStatus>;
152
+ unpublishedEvents: CacheHandler<UnpublishedEvent>;
153
+ private warmedUp;
154
+ private warmUpPromise;
155
+ devMode: boolean;
156
+ private saveSig;
157
+ _onReady?: () => void;
158
+ private moduleManager;
159
+ constructor(opts?: NDKCacheAdapterDexieOptions);
160
+ onReady(callback: () => void): void;
161
+ query(subscription: NDKSubscription): Promise<NDKEvent[]>;
162
+ fetchProfile(pubkey: Hexpubkey): Promise<NDKUserProfile | null>;
163
+ fetchProfileSync(pubkey: Hexpubkey): NDKUserProfile | null;
164
+ getProfiles(filter: ((pubkey: Hexpubkey, profile: NDKUserProfile) => boolean) | {
165
+ field?: string;
166
+ fields?: string[];
167
+ contains: string;
168
+ }): Promise<Map<Hexpubkey, NDKUserProfile> | undefined>;
169
+ saveProfile(pubkey: Hexpubkey, profile: NDKUserProfile): void;
170
+ loadNip05(nip05: string, maxAgeForMissing?: number): Promise<ProfilePointer | null | "missing">;
171
+ saveNip05(nip05: string, profile: ProfilePointer | null): Promise<void>;
172
+ loadUsersLNURLDoc?(pubkey: Hexpubkey, maxAgeInSecs?: number, maxAgeForMissing?: number): Promise<NDKLnUrlData | null | "missing">;
173
+ saveUsersLNURLDoc(pubkey: Hexpubkey, doc: NDKLnUrlData | null): Promise<void>;
174
+ private processFilter;
175
+ deleteEventIds(eventIds: NDKEventId[]): Promise<void>;
176
+ addUnpublishedEvent: (event: NDKEvent, relays: string[]) => void;
177
+ getUnpublishedEvents: () => Promise<{
178
+ event: NDKEvent;
179
+ relays: WebSocket["url"][];
180
+ lastTryAt?: number;
181
+ }[]>;
182
+ discardUnpublishedEvent: (id: string) => Promise<void>;
183
+ setEvent(event: NDKEvent, _filters: NDKFilter[], relay?: NDKRelay): Promise<void>;
184
+ setEventDup(event: NDKEvent, relay: NDKRelay): void;
185
+ updateRelayStatus(url: string, info: NDKCacheRelayInfo): void;
186
+ getRelayStatus(url: string): NDKCacheRelayInfo | undefined;
187
+ /**
188
+ * Searches by authors
189
+ */
190
+ private byAuthors;
191
+ /**
192
+ * Searches by ids
193
+ */
194
+ private byIdsQuery;
195
+ /**
196
+ * Searches by NIP-33
197
+ */
198
+ private byNip33Query;
199
+ /**
200
+ * Searches by tags and optionally filters by tags
201
+ */
202
+ private byTags;
203
+ private byKinds;
204
+ /**
205
+ * Register a cache module with its schema and migrations
206
+ */
207
+ registerModule(module: CacheModuleDefinition): Promise<void>;
208
+ /**
209
+ * Get a collection from a registered module
210
+ */
211
+ getModuleCollection<T>(namespace: string, collection: string): Promise<CacheModuleCollection<T>>;
212
+ /**
213
+ * Get a decrypted event from the cache by its wrapper ID
214
+ */
215
+ getDecryptedEvent(wrapperId: NDKEventId): Promise<NDKEvent | null>;
216
+ /**
217
+ * Add a decrypted event to the cache
218
+ */
219
+ addDecryptedEvent(wrapperId: NDKEventId, decryptedEvent: NDKEvent): Promise<void>;
220
+ }
221
+ declare function foundEvents(subscription: NDKSubscription, events: Event[], filter?: NDKFilter): void;
222
+ declare function foundEvent(subscription: NDKSubscription, event: Event, relayUrl: WebSocket["url"] | undefined, filter?: NDKFilter): void;
223
+
224
+ export { type NDKCacheAdapterDexieOptions, db, NDKCacheAdapterDexie as default, foundEvent, foundEvents };