applesauce-core 0.0.0-next-20250919114711 → 0.0.0-next-20250923113611

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.
Files changed (44) hide show
  1. package/dist/helpers/app-data.d.ts +4 -1
  2. package/dist/helpers/app-data.js +4 -3
  3. package/dist/helpers/bookmarks.d.ts +11 -1
  4. package/dist/helpers/bookmarks.js +29 -4
  5. package/dist/helpers/comment.d.ts +13 -20
  6. package/dist/helpers/comment.js +16 -27
  7. package/dist/helpers/contacts.d.ts +1 -1
  8. package/dist/helpers/contacts.js +2 -2
  9. package/dist/helpers/encrypted-content-cache.js +7 -7
  10. package/dist/helpers/encrypted-content.d.ts +9 -2
  11. package/dist/helpers/encrypted-content.js +12 -9
  12. package/dist/helpers/event.d.ts +5 -1
  13. package/dist/helpers/event.js +2 -0
  14. package/dist/helpers/file-metadata.d.ts +4 -9
  15. package/dist/helpers/file-metadata.js +2 -10
  16. package/dist/helpers/filter.d.ts +3 -3
  17. package/dist/helpers/filter.js +3 -3
  18. package/dist/helpers/gift-wraps.d.ts +32 -11
  19. package/dist/helpers/gift-wraps.js +56 -47
  20. package/dist/helpers/groups.d.ts +2 -5
  21. package/dist/helpers/groups.js +2 -5
  22. package/dist/helpers/hidden-content.d.ts +14 -5
  23. package/dist/helpers/hidden-content.js +19 -8
  24. package/dist/helpers/hidden-tags.d.ts +16 -7
  25. package/dist/helpers/hidden-tags.js +47 -26
  26. package/dist/helpers/legacy-messages.d.ts +14 -12
  27. package/dist/helpers/legacy-messages.js +15 -15
  28. package/dist/helpers/lists.js +2 -1
  29. package/dist/helpers/lnurl.d.ts +4 -0
  30. package/dist/helpers/lnurl.js +7 -3
  31. package/dist/helpers/mutes.d.ts +11 -1
  32. package/dist/helpers/mutes.js +30 -5
  33. package/dist/helpers/picture-post.d.ts +2 -1
  34. package/dist/helpers/pointers.d.ts +1 -1
  35. package/dist/helpers/profile.d.ts +7 -3
  36. package/dist/helpers/profile.js +7 -8
  37. package/dist/helpers/zap.d.ts +16 -14
  38. package/dist/helpers/zap.js +26 -28
  39. package/dist/models/gift-wrap.d.ts +1 -1
  40. package/dist/models/gift-wrap.js +4 -4
  41. package/dist/models/legacy-messages.js +2 -0
  42. package/dist/models/zaps.d.ts +5 -4
  43. package/dist/models/zaps.js +2 -2
  44. package/package.json +2 -2
@@ -2,6 +2,7 @@ import { NostrEvent } from "nostr-tools";
2
2
  import { EncryptionMethod } from "./encrypted-content.js";
3
3
  import { HiddenContentSigner } from "./hidden-content.js";
4
4
  export declare const APP_DATA_KIND = 30078;
5
+ /** A symbol used to cache the application data content */
5
6
  export declare const AppDataContentSymbol: unique symbol;
6
7
  /** Checks if an event has application data */
7
8
  export declare function hasAppData<T extends {
@@ -14,7 +15,9 @@ export declare function getAppDataEncryption<T extends {
14
15
  content: string;
15
16
  }>(event: T): EncryptionMethod | undefined;
16
17
  /** Checks if the application data is locked (encrypted and not decrypted) */
17
- export declare function isAppDataLocked<T extends object>(event: T): boolean;
18
+ export declare function isAppDataUnlocked<T extends {
19
+ kind: number;
20
+ }>(event: T): boolean;
18
21
  /** Returns the parsed application data for an event if it's unlocked */
19
22
  export declare function getAppDataContent<R extends unknown = unknown, T extends {
20
23
  kind: number;
@@ -1,8 +1,9 @@
1
1
  import { isNIP04Encrypted } from "./encryption.js";
2
- import { getHiddenContent, isHiddenContentLocked, lockHiddenContent, setHiddenContentEncryptionMethod, unlockHiddenContent, } from "./hidden-content.js";
2
+ import { getHiddenContent, isHiddenContentUnlocked, lockHiddenContent, setHiddenContentEncryptionMethod, unlockHiddenContent, } from "./hidden-content.js";
3
3
  import { safeParse } from "./json.js";
4
4
  // NIP-78 Application Data event kind
5
5
  export const APP_DATA_KIND = 30078;
6
+ /** A symbol used to cache the application data content */
6
7
  export const AppDataContentSymbol = Symbol.for("app-data-content");
7
8
  // Set the encryption method for app data events (default to nip44)
8
9
  setHiddenContentEncryptionMethod(APP_DATA_KIND, "nip44");
@@ -22,8 +23,8 @@ export function getAppDataEncryption(event) {
22
23
  return isNIP04Encrypted(event.content) ? "nip04" : "nip44";
23
24
  }
24
25
  /** Checks if the application data is locked (encrypted and not decrypted) */
25
- export function isAppDataLocked(event) {
26
- return isHiddenContentLocked(event);
26
+ export function isAppDataUnlocked(event) {
27
+ return isHiddenContentUnlocked(event);
27
28
  }
28
29
  /** Returns the parsed application data for an event if it's unlocked */
29
30
  export function getAppDataContent(event) {
@@ -1,7 +1,12 @@
1
1
  import { NostrEvent } from "nostr-tools";
2
2
  import { AddressPointer, EventPointer } from "nostr-tools/nip19";
3
+ import { HiddenContentSigner } from "./index.js";
3
4
  export declare const BookmarkPublicSymbol: unique symbol;
4
5
  export declare const BookmarkHiddenSymbol: unique symbol;
6
+ /** Type for unlocked bookmarks events */
7
+ export type UnlockedBookmarks = {
8
+ [BookmarkHiddenSymbol]: Bookmarks;
9
+ };
5
10
  export type Bookmarks = {
6
11
  notes: EventPointer[];
7
12
  articles: AddressPointer[];
@@ -16,5 +21,10 @@ export declare function mergeBookmarks(...bookmarks: (Bookmarks | undefined)[]):
16
21
  export declare function getBookmarks(bookmark: NostrEvent): Bookmarks;
17
22
  /** Returns the public bookmarks of the event */
18
23
  export declare function getPublicBookmarks(bookmark: NostrEvent): Bookmarks;
24
+ /** Checks if the hidden bookmarks are unlocked */
25
+ export declare function isHiddenBookmarksUnlocked<T extends NostrEvent>(bookmark: T): bookmark is T & UnlockedBookmarks;
19
26
  /** Returns the bookmarks of the event if its unlocked */
20
- export declare function getHiddenBookmarks(bookmark: NostrEvent): Bookmarks | undefined;
27
+ export declare function getHiddenBookmarks<T extends NostrEvent & UnlockedBookmarks>(bookmark: T): Bookmarks;
28
+ export declare function getHiddenBookmarks<T extends NostrEvent>(bookmark: T): Bookmarks | undefined;
29
+ /** Unlocks the hidden bookmarks on a bookmarks event */
30
+ export declare function unlockHiddenBookmarks(bookmark: NostrEvent, signer: HiddenContentSigner): Promise<Bookmarks>;
@@ -1,6 +1,6 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { getOrComputeCachedValue } from "./cache.js";
3
- import { getHiddenTags, isHiddenTagsLocked } from "./index.js";
3
+ import { getHiddenTags, isHiddenTagsUnlocked, notifyEventUpdate, unlockHiddenTags, } from "./index.js";
4
4
  import { getAddressPointerFromATag, getCoordinateFromAddressPointer, getEventPointerFromETag, mergeAddressPointers, mergeEventPointers, } from "./pointers.js";
5
5
  export const BookmarkPublicSymbol = Symbol.for("bookmark-public");
6
6
  export const BookmarkHiddenSymbol = Symbol.for("bookmark-hidden");
@@ -63,9 +63,34 @@ export function getBookmarks(bookmark) {
63
63
  export function getPublicBookmarks(bookmark) {
64
64
  return getOrComputeCachedValue(bookmark, BookmarkPublicSymbol, () => parseBookmarkTags(bookmark.tags));
65
65
  }
66
- /** Returns the bookmarks of the event if its unlocked */
66
+ /** Checks if the hidden bookmarks are unlocked */
67
+ export function isHiddenBookmarksUnlocked(bookmark) {
68
+ return isHiddenTagsUnlocked(bookmark) && Reflect.has(bookmark, BookmarkHiddenSymbol);
69
+ }
67
70
  export function getHiddenBookmarks(bookmark) {
68
- if (isHiddenTagsLocked(bookmark))
71
+ if (isHiddenBookmarksUnlocked(bookmark))
72
+ return bookmark[BookmarkHiddenSymbol];
73
+ //get hidden tags
74
+ const tags = getHiddenTags(bookmark);
75
+ if (!tags)
69
76
  return undefined;
70
- return getOrComputeCachedValue(bookmark, BookmarkHiddenSymbol, () => parseBookmarkTags(getHiddenTags(bookmark)));
77
+ // parse bookmarks
78
+ const bookmarks = parseBookmarkTags(tags);
79
+ // set cached value
80
+ Reflect.set(bookmark, BookmarkHiddenSymbol, bookmarks);
81
+ return bookmarks;
82
+ }
83
+ /** Unlocks the hidden bookmarks on a bookmarks event */
84
+ export async function unlockHiddenBookmarks(bookmark, signer) {
85
+ if (isHiddenBookmarksUnlocked(bookmark))
86
+ return bookmark[BookmarkHiddenSymbol];
87
+ // unlock hidden tags
88
+ await unlockHiddenTags(bookmark, signer);
89
+ // get hidden bookmarks
90
+ const bookmarks = getHiddenBookmarks(bookmark);
91
+ if (!bookmarks)
92
+ throw new Error("Failed to unlock hidden bookmarks");
93
+ // notify event store
94
+ notifyEventUpdate(bookmark);
95
+ return bookmarks;
71
96
  }
@@ -1,6 +1,9 @@
1
1
  import { NostrEvent } from "nostr-tools";
2
2
  import { ExternalPointer, ExternalIdentifiers } from "./external-id.js";
3
+ import { KnownEvent } from "./index.js";
3
4
  export declare const COMMENT_KIND = 1111;
5
+ /** Type for validated comment events */
6
+ export type CommentEvent = KnownEvent<typeof COMMENT_KIND>;
4
7
  export type CommentEventPointer = {
5
8
  type: "event";
6
9
  id: string;
@@ -22,30 +25,20 @@ export type CommentExternalPointer<T extends keyof ExternalIdentifiers> = Extern
22
25
  export type CommentPointer = CommentEventPointer | CommentAddressPointer | CommentExternalPointer<keyof ExternalIdentifiers>;
23
26
  export declare const CommentRootPointerSymbol: unique symbol;
24
27
  export declare const CommentReplyPointerSymbol: unique symbol;
25
- /**
26
- * Gets the EventPointer from an array of tags
27
- * @throws
28
- */
28
+ /** Gets the EventPointer from an array of tags */
29
29
  export declare function getCommentEventPointer(tags: string[][], root?: boolean): CommentEventPointer | null;
30
- /**
31
- * Gets the AddressPointer from an array of tags
32
- * @throws
33
- */
30
+ /** Gets the AddressPointer from an array of tags */
34
31
  export declare function getCommentAddressPointer(tags: string[][], root?: boolean): CommentAddressPointer | null;
35
- /**
36
- * Gets the ExternalPointer from an array of tags
37
- * @throws
38
- */
32
+ /** Gets the ExternalPointer from an array of tags */
39
33
  export declare function getCommentExternalPointer(tags: string[][], root?: boolean): CommentExternalPointer<keyof ExternalIdentifiers> | null;
40
- /**
41
- * Returns the root pointer for a comment
42
- * @throws
43
- */
34
+ /** Returns the root pointer for a comment */
35
+ export declare function getCommentRootPointer(comment: CommentEvent): CommentPointer;
44
36
  export declare function getCommentRootPointer(comment: NostrEvent): CommentPointer | null;
45
- /**
46
- * Returns the reply pointer for a comment
47
- * @throws
48
- */
37
+ /** Returns the reply pointer for a comment */
49
38
  export declare function getCommentReplyPointer(comment: NostrEvent): CommentPointer | null;
39
+ /** Checks if a pointer is a {@link CommentEventPointer} */
50
40
  export declare function isCommentEventPointer(pointer: any): pointer is CommentEventPointer;
41
+ /** Checks if a pointer is a {@link CommentAddressPointer} */
51
42
  export declare function isCommentAddressPointer(pointer: any): pointer is CommentAddressPointer;
43
+ /** Checks if a comment event is valid */
44
+ export declare function isValidComment(comment: NostrEvent): comment is CommentEvent;
@@ -5,16 +5,14 @@ import { isSafeRelayURL } from "./relays.js";
5
5
  export const COMMENT_KIND = 1111;
6
6
  export const CommentRootPointerSymbol = Symbol.for("comment-root-pointer");
7
7
  export const CommentReplyPointerSymbol = Symbol.for("comment-reply-pointer");
8
- /**
9
- * Gets the EventPointer from an array of tags
10
- * @throws
11
- */
8
+ /** Gets the EventPointer from an array of tags */
12
9
  export function getCommentEventPointer(tags, root = false) {
13
10
  const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
14
11
  const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
15
12
  if (eTag) {
13
+ // Missing kind tag, return null
16
14
  if (!kind)
17
- throw new Error("Missing kind tag");
15
+ return null;
18
16
  // only the root pubkey can be gotten from the tags, since due to quotes and mentions there will be many "p" tags for replies
19
17
  const rootPubkey = root ? tags.find((t) => t[0] === "P")?.[1] : undefined;
20
18
  const pointer = {
@@ -28,17 +26,15 @@ export function getCommentEventPointer(tags, root = false) {
28
26
  }
29
27
  return null;
30
28
  }
31
- /**
32
- * Gets the AddressPointer from an array of tags
33
- * @throws
34
- */
29
+ /** Gets the AddressPointer from an array of tags */
35
30
  export function getCommentAddressPointer(tags, root = false) {
36
31
  const aTag = tags.find((t) => t[0] === (root ? "A" : "a"));
37
32
  const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
38
33
  const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
39
34
  if (aTag) {
35
+ // Missing kind tag, return null
40
36
  if (!kind)
41
- throw new Error("Missing kind tag");
37
+ return null;
42
38
  const addressPointer = getAddressPointerFromATag(aTag);
43
39
  const pointer = {
44
40
  type: "address",
@@ -52,16 +48,10 @@ export function getCommentAddressPointer(tags, root = false) {
52
48
  }
53
49
  return null;
54
50
  }
55
- /**
56
- * Gets the ExternalPointer from an array of tags
57
- * @throws
58
- */
51
+ /** Gets the ExternalPointer from an array of tags */
59
52
  export function getCommentExternalPointer(tags, root = false) {
60
53
  const iTag = tags.find((t) => t[0] === (root ? "I" : "i"));
61
- const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
62
54
  if (iTag) {
63
- if (!kind)
64
- throw new Error("Missing kind tag");
65
55
  return {
66
56
  type: "external",
67
57
  ...getExternalPointerFromTag(iTag),
@@ -69,13 +59,9 @@ export function getCommentExternalPointer(tags, root = false) {
69
59
  }
70
60
  return null;
71
61
  }
72
- /**
73
- * Returns the root pointer for a comment
74
- * @throws
75
- */
76
62
  export function getCommentRootPointer(comment) {
77
63
  if (comment.kind !== COMMENT_KIND)
78
- throw new Error("Event is not a comment");
64
+ return null;
79
65
  return getOrComputeCachedValue(comment, CommentRootPointerSymbol, () => {
80
66
  // check for address pointer first since it can also have E tags
81
67
  const A = getCommentAddressPointer(comment.tags, true);
@@ -90,13 +76,10 @@ export function getCommentRootPointer(comment) {
90
76
  return null;
91
77
  });
92
78
  }
93
- /**
94
- * Returns the reply pointer for a comment
95
- * @throws
96
- */
79
+ /** Returns the reply pointer for a comment */
97
80
  export function getCommentReplyPointer(comment) {
98
81
  if (comment.kind !== COMMENT_KIND)
99
- throw new Error("Event is not a comment");
82
+ return null;
100
83
  return getOrComputeCachedValue(comment, CommentReplyPointerSymbol, () => {
101
84
  // check for address pointer first since it can also have E tags
102
85
  const A = getCommentAddressPointer(comment.tags, false);
@@ -111,15 +94,21 @@ export function getCommentReplyPointer(comment) {
111
94
  return null;
112
95
  });
113
96
  }
97
+ /** Checks if a pointer is a {@link CommentEventPointer} */
114
98
  export function isCommentEventPointer(pointer) {
115
99
  return (Reflect.has(pointer, "id") &&
116
100
  Reflect.has(pointer, "kind") &&
117
101
  !Reflect.has(pointer, "identifier") &&
118
102
  typeof pointer.kind === "number");
119
103
  }
104
+ /** Checks if a pointer is a {@link CommentAddressPointer} */
120
105
  export function isCommentAddressPointer(pointer) {
121
106
  return (Reflect.has(pointer, "identifier") &&
122
107
  Reflect.has(pointer, "pubkey") &&
123
108
  Reflect.has(pointer, "kind") &&
124
109
  typeof pointer.kind === "number");
125
110
  }
111
+ /** Checks if a comment event is valid */
112
+ export function isValidComment(comment) {
113
+ return (comment.kind === COMMENT_KIND && getCommentRootPointer(comment) !== null && getCommentReplyPointer(comment) !== null);
114
+ }
@@ -3,7 +3,7 @@ import { ProfilePointer } from "nostr-tools/nip19";
3
3
  export declare const ContactsRelaysSymbol: unique symbol;
4
4
  export declare const PublicContactsSymbol: unique symbol;
5
5
  export declare const HiddenContactsSymbol: unique symbol;
6
- export declare function getRelaysFromContactsEvent(event: NostrEvent): Map<string, "all" | "inbox" | "outbox"> | null;
6
+ export declare function getRelaysFromContactsEvent(event: NostrEvent): Map<string, "inbox" | "outbox" | "all"> | null;
7
7
  /** Merges any number of contact lists into a single list */
8
8
  export declare function mergeContacts(...pointers: (ProfilePointer | undefined | (ProfilePointer | undefined)[])[]): ProfilePointer[];
9
9
  /** Returns all public and hidden contacts from a contacts list event */
@@ -2,7 +2,7 @@ import { getOrComputeCachedValue } from "./cache.js";
2
2
  import { isSafeRelayURL } from "./relays.js";
3
3
  import { isPTag, processTags } from "./tags.js";
4
4
  import { getProfilePointerFromPTag } from "./pointers.js";
5
- import { getHiddenTags, isHiddenTagsLocked } from "./hidden-tags.js";
5
+ import { getHiddenTags, isHiddenTagsUnlocked } from "./hidden-tags.js";
6
6
  export const ContactsRelaysSymbol = Symbol.for("contacts-relays");
7
7
  export const PublicContactsSymbol = Symbol.for("public-contacts");
8
8
  export const HiddenContactsSymbol = Symbol.for("hidden-contacts");
@@ -53,7 +53,7 @@ export function getPublicContacts(event) {
53
53
  }
54
54
  /** Returns only the hidden contacts from a contacts list event */
55
55
  export function getHiddenContacts(event) {
56
- if (isHiddenTagsLocked(event))
56
+ if (isHiddenTagsUnlocked(event))
57
57
  return undefined;
58
58
  return getOrComputeCachedValue(event, HiddenContactsSymbol, () => processTags(getHiddenTags(event), (t) => (isPTag(t) ? t : undefined), getProfilePointerFromPTag));
59
59
  }
@@ -1,7 +1,7 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { catchError, combineLatest, distinct, EMPTY, filter, isObservable, map, merge, mergeMap, of, switchMap, } from "rxjs";
3
3
  import { logger } from "../logger.js";
4
- import { canHaveEncryptedContent, getEncryptedContent, isEncryptedContentLocked, setEncryptedContentCache, } from "./encrypted-content.js";
4
+ import { canHaveEncryptedContent, getEncryptedContent, isEncryptedContentUnlocked, setEncryptedContentCache, } from "./encrypted-content.js";
5
5
  import { notifyEventUpdate } from "./event.js";
6
6
  import { getGiftWrapSeal, getSealGiftWrap, getSealRumor } from "./gift-wraps.js";
7
7
  /** A symbol that is used to mark encrypted content as being from a cache */
@@ -32,7 +32,7 @@ export function persistEncryptedContent(eventStore, storage, fallback) {
32
32
  const restore = eventStore.insert$
33
33
  .pipe(
34
34
  // Look for events that support encrypted content and are locked
35
- filter((e) => canHaveEncryptedContent(e.kind) && isEncryptedContentLocked(e)),
35
+ filter((e) => canHaveEncryptedContent(e.kind) && isEncryptedContentUnlocked(e) === false),
36
36
  // Get the encrypted content from storage
37
37
  mergeMap((event) =>
38
38
  // Wait for storage to be available
@@ -52,11 +52,11 @@ export function persistEncryptedContent(eventStore, storage, fallback) {
52
52
  const restoreSeals = eventStore.update$
53
53
  .pipe(
54
54
  // Look for gift wraps that are unlocked
55
- filter((e) => e.kind === kinds.GiftWrap && !isEncryptedContentLocked(e)),
55
+ filter((e) => e.kind === kinds.GiftWrap && isEncryptedContentUnlocked(e)),
56
56
  // Get the seal event
57
57
  map((gift) => getGiftWrapSeal(gift)),
58
58
  // Look for gift wraps with locked seals
59
- filter((seal) => seal !== undefined && isEncryptedContentLocked(seal)),
59
+ filter((seal) => seal !== undefined && isEncryptedContentUnlocked(seal) === false),
60
60
  // Only attempt to unlock seals once
61
61
  distinct((seal) => seal.id),
62
62
  // Get encrypted content from storage
@@ -84,7 +84,7 @@ export function persistEncryptedContent(eventStore, storage, fallback) {
84
84
  .pipe(
85
85
  // Look for events that support encrypted content and are unlocked and not from the cache
86
86
  filter(([event]) => canHaveEncryptedContent(event.kind) &&
87
- !isEncryptedContentLocked(event) &&
87
+ isEncryptedContentUnlocked(event) &&
88
88
  !isEncryptedContentFromCache(event)),
89
89
  // Only persist the encrypted content once
90
90
  distinct(([event]) => event.id))
@@ -106,13 +106,13 @@ export function persistEncryptedContent(eventStore, storage, fallback) {
106
106
  const persistSeals = combineLatest([merge(eventStore.update$, eventStore.insert$), storage$])
107
107
  .pipe(
108
108
  // Look for gift wraps that are unlocked
109
- filter(([event]) => event.kind === kinds.GiftWrap && !isEncryptedContentLocked(event)),
109
+ filter(([event]) => event.kind === kinds.GiftWrap && isEncryptedContentUnlocked(event)),
110
110
  // Get the seal event
111
111
  map(([gift, storage]) => [getGiftWrapSeal(gift), storage]),
112
112
  // Make sure the seal is defined
113
113
  filter(([seal]) => seal !== undefined),
114
114
  // Make sure seal is unlocked and not from cache
115
- filter(([seal]) => !isEncryptedContentLocked(seal) && !isEncryptedContentFromCache(seal)),
115
+ filter(([seal]) => isEncryptedContentUnlocked(seal) && !isEncryptedContentFromCache(seal)),
116
116
  // Only persist the seal once
117
117
  distinct(([seal]) => seal.id))
118
118
  .subscribe(async ([seal, storage]) => {
@@ -10,7 +10,12 @@ export interface EncryptedContentSigner {
10
10
  decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
11
11
  };
12
12
  }
13
+ /** Encryption method types */
13
14
  export type EncryptionMethod = "nip04" | "nip44";
15
+ /** Type for an event who's encrypted content is unlocked */
16
+ export type UnlockedEncryptedContent = {
17
+ [EncryptedContentSymbol]: string;
18
+ };
14
19
  /** A pair of encryption methods for encrypting and decrypting event content */
15
20
  export interface EncryptionMethods {
16
21
  encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
@@ -37,14 +42,16 @@ export declare function hasEncryptedContent<T extends {
37
42
  content: string;
38
43
  }>(event: T): boolean;
39
44
  /** Returns the encrypted content for an event if it is unlocked */
45
+ export declare function getEncryptedContent<T extends UnlockedEncryptedContent>(event: T): string;
40
46
  export declare function getEncryptedContent<T extends object>(event: T): string | undefined;
41
- /** Checks if the encrypted content is locked */
42
- export declare function isEncryptedContentLocked<T extends object>(event: T): boolean;
47
+ /** Checks if the encrypted content is unlocked and casts it to the {@link UnlockedEncryptedContent} type */
48
+ export declare function isEncryptedContentUnlocked<T extends object>(event: T): event is T & UnlockedEncryptedContent;
43
49
  /**
44
50
  * Unlocks the encrypted content in an event and caches it
45
51
  * @param event The event with content to decrypt
46
52
  * @param pubkey The other pubkey that encrypted the content
47
53
  * @param signer A signer to use to decrypt the content
54
+ * @throws If the event kind does not support encrypted content
48
55
  */
49
56
  export declare function unlockEncryptedContent<T extends {
50
57
  kind: number;
@@ -1,5 +1,5 @@
1
1
  import { kinds } from "nostr-tools";
2
- import { isEvent, notifyEventUpdate } from "./event.js";
2
+ import { notifyEventUpdate } from "./event.js";
3
3
  /** A symbol use to store the encrypted content of an event in memory */
4
4
  export const EncryptedContentSymbol = Symbol.for("encrypted-content");
5
5
  /** Various event kinds that can have encrypted content and which encryption method they use */
@@ -39,37 +39,40 @@ export function canHaveEncryptedContent(kind) {
39
39
  export function hasEncryptedContent(event) {
40
40
  return event.content.length > 0;
41
41
  }
42
- /** Returns the encrypted content for an event if it is unlocked */
43
42
  export function getEncryptedContent(event) {
44
43
  return Reflect.get(event, EncryptedContentSymbol);
45
44
  }
46
- /** Checks if the encrypted content is locked */
47
- export function isEncryptedContentLocked(event) {
48
- return Reflect.has(event, EncryptedContentSymbol) === false;
45
+ /** Checks if the encrypted content is unlocked and casts it to the {@link UnlockedEncryptedContent} type */
46
+ export function isEncryptedContentUnlocked(event) {
47
+ return Reflect.has(event, EncryptedContentSymbol) === true;
49
48
  }
50
49
  /**
51
50
  * Unlocks the encrypted content in an event and caches it
52
51
  * @param event The event with content to decrypt
53
52
  * @param pubkey The other pubkey that encrypted the content
54
53
  * @param signer A signer to use to decrypt the content
54
+ * @throws If the event kind does not support encrypted content
55
55
  */
56
56
  export async function unlockEncryptedContent(event, pubkey, signer) {
57
+ if (!canHaveEncryptedContent(event.kind))
58
+ throw new Error("Event kind does not support encrypted content");
59
+ // Get the encryption methods from the signer
57
60
  const encryption = getEncryptedContentEncryptionMethods(event.kind, signer);
58
61
  const plaintext = await encryption.decrypt(pubkey, event.content);
62
+ // Set the cached value and trigger update
59
63
  setEncryptedContentCache(event, plaintext);
64
+ // Return the decrypted content
60
65
  return plaintext;
61
66
  }
62
67
  /** Sets the encrypted content on an event and updates it if its part of an event store */
63
68
  export function setEncryptedContentCache(event, plaintext) {
64
69
  Reflect.set(event, EncryptedContentSymbol, plaintext);
65
70
  // if the event has been added to an event store, notify it
66
- if (isEvent(event))
67
- notifyEventUpdate(event);
71
+ notifyEventUpdate(event);
68
72
  }
69
73
  /** Removes the encrypted content cache on an event */
70
74
  export function lockEncryptedContent(event) {
71
75
  Reflect.deleteProperty(event, EncryptedContentSymbol);
72
76
  // if the event has been added to an event store, notify it
73
- if (isEvent(event))
74
- notifyEventUpdate(event);
77
+ notifyEventUpdate(event);
75
78
  }
@@ -3,6 +3,10 @@ import { IEventStore } from "../event-store/interface.js";
3
3
  export { NostrEvent, EventTemplate, UnsignedEvent, verifiedSymbol, verifyEvent, VerifiedEvent } from "nostr-tools/pure";
4
4
  export { bytesToHex, hexToBytes, insertEventIntoAscendingList, insertEventIntoDescendingList, binarySearch, } from "nostr-tools/utils";
5
5
  export * as kinds from "nostr-tools/kinds";
6
+ /** An event with a known kind. this is used to know if events have been validated */
7
+ export type KnownEvent<K extends number> = Omit<NostrEvent, "kind"> & {
8
+ kind: K;
9
+ };
6
10
  /** A symbol on an event that marks which event store its part of */
7
11
  export declare const EventStoreSymbol: unique symbol;
8
12
  export declare const EventUIDSymbol: unique symbol;
@@ -41,7 +45,7 @@ export declare function isFromCache(event: NostrEvent): boolean;
41
45
  /** Returns the EventStore of an event if its been added to one */
42
46
  export declare function getParentEventStore<T extends object>(event: T): IEventStore | undefined;
43
47
  /** Notifies the events parent store that an event has been updated */
44
- export declare function notifyEventUpdate(event: NostrEvent): void;
48
+ export declare function notifyEventUpdate(event: any): void;
45
49
  /** Returns the replaceable identifier for a replaceable event */
46
50
  export declare function getReplaceableIdentifier(event: NostrEvent): string;
47
51
  /** Checks if an event is a NIP-70 protected event */
@@ -85,6 +85,8 @@ export function getParentEventStore(event) {
85
85
  }
86
86
  /** Notifies the events parent store that an event has been updated */
87
87
  export function notifyEventUpdate(event) {
88
+ if (!isEvent(event))
89
+ return;
88
90
  const eventStore = getParentEventStore(event);
89
91
  if (eventStore)
90
92
  eventStore.update(event);
@@ -1,7 +1,7 @@
1
1
  import { NostrEvent } from "nostr-tools";
2
2
  export type FileMetadata = {
3
3
  /** URL of the file */
4
- url: string;
4
+ url?: string;
5
5
  /** MIME type */
6
6
  type?: string;
7
7
  /** sha256 hash of the file */
@@ -32,24 +32,19 @@ export type FileMetadata = {
32
32
  /** fallback URLs */
33
33
  fallback?: string[];
34
34
  };
35
+ /** Alias for {@link FileMetadata} */
35
36
  export type MediaAttachment = FileMetadata;
36
37
  /**
37
38
  * Parses file metadata tags into {@link FileMetadata}
38
39
  * @throws
39
40
  */
40
41
  export declare function parseFileMetadataTags(tags: string[][]): FileMetadata;
41
- /**
42
- * Parses a imeta tag into a {@link FileMetadata}
43
- * @throws
44
- */
42
+ /** Parses a imeta tag into a {@link FileMetadata} */
45
43
  export declare function getFileMetadataFromImetaTag(tag: string[]): FileMetadata;
46
44
  export declare const MediaAttachmentsSymbol: unique symbol;
47
45
  /** Gets all the media attachments on an event */
48
46
  export declare function getMediaAttachments(event: NostrEvent): FileMetadata[];
49
- /**
50
- * Gets {@link FileMetadata} for a NIP-94 kind 1063 event
51
- * @throws
52
- */
47
+ /** Gets {@link FileMetadata} for a NIP-94 kind 1063 event */
53
48
  export declare function getFileMetadata(file: NostrEvent): FileMetadata;
54
49
  /** Returns the last 64 length hex string in a URL */
55
50
  export declare function getSha256FromURL(url: string | URL): string | undefined;
@@ -16,8 +16,6 @@ export function parseFileMetadataTags(tags) {
16
16
  break;
17
17
  }
18
18
  }
19
- if (!fields.url)
20
- throw new Error("Missing required url in file metadata");
21
19
  const metadata = { url: fields.url, fallback };
22
20
  // parse size
23
21
  if (fields.size)
@@ -47,10 +45,7 @@ export function parseFileMetadataTags(tags) {
47
45
  metadata.blurhash = fields.blurhash;
48
46
  return metadata;
49
47
  }
50
- /**
51
- * Parses a imeta tag into a {@link FileMetadata}
52
- * @throws
53
- */
48
+ /** Parses a imeta tag into a {@link FileMetadata} */
54
49
  export function getFileMetadataFromImetaTag(tag) {
55
50
  const parts = tag.slice(1);
56
51
  const tags = [];
@@ -81,10 +76,7 @@ export function getMediaAttachments(event) {
81
76
  .filter((a) => !!a);
82
77
  });
83
78
  }
84
- /**
85
- * Gets {@link FileMetadata} for a NIP-94 kind 1063 event
86
- * @throws
87
- */
79
+ /** Gets {@link FileMetadata} for a NIP-94 kind 1063 event */
88
80
  export function getFileMetadata(file) {
89
81
  return parseFileMetadataTags(file.tags);
90
82
  }
@@ -1,13 +1,13 @@
1
1
  import { Filter, NostrEvent } from "nostr-tools";
2
2
  export { Filter } from "nostr-tools/filter";
3
3
  /**
4
- * Copied from nostr-tools and modified to use getIndexableTags
4
+ * Copied from nostr-tools and modified to use {@link getIndexableTags}
5
5
  * @see https://github.com/nbd-wtf/nostr-tools/blob/a61cde77eacc9518001f11d7f67f1a50ae05fd80/filter.ts
6
6
  */
7
7
  export declare function matchFilter(filter: Filter, event: NostrEvent): boolean;
8
- /** Copied from nostr-tools */
8
+ /** Copied from nostr-tools and modified to use {@link matchFilter} */
9
9
  export declare function matchFilters(filters: Filter[], event: NostrEvent): boolean;
10
- /** Copied from nostr-tools and modified to support undefined */
10
+ /** Copied from nostr-tools and modified to support undefined values */
11
11
  export declare function mergeFilters(...filters: Filter[]): Filter;
12
12
  /** Check if two filters are equal */
13
13
  export declare function isFilterEqual(a: Filter | Filter[], b: Filter | Filter[]): boolean;
@@ -1,7 +1,7 @@
1
1
  import equal from "fast-deep-equal";
2
2
  import { getIndexableTags } from "./event-tags.js";
3
3
  /**
4
- * Copied from nostr-tools and modified to use getIndexableTags
4
+ * Copied from nostr-tools and modified to use {@link getIndexableTags}
5
5
  * @see https://github.com/nbd-wtf/nostr-tools/blob/a61cde77eacc9518001f11d7f67f1a50ae05fd80/filter.ts
6
6
  */
7
7
  export function matchFilter(filter, event) {
@@ -31,7 +31,7 @@ export function matchFilter(filter, event) {
31
31
  return false;
32
32
  return true;
33
33
  }
34
- /** Copied from nostr-tools */
34
+ /** Copied from nostr-tools and modified to use {@link matchFilter} */
35
35
  export function matchFilters(filters, event) {
36
36
  for (let i = 0; i < filters.length; i++) {
37
37
  if (matchFilter(filters[i], event)) {
@@ -40,7 +40,7 @@ export function matchFilters(filters, event) {
40
40
  }
41
41
  return false;
42
42
  }
43
- /** Copied from nostr-tools and modified to support undefined */
43
+ /** Copied from nostr-tools and modified to support undefined values */
44
44
  export function mergeFilters(...filters) {
45
45
  let result = {};
46
46
  for (let i = 0; i < filters.length; i++) {