applesauce-core 0.0.0-next-20241103143210

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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/event-store/common.d.ts +1 -0
  4. package/dist/event-store/common.js +2 -0
  5. package/dist/event-store/database.d.ts +60 -0
  6. package/dist/event-store/database.js +294 -0
  7. package/dist/event-store/event-store.d.ts +26 -0
  8. package/dist/event-store/event-store.js +236 -0
  9. package/dist/event-store/index.d.ts +2 -0
  10. package/dist/event-store/index.js +2 -0
  11. package/dist/helpers/bolt11.d.ts +8 -0
  12. package/dist/helpers/bolt11.js +14 -0
  13. package/dist/helpers/cache.d.ts +5 -0
  14. package/dist/helpers/cache.js +17 -0
  15. package/dist/helpers/emoji.d.ts +2 -0
  16. package/dist/helpers/emoji.js +4 -0
  17. package/dist/helpers/event.d.ts +34 -0
  18. package/dist/helpers/event.js +64 -0
  19. package/dist/helpers/filter.d.ts +12 -0
  20. package/dist/helpers/filter.js +50 -0
  21. package/dist/helpers/hashtag.d.ts +2 -0
  22. package/dist/helpers/hashtag.js +7 -0
  23. package/dist/helpers/index.d.ts +16 -0
  24. package/dist/helpers/index.js +16 -0
  25. package/dist/helpers/json.d.ts +1 -0
  26. package/dist/helpers/json.js +8 -0
  27. package/dist/helpers/lru.d.ts +32 -0
  28. package/dist/helpers/lru.js +148 -0
  29. package/dist/helpers/mailboxes.d.ts +17 -0
  30. package/dist/helpers/mailboxes.js +37 -0
  31. package/dist/helpers/mailboxes.test.d.ts +1 -0
  32. package/dist/helpers/mailboxes.test.js +80 -0
  33. package/dist/helpers/pointers.d.ts +22 -0
  34. package/dist/helpers/pointers.js +127 -0
  35. package/dist/helpers/profile.d.ts +25 -0
  36. package/dist/helpers/profile.js +28 -0
  37. package/dist/helpers/relays.d.ts +12 -0
  38. package/dist/helpers/relays.js +31 -0
  39. package/dist/helpers/string.d.ts +4 -0
  40. package/dist/helpers/string.js +13 -0
  41. package/dist/helpers/tags.d.ts +6 -0
  42. package/dist/helpers/tags.js +18 -0
  43. package/dist/helpers/threading.d.ts +55 -0
  44. package/dist/helpers/threading.js +73 -0
  45. package/dist/helpers/time.d.ts +2 -0
  46. package/dist/helpers/time.js +4 -0
  47. package/dist/helpers/url.d.ts +11 -0
  48. package/dist/helpers/url.js +29 -0
  49. package/dist/helpers/zap.d.ts +12 -0
  50. package/dist/helpers/zap.js +51 -0
  51. package/dist/index.d.ts +5 -0
  52. package/dist/index.js +5 -0
  53. package/dist/logger.d.ts +2 -0
  54. package/dist/logger.js +2 -0
  55. package/dist/observable/getValue.d.ts +2 -0
  56. package/dist/observable/getValue.js +13 -0
  57. package/dist/observable/index.d.ts +2 -0
  58. package/dist/observable/index.js +2 -0
  59. package/dist/observable/share-behavior.d.ts +2 -0
  60. package/dist/observable/share-behavior.js +7 -0
  61. package/dist/observable/share-latest-value.d.ts +8 -0
  62. package/dist/observable/share-latest-value.js +21 -0
  63. package/dist/observable/stateful.d.ts +10 -0
  64. package/dist/observable/stateful.js +60 -0
  65. package/dist/observable/throttle.d.ts +3 -0
  66. package/dist/observable/throttle.js +23 -0
  67. package/dist/promise/deferred.d.ts +5 -0
  68. package/dist/promise/deferred.js +14 -0
  69. package/dist/promise/index.d.ts +1 -0
  70. package/dist/promise/index.js +1 -0
  71. package/dist/queries/index.d.ts +6 -0
  72. package/dist/queries/index.js +6 -0
  73. package/dist/queries/mailboxes.d.ts +5 -0
  74. package/dist/queries/mailboxes.js +12 -0
  75. package/dist/queries/profile.d.ts +3 -0
  76. package/dist/queries/profile.js +11 -0
  77. package/dist/queries/reactions.d.ts +4 -0
  78. package/dist/queries/reactions.js +19 -0
  79. package/dist/queries/simple.d.ts +16 -0
  80. package/dist/queries/simple.js +38 -0
  81. package/dist/queries/thread.d.ts +23 -0
  82. package/dist/queries/thread.js +66 -0
  83. package/dist/queries/zaps.d.ts +4 -0
  84. package/dist/queries/zaps.js +16 -0
  85. package/dist/query-store/index.d.ts +47 -0
  86. package/dist/query-store/index.js +60 -0
  87. package/dist/utils/lru.d.ts +32 -0
  88. package/dist/utils/lru.js +148 -0
  89. package/package.json +83 -0
@@ -0,0 +1,2 @@
1
+ export * from "./event-store.js";
2
+ export * from "./database.js";
@@ -0,0 +1,8 @@
1
+ export type ParsedInvoice = {
2
+ paymentRequest: string;
3
+ description: string;
4
+ amount?: number;
5
+ timestamp: number;
6
+ expiry: number;
7
+ };
8
+ export declare function parseBolt11(paymentRequest: string): ParsedInvoice;
@@ -0,0 +1,14 @@
1
+ import { decode } from "light-bolt11-decoder";
2
+ export function parseBolt11(paymentRequest) {
3
+ const decoded = decode(paymentRequest);
4
+ const timestamp = decoded.sections.find((s) => s.name === "timestamp")?.value ?? 0;
5
+ const description = decoded.sections.find((s) => s.name === "description")?.value ?? "";
6
+ const amount = parseInt(decoded.sections.find((s) => s.name === "amount")?.value ?? "0");
7
+ return {
8
+ paymentRequest: decoded.paymentRequest,
9
+ description: description,
10
+ amount: amount,
11
+ timestamp: timestamp,
12
+ expiry: timestamp + decoded.expiry,
13
+ };
14
+ }
@@ -0,0 +1,5 @@
1
+ import { EventTemplate, NostrEvent } from "nostr-tools";
2
+ export declare function getCachedValue<T extends unknown>(event: NostrEvent | EventTemplate, symbol: symbol): T | undefined;
3
+ export declare function setCachedValue<T extends unknown>(event: NostrEvent | EventTemplate, symbol: symbol, value: T): void;
4
+ /** Internal method used to cache computed values on events */
5
+ export declare function getOrComputeCachedValue<T extends unknown>(event: NostrEvent | EventTemplate, symbol: symbol, compute: (event: NostrEvent | EventTemplate) => T): T;
@@ -0,0 +1,17 @@
1
+ export function getCachedValue(event, symbol) {
2
+ return Reflect.get(event, symbol);
3
+ }
4
+ export function setCachedValue(event, symbol, value) {
5
+ Reflect.set(event, symbol, value);
6
+ }
7
+ /** Internal method used to cache computed values on events */
8
+ export function getOrComputeCachedValue(event, symbol, compute) {
9
+ if (Reflect.has(event, symbol)) {
10
+ return Reflect.get(event, symbol);
11
+ }
12
+ else {
13
+ const value = compute(event);
14
+ Reflect.set(event, symbol, value);
15
+ return value;
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ import { EventTemplate, NostrEvent } from "nostr-tools";
2
+ export declare function getEmojiTag(event: NostrEvent | EventTemplate, code: string): ["emoji", string, string];
@@ -0,0 +1,4 @@
1
+ export function getEmojiTag(event, code) {
2
+ code = code.replace(/^:|:$/g, "").toLocaleLowerCase();
3
+ return event.tags.filter((t) => t[0] === "emoji" && t[1] && t[2]).find((t) => t[1].toLowerCase() === code);
4
+ }
@@ -0,0 +1,34 @@
1
+ import { NostrEvent, VerifiedEvent } from "nostr-tools";
2
+ export declare const EventUIDSymbol: unique symbol;
3
+ export declare const EventIndexableTagsSymbol: unique symbol;
4
+ export declare const FromCacheSymbol: unique symbol;
5
+ declare module "nostr-tools" {
6
+ interface Event {
7
+ [EventUIDSymbol]?: string;
8
+ [EventIndexableTagsSymbol]?: Set<string>;
9
+ [FromCacheSymbol]?: boolean;
10
+ }
11
+ }
12
+ /**
13
+ * Returns if a kind is replaceable ( 10000 <= n < 20000 || n == 0 || n == 3 )
14
+ * or parameterized replaceable ( 30000 <= n < 40000 )
15
+ */
16
+ export declare function isReplaceable(kind: number): boolean;
17
+ /**
18
+ * Returns the events Unique ID
19
+ * For normal or ephemeral events this is ( event.id )
20
+ * For replaceable events this is ( event.kind + ":" + event.pubkey )
21
+ * For parametrized replaceable events this is ( event.kind + ":" + event.pubkey + ":" + event.tags.d.1 )
22
+ */
23
+ export declare function getEventUID(event: NostrEvent): string;
24
+ export declare function getReplaceableUID(kind: number, pubkey: string, d?: string): string;
25
+ /** Returns a Set of tag names and values that are indexable */
26
+ export declare function getIndexableTags(event: NostrEvent): Set<string>;
27
+ /** Returns the second index ( tag[1] ) of the first tag that matches the name */
28
+ export declare function getTagValue(event: NostrEvent, name: string): string | undefined;
29
+ /** Sets events verified flag without checking anything */
30
+ export declare function fakeVerifyEvent(event: NostrEvent): event is VerifiedEvent;
31
+ /** Marks an event as being from a cache */
32
+ export declare function markFromCache(event: NostrEvent): void;
33
+ /** Returns if an event was from a cache */
34
+ export declare function isFromCache(event: NostrEvent): boolean;
@@ -0,0 +1,64 @@
1
+ import { kinds, verifiedSymbol } from "nostr-tools";
2
+ import { INDEXABLE_TAGS } from "../event-store/common.js";
3
+ export const EventUIDSymbol = Symbol.for("event-uid");
4
+ export const EventIndexableTagsSymbol = Symbol.for("indexable-tags");
5
+ export const FromCacheSymbol = Symbol.for("from-cache");
6
+ /**
7
+ * Returns if a kind is replaceable ( 10000 <= n < 20000 || n == 0 || n == 3 )
8
+ * or parameterized replaceable ( 30000 <= n < 40000 )
9
+ */
10
+ export function isReplaceable(kind) {
11
+ return kinds.isReplaceableKind(kind) || kinds.isParameterizedReplaceableKind(kind);
12
+ }
13
+ /**
14
+ * Returns the events Unique ID
15
+ * For normal or ephemeral events this is ( event.id )
16
+ * For replaceable events this is ( event.kind + ":" + event.pubkey )
17
+ * For parametrized replaceable events this is ( event.kind + ":" + event.pubkey + ":" + event.tags.d.1 )
18
+ */
19
+ export function getEventUID(event) {
20
+ let id = event[EventUIDSymbol];
21
+ if (!id) {
22
+ if (isReplaceable(event.kind)) {
23
+ const d = event.tags.find((t) => t[0] === "d")?.[1];
24
+ id = getReplaceableUID(event.kind, event.pubkey, d);
25
+ }
26
+ else {
27
+ id = event.id;
28
+ }
29
+ }
30
+ return id;
31
+ }
32
+ export function getReplaceableUID(kind, pubkey, d) {
33
+ return d ? `${kind}:${pubkey}:${d}` : `${kind}:${pubkey}`;
34
+ }
35
+ /** Returns a Set of tag names and values that are indexable */
36
+ export function getIndexableTags(event) {
37
+ let indexable = event[EventIndexableTagsSymbol];
38
+ if (!indexable) {
39
+ const tags = new Set();
40
+ for (const tag of event.tags) {
41
+ if (tag[0] && INDEXABLE_TAGS.has(tag[0]) && tag[1]) {
42
+ tags.add(tag[0] + ":" + tag[1]);
43
+ }
44
+ }
45
+ indexable = event[EventIndexableTagsSymbol] = tags;
46
+ }
47
+ return indexable;
48
+ }
49
+ /** Returns the second index ( tag[1] ) of the first tag that matches the name */
50
+ export function getTagValue(event, name) {
51
+ return event.tags.find((t) => t[0] === name)?.[1];
52
+ }
53
+ /** Sets events verified flag without checking anything */
54
+ export function fakeVerifyEvent(event) {
55
+ return (event[verifiedSymbol] = true);
56
+ }
57
+ /** Marks an event as being from a cache */
58
+ export function markFromCache(event) {
59
+ event[FromCacheSymbol] = true;
60
+ }
61
+ /** Returns if an event was from a cache */
62
+ export function isFromCache(event) {
63
+ return !!event[FromCacheSymbol];
64
+ }
@@ -0,0 +1,12 @@
1
+ import { Filter, NostrEvent } from "nostr-tools";
2
+ /**
3
+ * Copied from nostr-tools and modified to use getIndexableTags
4
+ * @see https://github.com/nbd-wtf/nostr-tools/blob/a61cde77eacc9518001f11d7f67f1a50ae05fd80/filter.ts
5
+ */
6
+ export declare function matchFilter(filter: Filter, event: NostrEvent): boolean;
7
+ /** Copied from nostr-tools */
8
+ export declare function matchFilters(filters: Filter[], event: NostrEvent): boolean;
9
+ /** Stringify filters in a predictable way */
10
+ export declare function stringifyFilter(filter: Filter | Filter[]): string;
11
+ /** Check if two filters are equal */
12
+ export declare function isFilterEqual(a: Filter | Filter[], b: Filter | Filter[]): boolean;
@@ -0,0 +1,50 @@
1
+ import { getIndexableTags } from "./event.js";
2
+ import stringify from "json-stringify-deterministic";
3
+ /**
4
+ * Copied from nostr-tools and modified to use getIndexableTags
5
+ * @see https://github.com/nbd-wtf/nostr-tools/blob/a61cde77eacc9518001f11d7f67f1a50ae05fd80/filter.ts
6
+ */
7
+ export function matchFilter(filter, event) {
8
+ if (filter.ids && filter.ids.indexOf(event.id) === -1) {
9
+ return false;
10
+ }
11
+ if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) {
12
+ return false;
13
+ }
14
+ if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {
15
+ return false;
16
+ }
17
+ for (let f in filter) {
18
+ if (f[0] === "#") {
19
+ let tagName = f.slice(1);
20
+ let values = filter[`#${tagName}`];
21
+ if (values) {
22
+ const tags = getIndexableTags(event);
23
+ if (values.some((v) => !tags.has(tagName + ":" + v)))
24
+ return false;
25
+ }
26
+ }
27
+ }
28
+ if (filter.since && event.created_at < filter.since)
29
+ return false;
30
+ if (filter.until && event.created_at > filter.until)
31
+ return false;
32
+ return true;
33
+ }
34
+ /** Copied from nostr-tools */
35
+ export function matchFilters(filters, event) {
36
+ for (let i = 0; i < filters.length; i++) {
37
+ if (matchFilter(filters[i], event)) {
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ }
43
+ /** Stringify filters in a predictable way */
44
+ export function stringifyFilter(filter) {
45
+ return stringify(filter);
46
+ }
47
+ /** Check if two filters are equal */
48
+ export function isFilterEqual(a, b) {
49
+ return stringifyFilter(a) === stringifyFilter(b);
50
+ }
@@ -0,0 +1,2 @@
1
+ import { EventTemplate, NostrEvent } from "nostr-tools";
2
+ export declare function getHashtagTag(event: NostrEvent | EventTemplate, hashtag: string): ["t", string];
@@ -0,0 +1,7 @@
1
+ import { stripInvisibleChar } from "./string.js";
2
+ export function getHashtagTag(event, hashtag) {
3
+ hashtag = stripInvisibleChar(hashtag.replace(/^#/, "").toLocaleLowerCase());
4
+ return event.tags
5
+ .filter((t) => t[0] === "t" && t[1])
6
+ .find((t) => stripInvisibleChar(t[1].toLowerCase()) === hashtag);
7
+ }
@@ -0,0 +1,16 @@
1
+ export * from "./profile.js";
2
+ export * from "./relays.js";
3
+ export * from "./event.js";
4
+ export * from "./filter.js";
5
+ export * from "./mailboxes.js";
6
+ export * from "./threading.js";
7
+ export * from "./pointers.js";
8
+ export * from "./string.js";
9
+ export * from "./time.js";
10
+ export * from "./tags.js";
11
+ export * from "./emoji.js";
12
+ export * from "./lru.js";
13
+ export * from "./hashtag.js";
14
+ export * from "./url.js";
15
+ export * from "./zap.js";
16
+ export * from "./bolt11.js";
@@ -0,0 +1,16 @@
1
+ export * from "./profile.js";
2
+ export * from "./relays.js";
3
+ export * from "./event.js";
4
+ export * from "./filter.js";
5
+ export * from "./mailboxes.js";
6
+ export * from "./threading.js";
7
+ export * from "./pointers.js";
8
+ export * from "./string.js";
9
+ export * from "./time.js";
10
+ export * from "./tags.js";
11
+ export * from "./emoji.js";
12
+ export * from "./lru.js";
13
+ export * from "./hashtag.js";
14
+ export * from "./url.js";
15
+ export * from "./zap.js";
16
+ export * from "./bolt11.js";
@@ -0,0 +1 @@
1
+ export declare function safeParse<T extends unknown = any>(str: string): T | undefined;
@@ -0,0 +1,8 @@
1
+ export function safeParse(str) {
2
+ try {
3
+ return JSON.parse(str);
4
+ }
5
+ catch (error) {
6
+ return undefined;
7
+ }
8
+ }
@@ -0,0 +1,32 @@
1
+ type Item<T> = {
2
+ key: string;
3
+ prev: Item<T> | null;
4
+ value: T;
5
+ next: Item<T> | null;
6
+ expiry: number;
7
+ };
8
+ /**
9
+ * Copied from tiny-lru and modified to support typescript
10
+ * @see https://github.com/avoidwork/tiny-lru/blob/master/src/lru.js
11
+ */
12
+ export declare class LRU<T extends unknown> {
13
+ first: Item<T> | null;
14
+ items: Record<string, Item<T>>;
15
+ last: Item<T> | null;
16
+ max: number;
17
+ resetTtl: boolean;
18
+ size: number;
19
+ ttl: number;
20
+ constructor(max?: number, ttl?: number, resetTtl?: boolean);
21
+ clear(): this;
22
+ delete(key: string): this;
23
+ entries(keys?: string[]): (string | T | undefined)[][];
24
+ evict(bypass?: boolean): this;
25
+ expiresAt(key: string): number | undefined;
26
+ get(key: string): T | undefined;
27
+ has(key: string): boolean;
28
+ keys(): string[];
29
+ set(key: string, value: T, bypass?: boolean, resetTtl?: boolean): this;
30
+ values(keys?: string[]): NonNullable<T>[];
31
+ }
32
+ export {};
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Copied from tiny-lru and modified to support typescript
3
+ * @see https://github.com/avoidwork/tiny-lru/blob/master/src/lru.js
4
+ */
5
+ export class LRU {
6
+ first = null;
7
+ items = Object.create(null);
8
+ last = null;
9
+ max;
10
+ resetTtl;
11
+ size;
12
+ ttl;
13
+ constructor(max = 0, ttl = 0, resetTtl = false) {
14
+ this.first = null;
15
+ this.items = Object.create(null);
16
+ this.last = null;
17
+ this.max = max;
18
+ this.resetTtl = resetTtl;
19
+ this.size = 0;
20
+ this.ttl = ttl;
21
+ }
22
+ clear() {
23
+ this.first = null;
24
+ this.items = Object.create(null);
25
+ this.last = null;
26
+ this.size = 0;
27
+ return this;
28
+ }
29
+ delete(key) {
30
+ if (this.has(key)) {
31
+ const item = this.items[key];
32
+ delete this.items[key];
33
+ this.size--;
34
+ if (item.prev !== null) {
35
+ item.prev.next = item.next;
36
+ }
37
+ if (item.next !== null) {
38
+ item.next.prev = item.prev;
39
+ }
40
+ if (this.first === item) {
41
+ this.first = item.next;
42
+ }
43
+ if (this.last === item) {
44
+ this.last = item.prev;
45
+ }
46
+ }
47
+ return this;
48
+ }
49
+ entries(keys = this.keys()) {
50
+ return keys.map((key) => [key, this.get(key)]);
51
+ }
52
+ evict(bypass = false) {
53
+ if (bypass || this.size > 0) {
54
+ const item = this.first;
55
+ delete this.items[item.key];
56
+ if (--this.size === 0) {
57
+ this.first = null;
58
+ this.last = null;
59
+ }
60
+ else {
61
+ this.first = item.next;
62
+ this.first.prev = null;
63
+ }
64
+ }
65
+ return this;
66
+ }
67
+ expiresAt(key) {
68
+ let result;
69
+ if (this.has(key)) {
70
+ result = this.items[key].expiry;
71
+ }
72
+ return result;
73
+ }
74
+ get(key) {
75
+ let result;
76
+ if (this.has(key)) {
77
+ const item = this.items[key];
78
+ if (this.ttl > 0 && item.expiry <= Date.now()) {
79
+ this.delete(key);
80
+ }
81
+ else {
82
+ result = item.value;
83
+ this.set(key, result, true);
84
+ }
85
+ }
86
+ return result;
87
+ }
88
+ has(key) {
89
+ return key in this.items;
90
+ }
91
+ keys() {
92
+ const result = [];
93
+ let x = this.first;
94
+ while (x !== null) {
95
+ result.push(x.key);
96
+ x = x.next;
97
+ }
98
+ return result;
99
+ }
100
+ set(key, value, bypass = false, resetTtl = this.resetTtl) {
101
+ let item;
102
+ if (bypass || this.has(key)) {
103
+ item = this.items[key];
104
+ item.value = value;
105
+ if (bypass === false && resetTtl) {
106
+ item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
107
+ }
108
+ if (this.last !== item) {
109
+ const last = this.last, next = item.next, prev = item.prev;
110
+ if (this.first === item) {
111
+ this.first = item.next;
112
+ }
113
+ item.next = null;
114
+ item.prev = this.last;
115
+ last.next = item;
116
+ if (prev !== null) {
117
+ prev.next = next;
118
+ }
119
+ if (next !== null) {
120
+ next.prev = prev;
121
+ }
122
+ }
123
+ }
124
+ else {
125
+ if (this.max > 0 && this.size === this.max) {
126
+ this.evict(true);
127
+ }
128
+ item = this.items[key] = {
129
+ expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
130
+ key: key,
131
+ prev: this.last,
132
+ next: null,
133
+ value,
134
+ };
135
+ if (++this.size === 1) {
136
+ this.first = item;
137
+ }
138
+ else {
139
+ this.last.next = item;
140
+ }
141
+ }
142
+ this.last = item;
143
+ return this;
144
+ }
145
+ values(keys = this.keys()) {
146
+ return keys.map((key) => this.get(key));
147
+ }
148
+ }
@@ -0,0 +1,17 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ export declare const MailboxesInboxesSymbol: unique symbol;
3
+ export declare const MailboxesOutboxesSymbol: unique symbol;
4
+ declare module "nostr-tools" {
5
+ interface Event {
6
+ [MailboxesInboxesSymbol]?: string[];
7
+ [MailboxesOutboxesSymbol]?: string[];
8
+ }
9
+ }
10
+ /**
11
+ * Parses a 10002 event and stores the inboxes in the event using the {@link MailboxesInboxesSymbol} symbol
12
+ */
13
+ export declare function getInboxes(event: NostrEvent): string[];
14
+ /**
15
+ * Parses a 10002 event and stores the outboxes in the event using the {@link MailboxesOutboxesSymbol} symbol
16
+ */
17
+ export declare function getOutboxes(event: NostrEvent): string[];
@@ -0,0 +1,37 @@
1
+ import { safeRelayUrl } from "./relays.js";
2
+ export const MailboxesInboxesSymbol = Symbol.for("mailboxes-inboxes");
3
+ export const MailboxesOutboxesSymbol = Symbol.for("mailboxes-outboxes");
4
+ /**
5
+ * Parses a 10002 event and stores the inboxes in the event using the {@link MailboxesInboxesSymbol} symbol
6
+ */
7
+ export function getInboxes(event) {
8
+ if (!event[MailboxesInboxesSymbol]) {
9
+ const inboxes = [];
10
+ for (const tag of event.tags) {
11
+ if (tag[0] === "r" && tag[1] && (tag[2] === "read" || tag[2] === undefined)) {
12
+ const url = safeRelayUrl(tag[1]);
13
+ if (url && !inboxes.includes(url))
14
+ inboxes.push(url);
15
+ }
16
+ }
17
+ event[MailboxesInboxesSymbol] = inboxes;
18
+ }
19
+ return event[MailboxesInboxesSymbol];
20
+ }
21
+ /**
22
+ * Parses a 10002 event and stores the outboxes in the event using the {@link MailboxesOutboxesSymbol} symbol
23
+ */
24
+ export function getOutboxes(event) {
25
+ if (!event[MailboxesOutboxesSymbol]) {
26
+ const outboxes = [];
27
+ for (const tag of event.tags) {
28
+ if (tag[0] === "r" && tag[1] && (tag[2] === "write" || tag[2] === undefined)) {
29
+ const url = safeRelayUrl(tag[1]);
30
+ if (url && !outboxes.includes(url))
31
+ outboxes.push(url);
32
+ }
33
+ }
34
+ event[MailboxesOutboxesSymbol] = outboxes;
35
+ }
36
+ return event[MailboxesOutboxesSymbol];
37
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ import { getInboxes, getOutboxes } from "./mailboxes.js";
2
+ const emptyEvent = {
3
+ kind: 10002,
4
+ content: "",
5
+ tags: [],
6
+ created_at: 0,
7
+ sig: "",
8
+ id: "",
9
+ pubkey: "",
10
+ };
11
+ describe("Mailboxes", () => {
12
+ describe("getInboxes", () => {
13
+ test("should transform urls", () => {
14
+ expect(Array.from(getInboxes({
15
+ ...emptyEvent,
16
+ tags: [["r", "wss://inbox.com"]],
17
+ }))).toIncludeAllMembers(["wss://inbox.com/"]);
18
+ });
19
+ test("should remove bad urls", () => {
20
+ expect(Array.from(getInboxes({
21
+ ...emptyEvent,
22
+ tags: [["r", "bad://inbox.com"]],
23
+ }))).toBeArrayOfSize(0);
24
+ expect(Array.from(getInboxes({
25
+ ...emptyEvent,
26
+ tags: [["r", "something that is not a url"]],
27
+ }))).toBeArrayOfSize(0);
28
+ expect(Array.from(getInboxes({
29
+ ...emptyEvent,
30
+ tags: [["r", "wss://inbox.com,wss://inbox.org"]],
31
+ }))).toBeArrayOfSize(0);
32
+ });
33
+ test("without marker", () => {
34
+ expect(Array.from(getInboxes({
35
+ ...emptyEvent,
36
+ tags: [["r", "wss://inbox.com/"]],
37
+ }))).toIncludeAllMembers(["wss://inbox.com/"]);
38
+ });
39
+ test("with marker", () => {
40
+ expect(Array.from(getInboxes({
41
+ ...emptyEvent,
42
+ tags: [["r", "wss://inbox.com/", "read"]],
43
+ }))).toIncludeAllMembers(["wss://inbox.com/"]);
44
+ });
45
+ });
46
+ describe("getOutboxes", () => {
47
+ test("should transform urls", () => {
48
+ expect(Array.from(getOutboxes({
49
+ ...emptyEvent,
50
+ tags: [["r", "wss://outbox.com"]],
51
+ }))).toIncludeAllMembers(["wss://outbox.com/"]);
52
+ });
53
+ test("should remove bad urls", () => {
54
+ expect(Array.from(getOutboxes({
55
+ ...emptyEvent,
56
+ tags: [["r", "bad://inbox.com"]],
57
+ }))).toBeArrayOfSize(0);
58
+ expect(Array.from(getOutboxes({
59
+ ...emptyEvent,
60
+ tags: [["r", "something that is not a url"]],
61
+ }))).toBeArrayOfSize(0);
62
+ expect(Array.from(getOutboxes({
63
+ ...emptyEvent,
64
+ tags: [["r", "wss://outbox.com,wss://inbox.org"]],
65
+ }))).toBeArrayOfSize(0);
66
+ });
67
+ test("without marker", () => {
68
+ expect(Array.from(getOutboxes({
69
+ ...emptyEvent,
70
+ tags: [["r", "wss://outbox.com/"]],
71
+ }))).toIncludeAllMembers(["wss://outbox.com/"]);
72
+ });
73
+ test("with marker", () => {
74
+ expect(Array.from(getOutboxes({
75
+ ...emptyEvent,
76
+ tags: [["r", "wss://outbox.com/", "write"]],
77
+ }))).toIncludeAllMembers(["wss://outbox.com/"]);
78
+ });
79
+ });
80
+ });
@@ -0,0 +1,22 @@
1
+ import { AddressPointer, DecodeResult, EventPointer, ProfilePointer } from "nostr-tools/nip19";
2
+ export type AddressPointerWithoutD = Omit<AddressPointer, "identifier"> & {
3
+ identifier?: string;
4
+ };
5
+ export declare function parseCoordinate(a: string): AddressPointerWithoutD | null;
6
+ export declare function parseCoordinate(a: string, requireD: false): AddressPointerWithoutD | null;
7
+ export declare function parseCoordinate(a: string, requireD: true): AddressPointer | null;
8
+ export declare function parseCoordinate(a: string, requireD: false, silent: false): AddressPointerWithoutD;
9
+ export declare function parseCoordinate(a: string, requireD: true, silent: false): AddressPointer;
10
+ export declare function parseCoordinate(a: string, requireD: true, silent: true): AddressPointer | null;
11
+ export declare function parseCoordinate(a: string, requireD: false, silent: true): AddressPointerWithoutD | null;
12
+ export declare function getPubkeyFromDecodeResult(result?: DecodeResult): string | undefined;
13
+ export declare function encodeDecodeResult(result: DecodeResult): "" | `nsec1${string}` | `npub1${string}` | `note1${string}` | `nprofile1${string}` | `nevent1${string}` | `naddr1${string}` | `nrelay1${string}`;
14
+ export declare function getEventPointerFromTag(tag: string[]): EventPointer;
15
+ export declare function getAddressPointerFromTag(tag: string[]): AddressPointer;
16
+ export declare function getProfilePointerFromTag(tag: string[]): ProfilePointer;
17
+ export declare function getPointerFromTag(tag: string[]): DecodeResult | null;
18
+ export declare function isAddressPointer(pointer: DecodeResult["data"]): pointer is AddressPointer;
19
+ export declare function isEventPointer(pointer: DecodeResult["data"]): pointer is EventPointer;
20
+ export declare function getCoordinateFromAddressPointer(pointer: AddressPointer): string;
21
+ export declare function getATagFromAddressPointer(pointer: AddressPointer): ["a", ...string[]];
22
+ export declare function getETagFromEventPointer(pointer: EventPointer): ["e", ...string[]];