applesauce-core 1.2.0 → 2.1.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} +36 -21
  3. package/dist/event-store/{database.js → event-set.js} +98 -67
  4. package/dist/event-store/event-store.d.ts +64 -25
  5. package/dist/event-store/event-store.js +164 -207
  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 +5 -8
  25. package/dist/helpers/event.js +25 -11
  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 +3 -1
  43. package/dist/helpers/lists.js +9 -3
  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,103 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { getFileMetadataFromImetaTag, parseFileMetadataTags } from "../file-metadata.js";
3
- describe("file metadata helpers", () => {
4
- describe("parseFileMetadataTags", () => {
5
- it("should parse a simple 1060 event", () => {
6
- const tags = [
7
- ["url", "https://image.nostr.build/30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae.gif"],
8
- ["ox", "30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae"],
9
- ["fallback", "https://media.tenor.com/wpvrkjn192gAAAAC/daenerys-targaryen.gif"],
10
- ["x", "77fcf42b2b720babcdbe686eff67273d8a68862d74a2672db672bc48439a3ea5"],
11
- ["m", "image/gif"],
12
- ["dim", "360x306"],
13
- ["bh", "L38zleNL00~W^kRj0L-p0KM_^kx]"],
14
- ["blurhash", "L38zleNL00~W^kRj0L-p0KM_^kx]"],
15
- [
16
- "thumb",
17
- "https://image.nostr.build/thumb/30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae.gif",
18
- ],
19
- ["t", "gifbuddy"],
20
- ["summary", "Khaleesi call dragons Daenerys Targaryen"],
21
- ["alt", "a woman with blonde hair and a brooch on her shoulder"],
22
- [
23
- "thumb",
24
- "https://media.tenor.com/wpvrkjn192gAAAAx/daenerys-targaryen.webp",
25
- "5d92423664fc15874b1d26c70a05a541ec09b5c438bf157977a87c8e64b31463",
26
- ],
27
- [
28
- "image",
29
- "https://media.tenor.com/wpvrkjn192gAAAAe/daenerys-targaryen.png",
30
- "5d92423664fc15874b1d26c70a05a541ec09b5c438bf157977a87c8e64b31463",
31
- ],
32
- ];
33
- expect(parseFileMetadataTags(tags)).toEqual({
34
- url: "https://image.nostr.build/30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae.gif",
35
- type: "image/gif",
36
- dimensions: "360x306",
37
- blurhash: "L38zleNL00~W^kRj0L-p0KM_^kx]",
38
- sha256: "77fcf42b2b720babcdbe686eff67273d8a68862d74a2672db672bc48439a3ea5",
39
- originalSha256: "30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae",
40
- thumbnail: "https://media.tenor.com/wpvrkjn192gAAAAx/daenerys-targaryen.webp",
41
- image: "https://media.tenor.com/wpvrkjn192gAAAAe/daenerys-targaryen.png",
42
- summary: "Khaleesi call dragons Daenerys Targaryen",
43
- fallback: ["https://media.tenor.com/wpvrkjn192gAAAAC/daenerys-targaryen.gif"],
44
- alt: "a woman with blonde hair and a brooch on her shoulder",
45
- });
46
- });
47
- });
48
- describe("getFileMetadataFromImetaTag", () => {
49
- it("should parse simple imeta tag", () => {
50
- expect(getFileMetadataFromImetaTag([
51
- "imeta",
52
- "url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
53
- "x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
54
- "dim 1024x1024",
55
- "m image/jpeg",
56
- "blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
57
- ])).toEqual({
58
- url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
59
- sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
60
- dimensions: "1024x1024",
61
- type: "image/jpeg",
62
- blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
63
- });
64
- });
65
- it("should parse thumbnail url", () => {
66
- expect(getFileMetadataFromImetaTag([
67
- "imeta",
68
- "url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
69
- "x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
70
- "dim 1024x1024",
71
- "m image/jpeg",
72
- "blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
73
- "thumb https://exmaple.com/thumb.jpg",
74
- ])).toEqual({
75
- url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
76
- sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
77
- dimensions: "1024x1024",
78
- type: "image/jpeg",
79
- blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
80
- thumbnail: "https://exmaple.com/thumb.jpg",
81
- });
82
- });
83
- it("should parse multiple fallback urls", () => {
84
- expect(getFileMetadataFromImetaTag([
85
- "imeta",
86
- "url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
87
- "x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
88
- "dim 1024x1024",
89
- "m image/jpeg",
90
- "blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
91
- "fallback https://exmaple.com/image2.jpg",
92
- "fallback https://exmaple.com/image3.jpg",
93
- ])).toEqual({
94
- url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
95
- sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
96
- dimensions: "1024x1024",
97
- type: "image/jpeg",
98
- blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
99
- fallback: ["https://exmaple.com/image2.jpg", "https://exmaple.com/image3.jpg"],
100
- });
101
- });
102
- });
103
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,29 +0,0 @@
1
- import { describe, beforeEach, it, expect } from "vitest";
2
- import { finalizeEvent, generateSecretKey, getPublicKey, kinds, nip04 } from "nostr-tools";
3
- import { getHiddenTags, unlockHiddenTags } from "../hidden-tags.js";
4
- import { unixNow } from "../time.js";
5
- const key = generateSecretKey();
6
- const pubkey = getPublicKey(key);
7
- const signer = {
8
- nip04: {
9
- encrypt: (pubkey, plaintext) => nip04.encrypt(key, pubkey, plaintext),
10
- decrypt: (pubkey, ciphertext) => nip04.decrypt(key, pubkey, ciphertext),
11
- },
12
- };
13
- describe("Private Lists", () => {
14
- describe("unlockHiddenTags", () => {
15
- let list;
16
- beforeEach(async () => {
17
- list = finalizeEvent({
18
- kind: kinds.Mutelist,
19
- created_at: unixNow(),
20
- content: await nip04.encrypt(key, pubkey, JSON.stringify([["p", "npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr"]])),
21
- tags: [],
22
- }, key);
23
- });
24
- it("should unlock hidden tags", async () => {
25
- await unlockHiddenTags(list, signer);
26
- expect(getHiddenTags(list)).toEqual(expect.arrayContaining([["p", "npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr"]]));
27
- });
28
- });
29
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,81 +0,0 @@
1
- import { describe, test, expect } from "vitest";
2
- import { getInboxes, getOutboxes } from "../mailboxes.js";
3
- const emptyEvent = {
4
- kind: 10002,
5
- content: "",
6
- tags: [],
7
- created_at: 0,
8
- sig: "",
9
- id: "",
10
- pubkey: "",
11
- };
12
- describe("Mailboxes", () => {
13
- describe("getInboxes", () => {
14
- test("should transform urls", () => {
15
- expect(Array.from(getInboxes({
16
- ...emptyEvent,
17
- tags: [["r", "wss://inbox.com"]],
18
- }))).toEqual(expect.arrayContaining(["wss://inbox.com/"]));
19
- });
20
- test("should remove bad urls", () => {
21
- expect(Array.from(getInboxes({
22
- ...emptyEvent,
23
- tags: [["r", "bad://inbox.com"]],
24
- }))).toHaveLength(0);
25
- expect(Array.from(getInboxes({
26
- ...emptyEvent,
27
- tags: [["r", "something that is not a url"]],
28
- }))).toHaveLength(0);
29
- expect(Array.from(getInboxes({
30
- ...emptyEvent,
31
- tags: [["r", "wss://inbox.com,wss://inbox.org"]],
32
- }))).toHaveLength(0);
33
- });
34
- test("without marker", () => {
35
- expect(Array.from(getInboxes({
36
- ...emptyEvent,
37
- tags: [["r", "wss://inbox.com/"]],
38
- }))).toEqual(expect.arrayContaining(["wss://inbox.com/"]));
39
- });
40
- test("with marker", () => {
41
- expect(Array.from(getInboxes({
42
- ...emptyEvent,
43
- tags: [["r", "wss://inbox.com/", "read"]],
44
- }))).toEqual(expect.arrayContaining(["wss://inbox.com/"]));
45
- });
46
- });
47
- describe("getOutboxes", () => {
48
- test("should transform urls", () => {
49
- expect(Array.from(getOutboxes({
50
- ...emptyEvent,
51
- tags: [["r", "wss://outbox.com"]],
52
- }))).toEqual(expect.arrayContaining(["wss://outbox.com/"]));
53
- });
54
- test("should remove bad urls", () => {
55
- expect(Array.from(getOutboxes({
56
- ...emptyEvent,
57
- tags: [["r", "bad://inbox.com"]],
58
- }))).toHaveLength(0);
59
- expect(Array.from(getOutboxes({
60
- ...emptyEvent,
61
- tags: [["r", "something that is not a url"]],
62
- }))).toHaveLength(0);
63
- expect(Array.from(getOutboxes({
64
- ...emptyEvent,
65
- tags: [["r", "wss://outbox.com,wss://inbox.org"]],
66
- }))).toHaveLength(0);
67
- });
68
- test("without marker", () => {
69
- expect(Array.from(getOutboxes({
70
- ...emptyEvent,
71
- tags: [["r", "wss://outbox.com/"]],
72
- }))).toEqual(expect.arrayContaining(["wss://outbox.com/"]));
73
- });
74
- test("with marker", () => {
75
- expect(Array.from(getOutboxes({
76
- ...emptyEvent,
77
- tags: [["r", "wss://outbox.com/", "write"]],
78
- }))).toEqual(expect.arrayContaining(["wss://outbox.com/"]));
79
- });
80
- });
81
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,55 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { matchMutes } from "../mutes.js";
3
- import { FakeUser } from "../../__tests__/fixtures.js";
4
- const mutedUser = new FakeUser();
5
- const nonMutedUser = new FakeUser();
6
- const thread = nonMutedUser.note("Hello world");
7
- // Create a mutes object with a pubkey to mute
8
- const mutes = {
9
- pubkeys: new Set([mutedUser.pubkey]),
10
- threads: new Set([thread.id]),
11
- hashtags: new Set(["nostr"]),
12
- words: new Set(["GM"]),
13
- };
14
- describe("matchMutes", () => {
15
- it("should match events with muted pubkeys", () => {
16
- const mutedEvent = mutedUser.note("Hello world");
17
- const nonMutedEvent = nonMutedUser.note("Hello world");
18
- // The event with the muted pubkey should match
19
- expect(matchMutes(mutes, mutedEvent)).toBe(true);
20
- // The event with a different pubkey should not match
21
- expect(matchMutes(mutes, nonMutedEvent)).toBe(false);
22
- });
23
- it("should match events with muted hashtags", () => {
24
- // Create events with and without the muted hashtag
25
- const eventWithMutedHashtag = nonMutedUser.note("Hello world");
26
- eventWithMutedHashtag.tags.push(["t", "nostr"]);
27
- const eventWithDifferentHashtag = nonMutedUser.note("Hello world");
28
- eventWithDifferentHashtag.tags.push(["t", "bitcoin"]);
29
- const eventWithNoHashtag = nonMutedUser.note("Hello world");
30
- // The event with the muted hashtag should match
31
- expect(matchMutes(mutes, eventWithMutedHashtag)).toBe(true);
32
- // The events without the muted hashtag should not match
33
- expect(matchMutes(mutes, eventWithDifferentHashtag)).toBe(false);
34
- expect(matchMutes(mutes, eventWithNoHashtag)).toBe(false);
35
- });
36
- it("should match events within threads", () => {
37
- // Create a reply to the thread
38
- const reply = nonMutedUser.note("Hello world");
39
- reply.tags.push(["e", thread.id, "", "root"]);
40
- // The reply should match the mute
41
- expect(matchMutes(mutes, reply)).toBe(true);
42
- // The thread should not match the mute
43
- expect(matchMutes(mutes, thread)).toBe(false);
44
- });
45
- it("should match events with muted words", () => {
46
- // The event with the muted word should match
47
- expect(matchMutes(mutes, nonMutedUser.note("GM"))).toBe(true);
48
- // Should not match other words that contain the muted word
49
- expect(matchMutes(mutes, nonMutedUser.note("GMing"))).toBe(false);
50
- // Should be case-insensitive
51
- expect(matchMutes(mutes, nonMutedUser.note("gm"))).toBe(true);
52
- // Should match if the muted word
53
- expect(matchMutes(mutes, nonMutedUser.note("Hello GM world"))).toBe(true);
54
- });
55
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,42 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { bytesToHex } from "@noble/hashes/utils";
3
- import { normalizeToPubkey, normalizeToSecretKey } from "../nip-19.js";
4
- describe("normalizeToPubkey", () => {
5
- it("should get pubkey from npub", () => {
6
- expect(normalizeToPubkey("npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr")).toEqual("266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5");
7
- });
8
- it("should get pubkey from nprofile", () => {
9
- expect(normalizeToPubkey("nprofile1qyw8wumn8ghj7umpw3jkcmrfw3jju6r6wfjrzdpe9e3k7mf0qyf8wumn8ghj7mn0wd68yat99e3k7mf0qqszv6q4uryjzr06xfxxew34wwc5hmjfmfpqn229d72gfegsdn2q3fg5g7lja")).toEqual("266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5");
10
- });
11
- it("should return hex pubkey", () => {
12
- expect(normalizeToPubkey("266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5")).toEqual("266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5");
13
- });
14
- it("should throw on invalid hex pubkey", () => {
15
- expect(() => {
16
- normalizeToPubkey("5028372");
17
- }).toThrow();
18
- });
19
- it("should throw on invalid string", () => {
20
- expect(() => {
21
- normalizeToPubkey("testing");
22
- }).toThrow();
23
- });
24
- });
25
- describe("normalizeToSecretKey", () => {
26
- it("should get secret key from nsec", () => {
27
- expect(bytesToHex(normalizeToSecretKey("nsec1xe7znq745x5n68566l32ru72aajz3pk2cys9lnf3tuexvkw0dldsj8v2lm"))).toEqual("367c2983d5a1a93d1e9ad7e2a1f3caef642886cac1205fcd315f326659cf6fdb");
28
- });
29
- it("should get secret key from raw hex", () => {
30
- expect(bytesToHex(normalizeToSecretKey("367c2983d5a1a93d1e9ad7e2a1f3caef642886cac1205fcd315f326659cf6fdb"))).toEqual("367c2983d5a1a93d1e9ad7e2a1f3caef642886cac1205fcd315f326659cf6fdb");
31
- });
32
- it("should throw on invalid hex key", () => {
33
- expect(() => {
34
- normalizeToSecretKey("209573290");
35
- }).toThrow();
36
- });
37
- it("should throw on npub", () => {
38
- expect(() => {
39
- normalizeToSecretKey("npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr");
40
- }).toThrow();
41
- });
42
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,21 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { isSafeRelayURL } from "../relays.js";
3
- describe("isSafeRelayURL", () => {
4
- it("should correctly filter URLs", () => {
5
- // safe URLs
6
- expect(isSafeRelayURL("wss://relay.damus.io/")).toBe(true);
7
- expect(isSafeRelayURL("wss://nostrue.com")).toBe(true);
8
- expect(isSafeRelayURL("ws://192.168.0.194:8080")).toBe(true);
9
- expect(isSafeRelayURL("ws://localhost:4869/ws")).toBe(true);
10
- expect(isSafeRelayURL("ws://localhost/testing")).toBe(true);
11
- expect(isSafeRelayURL("ws://437fqnfqtcaquzvs5sd43ugznw7dsoatvtskoowgnpn6q5vqkljcrsyd.onion")).toBe(true);
12
- expect(isSafeRelayURL("ws://hypr1fk4trjnhjf62r6hhkpettmvxhxx2uvkkg4u4ea44va2fvxvfkl4s82m6dy.hyper")).toBe(true);
13
- // bad URLs
14
- expect(isSafeRelayURL("")).toBe(false);
15
- expect(isSafeRelayURL("bad")).toBe(false);
16
- expect(isSafeRelayURL("bad wss://nostr.wine")).toBe(false);
17
- expect(isSafeRelayURL("http://nostr.wine")).toBe(false);
18
- expect(isSafeRelayURL("http://cache-relay.com")).toBe(false);
19
- expect(isSafeRelayURL("wss://nostr.wine,wss://relayable.com")).toBe(false);
20
- });
21
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,24 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { isATag, isNameValueTag, processTags } from "../tags.js";
3
- import { getAddressPointerFromATag } from "../pointers.js";
4
- describe("isNameValueTag", () => {
5
- it("should return true if tag has at least two indexes", () => {
6
- expect(isNameValueTag(["a", "30000:pubkey:list"])).toBe(true);
7
- expect(isNameValueTag(["title", "article", "other-value"])).toBe(true);
8
- });
9
- it("should ignore tags without values", () => {
10
- expect(isNameValueTag(["a"])).toBe(false);
11
- expect(isNameValueTag(["title"])).toBe(false);
12
- });
13
- });
14
- describe("processTags", () => {
15
- it("should filter out errors", () => {
16
- expect(processTags([["a", "bad coordinate"], ["e"], ["a", "30000:pubkey:list"]], getAddressPointerFromATag)).toEqual([{ identifier: "list", kind: 30000, pubkey: "pubkey" }]);
17
- });
18
- it("should filter out undefined", () => {
19
- expect(processTags([["a", "bad coordinate"], ["e"], ["a", "30000:pubkey:list"]], (tag) => isATag(tag) ? tag : undefined)).toEqual([
20
- ["a", "bad coordinate"],
21
- ["a", "30000:pubkey:list"],
22
- ]);
23
- });
24
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,41 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { interpretThreadTags } from "../threading.js";
3
- describe("threading helpers", () => {
4
- describe("interpretThreadTags", () => {
5
- it("should handle legacy tags", () => {
6
- expect(interpretThreadTags([
7
- ["e", "root-id"],
8
- ["e", "reply-id"],
9
- ])).toEqual({ root: { a: undefined, e: ["e", "root-id"] }, reply: { a: undefined, e: ["e", "reply-id"] } });
10
- });
11
- it("should handle nip-10 tags", () => {
12
- expect(interpretThreadTags([
13
- ["e", "root-id", "relay", "root"],
14
- ["e", "reply-id", "relay", "reply"],
15
- ])).toEqual({
16
- root: { a: undefined, e: ["e", "root-id", "relay", "root"] },
17
- reply: { a: undefined, e: ["e", "reply-id", "relay", "reply"] },
18
- });
19
- });
20
- it("should ignore mention nip-10 tags", () => {
21
- expect(interpretThreadTags([
22
- ["e", "root-id", "relay", "root"],
23
- ["e", "mention-id", "relay", "mention"],
24
- ["e", "reply-id", "relay", "reply"],
25
- ])).toEqual({
26
- root: { a: undefined, e: ["e", "root-id", "relay", "root"] },
27
- reply: { a: undefined, e: ["e", "reply-id", "relay", "reply"] },
28
- });
29
- });
30
- it("should handle single nip-10 tags", () => {
31
- expect(interpretThreadTags([["e", "root-id", "relay", "root"]])).toEqual({
32
- root: { a: undefined, e: ["e", "root-id", "relay", "root"] },
33
- reply: { a: undefined, e: ["e", "root-id", "relay", "root"] },
34
- });
35
- expect(interpretThreadTags([["e", "reply-id", "relay", "reply"]])).toEqual({
36
- root: { a: undefined, e: ["e", "reply-id", "relay", "reply"] },
37
- reply: { a: undefined, e: ["e", "reply-id", "relay", "reply"] },
38
- });
39
- });
40
- });
41
- });
@@ -1,4 +0,0 @@
1
- import { NostrEvent } from "nostr-tools";
2
- import { HiddenContentSigner } from "./hidden-content.js";
3
- /** Returns the decrypted content of a direct message */
4
- export declare function decryptDirectMessage(message: NostrEvent, signer: HiddenContentSigner): Promise<string>;
@@ -1,5 +0,0 @@
1
- import { getHiddenContent, unlockHiddenContent } from "./hidden-content.js";
2
- /** Returns the decrypted content of a direct message */
3
- export async function decryptDirectMessage(message, signer) {
4
- return getHiddenContent(message) || (await unlockHiddenContent(message, signer));
5
- }
@@ -1,18 +0,0 @@
1
- import { AddressPointer, EventPointer, ProfilePointer } from "nostr-tools/nip19";
2
- /** Gets the hex pubkey from any nip-19 encoded string */
3
- export declare function normalizeToPubkey(str: string): string;
4
- /** Converts hex to nsec strings into Uint8 secret keys */
5
- export declare function normalizeToSecretKey(str: string): Uint8Array;
6
- /**
7
- * Merges two event points and keeps all relays
8
- * @throws if the ids are different
9
- */
10
- export declare function mergeEventPointers(a: EventPointer, b: EventPointer): EventPointer;
11
- /** Merges two address pointers and keeps all relays
12
- * @throws if the kinds, pubkeys, or identifiers are different
13
- */
14
- export declare function mergeAddressPointers(a: AddressPointer, b: AddressPointer): AddressPointer;
15
- /** Merges two profile pointers and keeps all relays
16
- * @throws if the pubkeys are different
17
- */
18
- export declare function mergeProfilePointers(a: ProfilePointer, b: ProfilePointer): ProfilePointer;
@@ -1,56 +0,0 @@
1
- import { nip19 } from "nostr-tools";
2
- import { hexToBytes } from "@noble/hashes/utils";
3
- import { isHexKey } from "./string.js";
4
- import { getPubkeyFromDecodeResult } from "./pointers.js";
5
- import { mergeRelaySets } from "./relays.js";
6
- /** Gets the hex pubkey from any nip-19 encoded string */
7
- export function normalizeToPubkey(str) {
8
- if (isHexKey(str))
9
- return str;
10
- else {
11
- const decode = nip19.decode(str);
12
- const pubkey = getPubkeyFromDecodeResult(decode);
13
- if (!pubkey)
14
- throw new Error(`Cant find pubkey in ${decode.type}`);
15
- return pubkey;
16
- }
17
- }
18
- /** Converts hex to nsec strings into Uint8 secret keys */
19
- export function normalizeToSecretKey(str) {
20
- if (isHexKey(str))
21
- return hexToBytes(str);
22
- else {
23
- const decode = nip19.decode(str);
24
- if (decode.type !== "nsec")
25
- throw new Error(`Cant get secret key from ${decode.type}`);
26
- return decode.data;
27
- }
28
- }
29
- /**
30
- * Merges two event points and keeps all relays
31
- * @throws if the ids are different
32
- */
33
- export function mergeEventPointers(a, b) {
34
- if (a.id !== b.id)
35
- throw new Error("Cant merge event pointers with different ids");
36
- const relays = mergeRelaySets(a.relays, b.relays);
37
- return { id: a.id, kind: a.kind ?? b.kind, author: a.author ?? b.author, relays };
38
- }
39
- /** Merges two address pointers and keeps all relays
40
- * @throws if the kinds, pubkeys, or identifiers are different
41
- */
42
- export function mergeAddressPointers(a, b) {
43
- if (a.kind !== b.kind || a.pubkey !== b.pubkey || a.identifier !== b.identifier)
44
- throw new Error("Cant merge address pointers with different kinds, pubkeys, or identifiers");
45
- const relays = mergeRelaySets(a.relays, b.relays);
46
- return { ...a, relays };
47
- }
48
- /** Merges two profile pointers and keeps all relays
49
- * @throws if the pubkeys are different
50
- */
51
- export function mergeProfilePointers(a, b) {
52
- if (a.pubkey !== b.pubkey)
53
- throw new Error("Cant merge profile pointers with different pubkeys");
54
- const relays = mergeRelaySets(a.relays, b.relays);
55
- return { ...a, relays };
56
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,23 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { Database } from "../../event-store/database.js";
3
- import { claimEvents } from "../claim-events.js";
4
- const event = {
5
- content: '{"name":"hzrd149","picture":"https://cdn.hzrd149.com/5ed3fe5df09a74e8c126831eac999364f9eb7624e2b86d521521b8021de20bdc.png","about":"JavaScript developer working on some nostr stuff\\n- noStrudel https://nostrudel.ninja/ \\n- Blossom https://github.com/hzrd149/blossom \\n- Applesauce https://hzrd149.github.io/applesauce/","website":"https://hzrd149.com","nip05":"_@hzrd149.com","lud16":"hzrd1499@minibits.cash","pubkey":"266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5","display_name":"hzrd149","displayName":"hzrd149","banner":""}',
6
- created_at: 1738362529,
7
- id: "e9df8d5898c4ccfbd21fcd59f3f48abb3ff0ab7259b19570e2f1756de1e9306b",
8
- kind: 0,
9
- pubkey: "266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5",
10
- relays: [""],
11
- sig: "465a47b93626a587bf81dadc2b306b8f713a62db31d6ce1533198e9ae1e665a6eaf376a03250bf9ffbb02eb9059c8eafbd37ae1092d05d215757575bd8357586",
12
- tags: [],
13
- };
14
- describe("claimEvents", () => {
15
- it("it should claim events", () => {
16
- const database = new Database();
17
- const sub = database.inserted.pipe(claimEvents(database)).subscribe();
18
- database.addEvent(event);
19
- expect(database.isClaimed(event)).toBe(true);
20
- sub.unsubscribe();
21
- expect(database.isClaimed(event)).toBe(false);
22
- });
23
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,37 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { Database } from "../../event-store/database.js";
3
- import { claimLatest } from "../claim-latest.js";
4
- const event1 = {
5
- content: '{"name":"hzrd149","picture":"https://cdn.hzrd149.com/5ed3fe5df09a74e8c126831eac999364f9eb7624e2b86d521521b8021de20bdc.png","about":"JavaScript developer working on some nostr stuff\\n- noStrudel https://nostrudel.ninja/ \\n- Blossom https://github.com/hzrd149/blossom \\n- Applesauce https://hzrd149.github.io/applesauce/","website":"https://hzrd149.com","nip05":"_@hzrd149.com","lud16":"hzrd1499@minibits.cash","pubkey":"266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5","display_name":"hzrd149","displayName":"hzrd149","banner":""}',
6
- created_at: 1738362529,
7
- id: "e9df8d5898c4ccfbd21fcd59f3f48abb3ff0ab7259b19570e2f1756de1e9306b",
8
- kind: 0,
9
- pubkey: "266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5",
10
- relays: [""],
11
- sig: "465a47b93626a587bf81dadc2b306b8f713a62db31d6ce1533198e9ae1e665a6eaf376a03250bf9ffbb02eb9059c8eafbd37ae1092d05d215757575bd8357586",
12
- tags: [],
13
- };
14
- const event2 = {
15
- content: '{"name":"Cesar Dias","website":"dev.nosotros.app","picture":"https://nostr.build/i/5b0e4387b0fdfff9897ee7f8dcc554761fe377583a5fb71bbf3b915e7c4971c2.jpg","display_name":"Cesar Dias","nip05":"_@nosotros.app","lud16":"cesardias@getalby.com","about":"Developer 🇧🇷, building a client https://dev.nosotros.app and nostr-editor https://github.com/cesardeazevedo/nostr-editor","banner":"https://image.nostr.build/87dbc55a6391d15bddda206561d53867a5679dd95e84fe8ed62bfe2e3adcadf3.jpg\\",\\"ox 87dbc55a6391d15bddda206561d53867a5679dd95e84fe8ed62bfe2e3adcadf3"}',
16
- created_at: 1727998492,
17
- id: "c771fe19ac255ea28690c5547258a5e146d2f47805f7f48093b773478bdd137c",
18
- kind: 0,
19
- pubkey: "c6603b0f1ccfec625d9c08b753e4f774eaf7d1cf2769223125b5fd4da728019e",
20
- relays: [""],
21
- sig: "5220d6a8cdb4837b2569c26a84a2ac6a44427a224cb1602c05c578c6a63fe122a37e16455b09cb38bf297fc8161a8e715d7b444d017624c044d87a77e092c881",
22
- tags: [["alt", "User profile for Cesar Dias"]],
23
- };
24
- describe("claimLatest", () => {
25
- it("it should claim events", () => {
26
- const database = new Database();
27
- const sub = database.inserted.pipe(claimLatest(database)).subscribe();
28
- database.addEvent(event1);
29
- expect(database.isClaimed(event1)).toBe(true);
30
- database.addEvent(event2);
31
- expect(database.isClaimed(event1)).toBe(false);
32
- expect(database.isClaimed(event2)).toBe(true);
33
- sub.unsubscribe();
34
- expect(database.isClaimed(event1)).toBe(false);
35
- expect(database.isClaimed(event2)).toBe(false);
36
- });
37
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,18 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import * as exports from "../index.js";
3
- describe("exports", () => {
4
- it("should export the expected functions", () => {
5
- expect(Object.keys(exports).sort()).toMatchInlineSnapshot(`
6
- [
7
- "TimeoutError",
8
- "defined",
9
- "firstValueFrom",
10
- "getObservableValue",
11
- "lastValueFrom",
12
- "listenLatestUpdates",
13
- "simpleTimeout",
14
- "withImmediateValueOrDefault",
15
- ]
16
- `);
17
- });
18
- });