applesauce-core 1.2.0 → 2.0.0

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 (204) hide show
  1. package/README.md +7 -13
  2. package/dist/event-store/{database.d.ts → event-set.d.ts} +35 -20
  3. package/dist/event-store/{database.js → event-set.js} +91 -60
  4. package/dist/event-store/event-store.d.ts +64 -25
  5. package/dist/event-store/event-store.js +163 -206
  6. package/dist/event-store/index.d.ts +1 -1
  7. package/dist/event-store/index.js +1 -1
  8. package/dist/event-store/interface.d.ts +71 -13
  9. package/dist/helpers/app-handlers.d.ts +23 -0
  10. package/dist/helpers/app-handlers.js +68 -0
  11. package/dist/helpers/article.d.ts +9 -0
  12. package/dist/helpers/article.js +21 -0
  13. package/dist/helpers/bolt11.d.ts +1 -0
  14. package/dist/helpers/bolt11.js +2 -0
  15. package/dist/helpers/bookmarks.js +1 -2
  16. package/dist/helpers/emoji.d.ts +10 -2
  17. package/dist/helpers/emoji.js +21 -3
  18. package/dist/helpers/encrypted-content-cache.d.ts +15 -0
  19. package/dist/helpers/encrypted-content-cache.js +125 -0
  20. package/dist/helpers/encrypted-content.d.ts +48 -0
  21. package/dist/helpers/encrypted-content.js +65 -0
  22. package/dist/helpers/encryption.d.ts +5 -0
  23. package/dist/helpers/encryption.js +10 -0
  24. package/dist/helpers/event.d.ts +4 -1
  25. package/dist/helpers/event.js +13 -3
  26. package/dist/helpers/expiration.d.ts +6 -0
  27. package/dist/helpers/expiration.js +16 -0
  28. package/dist/helpers/filter.d.ts +1 -3
  29. package/dist/helpers/filter.js +1 -3
  30. package/dist/helpers/gift-wraps.d.ts +17 -5
  31. package/dist/helpers/gift-wraps.js +65 -27
  32. package/dist/helpers/groups.d.ts +5 -0
  33. package/dist/helpers/groups.js +12 -2
  34. package/dist/helpers/hidden-content.d.ts +27 -32
  35. package/dist/helpers/hidden-content.js +35 -65
  36. package/dist/helpers/hidden-tags.d.ts +23 -4
  37. package/dist/helpers/hidden-tags.js +39 -4
  38. package/dist/helpers/index.d.ts +11 -1
  39. package/dist/helpers/index.js +11 -1
  40. package/dist/helpers/legacy-messages.d.ts +21 -0
  41. package/dist/helpers/legacy-messages.js +39 -0
  42. package/dist/helpers/lists.d.ts +1 -1
  43. package/dist/helpers/lists.js +2 -2
  44. package/dist/helpers/messages.d.ts +11 -0
  45. package/dist/helpers/messages.js +19 -0
  46. package/dist/helpers/mutes.js +1 -1
  47. package/dist/helpers/pointers.d.ts +33 -9
  48. package/dist/helpers/pointers.js +80 -44
  49. package/dist/helpers/profile.d.ts +10 -2
  50. package/dist/helpers/profile.js +33 -4
  51. package/dist/helpers/reactions.d.ts +8 -0
  52. package/dist/helpers/reactions.js +56 -0
  53. package/dist/helpers/reports.d.ts +28 -0
  54. package/dist/helpers/reports.js +38 -0
  55. package/dist/helpers/share.d.ts +10 -1
  56. package/dist/helpers/share.js +22 -8
  57. package/dist/helpers/url.d.ts +4 -0
  58. package/dist/helpers/url.js +20 -0
  59. package/dist/helpers/user-status.js +2 -1
  60. package/dist/helpers/wrapped-messages.d.ts +23 -0
  61. package/dist/helpers/wrapped-messages.js +38 -0
  62. package/dist/helpers/zap.d.ts +8 -5
  63. package/dist/helpers/zap.js +11 -6
  64. package/dist/index.d.ts +2 -2
  65. package/dist/index.js +2 -2
  66. package/dist/models/blossom.d.ts +3 -0
  67. package/dist/models/blossom.js +8 -0
  68. package/dist/models/bookmarks.d.ts +8 -0
  69. package/dist/{queries → models}/bookmarks.js +9 -9
  70. package/dist/models/channels.d.ts +11 -0
  71. package/dist/{queries → models}/channels.js +9 -9
  72. package/dist/models/comments.d.ts +4 -0
  73. package/dist/models/comments.js +11 -0
  74. package/dist/models/common.d.ts +16 -0
  75. package/dist/models/common.js +176 -0
  76. package/dist/models/contacts.d.ts +8 -0
  77. package/dist/{queries → models}/contacts.js +10 -10
  78. package/dist/models/encrypted-content.d.ts +4 -0
  79. package/dist/models/encrypted-content.js +11 -0
  80. package/dist/models/gift-wrap.d.ts +7 -0
  81. package/dist/models/gift-wrap.js +20 -0
  82. package/dist/{queries → models}/index.d.ts +6 -2
  83. package/dist/{queries → models}/index.js +6 -2
  84. package/dist/models/legacy-messages.d.ts +8 -0
  85. package/dist/models/legacy-messages.js +29 -0
  86. package/dist/models/mailboxes.d.ts +6 -0
  87. package/dist/{queries → models}/mailboxes.js +2 -2
  88. package/dist/models/mutes.d.ts +8 -0
  89. package/dist/{queries → models}/mutes.js +9 -9
  90. package/dist/models/pins.d.ts +4 -0
  91. package/dist/{queries → models}/pins.js +3 -3
  92. package/dist/models/profile.d.ts +4 -0
  93. package/dist/models/profile.js +14 -0
  94. package/dist/models/reactions.d.ts +4 -0
  95. package/dist/{queries → models}/reactions.js +2 -2
  96. package/dist/models/relays.d.ts +27 -0
  97. package/dist/{queries → models}/relays.js +13 -13
  98. package/dist/{queries → models}/thread.d.ts +6 -5
  99. package/dist/{queries → models}/thread.js +4 -3
  100. package/dist/models/user-status.d.ts +11 -0
  101. package/dist/{queries → models}/user-status.js +5 -5
  102. package/dist/models/wrapped-messages.d.ts +25 -0
  103. package/dist/models/wrapped-messages.js +61 -0
  104. package/dist/models/zaps.d.ts +9 -0
  105. package/dist/{queries → models}/zaps.js +11 -3
  106. package/dist/observable/claim-events.d.ts +3 -3
  107. package/dist/observable/claim-events.js +4 -4
  108. package/dist/observable/claim-latest.d.ts +3 -3
  109. package/dist/observable/claim-latest.js +4 -4
  110. package/dist/observable/index.d.ts +3 -1
  111. package/dist/observable/index.js +3 -1
  112. package/dist/observable/map-events-timeline.d.ts +7 -0
  113. package/dist/observable/map-events-timeline.js +9 -0
  114. package/dist/observable/map-events-to-store.d.ts +5 -0
  115. package/dist/observable/map-events-to-store.js +12 -0
  116. package/dist/observable/simple-timeout.d.ts +1 -0
  117. package/dist/observable/simple-timeout.js +1 -0
  118. package/dist/observable/watch-event-updates.d.ts +7 -0
  119. package/dist/observable/watch-event-updates.js +25 -0
  120. package/package.json +11 -16
  121. package/dist/__tests__/exports.test.d.ts +0 -1
  122. package/dist/__tests__/exports.test.js +0 -17
  123. package/dist/__tests__/fixtures.d.ts +0 -8
  124. package/dist/__tests__/fixtures.js +0 -20
  125. package/dist/event-store/__tests__/event-store.test.d.ts +0 -1
  126. package/dist/event-store/__tests__/event-store.test.js +0 -354
  127. package/dist/helpers/__tests__/blossom.test.d.ts +0 -1
  128. package/dist/helpers/__tests__/blossom.test.js +0 -13
  129. package/dist/helpers/__tests__/bookmarks.test.d.ts +0 -1
  130. package/dist/helpers/__tests__/bookmarks.test.js +0 -88
  131. package/dist/helpers/__tests__/comment.test.d.ts +0 -1
  132. package/dist/helpers/__tests__/comment.test.js +0 -249
  133. package/dist/helpers/__tests__/contacts.test.d.ts +0 -1
  134. package/dist/helpers/__tests__/contacts.test.js +0 -34
  135. package/dist/helpers/__tests__/emoji.test.d.ts +0 -1
  136. package/dist/helpers/__tests__/emoji.test.js +0 -15
  137. package/dist/helpers/__tests__/event.test.d.ts +0 -1
  138. package/dist/helpers/__tests__/event.test.js +0 -36
  139. package/dist/helpers/__tests__/events.test.d.ts +0 -1
  140. package/dist/helpers/__tests__/events.test.js +0 -32
  141. package/dist/helpers/__tests__/exports.test.d.ts +0 -1
  142. package/dist/helpers/__tests__/exports.test.js +0 -220
  143. package/dist/helpers/__tests__/file-metadata.test.d.ts +0 -1
  144. package/dist/helpers/__tests__/file-metadata.test.js +0 -103
  145. package/dist/helpers/__tests__/hidden-tags.test.d.ts +0 -1
  146. package/dist/helpers/__tests__/hidden-tags.test.js +0 -29
  147. package/dist/helpers/__tests__/mailboxes.test.d.ts +0 -1
  148. package/dist/helpers/__tests__/mailboxes.test.js +0 -81
  149. package/dist/helpers/__tests__/mutes.test.d.ts +0 -1
  150. package/dist/helpers/__tests__/mutes.test.js +0 -55
  151. package/dist/helpers/__tests__/nip-19.test.d.ts +0 -1
  152. package/dist/helpers/__tests__/nip-19.test.js +0 -42
  153. package/dist/helpers/__tests__/relays.test.d.ts +0 -1
  154. package/dist/helpers/__tests__/relays.test.js +0 -21
  155. package/dist/helpers/__tests__/tags.test.d.ts +0 -1
  156. package/dist/helpers/__tests__/tags.test.js +0 -24
  157. package/dist/helpers/__tests__/threading.test.d.ts +0 -1
  158. package/dist/helpers/__tests__/threading.test.js +0 -41
  159. package/dist/helpers/direct-messages.d.ts +0 -4
  160. package/dist/helpers/direct-messages.js +0 -5
  161. package/dist/helpers/nip-19.d.ts +0 -18
  162. package/dist/helpers/nip-19.js +0 -56
  163. package/dist/observable/__tests__/claim-events.test.d.ts +0 -1
  164. package/dist/observable/__tests__/claim-events.test.js +0 -23
  165. package/dist/observable/__tests__/claim-latest.test.d.ts +0 -1
  166. package/dist/observable/__tests__/claim-latest.test.js +0 -37
  167. package/dist/observable/__tests__/exports.test.d.ts +0 -1
  168. package/dist/observable/__tests__/exports.test.js +0 -18
  169. package/dist/observable/__tests__/listen-latest-updates.test.d.ts +0 -1
  170. package/dist/observable/__tests__/listen-latest-updates.test.js +0 -55
  171. package/dist/observable/__tests__/simple-timeout.test.d.ts +0 -1
  172. package/dist/observable/__tests__/simple-timeout.test.js +0 -34
  173. package/dist/observable/listen-latest-updates.d.ts +0 -5
  174. package/dist/observable/listen-latest-updates.js +0 -12
  175. package/dist/promise/__tests__/exports.test.d.ts +0 -1
  176. package/dist/promise/__tests__/exports.test.js +0 -11
  177. package/dist/queries/__tests__/exports.test.d.ts +0 -1
  178. package/dist/queries/__tests__/exports.test.js +0 -41
  179. package/dist/queries/blossom.d.ts +0 -2
  180. package/dist/queries/blossom.js +0 -5
  181. package/dist/queries/bookmarks.d.ts +0 -8
  182. package/dist/queries/channels.d.ts +0 -11
  183. package/dist/queries/comments.d.ts +0 -4
  184. package/dist/queries/comments.js +0 -11
  185. package/dist/queries/contacts.d.ts +0 -8
  186. package/dist/queries/mailboxes.d.ts +0 -6
  187. package/dist/queries/mutes.d.ts +0 -8
  188. package/dist/queries/pins.d.ts +0 -4
  189. package/dist/queries/profile.d.ts +0 -4
  190. package/dist/queries/profile.js +0 -7
  191. package/dist/queries/reactions.d.ts +0 -4
  192. package/dist/queries/relays.d.ts +0 -27
  193. package/dist/queries/simple.d.ts +0 -16
  194. package/dist/queries/simple.js +0 -21
  195. package/dist/queries/user-status.d.ts +0 -11
  196. package/dist/queries/zaps.d.ts +0 -5
  197. package/dist/query-store/__tests__/exports.test.d.ts +0 -1
  198. package/dist/query-store/__tests__/exports.test.js +0 -12
  199. package/dist/query-store/__tests__/query-store.test.d.ts +0 -1
  200. package/dist/query-store/__tests__/query-store.test.js +0 -63
  201. package/dist/query-store/index.d.ts +0 -1
  202. package/dist/query-store/index.js +0 -1
  203. package/dist/query-store/query-store.d.ts +0 -54
  204. package/dist/query-store/query-store.js +0 -102
@@ -1,8 +1,8 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { map } from "rxjs/operators";
3
3
  import { getInboxes, getOutboxes } from "../helpers/mailboxes.js";
4
- /** A query that gets and parses the inbox and outbox relays for a pubkey */
5
- export function MailboxesQuery(pubkey) {
4
+ /** A model that gets and parses the inbox and outbox relays for a pubkey */
5
+ export function MailboxesModel(pubkey) {
6
6
  return (events) => events.replaceable(kinds.RelayList, pubkey).pipe(map((event) => event && {
7
7
  inboxes: getInboxes(event),
8
8
  outboxes: getOutboxes(event),
@@ -0,0 +1,8 @@
1
+ import { Mutes } from "../helpers/mutes.js";
2
+ import { Model } from "../event-store/interface.js";
3
+ /** A model that returns all a users muted things */
4
+ export declare function MuteModel(pubkey: string): Model<Mutes | undefined>;
5
+ /** A model that returns all a users public muted things */
6
+ export declare function PublicMuteModel(pubkey: string): Model<Mutes | undefined>;
7
+ /** A model that returns all a users hidden muted things */
8
+ export declare function HiddenMuteModel(pubkey: string): Model<Mutes | null | undefined>;
@@ -1,24 +1,24 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { map } from "rxjs/operators";
3
3
  import { getHiddenMutedThings, getMutedThings, getPublicMutedThings } from "../helpers/mutes.js";
4
- import { listenLatestUpdates } from "../observable/listen-latest-updates.js";
5
- /** A query that returns all a users muted things */
6
- export function MuteQuery(pubkey) {
4
+ import { watchEventUpdates } from "../observable/watch-event-updates.js";
5
+ /** A model that returns all a users muted things */
6
+ export function MuteModel(pubkey) {
7
7
  return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(
8
8
  // listen for event updates (hidden tags unlocked)
9
- listenLatestUpdates(events),
9
+ watchEventUpdates(events),
10
10
  // Get all muted things
11
11
  map((event) => event && getMutedThings(event)));
12
12
  }
13
- /** A query that returns all a users public muted things */
14
- export function PublicMuteQuery(pubkey) {
13
+ /** A model that returns all a users public muted things */
14
+ export function PublicMuteModel(pubkey) {
15
15
  return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(map((event) => event && getPublicMutedThings(event)));
16
16
  }
17
- /** A query that returns all a users hidden muted things */
18
- export function HiddenMuteQuery(pubkey) {
17
+ /** A model that returns all a users hidden muted things */
18
+ export function HiddenMuteModel(pubkey) {
19
19
  return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(
20
20
  // listen for event updates (hidden tags unlocked)
21
- listenLatestUpdates(events),
21
+ watchEventUpdates(events),
22
22
  // Get hidden muted things
23
23
  map((event) => event && getHiddenMutedThings(event)));
24
24
  }
@@ -0,0 +1,4 @@
1
+ import { EventPointer } from "nostr-tools/nip19";
2
+ import { Model } from "../event-store/interface.js";
3
+ /** A model that returns all pinned pointers for a user */
4
+ export declare function UserPinnedModel(pubkey: string): Model<EventPointer[] | undefined>;
@@ -1,9 +1,9 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { map } from "rxjs/operators";
3
- import { isETag, processTags } from "../helpers/tags.js";
4
3
  import { getEventPointerFromETag } from "../helpers/pointers.js";
5
- /** A query that returns all pinned pointers for a user */
6
- export function UserPinnedQuery(pubkey) {
4
+ import { isETag, processTags } from "../helpers/tags.js";
5
+ /** A model that returns all pinned pointers for a user */
6
+ export function UserPinnedModel(pubkey) {
7
7
  return (events) => events
8
8
  .replaceable(kinds.Pinlist, pubkey)
9
9
  .pipe(map((event) => event && processTags(event.tags.filter(isETag), getEventPointerFromETag)));
@@ -0,0 +1,4 @@
1
+ import { Model } from "../event-store/interface.js";
2
+ import { ProfileContent } from "../helpers/profile.js";
3
+ /** A model that gets and parses the kind 0 metadata for a pubkey */
4
+ export declare function ProfileModel(pubkey: string): Model<ProfileContent | undefined>;
@@ -0,0 +1,14 @@
1
+ import { kinds } from "nostr-tools";
2
+ import { filter, map } from "rxjs/operators";
3
+ import { getProfileContent, isValidProfile } from "../helpers/profile.js";
4
+ import { withImmediateValueOrDefault } from "../observable/with-immediate-value.js";
5
+ /** A model that gets and parses the kind 0 metadata for a pubkey */
6
+ export function ProfileModel(pubkey) {
7
+ return (events) => events.replaceable(kinds.Metadata, pubkey).pipe(
8
+ // Filter out invalid profile events
9
+ filter(isValidProfile),
10
+ // Parse the profile event into a ProfileContent
11
+ map((event) => event && getProfileContent(event)),
12
+ // Ensure the model is synchronous
13
+ withImmediateValueOrDefault(undefined));
14
+ }
@@ -0,0 +1,4 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ import { Model } from "../event-store/interface.js";
3
+ /** A model that returns all reactions to an event (supports replaceable events) */
4
+ export declare function ReactionsModel(event: NostrEvent): Model<NostrEvent[]>;
@@ -1,7 +1,7 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { getEventUID, isReplaceable } from "../helpers/event.js";
3
- /** A query that returns all reactions to an event (supports replaceable events) */
4
- export function ReactionsQuery(event) {
3
+ /** A model that returns all reactions to an event (supports replaceable events) */
4
+ export function ReactionsModel(event) {
5
5
  return (events) => events.timeline(isReplaceable(event.kind)
6
6
  ? [
7
7
  { kinds: [kinds.Reaction], "#e": [event.id] },
@@ -0,0 +1,27 @@
1
+ import { AddressPointer } from "nostr-tools/nip19";
2
+ import { ReadListTags } from "../helpers/lists.js";
3
+ import { Model } from "../event-store/interface.js";
4
+ /**
5
+ * A model that returns all favorite relays for a pubkey
6
+ * @param pubkey - The pubkey to get the favorite relays for
7
+ * @param type - Which types of tags to read
8
+ */
9
+ export declare function FavoriteRelaysModel(pubkey: string, type?: ReadListTags): Model<string[] | undefined>;
10
+ /**
11
+ * A model that returns all favorite relay sets for a pubkey
12
+ * @param pubkey - The pubkey to get the favorite relay sets for
13
+ * @param type - Which types of tags to read
14
+ */
15
+ export declare function FavoriteRelaySetsModel(pubkey: string, type?: ReadListTags): Model<AddressPointer[] | undefined>;
16
+ /**
17
+ * A model that returns all search relays for a pubkey
18
+ * @param pubkey - The pubkey to get the search relays for
19
+ * @param type - Which types of tags to read
20
+ */
21
+ export declare function SearchRelaysModel(pubkey: string, type?: ReadListTags): Model<string[] | undefined>;
22
+ /**
23
+ * A model that returns all blocked relays for a pubkey
24
+ * @param pubkey - The pubkey to get the blocked relays for
25
+ * @param type - Which types of tags to read
26
+ */
27
+ export declare function BlockedRelaysModel(pubkey: string, type?: ReadListTags): Model<string[] | undefined>;
@@ -1,44 +1,44 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { identity, map } from "rxjs";
3
3
  import { FAVORITE_RELAYS_KIND, getAddressPointersFromList, getRelaysFromList } from "../helpers/lists.js";
4
- import { listenLatestUpdates } from "../observable/listen-latest-updates.js";
4
+ import { watchEventUpdates } from "../observable/watch-event-updates.js";
5
5
  /**
6
- * A query that returns all favorite relays for a pubkey
6
+ * A model that returns all favorite relays for a pubkey
7
7
  * @param pubkey - The pubkey to get the favorite relays for
8
8
  * @param type - Which types of tags to read
9
9
  */
10
- export function FavoriteRelays(pubkey, type) {
10
+ export function FavoriteRelaysModel(pubkey, type) {
11
11
  return (events) => {
12
- return events.replaceable(FAVORITE_RELAYS_KIND, pubkey).pipe(type !== "public" ? listenLatestUpdates(events) : map(identity), map((e) => e && getRelaysFromList(e, type)));
12
+ return events.replaceable(FAVORITE_RELAYS_KIND, pubkey).pipe(type !== "public" ? watchEventUpdates(events) : map(identity), map((e) => e && getRelaysFromList(e, type)));
13
13
  };
14
14
  }
15
15
  /**
16
- * A query that returns all favorite relay sets for a pubkey
16
+ * A model that returns all favorite relay sets for a pubkey
17
17
  * @param pubkey - The pubkey to get the favorite relay sets for
18
18
  * @param type - Which types of tags to read
19
19
  */
20
- export function FavoriteRelaySets(pubkey, type) {
20
+ export function FavoriteRelaySetsModel(pubkey, type) {
21
21
  return (events) => {
22
- return events.replaceable(FAVORITE_RELAYS_KIND, pubkey).pipe(type !== "public" ? listenLatestUpdates(events) : map(identity), map((e) => e && getAddressPointersFromList(e, type)));
22
+ return events.replaceable(FAVORITE_RELAYS_KIND, pubkey).pipe(type !== "public" ? watchEventUpdates(events) : map(identity), map((e) => e && getAddressPointersFromList(e, type)));
23
23
  };
24
24
  }
25
25
  /**
26
- * A query that returns all search relays for a pubkey
26
+ * A model that returns all search relays for a pubkey
27
27
  * @param pubkey - The pubkey to get the search relays for
28
28
  * @param type - Which types of tags to read
29
29
  */
30
- export function SearchRelays(pubkey, type) {
30
+ export function SearchRelaysModel(pubkey, type) {
31
31
  return (events) => {
32
- return events.replaceable(kinds.SearchRelaysList, pubkey).pipe(type !== "public" ? listenLatestUpdates(events) : map(identity), map((e) => e && getRelaysFromList(e, type)));
32
+ return events.replaceable(kinds.SearchRelaysList, pubkey).pipe(type !== "public" ? watchEventUpdates(events) : map(identity), map((e) => e && getRelaysFromList(e, type)));
33
33
  };
34
34
  }
35
35
  /**
36
- * A query that returns all blocked relays for a pubkey
36
+ * A model that returns all blocked relays for a pubkey
37
37
  * @param pubkey - The pubkey to get the blocked relays for
38
38
  * @param type - Which types of tags to read
39
39
  */
40
- export function BlockedRelays(pubkey, type) {
40
+ export function BlockedRelaysModel(pubkey, type) {
41
41
  return (events) => {
42
- return events.replaceable(kinds.BlockedRelaysList, pubkey).pipe(type !== "public" ? listenLatestUpdates(events) : map(identity), map((e) => e && getRelaysFromList(e, type)));
42
+ return events.replaceable(kinds.BlockedRelaysList, pubkey).pipe(type !== "public" ? watchEventUpdates(events) : map(identity), map((e) => e && getRelaysFromList(e, type)));
43
43
  };
44
44
  }
@@ -1,7 +1,7 @@
1
1
  import { NostrEvent } from "nostr-tools";
2
2
  import { AddressPointer, EventPointer } from "nostr-tools/nip19";
3
- import { Query } from "../query-store/index.js";
4
3
  import { ThreadReferences } from "../helpers/threading.js";
4
+ import { Model } from "../event-store/interface.js";
5
5
  export type Thread = {
6
6
  root?: ThreadItem;
7
7
  all: Map<string, ThreadItem>;
@@ -17,9 +17,10 @@ export type ThreadItem = {
17
17
  /** direct child replies */
18
18
  replies: Set<ThreadItem>;
19
19
  };
20
- export type ThreadQueryOptions = {
20
+ export type ThreadModelOptions = {
21
21
  kinds?: number[];
22
22
  };
23
- export declare function ThreadQuery(root: string | AddressPointer | EventPointer, opts?: ThreadQueryOptions): Query<Thread>;
24
- /** A query that gets all legacy and NIP-10, and NIP-22 replies for an event */
25
- export declare function RepliesQuery(event: NostrEvent, overrideKinds?: number[]): Query<NostrEvent[]>;
23
+ /** A model that returns a NIP-10 thread of events */
24
+ export declare function ThreadModel(root: string | AddressPointer | EventPointer, opts?: ThreadModelOptions): Model<Thread>;
25
+ /** A model that gets all legacy and NIP-10, and NIP-22 replies for an event */
26
+ export declare function RepliesModel(event: NostrEvent, overrideKinds?: number[]): Model<NostrEvent[]>;
@@ -8,7 +8,8 @@ import { COMMENT_KIND } from "../helpers/comment.js";
8
8
  const defaultOptions = {
9
9
  kinds: [kinds.ShortTextNote],
10
10
  };
11
- export function ThreadQuery(root, opts) {
11
+ /** A model that returns a NIP-10 thread of events */
12
+ export function ThreadModel(root, opts) {
12
13
  const parentReferences = new Map();
13
14
  const items = new Map();
14
15
  const { kinds } = { ...defaultOptions, ...opts };
@@ -63,8 +64,8 @@ export function ThreadQuery(root, opts) {
63
64
  return { root: items.get(rootUID), all: items };
64
65
  }));
65
66
  }
66
- /** A query that gets all legacy and NIP-10, and NIP-22 replies for an event */
67
- export function RepliesQuery(event, overrideKinds) {
67
+ /** A model that gets all legacy and NIP-10, and NIP-22 replies for an event */
68
+ export function RepliesModel(event, overrideKinds) {
68
69
  return (events) => {
69
70
  const kinds = overrideKinds || event.kind === 1 ? [1, COMMENT_KIND] : [COMMENT_KIND];
70
71
  const filter = { kinds };
@@ -0,0 +1,11 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ import { Model } from "../event-store/interface.js";
3
+ import { UserStatusPointer } from "../helpers/user-status.js";
4
+ export type UserStatus = UserStatusPointer & {
5
+ event: NostrEvent;
6
+ content: string;
7
+ };
8
+ /** A model that returns a parsed {@link UserStatus} for a certain type */
9
+ export declare function UserStatusModel(pubkey: string, type?: string): Model<UserStatus | undefined | null>;
10
+ /** A model that returns a directory of parsed {@link UserStatus} for a pubkey */
11
+ export declare function UserStatusesModel(pubkey: string): Model<Record<string, UserStatus>>;
@@ -1,9 +1,9 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { map } from "rxjs";
3
- import { getUserStatusPointer } from "../helpers/user-status.js";
4
3
  import { getReplaceableIdentifier } from "../helpers/event.js";
5
- /** Creates a Query that returns a parsed {@link UserStatus} for a certain type */
6
- export function UserStatusQuery(pubkey, type = "general") {
4
+ import { getUserStatusPointer } from "../helpers/user-status.js";
5
+ /** A model that returns a parsed {@link UserStatus} for a certain type */
6
+ export function UserStatusModel(pubkey, type = "general") {
7
7
  return (events) => events.replaceable(kinds.UserStatuses, pubkey, type).pipe(map((event) => {
8
8
  if (!event)
9
9
  return undefined;
@@ -17,8 +17,8 @@ export function UserStatusQuery(pubkey, type = "general") {
17
17
  };
18
18
  }));
19
19
  }
20
- /** Creates a Query that returns a directory of parsed {@link UserStatus} for a pubkey */
21
- export function UserStatusesQuery(pubkey) {
20
+ /** A model that returns a directory of parsed {@link UserStatus} for a pubkey */
21
+ export function UserStatusesModel(pubkey) {
22
22
  return (events) => events.timeline([{ kinds: [kinds.UserStatuses], authors: [pubkey] }]).pipe(map((events) => {
23
23
  return events.reduce((dir, event) => {
24
24
  try {
@@ -0,0 +1,25 @@
1
+ import { Model } from "../event-store/interface.js";
2
+ import { Rumor } from "../helpers/gift-wraps.js";
3
+ /**
4
+ * A model that returns all wrapped messages for a pubkey
5
+ * @param self - The pubkey of the user
6
+ */
7
+ export declare function WrappedMessagesModel(self: string): Model<Rumor[]>;
8
+ /**
9
+ * A model that returns all wrapped direct messages in a conversation
10
+ * @param self - The pubkey of the user
11
+ * @param participants - A conversation identifier or a list of participant pubkeys
12
+ */
13
+ export declare function WrappedMessagesConversation(self: string, participants: string | string[]): Model<Rumor[]>;
14
+ /**
15
+ * Returns an array of root wrapped messages that have replies
16
+ * @param self - The pubkey of the user
17
+ * @param conversation - The conversation identifier
18
+ */
19
+ export declare function WrappedMessageThreads(self: string, conversation: string): Model<Rumor[]>;
20
+ /**
21
+ * A model that returns all the gift wrapped direct messages that are replies to a given message
22
+ * @param self - The pubkey of the user
23
+ * @param message - The message to get the replies for
24
+ */
25
+ export declare function WrappedMessageReplies(self: string, message: Rumor): Model<Rumor[]>;
@@ -0,0 +1,61 @@
1
+ import { kinds } from "nostr-tools";
2
+ import { map } from "rxjs";
3
+ import { getGiftWrapRumor } from "../helpers/gift-wraps.js";
4
+ import { createConversationIdentifier, getConversationIdentifierFromMessage, getConversationParticipants, getWrappedMessageParent, } from "../helpers/wrapped-messages.js";
5
+ import { watchEventsUpdates } from "../observable/watch-event-updates.js";
6
+ /**
7
+ * A model that returns all wrapped messages for a pubkey
8
+ * @param self - The pubkey of the user
9
+ */
10
+ export function WrappedMessagesModel(self) {
11
+ return (store) => store.timeline({ kinds: [kinds.GiftWrap], "#p": [self] }).pipe(
12
+ // Watch for updates to the gift wraps
13
+ watchEventsUpdates(store),
14
+ // Get rumors and filter out locked
15
+ map((rumors) => rumors
16
+ .map((gift) => getGiftWrapRumor(gift))
17
+ .filter((e) => !!e)
18
+ .sort((a, b) => b.created_at - a.created_at)));
19
+ }
20
+ /**
21
+ * A model that returns all wrapped direct messages in a conversation
22
+ * @param self - The pubkey of the user
23
+ * @param participants - A conversation identifier or a list of participant pubkeys
24
+ */
25
+ export function WrappedMessagesConversation(self, participants) {
26
+ // Get the conversation identifier include the users pubkey
27
+ const identifier = createConversationIdentifier([
28
+ self,
29
+ ...(typeof participants === "string" ? getConversationParticipants(participants) : participants),
30
+ ]);
31
+ return (store) => store.model(WrappedMessagesModel, self).pipe(
32
+ // Only select direct messages for this conversation
33
+ map((rumors) => rumors.filter((rumor) => rumor.kind === kinds.PrivateDirectMessage &&
34
+ // Only select message for this conversation (the identifier from the message will include "self")
35
+ getConversationIdentifierFromMessage(rumor) === identifier)));
36
+ }
37
+ /**
38
+ * Returns an array of root wrapped messages that have replies
39
+ * @param self - The pubkey of the user
40
+ * @param conversation - The conversation identifier
41
+ */
42
+ export function WrappedMessageThreads(self, conversation) {
43
+ return (store) => store.model(WrappedMessagesConversation, self, conversation).pipe(
44
+ // Filter down messages to only include root messages that have replies
45
+ map((rumors) => rumors.filter((rumor) =>
46
+ // Only select root messages
47
+ !getWrappedMessageParent(rumor) &&
48
+ // Check if message has any replies
49
+ rumors.some((r) => getWrappedMessageParent(r) === rumor.id))));
50
+ }
51
+ /**
52
+ * A model that returns all the gift wrapped direct messages that are replies to a given message
53
+ * @param self - The pubkey of the user
54
+ * @param message - The message to get the replies for
55
+ */
56
+ export function WrappedMessageReplies(self, message) {
57
+ const conversation = getConversationIdentifierFromMessage(message);
58
+ return (store) => store.model(WrappedMessagesConversation, self, conversation).pipe(
59
+ // Only select replies to this message
60
+ map((rumors) => rumors.filter((rumor) => getWrappedMessageParent(rumor) === message.id)));
61
+ }
@@ -0,0 +1,9 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ import { AddressPointer, EventPointer } from "nostr-tools/nip19";
3
+ import { Model } from "../event-store/interface.js";
4
+ /** A model that gets all zap events for an event */
5
+ export declare function EventZapsModel(id: string | EventPointer | AddressPointer): Model<NostrEvent[]>;
6
+ /** A model that returns all zaps sent by a user */
7
+ export declare function SentZapsModel(pubkey: string): Model<NostrEvent[]>;
8
+ /** A model that returns all zaps received by a user */
9
+ export declare function ReceivedZapsModel(pubkey: string): Model<NostrEvent[]>;
@@ -1,9 +1,9 @@
1
- import { map } from "rxjs";
2
1
  import { kinds } from "nostr-tools";
2
+ import { map } from "rxjs";
3
3
  import { getCoordinateFromAddressPointer, isAddressPointer } from "../helpers/pointers.js";
4
4
  import { isValidZap } from "../helpers/zap.js";
5
- /** A query that gets all zap events for an event */
6
- export function EventZapsQuery(id) {
5
+ /** A model that gets all zap events for an event */
6
+ export function EventZapsModel(id) {
7
7
  return (events) => {
8
8
  if (isAddressPointer(id)) {
9
9
  return events
@@ -16,3 +16,11 @@ export function EventZapsQuery(id) {
16
16
  }
17
17
  };
18
18
  }
19
+ /** A model that returns all zaps sent by a user */
20
+ export function SentZapsModel(pubkey) {
21
+ return (events) => events.timeline([{ kinds: [kinds.Zap], authors: [pubkey] }]);
22
+ }
23
+ /** A model that returns all zaps received by a user */
24
+ export function ReceivedZapsModel(pubkey) {
25
+ return (events) => events.timeline([{ kinds: [kinds.Zap], "#a": [pubkey] }]);
26
+ }
@@ -1,5 +1,5 @@
1
- import { MonoTypeOperatorFunction } from "rxjs";
2
1
  import { NostrEvent } from "nostr-tools";
3
- import { Database } from "../event-store/database.js";
2
+ import { MonoTypeOperatorFunction } from "rxjs";
3
+ import { IEventClaims } from "../event-store/interface.js";
4
4
  /** keep a claim on any event that goes through this observable, claims are removed when the observable completes */
5
- export declare function claimEvents<T extends NostrEvent[] | NostrEvent | undefined>(database: Database): MonoTypeOperatorFunction<T>;
5
+ export declare function claimEvents<T extends NostrEvent[] | NostrEvent | undefined>(claims: IEventClaims): MonoTypeOperatorFunction<T>;
@@ -1,6 +1,6 @@
1
1
  import { finalize, tap } from "rxjs";
2
2
  /** keep a claim on any event that goes through this observable, claims are removed when the observable completes */
3
- export function claimEvents(database) {
3
+ export function claimEvents(claims) {
4
4
  return (source) => {
5
5
  const seen = new Set();
6
6
  return source.pipe(
@@ -11,18 +11,18 @@ export function claimEvents(database) {
11
11
  if (Array.isArray(message)) {
12
12
  for (const event of message) {
13
13
  seen.add(event);
14
- database.claimEvent(event, source);
14
+ claims.claim(event, source);
15
15
  }
16
16
  }
17
17
  else {
18
18
  seen.add(message);
19
- database.claimEvent(message, source);
19
+ claims.claim(message, source);
20
20
  }
21
21
  }),
22
22
  // remove claims on cleanup
23
23
  finalize(() => {
24
24
  for (const e of seen)
25
- database.removeClaim(e, source);
25
+ claims.removeClaim(e, source);
26
26
  }));
27
27
  };
28
28
  }
@@ -1,5 +1,5 @@
1
- import { MonoTypeOperatorFunction } from "rxjs";
2
1
  import { NostrEvent } from "nostr-tools";
3
- import { type Database } from "../event-store/database.js";
2
+ import { MonoTypeOperatorFunction } from "rxjs";
3
+ import { IEventClaims } from "../event-store/interface.js";
4
4
  /** An operator that claims the latest event with the database */
5
- export declare function claimLatest<T extends NostrEvent | undefined>(database: Database): MonoTypeOperatorFunction<T>;
5
+ export declare function claimLatest<T extends NostrEvent | undefined>(claims: IEventClaims): MonoTypeOperatorFunction<T>;
@@ -1,21 +1,21 @@
1
1
  import { finalize, tap } from "rxjs";
2
2
  /** An operator that claims the latest event with the database */
3
- export function claimLatest(database) {
3
+ export function claimLatest(claims) {
4
4
  return (source) => {
5
5
  let latest = undefined;
6
6
  return source.pipe(tap((event) => {
7
7
  // remove old claim
8
8
  if (latest)
9
- database.removeClaim(latest, source);
9
+ claims.removeClaim(latest, source);
10
10
  // claim new event
11
11
  if (event)
12
- database.claimEvent(event, source);
12
+ claims.claim(event, source);
13
13
  // update state
14
14
  latest = event;
15
15
  }), finalize(() => {
16
16
  // remove latest claim
17
17
  if (latest)
18
- database.removeClaim(latest, source);
18
+ claims.removeClaim(latest, source);
19
19
  }));
20
20
  };
21
21
  }
@@ -1,7 +1,9 @@
1
1
  import { firstValueFrom, lastValueFrom } from "rxjs";
2
2
  export * from "./defined.js";
3
3
  export * from "./get-observable-value.js";
4
- export * from "./listen-latest-updates.js";
4
+ export * from "./map-events-timeline.js";
5
+ export * from "./map-events-to-store.js";
5
6
  export * from "./simple-timeout.js";
7
+ export * from "./watch-event-updates.js";
6
8
  export * from "./with-immediate-value.js";
7
9
  export { firstValueFrom, lastValueFrom };
@@ -1,8 +1,10 @@
1
1
  import { firstValueFrom, lastValueFrom } from "rxjs";
2
2
  export * from "./defined.js";
3
3
  export * from "./get-observable-value.js";
4
- export * from "./listen-latest-updates.js";
4
+ export * from "./map-events-timeline.js";
5
+ export * from "./map-events-to-store.js";
5
6
  export * from "./simple-timeout.js";
7
+ export * from "./watch-event-updates.js";
6
8
  export * from "./with-immediate-value.js";
7
9
  // Re-export some useful rxjs functions
8
10
  export { firstValueFrom, lastValueFrom };
@@ -0,0 +1,7 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ import { OperatorFunction } from "rxjs";
3
+ /**
4
+ * Accumulate events into an ordered timeline
5
+ * @note This does not remove duplicate events
6
+ */
7
+ export declare function mapEventsToTimeline(): OperatorFunction<NostrEvent, NostrEvent[]>;
@@ -0,0 +1,9 @@
1
+ import { insertEventIntoDescendingList } from "nostr-tools/utils";
2
+ import { scan } from "rxjs";
3
+ /**
4
+ * Accumulate events into an ordered timeline
5
+ * @note This does not remove duplicate events
6
+ */
7
+ export function mapEventsToTimeline() {
8
+ return scan((timeline, event) => insertEventIntoDescendingList(timeline, event), []);
9
+ }
@@ -0,0 +1,5 @@
1
+ import { MonoTypeOperatorFunction } from "rxjs";
2
+ import { NostrEvent } from "nostr-tools";
3
+ import { IEventStore } from "../event-store/interface.js";
4
+ /** Saves all events to an event store and filters out invalid events */
5
+ export declare function mapEventsToStore(store: IEventStore, removeDuplicates?: boolean): MonoTypeOperatorFunction<NostrEvent>;
@@ -0,0 +1,12 @@
1
+ import { distinct, filter, identity, map } from "rxjs";
2
+ /** Saves all events to an event store and filters out invalid events */
3
+ export function mapEventsToStore(store, removeDuplicates = true) {
4
+ return (source) => source.pipe(
5
+ // Map all events to the store
6
+ // NOTE: map is used here because we want to return the single cononical version of the event so that distinct() can be used later
7
+ map((event) => store.add(event)),
8
+ // Ignore invalid events
9
+ filter((e) => e !== null),
10
+ // Remove duplicates if requested
11
+ removeDuplicates ? distinct() : identity);
12
+ }
@@ -1,4 +1,5 @@
1
1
  import { MonoTypeOperatorFunction } from "rxjs";
2
2
  export declare class TimeoutError extends Error {
3
3
  }
4
+ /** Throws a {@link TimeoutError} if a value is not emitted within the timeout */
4
5
  export declare function simpleTimeout<T extends unknown>(first: number, message?: string): MonoTypeOperatorFunction<T>;
@@ -1,6 +1,7 @@
1
1
  import { throwError, timeout } from "rxjs";
2
2
  export class TimeoutError extends Error {
3
3
  }
4
+ /** Throws a {@link TimeoutError} if a value is not emitted within the timeout */
4
5
  export function simpleTimeout(first, message) {
5
6
  return timeout({ first, with: () => throwError(() => new TimeoutError(message ?? "Timeout")) });
6
7
  }
@@ -0,0 +1,7 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ import { MonoTypeOperatorFunction } from "rxjs";
3
+ import { IEventStoreStreams } from "../event-store/interface.js";
4
+ /** Watches for any updates to the latest event and remits the event when updated */
5
+ export declare function watchEventUpdates(eventStore: IEventStoreStreams): MonoTypeOperatorFunction<NostrEvent | undefined>;
6
+ /** Watches for any updates to the latest array of events and remits the array of events when updated */
7
+ export declare function watchEventsUpdates(eventStore: IEventStoreStreams): MonoTypeOperatorFunction<NostrEvent[]>;
@@ -0,0 +1,25 @@
1
+ import { filter, map, merge, tap } from "rxjs";
2
+ /** Watches for any updates to the latest event and remits the event when updated */
3
+ export function watchEventUpdates(eventStore) {
4
+ return (source) => {
5
+ let latest;
6
+ return merge(
7
+ // Get the latest event
8
+ source.pipe(tap((value) => (latest = value))),
9
+ // listen for updates
10
+ eventStore.update$.pipe(filter((e) => e.id === latest?.id)));
11
+ };
12
+ }
13
+ /** Watches for any updates to the latest array of events and remits the array of events when updated */
14
+ export function watchEventsUpdates(eventStore) {
15
+ return (source) => {
16
+ let latest = [];
17
+ return merge(
18
+ // Get the latest event
19
+ source.pipe(tap((value) => (latest = value))),
20
+ // listen for updates
21
+ eventStore.update$.pipe(filter((e) => latest.includes(e)),
22
+ // re-emit the array of events
23
+ map(() => latest)));
24
+ };
25
+ }