@qntx/nostr 0.1.0 → 0.2.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 (185) hide show
  1. package/dist/abort-Ba8tDrOI.mjs +38 -0
  2. package/dist/abort-Ba8tDrOI.mjs.map +1 -0
  3. package/dist/{builder-BphJa-Y-.d.mts → builder-BWn55Paf.d.mts} +20 -14
  4. package/dist/{builder-q0VsvnYE.mjs → builder-CyrGKRVP.mjs} +32 -16
  5. package/dist/builder-CyrGKRVP.mjs.map +1 -0
  6. package/dist/{client-Bd8B1mYm.mjs → client-BWsX9Cv1.mjs} +354 -195
  7. package/dist/client-BWsX9Cv1.mjs.map +1 -0
  8. package/dist/client.d.mts +1 -1
  9. package/dist/client.mjs +1 -1
  10. package/dist/core.d.mts +8 -8
  11. package/dist/core.mjs +8 -9
  12. package/dist/error-BW7re1UN.d.mts +9 -0
  13. package/dist/error-B__OMBRY.mjs +14 -0
  14. package/dist/error-B__OMBRY.mjs.map +1 -0
  15. package/dist/{error-WEFS-R-4.d.mts → error-CR8Urc84.d.mts} +20 -8
  16. package/dist/{error-CwBxle6N.mjs → error-DrEIM7FO.mjs} +5 -3
  17. package/dist/error-DrEIM7FO.mjs.map +1 -0
  18. package/dist/{event-CzoQEFMF.mjs → event-D8Nfoh4K.mjs} +40 -32
  19. package/dist/event-D8Nfoh4K.mjs.map +1 -0
  20. package/dist/{event-B5D2jxt_.d.mts → event-fU3Y01PR.d.mts} +23 -20
  21. package/dist/{filter-BxwjEkZp.mjs → filter-BQl3GlHt.mjs} +42 -35
  22. package/dist/filter-BQl3GlHt.mjs.map +1 -0
  23. package/dist/filter-C0IMByE3.d.mts +37 -0
  24. package/dist/{gossip-C5RVB1UB.d.mts → gossip-BRQwIM_q.d.mts} +25 -23
  25. package/dist/{gossip-3xkRRCm_.mjs → gossip-oloDMWEj.mjs} +52 -34
  26. package/dist/gossip-oloDMWEj.mjs.map +1 -0
  27. package/dist/gossip.d.mts +1 -1
  28. package/dist/gossip.mjs +1 -1
  29. package/dist/{http-6vevbBlu.d.mts → http-C4HwIu4B.d.mts} +7 -7
  30. package/dist/{http-D2rhokZo.mjs → http-CuazNRIP.mjs} +10 -6
  31. package/dist/http-CuazNRIP.mjs.map +1 -0
  32. package/dist/index-B425CAcQ.d.mts +328 -0
  33. package/dist/index-BVyfUBuG.d.mts +181 -0
  34. package/dist/{index-BYMnhRIC.d.mts → index-Ba7bJ7DD.d.mts} +68 -50
  35. package/dist/{index-DaRyjo7O.d.mts → index-Boe8FshM.d.mts} +13 -7
  36. package/dist/index-CUIvFQdE.d.mts +73 -0
  37. package/dist/index-JdaS_uce.d.mts +207 -0
  38. package/dist/index.d.mts +22 -20
  39. package/dist/index.mjs +19 -18
  40. package/dist/{key-Dn-aX4x4.mjs → key-Bbtys6o7.mjs} +22 -14
  41. package/dist/key-Bbtys6o7.mjs.map +1 -0
  42. package/dist/{key-BiGxGLhg.d.mts → key-BlsYhN1V.d.mts} +9 -6
  43. package/dist/{kind-BLl4cLOc.mjs → kind-Cxwhhkx8.mjs} +2 -1
  44. package/dist/kind-Cxwhhkx8.mjs.map +1 -0
  45. package/dist/{loaders-BNQszDAn.mjs → loaders-o6YXB_Ri.mjs} +329 -305
  46. package/dist/loaders-o6YXB_Ri.mjs.map +1 -0
  47. package/dist/loaders.d.mts +3 -3
  48. package/dist/loaders.mjs +2 -2
  49. package/dist/memory-C2EVx0_O.mjs +46 -0
  50. package/dist/memory-C2EVx0_O.mjs.map +1 -0
  51. package/dist/{memory-BCmhZPek.mjs → memory-index-Do1mz0WF.mjs} +212 -82
  52. package/dist/memory-index-Do1mz0WF.mjs.map +1 -0
  53. package/dist/{message-C_Uj-Y-c.mjs → message-DcY6Fi9o.mjs} +38 -24
  54. package/dist/message-DcY6Fi9o.mjs.map +1 -0
  55. package/dist/{message-DJC-Jz6T.d.mts → message-iGPIqnn0.d.mts} +15 -8
  56. package/dist/{nip17-BWq-Kfq5.d.mts → nip17-DNEkz8rM.d.mts} +18 -17
  57. package/dist/{nip19-D7905oIv.d.mts → nip19-BevCJZsp.d.mts} +23 -3
  58. package/dist/{nip46-C_DoxiS_.d.mts → nip46-DDV4dC56.d.mts} +13 -12
  59. package/dist/{nip59-DljW_sYh.d.mts → nip59-zQgdLcEr.d.mts} +28 -25
  60. package/dist/{nip65-Di5hZRuV.d.mts → nip65-DBfh2smt.d.mts} +8 -3
  61. package/dist/{nip77-ByxlgoQO.d.mts → nip77-DH4RhS5r.d.mts} +9 -8
  62. package/dist/nips/blossom.d.mts +37 -37
  63. package/dist/nips/blossom.mjs +67 -52
  64. package/dist/nips/blossom.mjs.map +1 -1
  65. package/dist/nips/nip04.d.mts +2 -3
  66. package/dist/nips/nip04.mjs +6 -10
  67. package/dist/nips/nip04.mjs.map +1 -1
  68. package/dist/nips/nip05.d.mts +37 -43
  69. package/dist/nips/nip05.mjs +57 -57
  70. package/dist/nips/nip05.mjs.map +1 -1
  71. package/dist/nips/nip10.d.mts +18 -19
  72. package/dist/nips/nip10.mjs +76 -61
  73. package/dist/nips/nip10.mjs.map +1 -1
  74. package/dist/nips/nip11.d.mts +9 -8
  75. package/dist/nips/nip11.mjs +14 -11
  76. package/dist/nips/nip11.mjs.map +1 -1
  77. package/dist/nips/nip13.d.mts +9 -9
  78. package/dist/nips/nip13.mjs +15 -17
  79. package/dist/nips/nip13.mjs.map +1 -1
  80. package/dist/nips/nip17.d.mts +1 -1
  81. package/dist/nips/nip17.mjs +17 -12
  82. package/dist/nips/nip17.mjs.map +1 -1
  83. package/dist/nips/nip19.d.mts +1 -1
  84. package/dist/nips/nip19.mjs +52 -29
  85. package/dist/nips/nip19.mjs.map +1 -1
  86. package/dist/nips/nip21.d.mts +5 -6
  87. package/dist/nips/nip21.mjs +8 -7
  88. package/dist/nips/nip21.mjs.map +1 -1
  89. package/dist/nips/nip27.d.mts +7 -8
  90. package/dist/nips/nip27.mjs +26 -25
  91. package/dist/nips/nip27.mjs.map +1 -1
  92. package/dist/nips/nip42.d.mts +5 -6
  93. package/dist/nips/nip42.mjs +3 -3
  94. package/dist/nips/nip42.mjs.map +1 -1
  95. package/dist/nips/nip44.d.mts +24 -7
  96. package/dist/nips/nip44.mjs +25 -15
  97. package/dist/nips/nip44.mjs.map +1 -1
  98. package/dist/nips/nip46.d.mts +1 -1
  99. package/dist/nips/nip46.mjs +52 -49
  100. package/dist/nips/nip46.mjs.map +1 -1
  101. package/dist/nips/nip49.d.mts +8 -7
  102. package/dist/nips/nip49.mjs +16 -12
  103. package/dist/nips/nip49.mjs.map +1 -1
  104. package/dist/nips/nip51.d.mts +25 -27
  105. package/dist/nips/nip51.mjs +47 -36
  106. package/dist/nips/nip51.mjs.map +1 -1
  107. package/dist/nips/nip57.d.mts +12 -13
  108. package/dist/nips/nip57.mjs +35 -38
  109. package/dist/nips/nip57.mjs.map +1 -1
  110. package/dist/nips/nip59.d.mts +1 -1
  111. package/dist/nips/nip59.mjs +14 -18
  112. package/dist/nips/nip59.mjs.map +1 -1
  113. package/dist/nips/nip65.d.mts +1 -1
  114. package/dist/nips/nip65.mjs +11 -8
  115. package/dist/nips/nip65.mjs.map +1 -1
  116. package/dist/nips/nip77.d.mts +1 -1
  117. package/dist/nips/nip77.mjs +56 -34
  118. package/dist/nips/nip77.mjs.map +1 -1
  119. package/dist/nips/nip96.d.mts +21 -12
  120. package/dist/nips/nip96.mjs +59 -36
  121. package/dist/nips/nip96.mjs.map +1 -1
  122. package/dist/nips/nip98.d.mts +12 -12
  123. package/dist/nips/nip98.mjs +18 -19
  124. package/dist/nips/nip98.mjs.map +1 -1
  125. package/dist/{pool-C_j1OmBB.mjs → pool-XmAGaufS.mjs} +611 -487
  126. package/dist/pool-XmAGaufS.mjs.map +1 -0
  127. package/dist/pool-tEr7c5bG.d.mts +302 -0
  128. package/dist/reactive-DDlThDSZ.mjs +324 -0
  129. package/dist/reactive-DDlThDSZ.mjs.map +1 -0
  130. package/dist/reactive-DFpqtIf_.d.mts +66 -0
  131. package/dist/relay.d.mts +5 -4
  132. package/dist/relay.mjs +2 -2
  133. package/dist/report-CHld4uWj.mjs +32 -0
  134. package/dist/report-CHld4uWj.mjs.map +1 -0
  135. package/dist/{signer-CZ6K6FUc.mjs → signer-CKR9EHce.mjs} +107 -72
  136. package/dist/signer-CKR9EHce.mjs.map +1 -0
  137. package/dist/signer.d.mts +3 -3
  138. package/dist/signer.mjs +3 -2
  139. package/dist/storage-xXxLGCVb.mjs +1376 -0
  140. package/dist/storage-xXxLGCVb.mjs.map +1 -0
  141. package/dist/storage.d.mts +4 -4
  142. package/dist/storage.mjs +5 -4
  143. package/dist/store.d.mts +2 -0
  144. package/dist/store.mjs +2 -0
  145. package/dist/testing.d.mts +125 -0
  146. package/dist/testing.mjs +957 -0
  147. package/dist/testing.mjs.map +1 -0
  148. package/dist/types-2pCUprRU.d.mts +47 -0
  149. package/dist/types-CRQEk0Oi.d.mts +19 -0
  150. package/dist/util-LfQirgDk.mjs +113 -0
  151. package/dist/util-LfQirgDk.mjs.map +1 -0
  152. package/dist/wasm.d.mts +4 -4
  153. package/dist/wasm.mjs +54 -55
  154. package/dist/wasm.mjs.map +1 -1
  155. package/dist/websocket-CmeqvAkp.d.mts +27 -0
  156. package/package.json +31 -9
  157. package/dist/builder-q0VsvnYE.mjs.map +0 -1
  158. package/dist/client-Bd8B1mYm.mjs.map +0 -1
  159. package/dist/error-B49rbDzT.d.mts +0 -7
  160. package/dist/error-CwBxle6N.mjs.map +0 -1
  161. package/dist/error-DZEs5OuZ.mjs +0 -24
  162. package/dist/error-DZEs5OuZ.mjs.map +0 -1
  163. package/dist/event-CzoQEFMF.mjs.map +0 -1
  164. package/dist/filter-BxwjEkZp.mjs.map +0 -1
  165. package/dist/filter-DUEKP3q1.d.mts +0 -40
  166. package/dist/gossip-3xkRRCm_.mjs.map +0 -1
  167. package/dist/http-D2rhokZo.mjs.map +0 -1
  168. package/dist/index-C0C4e-Gn.d.mts +0 -55
  169. package/dist/index-DgOugrpF.d.mts +0 -275
  170. package/dist/index-EwL6fHLo.d.mts +0 -267
  171. package/dist/index-k2YhCgsh.d.mts +0 -57
  172. package/dist/key-Dn-aX4x4.mjs.map +0 -1
  173. package/dist/kind-BLl4cLOc.mjs.map +0 -1
  174. package/dist/loaders-BNQszDAn.mjs.map +0 -1
  175. package/dist/memory-BCmhZPek.mjs.map +0 -1
  176. package/dist/message-C_Uj-Y-c.mjs.map +0 -1
  177. package/dist/pool-C_j1OmBB.mjs.map +0 -1
  178. package/dist/pool-DhRi7l-b.d.mts +0 -297
  179. package/dist/signer-CZ6K6FUc.mjs.map +0 -1
  180. package/dist/storage-DOy0iLRE.mjs +0 -870
  181. package/dist/storage-DOy0iLRE.mjs.map +0 -1
  182. package/dist/types-BzyADqnw.d.mts +0 -19
  183. package/dist/types-Dn24TPFs.d.mts +0 -43
  184. package/dist/util-6tfLQ9JF.mjs +0 -73
  185. package/dist/util-6tfLQ9JF.mjs.map +0 -1
@@ -1,10 +1,13 @@
1
1
  //#region src/core/tag.d.ts
2
2
  /** A NIP-01 tag: first element is the name, rest are values. */
3
- type Tag = readonly string[];
3
+ type Tag = ReadonlyArray<string>;
4
4
  /** Mutable tag builder input. */
5
5
  type TagInput = string[];
6
+ /** Type guard: a non-empty array of strings. */
6
7
  declare function isTag(value: unknown): value is Tag;
8
+ /** First element of a tag (its name). */
7
9
  declare function tagName(tag: Tag): string;
10
+ /** Second element of a tag (its primary value), or undefined for a bare name tag. */
8
11
  declare function tagValue(tag: Tag): string | undefined;
9
12
  /** Construct common tags. */
10
13
  declare const Tag: {
@@ -17,7 +20,7 @@ declare const Tag: {
17
20
  readonly k: (kind: number | string) => Tag;
18
21
  };
19
22
  /** First `d` tag value on an event, if any. */
20
- declare function getDTag(tags: readonly Tag[]): string | undefined;
23
+ declare function getDTag(tags: ReadonlyArray<Tag>): string | undefined;
21
24
  /** NIP-01 `a` tag: `kind:pubkey:identifier` (identifier may be empty and may contain extra colons). */
22
25
  type EventAddress = {
23
26
  kind: number;
@@ -26,22 +29,23 @@ type EventAddress = {
26
29
  };
27
30
  /** Parse a NIP-01 addressable/replaceable coordinate. */
28
31
  declare function parseEventAddress(value: string): EventAddress | undefined;
32
+ /** Format an address as a `kind:pubkey:dTag` coordinate string. */
29
33
  declare function formatEventAddress(kind: number, pubkey: string, identifier?: string): string;
30
34
  /**
31
- * Coordinate for replaceable (`kind:pubkey:`) and addressable (`kind:pubkey:d`) events.
32
- * Undefined for regular/ephemeral kinds.
35
+ * Coordinate for replaceable (`kind:pubkey:`) and addressable (`kind:pubkey:d`) events. Undefined
36
+ * for regular/ephemeral kinds.
33
37
  */
34
38
  declare function eventAddress(event: {
35
39
  kind: number;
36
40
  pubkey: string;
37
- tags: readonly Tag[];
41
+ tags: ReadonlyArray<Tag>;
38
42
  }): string | undefined;
39
43
  //#endregion
40
44
  //#region src/core/event.d.ts
41
45
  /** Wire event template before pubkey/id/sig. */
42
46
  type EventTemplate = {
43
47
  readonly kind: number;
44
- readonly tags: readonly Tag[];
48
+ readonly tags: ReadonlyArray<Tag>;
45
49
  readonly content: string;
46
50
  readonly created_at: number;
47
51
  };
@@ -50,8 +54,8 @@ type UnsignedEvent = EventTemplate & {
50
54
  readonly pubkey: string;
51
55
  };
52
56
  /**
53
- * Fully formed NIP-01 event (JSON-friendly plain object).
54
- * Fields are readonly at the type level; wire interop remains plain JSON.
57
+ * Fully formed NIP-01 event (JSON-friendly plain object). Fields are readonly at the type level;
58
+ * wire interop remains plain JSON.
55
59
  */
56
60
  type Event = UnsignedEvent & {
57
61
  readonly id: string;
@@ -59,29 +63,28 @@ type Event = UnsignedEvent & {
59
63
  };
60
64
  declare function markVerified(event: Event): void;
61
65
  declare function markUnverified(event: Event): void;
62
- declare function isMarkedVerified(event: Event): boolean;
63
66
  declare function isMarkedFailed(event: Event): boolean;
64
67
  /** Structural validation of an unsigned event (no crypto). */
65
68
  declare function validateEvent(event: unknown): event is UnsignedEvent;
66
69
  /** Structural validation of a full event including id and sig hex shape. */
67
70
  declare function validateSignedEvent(event: unknown): event is Event;
68
71
  /**
69
- * Canonical NIP-01 serialization used for hashing:
70
- * JSON array `[0, pubkey, created_at, kind, tags, content]` with no extra whitespace.
72
+ * Canonical NIP-01 serialization used for hashing: JSON array `[0, pubkey, created_at, kind, tags,
73
+ * content]` with no extra whitespace.
71
74
  */
72
75
  declare function serializeEvent(event: UnsignedEvent): string;
73
76
  /** SHA-256 of the canonical serialization, lowercase hex. */
74
77
  declare function getEventHash(event: UnsignedEvent): string;
75
78
  /**
76
- * Sort events reverse-chronologically by `created_at`, then by `id` lexicographically.
77
- * Mutates and returns the array.
79
+ * Sort events reverse-chronologically by `created_at`, then by `id` lexicographically. Mutates and
80
+ * returns the array.
78
81
  */
79
82
  declare function sortEvents(events: Event[]): Event[];
80
83
  /** Non-mutating sort; returns a new array. */
81
- declare function sortedEvents(events: readonly Event[]): Event[];
84
+ declare function sortedEvents(events: ReadonlyArray<Event>): Event[];
82
85
  /**
83
- * Negentropy item order: `created_at` ascending, then `id` lexicographic (`<`/`>`).
84
- * Time axis is opposite {@link sortEvents}; id tie-break is the same direction.
86
+ * Negentropy item order: `created_at` ascending, then `id` lexicographic (`<`/`>`). Time axis is
87
+ * opposite {@link sortEvents}; id tie-break is the same direction.
85
88
  */
86
89
  declare function itemCompare(a: {
87
90
  id: string;
@@ -91,8 +94,8 @@ declare function itemCompare(a: {
91
94
  created_at: number;
92
95
  }): number;
93
96
  /**
94
- * NIP-01 replaceable/addressable winner: higher `created_at`, or equal timestamp
95
- * and lexicographically lower `id`.
97
+ * NIP-01 replaceable/addressable winner: higher `created_at`, or equal timestamp and
98
+ * lexicographically lower `id`.
96
99
  */
97
100
  declare function isReplaceableWinner(candidate: {
98
101
  created_at: number;
@@ -104,5 +107,5 @@ declare function isReplaceableWinner(candidate: {
104
107
  /** True when a signed event is the signed form of `unsigned` (kind/tags/content/time/pubkey). */
105
108
  declare function signedMatchesUnsigned(signed: Event, unsigned: UnsignedEvent): boolean;
106
109
  //#endregion
107
- export { isTag as C, tagValue as E, getDTag as S, tagName as T, EventAddress as _, isMarkedFailed as a, eventAddress as b, itemCompare as c, serializeEvent as d, signedMatchesUnsigned as f, validateSignedEvent as g, validateEvent as h, getEventHash as i, markUnverified as l, sortedEvents as m, EventTemplate as n, isMarkedVerified as o, sortEvents as p, UnsignedEvent as r, isReplaceableWinner as s, Event as t, markVerified as u, Tag as v, parseEventAddress as w, formatEventAddress as x, TagInput as y };
108
- //# sourceMappingURL=event-B5D2jxt_.d.mts.map
110
+ export { parseEventAddress as C, isTag as S, tagValue as T, Tag as _, isMarkedFailed as a, formatEventAddress as b, markUnverified as c, signedMatchesUnsigned as d, sortEvents as f, EventAddress as g, validateSignedEvent as h, getEventHash as i, markVerified as l, validateEvent as m, EventTemplate as n, isReplaceableWinner as o, sortedEvents as p, UnsignedEvent as r, itemCompare as s, Event as t, serializeEvent as u, TagInput as v, tagName as w, getDTag as x, eventAddress as y };
111
+ //# sourceMappingURL=event-fU3Y01PR.d.mts.map
@@ -1,26 +1,28 @@
1
- import { o as isReplaceableKind, r as isAddressableKind } from "./kind-BLl4cLOc.mjs";
1
+ import { o as isReplaceableKind, r as isAddressableKind } from "./kind-Cxwhhkx8.mjs";
2
2
  //#region src/core/filter.ts
3
3
  /** Local NIP-01 match. `search` is ignored; relays interpret NIP-50. */
4
4
  function matchFilter(filter, event) {
5
- if (filter.ids && !filter.ids.some((id) => id.toLowerCase() === event.id.toLowerCase())) return false;
5
+ if (filter.ids && !filter.ids.some((id) => id.toLowerCase() === event.id)) return false;
6
6
  if (filter.kinds && !filter.kinds.includes(event.kind)) return false;
7
- if (filter.authors && !filter.authors.some((pk) => pk.toLowerCase() === event.pubkey.toLowerCase())) return false;
7
+ if (filter.authors && !filter.authors.some((pk) => pk.toLowerCase() === event.pubkey)) return false;
8
8
  for (const key of Object.keys(filter)) {
9
- if (key[0] !== "#") continue;
9
+ if (!key.startsWith("#")) continue;
10
10
  const tagName = key.slice(1);
11
11
  const values = filter[`#${tagName}`];
12
12
  if (!values) continue;
13
13
  const hexTag = tagName === "e" || tagName === "p";
14
14
  if (!event.tags.some((tag) => {
15
- if (tag[0] !== tagName || tag[1] === void 0) return false;
16
- if (hexTag) return values.some((v) => v.toLowerCase() === tag[1].toLowerCase());
17
- return values.includes(tag[1]);
15
+ const [tagKey, tagValue] = tag;
16
+ if (tagKey !== tagName || tagValue === void 0) return false;
17
+ if (hexTag) return values.some((v) => v.toLowerCase() === tagValue.toLowerCase());
18
+ return values.includes(tagValue);
18
19
  })) return false;
19
20
  }
20
21
  if (filter.since !== void 0 && event.created_at < filter.since) return false;
21
22
  if (filter.until !== void 0 && event.created_at > filter.until) return false;
22
23
  return true;
23
24
  }
25
+ /** True when the event matches any of the filters (NIP-01 OR semantics). */
24
26
  function matchFilters(filters, event) {
25
27
  for (const filter of filters) if (matchFilter(filter, event)) return true;
26
28
  return false;
@@ -28,37 +30,45 @@ function matchFilters(filters, event) {
28
30
  /** Merge filters by unioning list fields; returns a new plain object. */
29
31
  function mergeFilters(...filters) {
30
32
  const result = {};
33
+ const mergeList = (property, values) => {
34
+ if (values === void 0) return;
35
+ const existing = result[property];
36
+ const list = Array.isArray(existing) ? [...existing] : [];
37
+ for (const value of values) if (!list.includes(value)) list.push(value);
38
+ result[property] = list;
39
+ };
40
+ const mergeMax = (property, value) => {
41
+ if (value === void 0) return;
42
+ const prev = result[property];
43
+ if (typeof prev !== "number" || value > prev) result[property] = value;
44
+ };
31
45
  for (const filter of filters) {
32
- for (const [property, values] of Object.entries(filter)) if (property === "kinds" || property === "ids" || property === "authors" || property[0] === "#") {
33
- const list = result[property] ?? [];
34
- for (const value of values) if (!list.includes(value)) list.push(value);
35
- result[property] = list;
36
- }
37
- if (filter.limit !== void 0) {
38
- const prev = result.limit;
39
- if (prev === void 0 || filter.limit > prev) result.limit = filter.limit;
40
- }
41
- if (filter.until !== void 0) {
42
- const prev = result.until;
43
- if (prev === void 0 || filter.until > prev) result.until = filter.until;
46
+ mergeList("ids", filter.ids);
47
+ mergeList("authors", filter.authors);
48
+ mergeList("kinds", filter.kinds);
49
+ for (const key of Object.keys(filter)) {
50
+ if (!key.startsWith("#")) continue;
51
+ mergeList(key, filter[key]);
44
52
  }
53
+ mergeMax("limit", filter.limit);
54
+ mergeMax("until", filter.until);
45
55
  if (filter.since !== void 0) {
46
- const prev = result.since;
47
- if (prev === void 0 || filter.since < prev) result.since = filter.since;
56
+ const prev = result["since"];
57
+ if (typeof prev !== "number" || filter.since < prev) result["since"] = filter.since;
48
58
  }
49
- if (filter.search !== void 0) result.search = filter.search;
59
+ if (filter.search !== void 0) result["search"] = filter.search;
50
60
  }
51
61
  return result;
52
62
  }
53
63
  /**
54
- * Intrinsic upper bound implied by the filter alone.
55
- * Returns a positive integer, or `Infinity` when unbounded.
64
+ * Intrinsic upper bound implied by the filter alone. Returns a positive integer, or `Infinity` when
65
+ * unbounded.
56
66
  */
57
67
  function getFilterLimit(filter) {
58
68
  if (filter.ids && filter.ids.length === 0) return 0;
59
69
  if (filter.kinds && filter.kinds.length === 0) return 0;
60
70
  if (filter.authors && filter.authors.length === 0) return 0;
61
- let limit = Infinity;
71
+ let limit = Number.POSITIVE_INFINITY;
62
72
  if (filter.ids) limit = Math.min(limit, filter.ids.length);
63
73
  if (filter.limit !== void 0) limit = Math.min(limit, filter.limit);
64
74
  if (filter.kinds && filter.authors) {
@@ -70,10 +80,6 @@ function getFilterLimit(filter) {
70
80
  }
71
81
  return limit;
72
82
  }
73
- /** Shallow-clone a filter (for per-relay narrowing). */
74
- function cloneFilter(filter) {
75
- return { ...filter };
76
- }
77
83
  const HEX_LIST_KEYS = /* @__PURE__ */ new Set([
78
84
  "ids",
79
85
  "authors",
@@ -89,18 +95,19 @@ function canonicalizeFilter(filter) {
89
95
  if (value === void 0) continue;
90
96
  if (Array.isArray(value)) {
91
97
  if (HEX_LIST_KEYS.has(key)) out[key] = value.map((v) => String(v).toLowerCase()).sort();
92
- else if (key === "kinds") out[key] = value.map((v) => Number(v)).sort((a, b) => a - b);
93
- else out[key] = value.map((v) => String(v)).sort();
98
+ else if (key === "kinds") out[key] = value.map(Number).sort((a, b) => a - b);
99
+ else out[key] = value.map(String).sort();
94
100
  } else out[key] = value;
95
101
  }
96
102
  return out;
97
103
  }
104
+ /** Apply {@link canonicalizeFilter} to each filter. */
98
105
  function canonicalizeFilters(filters) {
99
106
  return filters.map(canonicalizeFilter);
100
107
  }
101
108
  /**
102
- * Canonical identity for live REQ coalescing.
103
- * Relays treat a missing list key as unconstrained and `[]` as match-nothing.
109
+ * Canonical identity for live REQ coalescing. Relays treat a missing list key as unconstrained and
110
+ * `[]` as match-nothing.
104
111
  */
105
112
  function filterFingerprint(filters) {
106
113
  const parts = filters.map((filter) => JSON.stringify(canonicalizeFilter(filter)));
@@ -108,6 +115,6 @@ function filterFingerprint(filters) {
108
115
  return `[${parts.join(",")}]`;
109
116
  }
110
117
  //#endregion
111
- export { getFilterLimit as a, mergeFilters as c, filterFingerprint as i, canonicalizeFilters as n, matchFilter as o, cloneFilter as r, matchFilters as s, canonicalizeFilter as t };
118
+ export { matchFilter as a, getFilterLimit as i, canonicalizeFilters as n, matchFilters as o, filterFingerprint as r, mergeFilters as s, canonicalizeFilter as t };
112
119
 
113
- //# sourceMappingURL=filter-BxwjEkZp.mjs.map
120
+ //# sourceMappingURL=filter-BQl3GlHt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-BQl3GlHt.mjs","names":[],"sources":["../src/core/filter.ts"],"sourcesContent":["import type { Event } from \"./event.ts\";\nimport { isAddressableKind, isReplaceableKind } from \"./kind.ts\";\n\n/** NIP-01 filter object (immutable-friendly; callers may still pass plain objects). */\nexport type Filter = {\n readonly ids?: ReadonlyArray<string> | undefined;\n readonly kinds?: ReadonlyArray<number> | undefined;\n readonly authors?: ReadonlyArray<string> | undefined;\n readonly since?: number | undefined;\n readonly until?: number | undefined;\n readonly limit?: number | undefined;\n /** NIP-50 full-text search. Relays interpret this. Local `matchFilter` / `query` ignore it. */\n readonly search?: string | undefined;\n readonly [key: `#${string}`]: ReadonlyArray<string> | undefined;\n};\n\n/** Local NIP-01 match. `search` is ignored; relays interpret NIP-50. */\nexport function matchFilter(filter: Filter, event: Event): boolean {\n if (filter.ids && !filter.ids.some((id) => id.toLowerCase() === event.id)) {\n return false;\n }\n if (filter.kinds && !filter.kinds.includes(event.kind)) {\n return false;\n }\n if (filter.authors && !filter.authors.some((pk) => pk.toLowerCase() === event.pubkey)) {\n return false;\n }\n\n for (const key of Object.keys(filter)) {\n if (!key.startsWith(\"#\")) {\n continue;\n }\n const tagName = key.slice(1);\n const values = filter[`#${tagName}`];\n if (!values) {\n continue;\n }\n const hexTag = tagName === \"e\" || tagName === \"p\";\n const hit = event.tags.some((tag) => {\n const [tagKey, tagValue] = tag;\n if (tagKey !== tagName || tagValue === undefined) {\n return false;\n }\n if (hexTag) {\n return values.some((v) => v.toLowerCase() === tagValue.toLowerCase());\n }\n return values.includes(tagValue);\n });\n if (!hit) {\n return false;\n }\n }\n\n if (filter.since !== undefined && event.created_at < filter.since) {\n return false;\n }\n if (filter.until !== undefined && event.created_at > filter.until) {\n return false;\n }\n\n return true;\n}\n\n/** True when the event matches any of the filters (NIP-01 OR semantics). */\nexport function matchFilters(filters: ReadonlyArray<Filter>, event: Event): boolean {\n for (const filter of filters) {\n if (matchFilter(filter, event)) {\n return true;\n }\n }\n return false;\n}\n\n/** Merge filters by unioning list fields; returns a new plain object. */\nexport function mergeFilters(...filters: Filter[]): Filter {\n const result: Record<string, unknown> = {};\n const mergeList = (property: string, values: ReadonlyArray<unknown> | undefined): void => {\n if (values === undefined) {\n return;\n }\n const existing = result[property];\n const list: unknown[] = Array.isArray(existing) ? [...(existing as unknown[])] : [];\n for (const value of values) {\n if (!list.includes(value)) {\n list.push(value);\n }\n }\n result[property] = list;\n };\n const mergeMax = (property: \"limit\" | \"until\", value: number | undefined): void => {\n if (value === undefined) {\n return;\n }\n const prev = result[property];\n if (typeof prev !== \"number\" || value > prev) {\n result[property] = value;\n }\n };\n for (const filter of filters) {\n mergeList(\"ids\", filter.ids);\n mergeList(\"authors\", filter.authors);\n mergeList(\"kinds\", filter.kinds);\n for (const key of Object.keys(filter)) {\n if (!key.startsWith(\"#\")) {\n continue;\n }\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- startsWith(\"#\") above guarantees the template key\n mergeList(key, filter[key as `#${string}`]);\n }\n mergeMax(\"limit\", filter.limit);\n mergeMax(\"until\", filter.until);\n if (filter.since !== undefined) {\n const prev = result[\"since\"];\n if (typeof prev !== \"number\" || filter.since < prev) {\n result[\"since\"] = filter.since;\n }\n }\n if (filter.search !== undefined) {\n result[\"search\"] = filter.search;\n }\n }\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- built key by key above; the record is filter-shaped by construction\n return result as Filter;\n}\n\n/**\n * Intrinsic upper bound implied by the filter alone. Returns a positive integer, or `Infinity` when\n * unbounded.\n */\nexport function getFilterLimit(filter: Filter): number {\n if (filter.ids && filter.ids.length === 0) {\n return 0;\n }\n if (filter.kinds && filter.kinds.length === 0) {\n return 0;\n }\n if (filter.authors && filter.authors.length === 0) {\n return 0;\n }\n\n let limit = Number.POSITIVE_INFINITY;\n if (filter.ids) {\n limit = Math.min(limit, filter.ids.length);\n }\n if (filter.limit !== undefined) {\n limit = Math.min(limit, filter.limit);\n }\n\n if (filter.kinds && filter.authors) {\n const allReplaceable = filter.kinds.every((k) => isReplaceableKind(k) || isAddressableKind(k));\n if (allReplaceable) {\n const dTags = filter[\"#d\"];\n const perAuthor = dTags && dTags.length > 0 ? dTags.length : 1;\n limit = Math.min(limit, filter.authors.length * filter.kinds.length * perAuthor);\n }\n }\n\n return limit;\n}\n\nconst HEX_LIST_KEYS = new Set([\"ids\", \"authors\", \"#e\", \"#p\"]);\n\n/** Lowercase hex lists and sort every array. Omits undefined so `[]` stays distinct from missing. */\nexport function canonicalizeFilter(filter: Filter): Filter {\n const raw = filter as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(raw).sort()) {\n const value = raw[key];\n // omit undefined so a missing key is not `[]` / null\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n if (HEX_LIST_KEYS.has(key)) {\n out[key] = value.map((v) => String(v).toLowerCase()).sort();\n } else if (key === \"kinds\") {\n out[key] = value.map(Number).sort((a, b) => a - b);\n } else {\n out[key] = value.map(String).sort();\n }\n } else {\n out[key] = value;\n }\n }\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- built key by key above; the record is filter-shaped by construction\n return out as Filter;\n}\n\n/** Apply {@link canonicalizeFilter} to each filter. */\nexport function canonicalizeFilters(filters: ReadonlyArray<Filter>): Filter[] {\n return filters.map(canonicalizeFilter);\n}\n\n/**\n * Canonical identity for live REQ coalescing. Relays treat a missing list key as unconstrained and\n * `[]` as match-nothing.\n */\nexport function filterFingerprint(filters: ReadonlyArray<Filter>): string {\n const parts = filters.map((filter) => JSON.stringify(canonicalizeFilter(filter)));\n parts.sort();\n return `[${parts.join(\",\")}]`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { t as Event } from "./event-fU3Y01PR.mjs";
2
+ //#region src/core/filter.d.ts
3
+ /** NIP-01 filter object (immutable-friendly; callers may still pass plain objects). */
4
+ type Filter = {
5
+ readonly ids?: ReadonlyArray<string> | undefined;
6
+ readonly kinds?: ReadonlyArray<number> | undefined;
7
+ readonly authors?: ReadonlyArray<string> | undefined;
8
+ readonly since?: number | undefined;
9
+ readonly until?: number | undefined;
10
+ readonly limit?: number | undefined;
11
+ /** NIP-50 full-text search. Relays interpret this. Local `matchFilter` / `query` ignore it. */
12
+ readonly search?: string | undefined;
13
+ readonly [key: `#${string}`]: ReadonlyArray<string> | undefined;
14
+ };
15
+ /** Local NIP-01 match. `search` is ignored; relays interpret NIP-50. */
16
+ declare function matchFilter(filter: Filter, event: Event): boolean;
17
+ /** True when the event matches any of the filters (NIP-01 OR semantics). */
18
+ declare function matchFilters(filters: ReadonlyArray<Filter>, event: Event): boolean;
19
+ /** Merge filters by unioning list fields; returns a new plain object. */
20
+ declare function mergeFilters(...filters: Filter[]): Filter;
21
+ /**
22
+ * Intrinsic upper bound implied by the filter alone. Returns a positive integer, or `Infinity` when
23
+ * unbounded.
24
+ */
25
+ declare function getFilterLimit(filter: Filter): number;
26
+ /** Lowercase hex lists and sort every array. Omits undefined so `[]` stays distinct from missing. */
27
+ declare function canonicalizeFilter(filter: Filter): Filter;
28
+ /** Apply {@link canonicalizeFilter} to each filter. */
29
+ declare function canonicalizeFilters(filters: ReadonlyArray<Filter>): Filter[];
30
+ /**
31
+ * Canonical identity for live REQ coalescing. Relays treat a missing list key as unconstrained and
32
+ * `[]` as match-nothing.
33
+ */
34
+ declare function filterFingerprint(filters: ReadonlyArray<Filter>): string;
35
+ //#endregion
36
+ export { getFilterLimit as a, mergeFilters as c, filterFingerprint as i, canonicalizeFilter as n, matchFilter as o, canonicalizeFilters as r, matchFilters as s, Filter as t };
37
+ //# sourceMappingURL=filter-C0IMByE3.d.mts.map
@@ -1,7 +1,8 @@
1
- import { t as Event } from "./event-B5D2jxt_.mjs";
2
- import { t as Filter } from "./filter-DUEKP3q1.mjs";
3
- import { t as RelayListItem } from "./nip65-Di5hZRuV.mjs";
1
+ import { t as Event } from "./event-fU3Y01PR.mjs";
2
+ import { t as Filter } from "./filter-C0IMByE3.mjs";
3
+ import { t as RelayListItem } from "./nip65-DBfh2smt.mjs";
4
4
  //#region src/gossip/gossip.d.ts
5
+ /** Relay routing state for one pubkey: NIP-65 outbox/inbox plus NIP-17 DM relays. */
5
6
  type PubkeyRoutes = {
6
7
  /** Relays the user writes to (outbox). NIP-65. */
7
8
  write: string[];
@@ -14,42 +15,44 @@ type PubkeyRoutes = {
14
15
  /** `created_at` of the last accepted kind:10050 list. */
15
16
  dmUpdatedAt: number;
16
17
  /** Event id of the last accepted kind:10002 (NIP-01 equal-timestamp tie-break). */
17
- relayListId?: string;
18
+ relayListId?: string | undefined;
18
19
  /** Event id of the last accepted kind:10050. */
19
- dmListId?: string;
20
+ dmListId?: string | undefined;
20
21
  };
22
+ /** A filter split by gossip routes: per-relay narrowed filters plus the unrouted remainder. */
21
23
  type RoutedFilter = {
22
- /** url → already-narrowed filter. Empty when nothing routed. */
24
+ /** Url → already-narrowed filter. Empty when nothing routed. */
23
25
  perRelay: Map<string, Filter>;
24
26
  /**
25
- * Unrouted work for the caller:
26
- * - no authors and no #p: original filter (today's "generic")
27
- * - authors/#p all unrouted: original filter (today's "orphan")
28
- * - mixed: narrowed leftover (today's fallback)
29
- * - all routed: undefined
27
+ * Unrouted work for the caller: - no authors and no #p: original filter (today's "generic") -
28
+ * authors/#p all unrouted: original filter (today's "orphan") - mixed: narrowed leftover (today's
29
+ * fallback) - all routed: undefined
30
30
  */
31
31
  remainder?: Filter;
32
32
  };
33
33
  type GossipOptions = {
34
34
  /** Max relays to keep per direction when ranking. Default 4. */
35
35
  maxRelaysPerPubkey?: number;
36
+ /**
37
+ * Max pubkeys with tracked routes; the map is LRU — writes and lookups refresh recency, and
38
+ * inserting beyond the cap drops the oldest entry. Default 10_000.
39
+ */
40
+ maxPubkeys?: number;
36
41
  };
37
42
  /**
38
- * Routing table for NIP-65 (10002) and NIP-17 DM relays (10050).
39
- * Ingest replaceable list events, then route filters into per-relay REQs.
43
+ * Routing table for NIP-65 (10002) and NIP-17 DM relays (10050). Ingest replaceable list events,
44
+ * then route filters into per-relay REQs.
40
45
  */
41
46
  declare class Gossip {
42
47
  #private;
43
48
  constructor(opts?: GossipOptions);
44
49
  /**
45
- * Ingest a routing list event.
46
- * - kind:10002 → write/read (NIP-65)
47
- * - kind:10050 → dm (NIP-17)
50
+ * Ingest a routing list event. - kind:10002 → write/read (NIP-65) - kind:10050 → dm (NIP-17)
48
51
  * Returns true if routes for that list type were updated.
49
52
  */
50
53
  ingest(event: Event): boolean;
51
54
  setRoutes(pubkey: string, items: RelayListItem[], updatedAt?: number, eventId?: string): boolean;
52
- setDmRoutes(pubkey: string, relays: readonly string[], updatedAt?: number, eventId?: string): boolean;
55
+ setDmRoutes(pubkey: string, relays: ReadonlyArray<string>, updatedAt?: number, eventId?: string): boolean;
53
56
  getRoutes(pubkey: string): PubkeyRoutes | undefined;
54
57
  outboxRelays(pubkey: string): string[];
55
58
  inboxRelays(pubkey: string): string[];
@@ -58,14 +61,13 @@ declare class Gossip {
58
61
  clear(pubkey?: string): void;
59
62
  get size(): number;
60
63
  /**
61
- * Route a user-facing filter into per-relay sub-filters plus leftover.
62
- * - authors → outbox relays, filter narrowed per relay's authors
63
- * - #p only → inbox relays of those pubkeys
64
- * - neither / all unrouted → remainder is the original filter
65
- * - mixed → remainder is the narrowed leftover; all routed → no remainder
64
+ * Route a user-facing filter into per-relay sub-filters plus leftover. - authors → outbox relays,
65
+ * filter narrowed per relay's authors - #p only → inbox relays of those pubkeys - neither / all
66
+ * unrouted → remainder is the original filter - mixed → remainder is the narrowed leftover; all
67
+ * routed → no remainder
66
68
  */
67
69
  route(filter: Filter): RoutedFilter;
68
70
  }
69
71
  //#endregion
70
72
  export { RoutedFilter as i, GossipOptions as n, PubkeyRoutes as r, Gossip as t };
71
- //# sourceMappingURL=gossip-C5RVB1UB.d.mts.map
73
+ //# sourceMappingURL=gossip-BRQwIM_q.d.mts.map
@@ -1,6 +1,6 @@
1
- import { s as normalizeURL } from "./util-6tfLQ9JF.mjs";
2
- import { t as Kind } from "./kind-BLl4cLOc.mjs";
3
- import { i as isReplaceableWinner } from "./event-CzoQEFMF.mjs";
1
+ import { l as normalizeURL } from "./util-LfQirgDk.mjs";
2
+ import { t as Kind } from "./kind-Cxwhhkx8.mjs";
3
+ import { a as isReplaceableWinner } from "./event-D8Nfoh4K.mjs";
4
4
  import { parseRelayList } from "./nips/nip65.mjs";
5
5
  import { parseDmRelayList } from "./nips/nip17.mjs";
6
6
  //#region src/gossip/gossip.ts
@@ -14,19 +14,19 @@ function emptyRoutes() {
14
14
  };
15
15
  }
16
16
  /**
17
- * Routing table for NIP-65 (10002) and NIP-17 DM relays (10050).
18
- * Ingest replaceable list events, then route filters into per-relay REQs.
17
+ * Routing table for NIP-65 (10002) and NIP-17 DM relays (10050). Ingest replaceable list events,
18
+ * then route filters into per-relay REQs.
19
19
  */
20
20
  var Gossip = class {
21
21
  #routes = /* @__PURE__ */ new Map();
22
22
  #maxRelays;
23
+ #maxPubkeys;
23
24
  constructor(opts = {}) {
24
25
  this.#maxRelays = opts.maxRelaysPerPubkey ?? 4;
26
+ this.#maxPubkeys = opts.maxPubkeys ?? 1e4;
25
27
  }
26
28
  /**
27
- * Ingest a routing list event.
28
- * - kind:10002 → write/read (NIP-65)
29
- * - kind:10050 → dm (NIP-17)
29
+ * Ingest a routing list event. - kind:10002 → write/read (NIP-65) - kind:10050 → dm (NIP-17)
30
30
  * Returns true if routes for that list type were updated.
31
31
  */
32
32
  ingest(event) {
@@ -52,9 +52,9 @@ var Gossip = class {
52
52
  }
53
53
  setRoutes(pubkey, items, updatedAt = Math.floor(Date.now() / 1e3), eventId) {
54
54
  const pk = pubkey.toLowerCase();
55
- const prev = this.#routes.get(pk) ?? emptyRoutes();
55
+ const prev = this.#lookup(pk) ?? emptyRoutes();
56
56
  if (prev.updatedAt > updatedAt) return false;
57
- if (eventId && prev.relayListId && prev.updatedAt === updatedAt && !isReplaceableWinner({
57
+ if (eventId !== void 0 && prev.relayListId !== void 0 && prev.updatedAt === updatedAt && !isReplaceableWinner({
58
58
  created_at: updatedAt,
59
59
  id: eventId
60
60
  }, {
@@ -73,7 +73,7 @@ var Gossip = class {
73
73
  if (item.write && !write.includes(url)) write.push(url);
74
74
  if (item.read && !read.includes(url)) read.push(url);
75
75
  }
76
- this.#routes.set(pk, {
76
+ this.#put(pk, {
77
77
  write: write.slice(0, this.#maxRelays),
78
78
  read: read.slice(0, this.#maxRelays),
79
79
  dm: prev.dm,
@@ -86,9 +86,9 @@ var Gossip = class {
86
86
  }
87
87
  setDmRoutes(pubkey, relays, updatedAt = Math.floor(Date.now() / 1e3), eventId) {
88
88
  const pk = pubkey.toLowerCase();
89
- const prev = this.#routes.get(pk) ?? emptyRoutes();
89
+ const prev = this.#lookup(pk) ?? emptyRoutes();
90
90
  if (prev.dmUpdatedAt > updatedAt) return false;
91
- if (eventId && prev.dmListId && prev.dmUpdatedAt === updatedAt && !isReplaceableWinner({
91
+ if (eventId !== void 0 && prev.dmListId !== void 0 && prev.dmUpdatedAt === updatedAt && !isReplaceableWinner({
92
92
  created_at: updatedAt,
93
93
  id: eventId
94
94
  }, {
@@ -105,7 +105,7 @@ var Gossip = class {
105
105
  }
106
106
  if (!dm.includes(url)) dm.push(url);
107
107
  }
108
- this.#routes.set(pk, {
108
+ this.#put(pk, {
109
109
  write: prev.write,
110
110
  read: prev.read,
111
111
  dm: dm.slice(0, this.#maxRelays),
@@ -117,31 +117,30 @@ var Gossip = class {
117
117
  return true;
118
118
  }
119
119
  getRoutes(pubkey) {
120
- return this.#routes.get(pubkey.toLowerCase());
120
+ return this.#lookup(pubkey.toLowerCase());
121
121
  }
122
122
  outboxRelays(pubkey) {
123
- return this.#routes.get(pubkey.toLowerCase())?.write ?? [];
123
+ return this.#lookup(pubkey.toLowerCase())?.write ?? [];
124
124
  }
125
125
  inboxRelays(pubkey) {
126
- return this.#routes.get(pubkey.toLowerCase())?.read ?? [];
126
+ return this.#lookup(pubkey.toLowerCase())?.read ?? [];
127
127
  }
128
128
  /** NIP-17 kind:10050 delivery relays for gift-wraps. */
129
129
  dmRelays(pubkey) {
130
- return this.#routes.get(pubkey.toLowerCase())?.dm ?? [];
130
+ return this.#lookup(pubkey.toLowerCase())?.dm ?? [];
131
131
  }
132
132
  clear(pubkey) {
133
- if (pubkey) this.#routes.delete(pubkey.toLowerCase());
133
+ if (pubkey !== void 0 && pubkey !== "") this.#routes.delete(pubkey.toLowerCase());
134
134
  else this.#routes.clear();
135
135
  }
136
136
  get size() {
137
137
  return this.#routes.size;
138
138
  }
139
139
  /**
140
- * Route a user-facing filter into per-relay sub-filters plus leftover.
141
- * - authors → outbox relays, filter narrowed per relay's authors
142
- * - #p only → inbox relays of those pubkeys
143
- * - neither / all unrouted → remainder is the original filter
144
- * - mixed → remainder is the narrowed leftover; all routed → no remainder
140
+ * Route a user-facing filter into per-relay sub-filters plus leftover. - authors → outbox relays,
141
+ * filter narrowed per relay's authors - #p only → inbox relays of those pubkeys - neither / all
142
+ * unrouted → remainder is the original filter - mixed → remainder is the narrowed leftover; all
143
+ * routed → no remainder
145
144
  */
146
145
  route(filter) {
147
146
  const authors = filter.authors?.map((a) => a.toLowerCase());
@@ -151,18 +150,18 @@ var Gossip = class {
151
150
  remainder: filter
152
151
  };
153
152
  if (authors && authors.length > 0 && (!pTags || pTags.length === 0)) return this.#breakAuthors(filter, authors, "write");
154
- if (pTags && pTags.length > 0 && (!authors || authors.length === 0)) return this.#breakAuthors({
155
- ...filter,
156
- authors: void 0
157
- }, pTags, "read", (base, pubkeys) => ({
158
- ...base,
159
- "#p": pubkeys
160
- }));
153
+ if (pTags && pTags.length > 0 && (!authors || authors.length === 0)) {
154
+ const { authors: _authors, ...base } = filter;
155
+ return this.#breakAuthors(base, pTags, "read", (b, pubkeys) => ({
156
+ ...b,
157
+ "#p": pubkeys
158
+ }));
159
+ }
161
160
  const unionKeys = /* @__PURE__ */ new Set([...authors ?? [], ...pTags ?? []]);
162
161
  const relays = /* @__PURE__ */ new Set();
163
162
  let anyUnrouted = false;
164
163
  for (const pk of unionKeys) {
165
- const r = this.#routes.get(pk);
164
+ const r = this.#lookup(pk);
166
165
  const urls = r ? [...r.write, ...r.read] : [];
167
166
  if (urls.length === 0) {
168
167
  anyUnrouted = true;
@@ -189,7 +188,7 @@ var Gossip = class {
189
188
  const unrouted = [];
190
189
  let anyRoute = false;
191
190
  for (const pk of pubkeys) {
192
- const routes = this.#routes.get(pk);
191
+ const routes = this.#lookup(pk);
193
192
  const urls = direction === "write" ? routes?.write : routes?.read;
194
193
  if (!urls || urls.length === 0) {
195
194
  unrouted.push(pk);
@@ -213,8 +212,27 @@ var Gossip = class {
213
212
  remainder: narrow(filter, unrouted)
214
213
  } : { perRelay: map };
215
214
  }
215
+ /** Read that refreshes LRU recency. */
216
+ #lookup(pk) {
217
+ const routes = this.#routes.get(pk);
218
+ if (routes !== void 0) {
219
+ this.#routes.delete(pk);
220
+ this.#routes.set(pk, routes);
221
+ }
222
+ return routes;
223
+ }
224
+ /** Write at the newest LRU end, then trim the oldest beyond the cap. */
225
+ #put(pk, routes) {
226
+ this.#routes.delete(pk);
227
+ this.#routes.set(pk, routes);
228
+ while (this.#routes.size > this.#maxPubkeys) {
229
+ const oldest = this.#routes.keys().next().value;
230
+ if (oldest === void 0) break;
231
+ this.#routes.delete(oldest);
232
+ }
233
+ }
216
234
  };
217
235
  //#endregion
218
236
  export { Gossip as t };
219
237
 
220
- //# sourceMappingURL=gossip-3xkRRCm_.mjs.map
238
+ //# sourceMappingURL=gossip-oloDMWEj.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gossip-oloDMWEj.mjs","names":[],"sources":["../src/gossip/gossip.ts"],"sourcesContent":["import type { Event } from \"../core/event.ts\";\nimport { isReplaceableWinner } from \"../core/event.ts\";\nimport type { Filter } from \"../core/filter.ts\";\nimport { Kind } from \"../core/kind.ts\";\nimport { normalizeURL } from \"../core/util.ts\";\nimport { parseDmRelayList } from \"../nips/nip17.ts\";\nimport { parseRelayList } from \"../nips/nip65.ts\";\nimport type { RelayListItem } from \"../nips/nip65.ts\";\n\n/** Relay routing state for one pubkey: NIP-65 outbox/inbox plus NIP-17 DM relays. */\nexport type PubkeyRoutes = {\n /** Relays the user writes to (outbox). NIP-65. */\n write: string[];\n /** Relays the user reads from (inbox). NIP-65. */\n read: string[];\n /** Relays for NIP-17 gift-wrap delivery. Kind 10050. */\n dm: string[];\n /** `created_at` of the last accepted kind:10002 list. */\n updatedAt: number;\n /** `created_at` of the last accepted kind:10050 list. */\n dmUpdatedAt: number;\n /** Event id of the last accepted kind:10002 (NIP-01 equal-timestamp tie-break). */\n relayListId?: string | undefined;\n /** Event id of the last accepted kind:10050. */\n dmListId?: string | undefined;\n};\n\n/** A filter split by gossip routes: per-relay narrowed filters plus the unrouted remainder. */\nexport type RoutedFilter = {\n /** Url → already-narrowed filter. Empty when nothing routed. */\n perRelay: Map<string, Filter>;\n /**\n * Unrouted work for the caller: - no authors and no #p: original filter (today's \"generic\") -\n * authors/#p all unrouted: original filter (today's \"orphan\") - mixed: narrowed leftover (today's\n * fallback) - all routed: undefined\n */\n remainder?: Filter;\n};\n\nexport type GossipOptions = {\n /** Max relays to keep per direction when ranking. Default 4. */\n maxRelaysPerPubkey?: number;\n /**\n * Max pubkeys with tracked routes; the map is LRU — writes and lookups refresh recency, and\n * inserting beyond the cap drops the oldest entry. Default 10_000.\n */\n maxPubkeys?: number;\n};\n\nfunction emptyRoutes(): PubkeyRoutes {\n return {\n write: [],\n read: [],\n dm: [],\n updatedAt: 0,\n dmUpdatedAt: 0,\n };\n}\n\n/**\n * Routing table for NIP-65 (10002) and NIP-17 DM relays (10050). Ingest replaceable list events,\n * then route filters into per-relay REQs.\n */\nexport class Gossip {\n readonly #routes = new Map<string, PubkeyRoutes>();\n readonly #maxRelays: number;\n readonly #maxPubkeys: number;\n\n constructor(opts: GossipOptions = {}) {\n this.#maxRelays = opts.maxRelaysPerPubkey ?? 4;\n this.#maxPubkeys = opts.maxPubkeys ?? 10_000;\n }\n\n /**\n * Ingest a routing list event. - kind:10002 → write/read (NIP-65) - kind:10050 → dm (NIP-17)\n * Returns true if routes for that list type were updated.\n */\n ingest(event: Event): boolean {\n if (event.kind === Kind.RelayList) {\n let items: RelayListItem[];\n try {\n items = parseRelayList(event);\n } catch {\n return false;\n }\n return this.setRoutes(event.pubkey, items, event.created_at, event.id);\n }\n if (event.kind === Kind.DirectMessageRelaysList) {\n let relays: string[];\n try {\n relays = parseDmRelayList(event);\n } catch {\n return false;\n }\n return this.setDmRoutes(event.pubkey, relays, event.created_at, event.id);\n }\n return false;\n }\n\n setRoutes(\n pubkey: string,\n items: RelayListItem[],\n updatedAt: number = Math.floor(Date.now() / 1000),\n eventId?: string,\n ): boolean {\n const pk = pubkey.toLowerCase();\n const prev = this.#lookup(pk) ?? emptyRoutes();\n if (prev.updatedAt > updatedAt) {\n return false;\n }\n if (\n eventId !== undefined &&\n prev.relayListId !== undefined &&\n prev.updatedAt === updatedAt &&\n !isReplaceableWinner(\n { created_at: updatedAt, id: eventId },\n { created_at: prev.updatedAt, id: prev.relayListId },\n )\n ) {\n return false;\n }\n\n const write: string[] = [];\n const read: string[] = [];\n for (const item of items) {\n let url: string;\n try {\n url = normalizeURL(item.url);\n } catch {\n continue;\n }\n if (item.write && !write.includes(url)) {\n write.push(url);\n }\n if (item.read && !read.includes(url)) {\n read.push(url);\n }\n }\n\n this.#put(pk, {\n write: write.slice(0, this.#maxRelays),\n read: read.slice(0, this.#maxRelays),\n dm: prev.dm,\n updatedAt,\n dmUpdatedAt: prev.dmUpdatedAt,\n relayListId: eventId ?? prev.relayListId,\n dmListId: prev.dmListId,\n });\n return true;\n }\n\n setDmRoutes(\n pubkey: string,\n relays: ReadonlyArray<string>,\n updatedAt: number = Math.floor(Date.now() / 1000),\n eventId?: string,\n ): boolean {\n const pk = pubkey.toLowerCase();\n const prev = this.#lookup(pk) ?? emptyRoutes();\n if (prev.dmUpdatedAt > updatedAt) {\n return false;\n }\n if (\n eventId !== undefined &&\n prev.dmListId !== undefined &&\n prev.dmUpdatedAt === updatedAt &&\n !isReplaceableWinner(\n { created_at: updatedAt, id: eventId },\n { created_at: prev.dmUpdatedAt, id: prev.dmListId },\n )\n ) {\n return false;\n }\n\n const dm: string[] = [];\n for (const raw of relays) {\n let url: string;\n try {\n url = normalizeURL(raw);\n } catch {\n continue;\n }\n if (!dm.includes(url)) {\n dm.push(url);\n }\n }\n\n this.#put(pk, {\n write: prev.write,\n read: prev.read,\n dm: dm.slice(0, this.#maxRelays),\n updatedAt: prev.updatedAt,\n dmUpdatedAt: updatedAt,\n relayListId: prev.relayListId,\n dmListId: eventId ?? prev.dmListId,\n });\n return true;\n }\n\n getRoutes(pubkey: string): PubkeyRoutes | undefined {\n return this.#lookup(pubkey.toLowerCase());\n }\n\n outboxRelays(pubkey: string): string[] {\n return this.#lookup(pubkey.toLowerCase())?.write ?? [];\n }\n\n inboxRelays(pubkey: string): string[] {\n return this.#lookup(pubkey.toLowerCase())?.read ?? [];\n }\n\n /** NIP-17 kind:10050 delivery relays for gift-wraps. */\n dmRelays(pubkey: string): string[] {\n return this.#lookup(pubkey.toLowerCase())?.dm ?? [];\n }\n\n clear(pubkey?: string): void {\n if (pubkey !== undefined && pubkey !== \"\") {\n this.#routes.delete(pubkey.toLowerCase());\n } else {\n this.#routes.clear();\n }\n }\n\n get size(): number {\n return this.#routes.size;\n }\n\n /**\n * Route a user-facing filter into per-relay sub-filters plus leftover. - authors → outbox relays,\n * filter narrowed per relay's authors - #p only → inbox relays of those pubkeys - neither / all\n * unrouted → remainder is the original filter - mixed → remainder is the narrowed leftover; all\n * routed → no remainder\n */\n route(filter: Filter): RoutedFilter {\n const authors = filter.authors?.map((a) => a.toLowerCase());\n const pTags = filter[\"#p\"]?.map((p) => p.toLowerCase());\n\n if ((!authors || authors.length === 0) && (!pTags || pTags.length === 0)) {\n return { perRelay: new Map(), remainder: filter };\n }\n\n if (authors && authors.length > 0 && (!pTags || pTags.length === 0)) {\n return this.#breakAuthors(filter, authors, \"write\");\n }\n\n if (pTags && pTags.length > 0 && (!authors || authors.length === 0)) {\n const { authors: _authors, ...base } = filter;\n return this.#breakAuthors(base, pTags, \"read\", (b, pubkeys) => ({ ...b, \"#p\": pubkeys }));\n }\n\n // both authors and #p: send full filter to union of routes\n const unionKeys = new Set([...(authors ?? []), ...(pTags ?? [])]);\n const relays = new Set<string>();\n let anyUnrouted = false;\n for (const pk of unionKeys) {\n const r = this.#lookup(pk);\n const urls = r ? [...r.write, ...r.read] : [];\n if (urls.length === 0) {\n anyUnrouted = true;\n continue;\n }\n for (const u of urls) {\n relays.add(u);\n }\n }\n if (relays.size === 0) {\n return { perRelay: new Map(), remainder: filter };\n }\n const map = new Map<string, Filter>();\n for (const url of relays) {\n map.set(url, { ...filter });\n }\n return anyUnrouted ? { perRelay: map, remainder: filter } : { perRelay: map };\n }\n\n #breakAuthors(\n filter: Filter,\n pubkeys: string[],\n direction: \"read\" | \"write\",\n narrow: (base: Filter, pubkeys: string[]) => Filter = (base, pks) => ({\n ...base,\n authors: pks,\n }),\n ): RoutedFilter {\n const perRelay = new Map<string, string[]>();\n const unrouted: string[] = [];\n let anyRoute = false;\n\n for (const pk of pubkeys) {\n const routes = this.#lookup(pk);\n const urls = direction === \"write\" ? routes?.write : routes?.read;\n if (!urls || urls.length === 0) {\n unrouted.push(pk);\n continue;\n }\n anyRoute = true;\n for (const url of urls) {\n const list = perRelay.get(url) ?? [];\n list.push(pk);\n perRelay.set(url, list);\n }\n }\n\n if (!anyRoute) {\n return { perRelay: new Map(), remainder: filter };\n }\n\n const map = new Map<string, Filter>();\n for (const [url, pks] of perRelay) {\n map.set(url, narrow(filter, pks));\n }\n return unrouted.length > 0\n ? { perRelay: map, remainder: narrow(filter, unrouted) }\n : { perRelay: map };\n }\n\n /** Read that refreshes LRU recency. */\n #lookup(pk: string): PubkeyRoutes | undefined {\n const routes = this.#routes.get(pk);\n if (routes !== undefined) {\n this.#routes.delete(pk);\n this.#routes.set(pk, routes);\n }\n return routes;\n }\n\n /** Write at the newest LRU end, then trim the oldest beyond the cap. */\n #put(pk: string, routes: PubkeyRoutes): void {\n this.#routes.delete(pk);\n this.#routes.set(pk, routes);\n while (this.#routes.size > this.#maxPubkeys) {\n const oldest = this.#routes.keys().next().value;\n if (oldest === undefined) {\n break;\n }\n this.#routes.delete(oldest);\n }\n }\n}\n"],"mappings":"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"}
package/dist/gossip.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { i as RoutedFilter, n as GossipOptions, r as PubkeyRoutes, t as Gossip } from "./gossip-C5RVB1UB.mjs";
1
+ import { i as RoutedFilter, n as GossipOptions, r as PubkeyRoutes, t as Gossip } from "./gossip-BRQwIM_q.mjs";
2
2
  import "./index-CaxrMD1A.mjs";
3
3
  export { Gossip, type GossipOptions, type PubkeyRoutes, type RoutedFilter };
package/dist/gossip.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as Gossip } from "./gossip-3xkRRCm_.mjs";
1
+ import { t as Gossip } from "./gossip-oloDMWEj.mjs";
2
2
  export { Gossip };