applesauce-core 0.0.0-next-20250729145125 → 0.0.0-next-20250808173123
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/dist/event-store/event-store.d.ts +13 -3
- package/dist/event-store/event-store.js +51 -0
- package/dist/event-store/interface.d.ts +7 -3
- package/dist/helpers/encrypted-content.d.ts +16 -10
- package/dist/helpers/encrypted-content.js +9 -3
- package/dist/helpers/event-cache.d.ts +15 -0
- package/dist/helpers/event-cache.js +32 -0
- package/dist/helpers/expiration.js +1 -2
- package/dist/helpers/hidden-content.d.ts +3 -3
- package/dist/helpers/hidden-content.js +2 -2
- package/dist/helpers/hidden-tags.d.ts +5 -10
- package/dist/helpers/hidden-tags.js +3 -3
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/models/common.js +14 -6
- package/package.json +1 -1
|
@@ -9,6 +9,8 @@ export declare class EventStore implements IEventStore {
|
|
|
9
9
|
database: EventSet;
|
|
10
10
|
/** Enable this to keep old versions of replaceable events */
|
|
11
11
|
keepOldVersions: boolean;
|
|
12
|
+
/** Enable this to keep expired events */
|
|
13
|
+
keepExpired: boolean;
|
|
12
14
|
/**
|
|
13
15
|
* A method used to verify new events before added them
|
|
14
16
|
* @returns true if the event is valid, false if it should be ignored
|
|
@@ -24,21 +26,29 @@ export declare class EventStore implements IEventStore {
|
|
|
24
26
|
* A method that will be called when an event isn't found in the store
|
|
25
27
|
* @experimental
|
|
26
28
|
*/
|
|
27
|
-
eventLoader?: (pointer: EventPointer) => Observable<NostrEvent>;
|
|
29
|
+
eventLoader?: (pointer: EventPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
|
28
30
|
/**
|
|
29
31
|
* A method that will be called when a replaceable event isn't found in the store
|
|
30
32
|
* @experimental
|
|
31
33
|
*/
|
|
32
|
-
replaceableLoader?: (pointer: AddressPointerWithoutD) => Observable<NostrEvent>;
|
|
34
|
+
replaceableLoader?: (pointer: AddressPointerWithoutD) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
|
33
35
|
/**
|
|
34
36
|
* A method that will be called when an addressable event isn't found in the store
|
|
35
37
|
* @experimental
|
|
36
38
|
*/
|
|
37
|
-
addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent>;
|
|
39
|
+
addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
|
38
40
|
constructor();
|
|
39
41
|
protected deletedIds: Set<string>;
|
|
40
42
|
protected deletedCoords: Map<string, number>;
|
|
41
43
|
protected checkDeleted(event: string | NostrEvent): boolean;
|
|
44
|
+
protected expirations: Map<string, number>;
|
|
45
|
+
/** Adds an event to the expiration map */
|
|
46
|
+
protected addExpiration(event: NostrEvent): void;
|
|
47
|
+
protected expirationTimeout: number | null;
|
|
48
|
+
protected nextExpirationCheck: number | null;
|
|
49
|
+
protected handleExpiringEvent(event: NostrEvent): void;
|
|
50
|
+
/** Remove expired events from the store */
|
|
51
|
+
protected pruneExpired(): void;
|
|
42
52
|
protected handleDeleteEvent(deleteEvent: NostrEvent): void;
|
|
43
53
|
/** Copies important metadata from and identical event to another */
|
|
44
54
|
static mergeDuplicateEvent(source: NostrEvent, dest: NostrEvent): void;
|
|
@@ -4,9 +4,11 @@ import { EMPTY, filter, finalize, from, merge, mergeMap, ReplaySubject, share, t
|
|
|
4
4
|
import hash_sum from "hash-sum";
|
|
5
5
|
import { getDeleteCoordinates, getDeleteIds } from "../helpers/delete.js";
|
|
6
6
|
import { createReplaceableAddress, EventStoreSymbol, FromCacheSymbol, isReplaceable } from "../helpers/event.js";
|
|
7
|
+
import { getExpirationTimestamp } from "../helpers/expiration.js";
|
|
7
8
|
import { matchFilters } from "../helpers/filter.js";
|
|
8
9
|
import { parseCoordinate } from "../helpers/pointers.js";
|
|
9
10
|
import { addSeenRelay, getSeenRelays } from "../helpers/relays.js";
|
|
11
|
+
import { unixNow } from "../helpers/time.js";
|
|
10
12
|
import { UserBlossomServersModel } from "../models/blossom.js";
|
|
11
13
|
import { EventModel, EventsModel, ReplaceableModel, ReplaceableSetModel, TimelineModel } from "../models/common.js";
|
|
12
14
|
import { ContactsModel } from "../models/contacts.js";
|
|
@@ -21,6 +23,8 @@ export class EventStore {
|
|
|
21
23
|
database;
|
|
22
24
|
/** Enable this to keep old versions of replaceable events */
|
|
23
25
|
keepOldVersions = false;
|
|
26
|
+
/** Enable this to keep expired events */
|
|
27
|
+
keepExpired = false;
|
|
24
28
|
/**
|
|
25
29
|
* A method used to verify new events before added them
|
|
26
30
|
* @returns true if the event is valid, false if it should be ignored
|
|
@@ -87,6 +91,46 @@ export class EventStore {
|
|
|
87
91
|
}
|
|
88
92
|
return false;
|
|
89
93
|
}
|
|
94
|
+
expirations = new Map();
|
|
95
|
+
/** Adds an event to the expiration map */
|
|
96
|
+
addExpiration(event) {
|
|
97
|
+
const expiration = getExpirationTimestamp(event);
|
|
98
|
+
if (expiration && Number.isFinite(expiration))
|
|
99
|
+
this.expirations.set(event.id, expiration);
|
|
100
|
+
}
|
|
101
|
+
expirationTimeout = null;
|
|
102
|
+
nextExpirationCheck = null;
|
|
103
|
+
handleExpiringEvent(event) {
|
|
104
|
+
const expiration = getExpirationTimestamp(event);
|
|
105
|
+
if (!expiration)
|
|
106
|
+
return;
|
|
107
|
+
// Add event to expiration map
|
|
108
|
+
this.expirations.set(event.id, expiration);
|
|
109
|
+
// Exit if the next check is already less than the next expiration
|
|
110
|
+
if (this.expirationTimeout && this.nextExpirationCheck && this.nextExpirationCheck < expiration)
|
|
111
|
+
return;
|
|
112
|
+
// Set timeout to prune expired events
|
|
113
|
+
if (this.expirationTimeout)
|
|
114
|
+
clearTimeout(this.expirationTimeout);
|
|
115
|
+
const timeout = expiration - unixNow();
|
|
116
|
+
this.expirationTimeout = setTimeout(this.pruneExpired.bind(this), timeout * 1000 + 10);
|
|
117
|
+
this.nextExpirationCheck = expiration;
|
|
118
|
+
}
|
|
119
|
+
/** Remove expired events from the store */
|
|
120
|
+
pruneExpired() {
|
|
121
|
+
const now = unixNow();
|
|
122
|
+
for (const [id, expiration] of this.expirations) {
|
|
123
|
+
if (expiration <= now) {
|
|
124
|
+
this.expirations.delete(id);
|
|
125
|
+
this.remove(id);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Cleanup timers
|
|
129
|
+
if (this.expirationTimeout)
|
|
130
|
+
clearTimeout(this.expirationTimeout);
|
|
131
|
+
this.nextExpirationCheck = null;
|
|
132
|
+
this.expirationTimeout = null;
|
|
133
|
+
}
|
|
90
134
|
// handling delete events
|
|
91
135
|
handleDeleteEvent(deleteEvent) {
|
|
92
136
|
const ids = getDeleteIds(deleteEvent);
|
|
@@ -134,6 +178,10 @@ export class EventStore {
|
|
|
134
178
|
// Ignore if the event was deleted
|
|
135
179
|
if (this.checkDeleted(event))
|
|
136
180
|
return event;
|
|
181
|
+
// Reject expired events if keepExpired is false
|
|
182
|
+
const expiration = getExpirationTimestamp(event);
|
|
183
|
+
if (this.keepExpired === false && expiration && expiration <= unixNow())
|
|
184
|
+
return null;
|
|
137
185
|
// Get the replaceable identifier
|
|
138
186
|
const identifier = isReplaceable(event.kind) ? event.tags.find((t) => t[0] === "d")?.[1] : undefined;
|
|
139
187
|
// Don't insert the event if there is already a newer version
|
|
@@ -177,6 +225,9 @@ export class EventStore {
|
|
|
177
225
|
return existing[0];
|
|
178
226
|
}
|
|
179
227
|
}
|
|
228
|
+
// Add event to expiration map
|
|
229
|
+
if (this.keepExpired === false && expiration)
|
|
230
|
+
this.handleExpiringEvent(inserted);
|
|
180
231
|
return inserted;
|
|
181
232
|
}
|
|
182
233
|
/** Removes an event from the database and updates subscriptions */
|
|
@@ -84,14 +84,18 @@ export interface IEventSet extends IEventStoreRead, IEventStoreStreams, IEventSt
|
|
|
84
84
|
events: LRU<NostrEvent>;
|
|
85
85
|
}
|
|
86
86
|
export interface IEventStore extends IEventStoreRead, IEventStoreStreams, IEventStoreActions, IEventStoreModels, IEventClaims {
|
|
87
|
+
/** Enable this to keep old versions of replaceable events */
|
|
88
|
+
keepOldVersions: boolean;
|
|
89
|
+
/** Enable this to keep expired events */
|
|
90
|
+
keepExpired: boolean;
|
|
87
91
|
filters(filters: Filter | Filter[]): Observable<NostrEvent>;
|
|
88
92
|
updated(id: string | NostrEvent): Observable<NostrEvent>;
|
|
89
93
|
removed(id: string): Observable<never>;
|
|
90
94
|
replaceable(kind: number, pubkey: string, identifier?: string): Observable<NostrEvent | undefined>;
|
|
91
95
|
replaceable(pointer: AddressPointerWithoutD): Observable<NostrEvent | undefined>;
|
|
92
|
-
eventLoader?: (pointer: EventPointer) => Observable<NostrEvent>;
|
|
93
|
-
replaceableLoader?: (pointer: AddressPointerWithoutD) => Observable<NostrEvent>;
|
|
94
|
-
addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent>;
|
|
96
|
+
eventLoader?: (pointer: EventPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
|
97
|
+
replaceableLoader?: (pointer: AddressPointerWithoutD) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
|
98
|
+
addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
|
|
95
99
|
profile(user: string | ProfilePointer): Observable<ProfileContent | undefined>;
|
|
96
100
|
contacts(user: string | ProfilePointer): Observable<ProfilePointer[]>;
|
|
97
101
|
mutes(user: string | ProfilePointer): Observable<Mutes | undefined>;
|
|
@@ -10,18 +10,24 @@ export interface EncryptedContentSigner {
|
|
|
10
10
|
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export declare function setEncryptedContentEncryptionMethod(kind: number, method: "nip04" | "nip44"): number;
|
|
17
|
-
/** Returns either nip04 or nip44 encryption methods depending on event kind */
|
|
18
|
-
export declare function getEncryptedContentEncryptionMethods(kind: number, signer: EncryptedContentSigner): {
|
|
13
|
+
export type EncryptionMethod = "nip04" | "nip44";
|
|
14
|
+
/** A pair of encryption methods for encrypting and decrypting event content */
|
|
15
|
+
export interface EncryptionMethods {
|
|
19
16
|
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
20
17
|
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
}
|
|
19
|
+
/** Various event kinds that can have encrypted content and which encryption method they use */
|
|
20
|
+
export declare const EventContentEncryptionMethod: Record<number, EncryptionMethod>;
|
|
21
|
+
/** Sets the encryption method that is used for the contents of a specific event kind */
|
|
22
|
+
export declare function setEncryptedContentEncryptionMethod(kind: number, method: EncryptionMethod): number;
|
|
23
|
+
/**
|
|
24
|
+
* Returns either nip04 or nip44 encryption methods depending on event kind
|
|
25
|
+
* @param kind The event kind to get the encryption method for
|
|
26
|
+
* @param signer The signer to use to get the encryption methods
|
|
27
|
+
* @param override The encryption method to use instead of the default
|
|
28
|
+
* @returns The encryption methods for the event kind
|
|
29
|
+
*/
|
|
30
|
+
export declare function getEncryptedContentEncryptionMethods(kind: number, signer: EncryptedContentSigner, override?: EncryptionMethod): EncryptionMethods;
|
|
25
31
|
/** Checks if an event can have encrypted content */
|
|
26
32
|
export declare function canHaveEncryptedContent(kind: number): boolean;
|
|
27
33
|
/** Checks if an event has encrypted content */
|
|
@@ -13,9 +13,15 @@ export function setEncryptedContentEncryptionMethod(kind, method) {
|
|
|
13
13
|
EventContentEncryptionMethod[kind] = method;
|
|
14
14
|
return kind;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Returns either nip04 or nip44 encryption methods depending on event kind
|
|
18
|
+
* @param kind The event kind to get the encryption method for
|
|
19
|
+
* @param signer The signer to use to get the encryption methods
|
|
20
|
+
* @param override The encryption method to use instead of the default
|
|
21
|
+
* @returns The encryption methods for the event kind
|
|
22
|
+
*/
|
|
23
|
+
export function getEncryptedContentEncryptionMethods(kind, signer, override) {
|
|
24
|
+
const method = override ?? EventContentEncryptionMethod[kind];
|
|
19
25
|
if (!method)
|
|
20
26
|
throw new Error(`Event kind ${kind} does not support encrypted content`);
|
|
21
27
|
const encryption = signer[method];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NostrEvent } from "nostr-tools";
|
|
2
|
+
import { IEventStoreStreams } from "../event-store/interface.js";
|
|
3
|
+
/**
|
|
4
|
+
* Setups a process to write batches of new events from an event store to a cache
|
|
5
|
+
* @param eventStore - The event store to read from
|
|
6
|
+
* @param write - The function to write the events to the cache
|
|
7
|
+
* @param opts - The options for the process
|
|
8
|
+
* @param opts.batchTime - The time to wait before writing a batch (default: 5 seconds)
|
|
9
|
+
* @param opts.maxBatchSize - The maximum number of events to write in a batch
|
|
10
|
+
* @returns A function to stop the process
|
|
11
|
+
*/
|
|
12
|
+
export declare function presistEventsToCache(eventStore: IEventStoreStreams, write: (events: NostrEvent[]) => Promise<void>, opts?: {
|
|
13
|
+
maxBatchSize?: number;
|
|
14
|
+
batchTime?: number;
|
|
15
|
+
}): () => void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { bufferTime, filter } from "rxjs";
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
|
+
import { isFromCache } from "./index.js";
|
|
4
|
+
const log = logger.extend("event-cache");
|
|
5
|
+
/**
|
|
6
|
+
* Setups a process to write batches of new events from an event store to a cache
|
|
7
|
+
* @param eventStore - The event store to read from
|
|
8
|
+
* @param write - The function to write the events to the cache
|
|
9
|
+
* @param opts - The options for the process
|
|
10
|
+
* @param opts.batchTime - The time to wait before writing a batch (default: 5 seconds)
|
|
11
|
+
* @param opts.maxBatchSize - The maximum number of events to write in a batch
|
|
12
|
+
* @returns A function to stop the process
|
|
13
|
+
*/
|
|
14
|
+
export function presistEventsToCache(eventStore, write, opts) {
|
|
15
|
+
const time = opts?.batchTime ?? 5_000;
|
|
16
|
+
// Save all new events to the cache
|
|
17
|
+
const sub = eventStore.insert$
|
|
18
|
+
.pipe(
|
|
19
|
+
// Only select events that are not from the cache
|
|
20
|
+
filter((e) => !isFromCache(e)),
|
|
21
|
+
// Buffer events for 5 seconds
|
|
22
|
+
opts?.maxBatchSize ? bufferTime(time, undefined, opts?.maxBatchSize ?? 100) : bufferTime(time),
|
|
23
|
+
// Only select buffers with events
|
|
24
|
+
filter((b) => b.length > 0))
|
|
25
|
+
.subscribe((events) => {
|
|
26
|
+
// Save all new events to the cache
|
|
27
|
+
write(events)
|
|
28
|
+
.then(() => log(`Saved ${events.length} events to cache`))
|
|
29
|
+
.catch((e) => log(`Failed to save ${events.length} events to cache`, e));
|
|
30
|
+
});
|
|
31
|
+
return () => sub.unsubscribe();
|
|
32
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { getOrComputeCachedValue } from "./cache.js";
|
|
2
2
|
import { unixNow } from "./time.js";
|
|
3
|
-
import { getTagValue } from "./event-tags.js";
|
|
4
3
|
export const ExpirationTimestampSymbol = Symbol("expiration-timestamp");
|
|
5
4
|
/** Returns the NIP-40 expiration timestamp for an event */
|
|
6
5
|
export function getExpirationTimestamp(event) {
|
|
7
6
|
return getOrComputeCachedValue(event, ExpirationTimestampSymbol, () => {
|
|
8
|
-
const expiration =
|
|
7
|
+
const expiration = event.tags.find((t) => t[0] === "expiration")?.[1];
|
|
9
8
|
return expiration ? parseInt(expiration) : undefined;
|
|
10
9
|
});
|
|
11
10
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EncryptedContentSigner, getEncryptedContentEncryptionMethods } from "./encrypted-content.js";
|
|
1
|
+
import { EncryptedContentSigner, EncryptionMethod, getEncryptedContentEncryptionMethods } from "./encrypted-content.js";
|
|
2
2
|
export declare const HiddenContentSymbol: symbol;
|
|
3
3
|
export interface HiddenContentSigner extends EncryptedContentSigner {
|
|
4
4
|
}
|
|
@@ -6,7 +6,7 @@ export declare const getHiddenContentEncryptionMethods: typeof getEncryptedConte
|
|
|
6
6
|
/** Various event kinds that can have hidden content */
|
|
7
7
|
export declare const HiddenContentKinds: Set<number>;
|
|
8
8
|
/** Sets the encryption method for hidden content on a kind */
|
|
9
|
-
export declare function setHiddenContentEncryptionMethod(kind: number, method:
|
|
9
|
+
export declare function setHiddenContentEncryptionMethod(kind: number, method: EncryptionMethod): number;
|
|
10
10
|
/** Checks if an event can have hidden content */
|
|
11
11
|
export declare function canHaveHiddenContent(kind: number): boolean;
|
|
12
12
|
/** Checks if an event has hidden content */
|
|
@@ -31,7 +31,7 @@ export declare function unlockHiddenContent<T extends {
|
|
|
31
31
|
kind: number;
|
|
32
32
|
pubkey: string;
|
|
33
33
|
content: string;
|
|
34
|
-
}>(event: T, signer: EncryptedContentSigner): Promise<string>;
|
|
34
|
+
}>(event: T, signer: EncryptedContentSigner, override?: EncryptionMethod): Promise<string>;
|
|
35
35
|
/**
|
|
36
36
|
* Sets the hidden content on an event and updates it if its part of an event store
|
|
37
37
|
* @throws
|
|
@@ -34,10 +34,10 @@ export function getHiddenContent(event) {
|
|
|
34
34
|
* @param signer A signer to use to decrypt the content
|
|
35
35
|
* @throws
|
|
36
36
|
*/
|
|
37
|
-
export async function unlockHiddenContent(event, signer) {
|
|
37
|
+
export async function unlockHiddenContent(event, signer, override) {
|
|
38
38
|
if (!canHaveHiddenContent(event.kind))
|
|
39
39
|
throw new Error("Event kind does not support hidden content");
|
|
40
|
-
const encryption = getEncryptedContentEncryptionMethods(event.kind, signer);
|
|
40
|
+
const encryption = getEncryptedContentEncryptionMethods(event.kind, signer, override);
|
|
41
41
|
const plaintext = await encryption.decrypt(event.pubkey, event.content);
|
|
42
42
|
setHiddenContentCache(event, plaintext);
|
|
43
43
|
return plaintext;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { HiddenContentSigner } from "./hidden-content.js";
|
|
2
|
+
import { EncryptionMethod } from "./encrypted-content.js";
|
|
2
3
|
export declare const HiddenTagsSymbol: unique symbol;
|
|
3
4
|
/** Various event kinds that can have hidden tags */
|
|
4
5
|
export declare const HiddenTagsKinds: Set<number>;
|
|
5
6
|
/** Checks if an event can have hidden tags */
|
|
6
7
|
export declare function canHaveHiddenTags(kind: number): boolean;
|
|
7
8
|
/** Sets the type of encryption to use for hidden tags on a kind */
|
|
8
|
-
export declare function setHiddenTagsEncryptionMethod(kind: number, method:
|
|
9
|
+
export declare function setHiddenTagsEncryptionMethod(kind: number, method: EncryptionMethod): number;
|
|
9
10
|
/** Checks if an event has hidden tags */
|
|
10
11
|
export declare function hasHiddenTags<T extends {
|
|
11
12
|
kind: number;
|
|
@@ -19,25 +20,19 @@ export declare function getHiddenTags<T extends {
|
|
|
19
20
|
/** Checks if the hidden tags are locked */
|
|
20
21
|
export declare function isHiddenTagsLocked<T extends object>(event: T): boolean;
|
|
21
22
|
/** Returns either nip04 or nip44 encryption method depending on list kind */
|
|
22
|
-
export declare function getHiddenTagsEncryptionMethods(kind: number, signer: HiddenContentSigner):
|
|
23
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
24
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
25
|
-
} | {
|
|
26
|
-
encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
|
|
27
|
-
decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
|
|
28
|
-
};
|
|
23
|
+
export declare function getHiddenTagsEncryptionMethods(kind: number, signer: HiddenContentSigner): import("./encrypted-content.js").EncryptionMethods;
|
|
29
24
|
/**
|
|
30
25
|
* Decrypts the private list
|
|
31
26
|
* @param event The list event to decrypt
|
|
32
27
|
* @param signer A signer to use to decrypt the tags
|
|
33
|
-
* @param
|
|
28
|
+
* @param override The encryption method to use instead of the default
|
|
34
29
|
* @throws
|
|
35
30
|
*/
|
|
36
31
|
export declare function unlockHiddenTags<T extends {
|
|
37
32
|
kind: number;
|
|
38
33
|
pubkey: string;
|
|
39
34
|
content: string;
|
|
40
|
-
}>(event: T, signer: HiddenContentSigner): Promise<string[][]>;
|
|
35
|
+
}>(event: T, signer: HiddenContentSigner, override?: EncryptionMethod): Promise<string[][]>;
|
|
41
36
|
/**
|
|
42
37
|
* Sets the hidden tags on an event and updates it if its part of an event store
|
|
43
38
|
* @throws
|
|
@@ -58,15 +58,15 @@ export function getHiddenTagsEncryptionMethods(kind, signer) {
|
|
|
58
58
|
* Decrypts the private list
|
|
59
59
|
* @param event The list event to decrypt
|
|
60
60
|
* @param signer A signer to use to decrypt the tags
|
|
61
|
-
* @param
|
|
61
|
+
* @param override The encryption method to use instead of the default
|
|
62
62
|
* @throws
|
|
63
63
|
*/
|
|
64
|
-
export async function unlockHiddenTags(event, signer) {
|
|
64
|
+
export async function unlockHiddenTags(event, signer, override) {
|
|
65
65
|
if (!canHaveHiddenTags(event.kind))
|
|
66
66
|
throw new Error("Event kind does not support hidden tags");
|
|
67
67
|
// unlock hidden content is needed
|
|
68
68
|
if (isHiddenContentLocked(event))
|
|
69
|
-
await unlockHiddenContent(event, signer);
|
|
69
|
+
await unlockHiddenContent(event, signer, override);
|
|
70
70
|
return getHiddenTags(event);
|
|
71
71
|
}
|
|
72
72
|
/**
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export * from "./emoji.js";
|
|
|
17
17
|
export * from "./encrypted-content-cache.js";
|
|
18
18
|
export * from "./encrypted-content.js";
|
|
19
19
|
export * from "./encryption.js";
|
|
20
|
+
export * from "./event-cache.js";
|
|
20
21
|
export * from "./event-tags.js";
|
|
21
22
|
export * from "./event.js";
|
|
22
23
|
export * from "./expiration.js";
|
package/dist/helpers/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export * from "./emoji.js";
|
|
|
17
17
|
export * from "./encrypted-content-cache.js";
|
|
18
18
|
export * from "./encrypted-content.js";
|
|
19
19
|
export * from "./encryption.js";
|
|
20
|
+
export * from "./event-cache.js";
|
|
20
21
|
export * from "./event-tags.js";
|
|
21
22
|
export * from "./event.js";
|
|
22
23
|
export * from "./expiration.js";
|
package/dist/models/common.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { combineLatest, defer, distinctUntilChanged, EMPTY, endWith, filter, finalize, map, merge, mergeWith, of, repeat, scan, takeUntil, tap, } from "rxjs";
|
|
1
|
+
import { combineLatest, defer, distinctUntilChanged, EMPTY, endWith, filter, finalize, from, map, merge, mergeWith, of, repeat, scan, takeUntil, tap, } from "rxjs";
|
|
2
2
|
import { insertEventIntoDescendingList } from "nostr-tools/utils";
|
|
3
3
|
import { createReplaceableAddress, getEventUID, getReplaceableIdentifier, isReplaceable, matchFilters, } from "../helpers/index.js";
|
|
4
4
|
import { claimEvents } from "../observable/claim-events.js";
|
|
@@ -15,7 +15,9 @@ export function EventModel(pointer) {
|
|
|
15
15
|
if (event)
|
|
16
16
|
return of(event);
|
|
17
17
|
// If there is a loader, use it to get the event
|
|
18
|
-
|
|
18
|
+
if (!events.eventLoader)
|
|
19
|
+
return EMPTY;
|
|
20
|
+
return from(events.eventLoader(pointer)).pipe(filter((e) => !!e));
|
|
19
21
|
}),
|
|
20
22
|
// Listen for new events
|
|
21
23
|
events.insert$.pipe(filter((e) => e.id === pointer.id)),
|
|
@@ -38,10 +40,16 @@ export function ReplaceableModel(pointer) {
|
|
|
38
40
|
let event = events.getReplaceable(pointer.kind, pointer.pubkey, pointer.identifier);
|
|
39
41
|
if (event)
|
|
40
42
|
return of(event);
|
|
41
|
-
else if (pointer.identifier !== undefined)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return events.
|
|
43
|
+
else if (pointer.identifier !== undefined) {
|
|
44
|
+
if (!events.addressableLoader)
|
|
45
|
+
return EMPTY;
|
|
46
|
+
return from(events.addressableLoader(pointer)).pipe(filter((e) => !!e));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (!events.replaceableLoader)
|
|
50
|
+
return EMPTY;
|
|
51
|
+
return from(events.replaceableLoader(pointer)).pipe(filter((e) => !!e));
|
|
52
|
+
}
|
|
45
53
|
}),
|
|
46
54
|
// subscribe to new events
|
|
47
55
|
events.insert$.pipe(filter((e) => e.pubkey == pointer.pubkey &&
|