applesauce-core 0.0.0-next-20250609184904 → 0.0.0-next-20250610175335

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 (136) hide show
  1. package/dist/helpers/bolt11.d.ts +1 -0
  2. package/dist/helpers/bolt11.js +2 -0
  3. package/dist/helpers/expiration.js +1 -1
  4. package/package.json +2 -2
  5. package/dist/__tests__/exports.test.d.ts +0 -1
  6. package/dist/__tests__/exports.test.js +0 -27
  7. package/dist/event-store/__tests__/event-store.test.d.ts +0 -1
  8. package/dist/event-store/__tests__/event-store.test.js +0 -386
  9. package/dist/event-store/database.d.ts +0 -67
  10. package/dist/event-store/database.js +0 -319
  11. package/dist/helpers/__tests__/app-handlers.test.d.ts +0 -1
  12. package/dist/helpers/__tests__/app-handlers.test.js +0 -184
  13. package/dist/helpers/__tests__/blossom.test.d.ts +0 -1
  14. package/dist/helpers/__tests__/blossom.test.js +0 -13
  15. package/dist/helpers/__tests__/bookmarks.test.d.ts +0 -1
  16. package/dist/helpers/__tests__/bookmarks.test.js +0 -88
  17. package/dist/helpers/__tests__/comment.test.d.ts +0 -1
  18. package/dist/helpers/__tests__/comment.test.js +0 -249
  19. package/dist/helpers/__tests__/contacts.test.d.ts +0 -1
  20. package/dist/helpers/__tests__/contacts.test.js +0 -34
  21. package/dist/helpers/__tests__/emoji.test.d.ts +0 -1
  22. package/dist/helpers/__tests__/emoji.test.js +0 -110
  23. package/dist/helpers/__tests__/encrypted-content-cache.test.d.ts +0 -1
  24. package/dist/helpers/__tests__/encrypted-content-cache.test.js +0 -65
  25. package/dist/helpers/__tests__/encryption.test.d.ts +0 -1
  26. package/dist/helpers/__tests__/encryption.test.js +0 -21
  27. package/dist/helpers/__tests__/event.test.d.ts +0 -1
  28. package/dist/helpers/__tests__/event.test.js +0 -36
  29. package/dist/helpers/__tests__/events.test.d.ts +0 -1
  30. package/dist/helpers/__tests__/events.test.js +0 -32
  31. package/dist/helpers/__tests__/exports.test.d.ts +0 -1
  32. package/dist/helpers/__tests__/exports.test.js +0 -295
  33. package/dist/helpers/__tests__/file-metadata.test.d.ts +0 -1
  34. package/dist/helpers/__tests__/file-metadata.test.js +0 -103
  35. package/dist/helpers/__tests__/groups.test.d.ts +0 -1
  36. package/dist/helpers/__tests__/groups.test.js +0 -61
  37. package/dist/helpers/__tests__/hidden-tags.test.d.ts +0 -1
  38. package/dist/helpers/__tests__/hidden-tags.test.js +0 -29
  39. package/dist/helpers/__tests__/mailboxes.test.d.ts +0 -1
  40. package/dist/helpers/__tests__/mailboxes.test.js +0 -81
  41. package/dist/helpers/__tests__/messages.test.d.ts +0 -1
  42. package/dist/helpers/__tests__/messages.test.js +0 -91
  43. package/dist/helpers/__tests__/mutes.test.d.ts +0 -1
  44. package/dist/helpers/__tests__/mutes.test.js +0 -55
  45. package/dist/helpers/__tests__/nip-19.test.d.ts +0 -1
  46. package/dist/helpers/__tests__/nip-19.test.js +0 -42
  47. package/dist/helpers/__tests__/pointers.test.d.ts +0 -1
  48. package/dist/helpers/__tests__/pointers.test.js +0 -118
  49. package/dist/helpers/__tests__/profile.test.d.ts +0 -1
  50. package/dist/helpers/__tests__/profile.test.js +0 -72
  51. package/dist/helpers/__tests__/reactions.test.d.ts +0 -1
  52. package/dist/helpers/__tests__/reactions.test.js +0 -88
  53. package/dist/helpers/__tests__/relays.test.d.ts +0 -1
  54. package/dist/helpers/__tests__/relays.test.js +0 -21
  55. package/dist/helpers/__tests__/tags.test.d.ts +0 -1
  56. package/dist/helpers/__tests__/tags.test.js +0 -24
  57. package/dist/helpers/__tests__/threading.test.d.ts +0 -1
  58. package/dist/helpers/__tests__/threading.test.js +0 -41
  59. package/dist/helpers/direct-messages.d.ts +0 -4
  60. package/dist/helpers/direct-messages.js +0 -5
  61. package/dist/helpers/legacy-direct-messages.d.ts +0 -19
  62. package/dist/helpers/legacy-direct-messages.js +0 -35
  63. package/dist/helpers/nip-19.d.ts +0 -18
  64. package/dist/helpers/nip-19.js +0 -56
  65. package/dist/helpers/wrapped-direct-messages.d.ts +0 -10
  66. package/dist/helpers/wrapped-direct-messages.js +0 -19
  67. package/dist/models/__tests__/comments.test.d.ts +0 -1
  68. package/dist/models/__tests__/comments.test.js +0 -36
  69. package/dist/models/__tests__/exports.test.d.ts +0 -1
  70. package/dist/models/__tests__/exports.test.js +0 -53
  71. package/dist/models/legacy-direct-messages.d.ts +0 -5
  72. package/dist/models/legacy-direct-messages.js +0 -16
  73. package/dist/models/simple.d.ts +0 -16
  74. package/dist/models/simple.js +0 -21
  75. package/dist/models/wrapped-direct-messages.d.ts +0 -14
  76. package/dist/models/wrapped-direct-messages.js +0 -30
  77. package/dist/observable/__tests__/claim-events.test.d.ts +0 -1
  78. package/dist/observable/__tests__/claim-events.test.js +0 -23
  79. package/dist/observable/__tests__/claim-latest.test.d.ts +0 -1
  80. package/dist/observable/__tests__/claim-latest.test.js +0 -37
  81. package/dist/observable/__tests__/exports.test.d.ts +0 -1
  82. package/dist/observable/__tests__/exports.test.js +0 -21
  83. package/dist/observable/__tests__/map-events-to-store.test.d.ts +0 -1
  84. package/dist/observable/__tests__/map-events-to-store.test.js +0 -38
  85. package/dist/observable/__tests__/simple-timeout.test.d.ts +0 -1
  86. package/dist/observable/__tests__/simple-timeout.test.js +0 -34
  87. package/dist/observable/__tests__/watch-event-updates.test.d.ts +0 -1
  88. package/dist/observable/__tests__/watch-event-updates.test.js +0 -55
  89. package/dist/promise/__tests__/exports.test.d.ts +0 -1
  90. package/dist/promise/__tests__/exports.test.js +0 -11
  91. package/dist/queries/__tests__/comments.test.d.ts +0 -1
  92. package/dist/queries/__tests__/comments.test.js +0 -39
  93. package/dist/queries/__tests__/exports.test.d.ts +0 -1
  94. package/dist/queries/__tests__/exports.test.js +0 -44
  95. package/dist/queries/blossom.d.ts +0 -2
  96. package/dist/queries/blossom.js +0 -5
  97. package/dist/queries/bookmarks.d.ts +0 -8
  98. package/dist/queries/bookmarks.js +0 -24
  99. package/dist/queries/channels.d.ts +0 -11
  100. package/dist/queries/channels.js +0 -61
  101. package/dist/queries/comments.d.ts +0 -4
  102. package/dist/queries/comments.js +0 -11
  103. package/dist/queries/contacts.d.ts +0 -8
  104. package/dist/queries/contacts.js +0 -24
  105. package/dist/queries/gift-wrap.d.ts +0 -4
  106. package/dist/queries/gift-wrap.js +0 -12
  107. package/dist/queries/index.d.ts +0 -15
  108. package/dist/queries/index.js +0 -15
  109. package/dist/queries/mailboxes.d.ts +0 -6
  110. package/dist/queries/mailboxes.js +0 -10
  111. package/dist/queries/mutes.d.ts +0 -8
  112. package/dist/queries/mutes.js +0 -24
  113. package/dist/queries/pins.d.ts +0 -4
  114. package/dist/queries/pins.js +0 -10
  115. package/dist/queries/profile.d.ts +0 -4
  116. package/dist/queries/profile.js +0 -7
  117. package/dist/queries/reactions.d.ts +0 -4
  118. package/dist/queries/reactions.js +0 -16
  119. package/dist/queries/relays.d.ts +0 -27
  120. package/dist/queries/relays.js +0 -44
  121. package/dist/queries/simple.d.ts +0 -16
  122. package/dist/queries/simple.js +0 -21
  123. package/dist/queries/thread.d.ts +0 -25
  124. package/dist/queries/thread.js +0 -86
  125. package/dist/queries/user-status.d.ts +0 -11
  126. package/dist/queries/user-status.js +0 -33
  127. package/dist/queries/zaps.d.ts +0 -9
  128. package/dist/queries/zaps.js +0 -26
  129. package/dist/query-store/__tests__/exports.test.d.ts +0 -1
  130. package/dist/query-store/__tests__/exports.test.js +0 -12
  131. package/dist/query-store/__tests__/query-store.test.d.ts +0 -1
  132. package/dist/query-store/__tests__/query-store.test.js +0 -63
  133. package/dist/query-store/index.d.ts +0 -1
  134. package/dist/query-store/index.js +0 -1
  135. package/dist/query-store/query-store.d.ts +0 -51
  136. package/dist/query-store/query-store.js +0 -102
@@ -4,6 +4,7 @@ export type ParsedInvoice = {
4
4
  amount?: number;
5
5
  timestamp: number;
6
6
  expiry: number;
7
+ paymentHash?: string;
7
8
  };
8
9
  /** Parses a lightning invoice */
9
10
  export declare function parseBolt11(paymentRequest: string): ParsedInvoice;
@@ -5,11 +5,13 @@ export function parseBolt11(paymentRequest) {
5
5
  const timestamp = decoded.sections.find((s) => s.name === "timestamp")?.value ?? 0;
6
6
  const description = decoded.sections.find((s) => s.name === "description")?.value ?? "";
7
7
  const amount = parseInt(decoded.sections.find((s) => s.name === "amount")?.value ?? "0");
8
+ const paymentHash = decoded.sections.find((s) => s.name === "payment_hash");
8
9
  return {
9
10
  paymentRequest: decoded.paymentRequest,
10
11
  description: description,
11
12
  amount: amount,
12
13
  timestamp: timestamp,
13
14
  expiry: timestamp + decoded.expiry,
15
+ paymentHash: paymentHash?.value,
14
16
  };
15
17
  }
@@ -6,7 +6,7 @@ export const ExpirationTimestampSymbol = Symbol("expiration-timestamp");
6
6
  export function getExpirationTimestamp(event) {
7
7
  return getOrComputeCachedValue(event, ExpirationTimestampSymbol, () => {
8
8
  const expiration = getTagValue(event, "expiration");
9
- return expiration ? parseInt(expiration[1]) : undefined;
9
+ return expiration ? parseInt(expiration) : undefined;
10
10
  });
11
11
  }
12
12
  /** Checks if an event has expired based on the NIP-40 expiration timestamp */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "0.0.0-next-20250609184904",
3
+ "version": "0.0.0-next-20250610175335",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,7 @@
72
72
  "@types/debug": "^4.1.12",
73
73
  "@types/hash-sum": "^1.0.2",
74
74
  "typescript": "^5.8.3",
75
- "vitest": "^3.1.1"
75
+ "vitest": "^3.2.3"
76
76
  },
77
77
  "funding": {
78
78
  "type": "lightning",
@@ -1 +0,0 @@
1
- export {};
@@ -1,27 +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
- "EventSet",
8
- "EventStore",
9
- "EventStoreSymbol",
10
- "Helpers",
11
- "Models",
12
- "TimeoutError",
13
- "defined",
14
- "firstValueFrom",
15
- "getObservableValue",
16
- "lastValueFrom",
17
- "logger",
18
- "mapEventsToStore",
19
- "mapEventsToTimeline",
20
- "simpleTimeout",
21
- "watchEventUpdates",
22
- "watchEventsUpdates",
23
- "withImmediateValueOrDefault",
24
- ]
25
- `);
26
- });
27
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,386 +0,0 @@
1
- import { subscribeSpyTo } from "@hirez_io/observer-spy";
2
- import { kinds } from "nostr-tools";
3
- import { beforeEach, describe, expect, it, vi } from "vitest";
4
- import { FakeUser } from "../../__tests__/fixtures.js";
5
- import { getEventUID } from "../../helpers/event.js";
6
- import { addSeenRelay, getSeenRelays } from "../../helpers/relays.js";
7
- import { EventModel } from "../../models/common.js";
8
- import { ProfileModel } from "../../models/profile.js";
9
- import { EventStore } from "../event-store.js";
10
- let eventStore;
11
- beforeEach(() => {
12
- eventStore = new EventStore();
13
- });
14
- const user = new FakeUser();
15
- const profile = user.profile({ name: "fake user" });
16
- const note = user.note();
17
- describe("add", () => {
18
- it("should return original event in case of duplicates", () => {
19
- const a = { ...profile };
20
- expect(eventStore.add(a)).toBe(a);
21
- const b = { ...profile };
22
- expect(eventStore.add(b)).toBe(a);
23
- const c = { ...profile };
24
- expect(eventStore.add(c)).toBe(a);
25
- });
26
- it("should merge seen relays on duplicate events", () => {
27
- const a = { ...profile };
28
- addSeenRelay(a, "wss://relay.a.com");
29
- eventStore.add(a);
30
- const b = { ...profile };
31
- addSeenRelay(b, "wss://relay.b.com");
32
- eventStore.add(b);
33
- expect(eventStore.getEvent(profile.id)).toBeDefined();
34
- expect([...getSeenRelays(eventStore.getEvent(profile.id))]).toEqual(expect.arrayContaining(["wss://relay.a.com", "wss://relay.b.com"]));
35
- });
36
- it("should ignore old deleted events but not newer ones", () => {
37
- const deleteEvent = {
38
- id: "delete event id",
39
- kind: kinds.EventDeletion,
40
- created_at: profile.created_at + 100,
41
- pubkey: user.pubkey,
42
- tags: [["e", profile.id]],
43
- sig: "this should be ignored for the test",
44
- content: "test",
45
- };
46
- // add delete event first
47
- eventStore.add(deleteEvent);
48
- // now event should be ignored
49
- eventStore.add(profile);
50
- const newProfile = user.profile({ name: "new name" }, { created_at: profile.created_at + 1000 });
51
- eventStore.add(newProfile);
52
- expect(eventStore.getEvent(profile.id)).toBeUndefined();
53
- expect(eventStore.getEvent(newProfile.id)).toBeDefined();
54
- });
55
- it("should remove profile events when delete event is added", () => {
56
- // Add initial replaceable event
57
- eventStore.add(profile);
58
- expect(eventStore.getEvent(profile.id)).toBeDefined();
59
- const newProfile = user.profile({ name: "new name" }, { created_at: profile.created_at + 1000 });
60
- eventStore.add(newProfile);
61
- const deleteEvent = {
62
- id: "delete event id",
63
- kind: kinds.EventDeletion,
64
- created_at: profile.created_at + 100,
65
- pubkey: user.pubkey,
66
- tags: [["a", `${profile.kind}:${profile.pubkey}`]],
67
- sig: "this should be ignored for the test",
68
- content: "test",
69
- };
70
- // Add delete event with coordinate
71
- eventStore.add(deleteEvent);
72
- // Profile should be removed since delete event is newer
73
- expect(eventStore.getEvent(profile.id)).toBeUndefined();
74
- expect(eventStore.getEvent(newProfile.id)).toBeDefined();
75
- expect(eventStore.getReplaceable(profile.kind, profile.pubkey)).toBe(newProfile);
76
- });
77
- it("should remove addressable replaceable events when delete event is added", () => {
78
- // Add initial replaceable event
79
- const event = user.event({ content: "test", kind: 30000, tags: [["d", "test"]] });
80
- eventStore.add(event);
81
- expect(eventStore.getEvent(event.id)).toBeDefined();
82
- const newEvent = user.event({
83
- ...event,
84
- created_at: event.created_at + 500,
85
- });
86
- eventStore.add(newEvent);
87
- const deleteEvent = {
88
- id: "delete event id",
89
- kind: kinds.EventDeletion,
90
- created_at: event.created_at + 100,
91
- pubkey: user.pubkey,
92
- tags: [["a", `${event.kind}:${event.pubkey}:test`]],
93
- sig: "this should be ignored for the test",
94
- content: "test",
95
- };
96
- // Add delete event with coordinate
97
- eventStore.add(deleteEvent);
98
- // Profile should be removed since delete event is newer
99
- expect(eventStore.getEvent(event.id)).toBeUndefined();
100
- expect(eventStore.getEvent(newEvent.id)).toBeDefined();
101
- expect(eventStore.getReplaceable(event.kind, event.pubkey, "test")).toBe(newEvent);
102
- });
103
- it("should return null when event is invalid and there isn't an existing event", () => {
104
- const verifyEvent = vi.fn().mockReturnValue(false);
105
- eventStore.verifyEvent = verifyEvent;
106
- expect(eventStore.add(profile)).toBeNull();
107
- expect(verifyEvent).toHaveBeenCalledWith(profile);
108
- });
109
- });
110
- describe("inserts", () => {
111
- it("should emit newer replaceable events", () => {
112
- const spy = subscribeSpyTo(eventStore.insert$);
113
- eventStore.add(profile);
114
- const newer = user.profile({ name: "new name" }, { created_at: profile.created_at + 100 });
115
- eventStore.add(newer);
116
- expect(spy.getValues()).toEqual([profile, newer]);
117
- });
118
- it("should not emit when older replaceable event is added", () => {
119
- const spy = subscribeSpyTo(eventStore.insert$);
120
- eventStore.add(profile);
121
- eventStore.add(user.profile({ name: "new name" }, { created_at: profile.created_at - 1000 }));
122
- expect(spy.getValues()).toEqual([profile]);
123
- });
124
- });
125
- describe("removes", () => {
126
- it("should emit older replaceable events when the newest replaceable event is added", () => {
127
- const spy = subscribeSpyTo(eventStore.remove$);
128
- eventStore.add(profile);
129
- const newer = user.profile({ name: "new name" }, { created_at: profile.created_at + 1000 });
130
- eventStore.add(newer);
131
- expect(spy.getValues()).toEqual([profile]);
132
- });
133
- });
134
- describe("verifyEvent", () => {
135
- it("should be called for all events added", () => {
136
- const verifyEvent = vi.fn().mockReturnValue(true);
137
- eventStore.verifyEvent = verifyEvent;
138
- eventStore.add(profile);
139
- expect(verifyEvent).toHaveBeenCalledWith(profile);
140
- });
141
- it("should not be called for duplicate events", () => {
142
- const verifyEvent = vi.fn().mockReturnValue(true);
143
- eventStore.verifyEvent = verifyEvent;
144
- const a = { ...profile };
145
- eventStore.add(a);
146
- expect(verifyEvent).toHaveBeenCalledWith(a);
147
- const b = { ...profile };
148
- eventStore.add(b);
149
- expect(verifyEvent).toHaveBeenCalledTimes(1);
150
- const c = { ...profile };
151
- eventStore.add(c);
152
- expect(verifyEvent).toHaveBeenCalledTimes(1);
153
- });
154
- });
155
- describe("removed", () => {
156
- it("should complete when event is removed", () => {
157
- eventStore.add(profile);
158
- const spy = subscribeSpyTo(eventStore.removed(profile.id));
159
- eventStore.remove(profile);
160
- expect(spy.getValues()).toEqual([]);
161
- expect(spy.receivedComplete()).toBe(true);
162
- });
163
- });
164
- describe("model", () => {
165
- it("should emit synchronous value if it exists", () => {
166
- let value = undefined;
167
- eventStore.add(profile);
168
- eventStore.model(ProfileModel, user.pubkey).subscribe((v) => (value = v));
169
- expect(value).not.toBe(undefined);
170
- });
171
- it("should not emit undefined if value exists", () => {
172
- eventStore.add(profile);
173
- const spy = subscribeSpyTo(eventStore.model(EventModel, profile.id));
174
- expect(spy.getValues()).toEqual([profile]);
175
- });
176
- it("should emit synchronous undefined if value does not exists", () => {
177
- let value = 0;
178
- eventStore.model(ProfileModel, user.pubkey).subscribe((v) => {
179
- value = v;
180
- });
181
- expect(value).not.toBe(0);
182
- expect(value).toBe(undefined);
183
- });
184
- it("should share latest value", () => {
185
- eventStore.add(profile);
186
- const spy = subscribeSpyTo(eventStore.model(EventModel, profile.id));
187
- const spy2 = subscribeSpyTo(eventStore.model(EventModel, profile.id));
188
- expect(spy.getValues()).toEqual([profile]);
189
- expect(spy2.getValues()).toEqual([profile]);
190
- });
191
- });
192
- describe("event", () => {
193
- it("should emit existing event", () => {
194
- eventStore.add(profile);
195
- const spy = subscribeSpyTo(eventStore.event(profile.id));
196
- expect(spy.getValues()).toEqual([profile]);
197
- });
198
- it("should emit then event when its added", () => {
199
- const spy = subscribeSpyTo(eventStore.event(profile.id));
200
- expect(spy.getValues()).toEqual([undefined]);
201
- eventStore.add(profile);
202
- expect(spy.getValues()).toEqual([undefined, profile]);
203
- });
204
- it("should emit undefined when event is removed", () => {
205
- eventStore.add(profile);
206
- const spy = subscribeSpyTo(eventStore.event(profile.id));
207
- expect(spy.getValues()).toEqual([profile]);
208
- eventStore.remove(profile);
209
- expect(spy.getValues()).toEqual([profile, undefined]);
210
- });
211
- it("should emit new value if event is re-added", () => {
212
- eventStore.add(profile);
213
- const spy = subscribeSpyTo(eventStore.event(profile.id));
214
- eventStore.remove(profile);
215
- eventStore.add(profile);
216
- expect(spy.getValues()).toEqual([profile, undefined, profile]);
217
- });
218
- it("should not complete when event is removed", () => {
219
- eventStore.add(profile);
220
- const spy = subscribeSpyTo(eventStore.event(profile.id));
221
- eventStore.remove(profile);
222
- expect(spy.receivedComplete()).toBe(false);
223
- });
224
- it("should emit undefined if event is not found", () => {
225
- const spy = subscribeSpyTo(eventStore.event(profile.id));
226
- expect(spy.getValues()).toEqual([undefined]);
227
- });
228
- });
229
- describe("events", () => {
230
- it("should emit existing events", () => {
231
- eventStore.add(profile);
232
- const spy = subscribeSpyTo(eventStore.events([profile.id]));
233
- expect(spy.getValues()).toEqual([{ [profile.id]: profile }]);
234
- });
235
- it("should remove events when they are removed", () => {
236
- eventStore.add(profile);
237
- const spy = subscribeSpyTo(eventStore.events([profile.id]));
238
- expect(spy.getValues()).toEqual([{ [profile.id]: profile }]);
239
- eventStore.remove(profile);
240
- expect(spy.getValues()).toEqual([{ [profile.id]: profile }, {}]);
241
- });
242
- it("should add events back if then are re-added", () => {
243
- eventStore.add(profile);
244
- const spy = subscribeSpyTo(eventStore.events([profile.id]));
245
- eventStore.remove(profile);
246
- eventStore.add(profile);
247
- expect(spy.getValues()).toEqual([{ [profile.id]: profile }, {}, { [profile.id]: profile }]);
248
- });
249
- it("should not emit any values if there are no events", () => {
250
- const spy = subscribeSpyTo(eventStore.events([profile.id]));
251
- expect(spy.receivedNext()).toBe(false);
252
- });
253
- });
254
- describe("replaceable", () => {
255
- it("should emit existing events", () => {
256
- eventStore.add(profile);
257
- const spy = subscribeSpyTo(eventStore.replaceable(0, user.pubkey));
258
- expect(spy.getValues()).toEqual([profile]);
259
- });
260
- it("should emit undefined when event is removed", () => {
261
- eventStore.add(profile);
262
- const spy = subscribeSpyTo(eventStore.replaceable(0, user.pubkey));
263
- eventStore.remove(profile);
264
- expect(spy.getValues()).toEqual([profile, undefined]);
265
- });
266
- it("should not complete when event is removed", () => {
267
- eventStore.add(profile);
268
- const spy = subscribeSpyTo(eventStore.replaceable(0, user.pubkey));
269
- eventStore.remove(profile);
270
- expect(spy.receivedComplete()).toBe(false);
271
- });
272
- it("should emit event when re-added", () => {
273
- eventStore.add(profile);
274
- const spy = subscribeSpyTo(eventStore.replaceable(0, user.pubkey));
275
- eventStore.remove(profile);
276
- eventStore.add(profile);
277
- expect(spy.getValues()).toEqual([profile, undefined, profile]);
278
- });
279
- it("should claim event", () => {
280
- eventStore.add(profile);
281
- eventStore.replaceable(0, user.pubkey).subscribe();
282
- expect(eventStore.database.isClaimed(profile)).toBe(true);
283
- });
284
- it("should remove claim when event is removed", () => {
285
- eventStore.add(profile);
286
- eventStore.replaceable(0, user.pubkey).subscribe();
287
- eventStore.remove(profile);
288
- expect(eventStore.database.isClaimed(profile)).toBe(false);
289
- });
290
- it("should ignore older events added later", () => {
291
- eventStore.add(profile);
292
- const spy = subscribeSpyTo(eventStore.replaceable(0, user.pubkey));
293
- eventStore.add(user.profile({ name: "old name" }, { created_at: profile.created_at - 500 }));
294
- eventStore.add(user.profile({ name: "really old name" }, { created_at: profile.created_at - 1000 }));
295
- expect(spy.getValues()).toEqual([profile]);
296
- });
297
- it("should emit newer events", () => {
298
- eventStore.add(profile);
299
- const spy = subscribeSpyTo(eventStore.replaceable(0, user.pubkey));
300
- const newProfile = user.profile({ name: "new name" }, { created_at: profile.created_at + 500 });
301
- eventStore.add(newProfile);
302
- expect(spy.getValues()).toEqual([profile, newProfile]);
303
- });
304
- });
305
- describe("timeline", () => {
306
- it("should emit an empty array if there are not events", () => {
307
- const spy = subscribeSpyTo(eventStore.timeline({ kinds: [1] }));
308
- expect(spy.getValues()).toEqual([[]]);
309
- });
310
- it("should emit existing events", () => {
311
- eventStore.add(profile);
312
- const spy = subscribeSpyTo(eventStore.timeline({ kinds: [0] }));
313
- expect(spy.getValues()).toEqual([[profile]]);
314
- });
315
- it("should emit new events", () => {
316
- const spy = subscribeSpyTo(eventStore.timeline({ kinds: [0, 1] }));
317
- eventStore.add(profile);
318
- eventStore.add(note);
319
- expect(spy.getValues()).toEqual([[], [profile], [note, profile]]);
320
- });
321
- it("should remove event when its removed", () => {
322
- eventStore.add(profile);
323
- const spy = subscribeSpyTo(eventStore.timeline({ kinds: [0] }));
324
- eventStore.remove(profile);
325
- expect(spy.getValues()).toEqual([[profile], []]);
326
- });
327
- it("should not emit when other events are removed", () => {
328
- eventStore.add(profile);
329
- const spy = subscribeSpyTo(eventStore.timeline({ kinds: [0] }));
330
- eventStore.add(note);
331
- eventStore.remove(note);
332
- expect(spy.getValues()).toEqual([[profile]]);
333
- });
334
- it("should ignore older events added later", () => {
335
- eventStore.add(profile);
336
- const spy = subscribeSpyTo(eventStore.timeline({ kinds: [0] }));
337
- eventStore.add(user.profile({ name: "old-name" }, { created_at: profile.created_at - 1000 }));
338
- expect(spy.getValues()).toEqual([[profile]]);
339
- });
340
- it("should return new array for every value", () => {
341
- const first = user.note("first note");
342
- const second = user.note("second note");
343
- const third = user.note("third note");
344
- eventStore.add(first);
345
- const spy = subscribeSpyTo(eventStore.timeline({ kinds: [0] }));
346
- eventStore.add(second);
347
- eventStore.add(third);
348
- const hasDuplicates = (arr) => {
349
- return new Set(arr).size !== arr.length;
350
- };
351
- expect(hasDuplicates(spy.getValues())).toBe(false);
352
- });
353
- });
354
- describe("replaceableSet", () => {
355
- it("should not emit if there are not events", () => {
356
- const spy = subscribeSpyTo(eventStore.replaceableSet([{ kind: 0, pubkey: user.pubkey }]));
357
- expect(spy.receivedNext()).toBe(false);
358
- });
359
- it("should emit existing events", () => {
360
- eventStore.add(profile);
361
- const spy = subscribeSpyTo(eventStore.replaceableSet([{ kind: 0, pubkey: user.pubkey }]));
362
- expect(spy.getValues()).toEqual([{ [getEventUID(profile)]: profile }]);
363
- });
364
- it("should remove event when removed", () => {
365
- eventStore.add(profile);
366
- const spy = subscribeSpyTo(eventStore.replaceableSet([{ kind: 0, pubkey: user.pubkey }]));
367
- eventStore.remove(profile);
368
- expect(spy.getValues()).toEqual([{ [getEventUID(profile)]: profile }, {}]);
369
- });
370
- it("should replace older events", () => {
371
- const event2 = { ...profile, created_at: profile.created_at + 100, id: "newer-event" };
372
- const uid = getEventUID(profile);
373
- eventStore.add(profile);
374
- const spy = subscribeSpyTo(eventStore.replaceableSet([{ kind: 0, pubkey: user.pubkey }]));
375
- eventStore.add(event2);
376
- expect(spy.getValues()).toEqual([{ [uid]: profile }, { [uid]: event2 }]);
377
- });
378
- it("should ignore old events added later", () => {
379
- const old = user.profile({ name: "old-name" }, { created_at: profile.created_at - 1000 });
380
- const uid = getEventUID(profile);
381
- eventStore.add(profile);
382
- const spy = subscribeSpyTo(eventStore.replaceableSet([{ kind: 0, pubkey: user.pubkey }]));
383
- eventStore.add(old);
384
- expect(spy.getValues()).toEqual([{ [uid]: profile }]);
385
- });
386
- });
@@ -1,67 +0,0 @@
1
- import { Filter, NostrEvent } from "nostr-tools";
2
- import { Subject } from "rxjs";
3
- import { LRU } from "../helpers/lru.js";
4
- /**
5
- * An in-memory database for nostr events
6
- * NOTE: does not handle replaceable events
7
- */
8
- export declare class Database {
9
- protected log: import("debug").Debugger;
10
- /** Indexes */
11
- protected kinds: Map<number, Set<import("nostr-tools").Event>>;
12
- protected authors: Map<string, Set<import("nostr-tools").Event>>;
13
- protected tags: LRU<Set<import("nostr-tools").Event>>;
14
- protected created_at: NostrEvent[];
15
- /** LRU cache of last events touched */
16
- events: LRU<import("nostr-tools").Event>;
17
- /** A sorted array of replaceable events by uid */
18
- protected replaceable: Map<string, import("nostr-tools").Event[]>;
19
- /** A stream of events inserted into the database */
20
- inserted: Subject<import("nostr-tools").Event>;
21
- /** A stream of events that have been updated */
22
- updated: Subject<import("nostr-tools").Event>;
23
- /** A stream of events removed from the database */
24
- removed: Subject<import("nostr-tools").Event>;
25
- /** A method thats called before a new event is inserted */
26
- onBeforeInsert?: (event: NostrEvent) => boolean;
27
- get size(): number;
28
- protected claims: WeakMap<import("nostr-tools").Event, any>;
29
- /** Index helper methods */
30
- protected getKindIndex(kind: number): Set<import("nostr-tools").Event>;
31
- protected getAuthorsIndex(author: string): Set<import("nostr-tools").Event>;
32
- protected getTagIndex(tagAndValue: string): Set<import("nostr-tools").Event>;
33
- /** Moves an event to the top of the LRU cache */
34
- touch(event: NostrEvent): void;
35
- /** Checks if the database contains an event without touching it */
36
- hasEvent(id: string): boolean;
37
- /** Gets a single event based on id */
38
- getEvent(id: string): NostrEvent | undefined;
39
- /** Checks if the database contains a replaceable event without touching it */
40
- hasReplaceable(kind: number, pubkey: string, d?: string): boolean;
41
- /** Gets an array of replaceable events */
42
- getReplaceable(kind: number, pubkey: string, d?: string): NostrEvent[] | undefined;
43
- /** Inserts an event into the database and notifies all subscriptions */
44
- addEvent(event: NostrEvent): NostrEvent | null;
45
- /** Inserts and event into the database and notifies all subscriptions that the event has updated */
46
- updateEvent(event: NostrEvent): boolean;
47
- /** Removes an event from the database and notifies all subscriptions */
48
- removeEvent(eventOrId: string | NostrEvent): boolean;
49
- /** Sets the claim on the event and touches it */
50
- claimEvent(event: NostrEvent, claim: any): void;
51
- /** Checks if an event is claimed by anything */
52
- isClaimed(event: NostrEvent): boolean;
53
- /** Removes a claim from an event */
54
- removeClaim(event: NostrEvent, claim: any): void;
55
- /** Removes all claims on an event */
56
- clearClaim(event: NostrEvent): void;
57
- iterateAuthors(authors: Iterable<string>): Generator<NostrEvent>;
58
- iterateTag(tag: string, values: Iterable<string>): Generator<NostrEvent>;
59
- iterateKinds(kinds: Iterable<number>): Generator<NostrEvent>;
60
- iterateTime(since: number | undefined, until: number | undefined): Generator<NostrEvent>;
61
- iterateIds(ids: Iterable<string>): Generator<NostrEvent>;
62
- /** Returns all events that match the filter */
63
- getEventsForFilter(filter: Filter): Set<NostrEvent>;
64
- getEventsForFilters(filters: Filter[]): Set<NostrEvent>;
65
- /** Remove the oldest events that are not claimed */
66
- prune(limit?: number): number;
67
- }