@qntx/nostr 0.6.0 → 0.8.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 (183) hide show
  1. package/dist/{abort-Ba8tDrOI.mjs → abort-DBq2STPj.mjs} +13 -6
  2. package/dist/abort-DBq2STPj.mjs.map +1 -0
  3. package/dist/{builder-sSflu6nB.d.mts → builder-CTwkB2zM.d.mts} +14 -15
  4. package/dist/{builder-9tjI6WQ3.mjs → builder-aNU2gGFP.mjs} +11 -17
  5. package/dist/builder-aNU2gGFP.mjs.map +1 -0
  6. package/dist/{client-CadO5fAX.mjs → client-Cj2lUaVh.mjs} +141 -353
  7. package/dist/client-Cj2lUaVh.mjs.map +1 -0
  8. package/dist/client.d.mts +2 -2
  9. package/dist/client.mjs +2 -2
  10. package/dist/collections-DtwMc1NU.mjs +33 -0
  11. package/dist/collections-DtwMc1NU.mjs.map +1 -0
  12. package/dist/core.d.mts +9 -8
  13. package/dist/core.mjs +7 -7
  14. package/dist/emitter-DkCY6NkU.mjs +32 -0
  15. package/dist/emitter-DkCY6NkU.mjs.map +1 -0
  16. package/dist/{error-BW7re1UN.d.mts → error-BD_0QFKT.d.mts} +2 -2
  17. package/dist/{error-DrEIM7FO.mjs → error-BILMe3Gr.mjs} +2 -2
  18. package/dist/{error-DrEIM7FO.mjs.map → error-BILMe3Gr.mjs.map} +1 -1
  19. package/dist/{error-CR8Urc84.d.mts → error-BquXDmIN.d.mts} +4 -4
  20. package/dist/{error-B__OMBRY.mjs → error-DlhGW4mJ.mjs} +2 -2
  21. package/dist/{error-B__OMBRY.mjs.map → error-DlhGW4mJ.mjs.map} +1 -1
  22. package/dist/{event-D8Nfoh4K.mjs → event-CHf47dPM.mjs} +16 -10
  23. package/dist/event-CHf47dPM.mjs.map +1 -0
  24. package/dist/{event-fU3Y01PR.d.mts → event-DJeb_DIL.d.mts} +4 -2
  25. package/dist/{filter-C0IMByE3.d.mts → filter-jI_9htF7.d.mts} +2 -2
  26. package/dist/{gossip-oloDMWEj.mjs → gossip-DFxIBlsr.mjs} +23 -33
  27. package/dist/gossip-DFxIBlsr.mjs.map +1 -0
  28. package/dist/{gossip-DpIvkBuj.d.mts → gossip-OOeeFzG5.d.mts} +37 -28
  29. package/dist/gossip.d.mts +1 -1
  30. package/dist/gossip.mjs +1 -1
  31. package/dist/{index-D1bqFHKB.d.mts → index-BxCBX-8R.d.mts} +18 -18
  32. package/dist/{index-lvXeER5t.d.mts → index-CPVEyzNX.d.mts} +32 -50
  33. package/dist/{index-MxC28S4P.d.mts → index-C_w2WfVz.d.mts} +27 -29
  34. package/dist/{index-CNl2q67H.d.mts → index-Cl_1XdYP.d.mts} +111 -180
  35. package/dist/{index-CvkvqB16.d.mts → index-DU9tRFTZ.d.mts} +7 -20
  36. package/dist/{index-q4MDce_r.d.mts → index-DyKwQnbt.d.mts} +6 -8
  37. package/dist/index.d.mts +23 -21
  38. package/dist/index.mjs +21 -19
  39. package/dist/{instance-DQE8BoWt.mjs → instance-C62w3cEt.mjs} +26 -27
  40. package/dist/instance-C62w3cEt.mjs.map +1 -0
  41. package/dist/{instance-CIca-ynn.d.mts → instance-DjsL8h84.d.mts} +5 -5
  42. package/dist/{key-Cv4_pN3x.d.mts → key-D_5OgGT7.d.mts} +11 -7
  43. package/dist/{key-Bps-LqX7.mjs → key-DnVpchl6.mjs} +13 -9
  44. package/dist/key-DnVpchl6.mjs.map +1 -0
  45. package/dist/{loaders-o6YXB_Ri.mjs → loaders-BmPkQfzI.mjs} +73 -82
  46. package/dist/loaders-BmPkQfzI.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 → memory-CdJ07kub.mjs} +2 -2
  50. package/dist/memory-CdJ07kub.mjs.map +1 -0
  51. package/dist/{memory-index-Do1mz0WF.mjs → memory-index-Cbc83vOZ.mjs} +30 -247
  52. package/dist/memory-index-Cbc83vOZ.mjs.map +1 -0
  53. package/dist/message-oNr7t0SJ.mjs +194 -0
  54. package/dist/message-oNr7t0SJ.mjs.map +1 -0
  55. package/dist/{message-iGPIqnn0.d.mts → message-tclYCVNc.d.mts} +6 -6
  56. package/dist/{nip17-CKIufV98.d.mts → nip17-B5WgW4C4.d.mts} +6 -7
  57. package/dist/{nip19-BevCJZsp.d.mts → nip19-DpPN17bY.d.mts} +25 -31
  58. package/dist/{nip46-DDV4dC56.d.mts → nip46-BHaxC9TZ.d.mts} +19 -21
  59. package/dist/nip51-CR0Q8eym.d.mts +87 -0
  60. package/dist/{nip59-zQgdLcEr.d.mts → nip59-C-RWFQIv.d.mts} +11 -5
  61. package/dist/nip65-D1fbmhOg.d.mts +23 -0
  62. package/dist/{nip77-DH4RhS5r.d.mts → nip77-DzUwUxHq.d.mts} +8 -9
  63. package/dist/nips/blossom.d.mts +17 -13
  64. package/dist/nips/blossom.mjs +30 -9
  65. package/dist/nips/blossom.mjs.map +1 -1
  66. package/dist/nips/nip04.mjs +17 -7
  67. package/dist/nips/nip04.mjs.map +1 -1
  68. package/dist/nips/nip05.d.mts +9 -10
  69. package/dist/nips/nip05.mjs +1 -4
  70. package/dist/nips/nip05.mjs.map +1 -1
  71. package/dist/nips/nip10.d.mts +8 -8
  72. package/dist/nips/nip10.mjs +34 -32
  73. package/dist/nips/nip10.mjs.map +1 -1
  74. package/dist/nips/nip11.d.mts +28 -28
  75. package/dist/nips/nip11.mjs +4 -4
  76. package/dist/nips/nip11.mjs.map +1 -1
  77. package/dist/nips/nip13.d.mts +7 -7
  78. package/dist/nips/nip13.mjs +32 -10
  79. package/dist/nips/nip13.mjs.map +1 -1
  80. package/dist/nips/nip17.d.mts +1 -1
  81. package/dist/nips/nip17.mjs +16 -34
  82. package/dist/nips/nip17.mjs.map +1 -1
  83. package/dist/nips/nip19.d.mts +2 -2
  84. package/dist/nips/nip19.mjs +16 -28
  85. package/dist/nips/nip19.mjs.map +1 -1
  86. package/dist/nips/nip21.d.mts +9 -4
  87. package/dist/nips/nip21.mjs +15 -5
  88. package/dist/nips/nip21.mjs.map +1 -1
  89. package/dist/nips/nip27.d.mts +22 -22
  90. package/dist/nips/nip27.mjs +2 -2
  91. package/dist/nips/nip27.mjs.map +1 -1
  92. package/dist/nips/nip42.d.mts +1 -1
  93. package/dist/nips/nip42.mjs +2 -1
  94. package/dist/nips/nip42.mjs.map +1 -1
  95. package/dist/nips/nip44.mjs +2 -2
  96. package/dist/nips/nip44.mjs.map +1 -1
  97. package/dist/nips/nip46.d.mts +2 -2
  98. package/dist/nips/nip46.mjs +15 -19
  99. package/dist/nips/nip46.mjs.map +1 -1
  100. package/dist/nips/nip49.d.mts +9 -9
  101. package/dist/nips/nip49.mjs +4 -4
  102. package/dist/nips/nip49.mjs.map +1 -1
  103. package/dist/nips/nip51.d.mts +2 -86
  104. package/dist/nips/nip51.mjs +7 -23
  105. package/dist/nips/nip51.mjs.map +1 -1
  106. package/dist/nips/nip57.d.mts +25 -23
  107. package/dist/nips/nip57.mjs +12 -17
  108. package/dist/nips/nip57.mjs.map +1 -1
  109. package/dist/nips/nip59.d.mts +1 -1
  110. package/dist/nips/nip59.mjs +27 -19
  111. package/dist/nips/nip59.mjs.map +1 -1
  112. package/dist/nips/nip65.d.mts +2 -2
  113. package/dist/nips/nip65.mjs +14 -37
  114. package/dist/nips/nip65.mjs.map +1 -1
  115. package/dist/nips/nip77.d.mts +1 -1
  116. package/dist/nips/nip77.mjs +33 -32
  117. package/dist/nips/nip77.mjs.map +1 -1
  118. package/dist/nips/nip98.d.mts +5 -5
  119. package/dist/nips/nip98.mjs +8 -8
  120. package/dist/nips/nip98.mjs.map +1 -1
  121. package/dist/{pool-DBIYMtwy.d.mts → pool-CqQvUnsq.d.mts} +132 -108
  122. package/dist/pool-vlw74C4t.mjs +606 -0
  123. package/dist/pool-vlw74C4t.mjs.map +1 -0
  124. package/dist/put-w13ci3sC.mjs +187 -0
  125. package/dist/put-w13ci3sC.mjs.map +1 -0
  126. package/dist/{reactive-BfhPp9a3.mjs → reactive-Tz0otDIP.mjs} +125 -88
  127. package/dist/reactive-Tz0otDIP.mjs.map +1 -0
  128. package/dist/{reactive-7aqeip4A.d.mts → reactive-gGqUrzW8.d.mts} +20 -26
  129. package/dist/relay-quCs7MHD.mjs +1811 -0
  130. package/dist/relay-quCs7MHD.mjs.map +1 -0
  131. package/dist/relay.d.mts +4 -4
  132. package/dist/relay.mjs +3 -2
  133. package/dist/serial-Bzpw-xz3.mjs +21 -0
  134. package/dist/serial-Bzpw-xz3.mjs.map +1 -0
  135. package/dist/{signer-CYQutDzD.mjs → signer-poTGe6Er.mjs} +12 -14
  136. package/dist/signer-poTGe6Er.mjs.map +1 -0
  137. package/dist/signer.d.mts +2 -2
  138. package/dist/signer.mjs +2 -2
  139. package/dist/{storage-Dky3wuoH.mjs → storage-B5IXTVuS.mjs} +28 -51
  140. package/dist/storage-B5IXTVuS.mjs.map +1 -0
  141. package/dist/storage.d.mts +3 -3
  142. package/dist/storage.mjs +4 -4
  143. package/dist/store.d.mts +2 -2
  144. package/dist/store.mjs +1 -1
  145. package/dist/testing.d.mts +19 -19
  146. package/dist/testing.mjs +9 -9
  147. package/dist/testing.mjs.map +1 -1
  148. package/dist/{types-2pCUprRU.d.mts → types-BacwnDtU.d.mts} +10 -10
  149. package/dist/{types-CRQEk0Oi.d.mts → types-DNmiscfd.d.mts} +2 -2
  150. package/dist/{util-LfQirgDk.mjs → util-DMF9AIO0.mjs} +33 -7
  151. package/dist/util-DMF9AIO0.mjs.map +1 -0
  152. package/dist/{verifier-t5WoWbtY.mjs → verifier-B51Wkt5H.mjs} +3 -3
  153. package/dist/verifier-B51Wkt5H.mjs.map +1 -0
  154. package/dist/verifier-CgTFpgsC.d.mts +22 -0
  155. package/dist/wasm.browser.d.mts +3 -3
  156. package/dist/wasm.browser.mjs +3 -3
  157. package/dist/wasm.d.mts +3 -3
  158. package/dist/wasm.mjs +3 -3
  159. package/dist/wasm.mjs.map +1 -1
  160. package/package.json +5 -9
  161. package/dist/abort-Ba8tDrOI.mjs.map +0 -1
  162. package/dist/builder-9tjI6WQ3.mjs.map +0 -1
  163. package/dist/client-CadO5fAX.mjs.map +0 -1
  164. package/dist/event-D8Nfoh4K.mjs.map +0 -1
  165. package/dist/gossip-oloDMWEj.mjs.map +0 -1
  166. package/dist/instance-DQE8BoWt.mjs.map +0 -1
  167. package/dist/key-Bps-LqX7.mjs.map +0 -1
  168. package/dist/loaders-o6YXB_Ri.mjs.map +0 -1
  169. package/dist/memory-C2EVx0_O.mjs.map +0 -1
  170. package/dist/memory-index-Do1mz0WF.mjs.map +0 -1
  171. package/dist/message-DcY6Fi9o.mjs +0 -193
  172. package/dist/message-DcY6Fi9o.mjs.map +0 -1
  173. package/dist/nip65-CjgmdpPB.d.mts +0 -26
  174. package/dist/nips/nip96.d.mts +0 -40
  175. package/dist/nips/nip96.mjs +0 -118
  176. package/dist/nips/nip96.mjs.map +0 -1
  177. package/dist/pool-As20OGxB.mjs +0 -2166
  178. package/dist/pool-As20OGxB.mjs.map +0 -1
  179. package/dist/reactive-BfhPp9a3.mjs.map +0 -1
  180. package/dist/signer-CYQutDzD.mjs.map +0 -1
  181. package/dist/storage-Dky3wuoH.mjs.map +0 -1
  182. package/dist/util-LfQirgDk.mjs.map +0 -1
  183. package/dist/verifier-t5WoWbtY.mjs.map +0 -1
@@ -1,7 +1,8 @@
1
- import { l as normalizeURL } from "./util-LfQirgDk.mjs";
1
+ import { d as nowSeconds, l as normalizeRelayUrls, u as normalizeURL } from "./util-DMF9AIO0.mjs";
2
2
  import { t as Kind } from "./kind-Cxwhhkx8.mjs";
3
- import { a as isReplaceableWinner } from "./event-D8Nfoh4K.mjs";
3
+ import { a as isReplaceableWinner } from "./event-CHf47dPM.mjs";
4
4
  import { parseRelayList } from "./nips/nip65.mjs";
5
+ import { i as trimOldest, r as touchKey } from "./collections-DtwMc1NU.mjs";
5
6
  import { parseDmRelayList } from "./nips/nip17.mjs";
6
7
  //#region src/gossip/gossip.ts
7
8
  function emptyRoutes() {
@@ -26,7 +27,11 @@ var Gossip = class {
26
27
  this.#maxPubkeys = opts.maxPubkeys ?? 1e4;
27
28
  }
28
29
  /**
29
- * Ingest a routing list event. - kind:10002 → write/read (NIP-65) - kind:10050 → dm (NIP-17)
30
+ * Ingest a routing list event.
31
+ *
32
+ * - Kind:10002 → write/read (NIP-65)
33
+ * - Kind:10050 → dm (NIP-17)
34
+ *
30
35
  * Returns true if routes for that list type were updated.
31
36
  */
32
37
  ingest(event) {
@@ -50,7 +55,7 @@ var Gossip = class {
50
55
  }
51
56
  return false;
52
57
  }
53
- setRoutes(pubkey, items, updatedAt = Math.floor(Date.now() / 1e3), eventId) {
58
+ setRoutes(pubkey, items, updatedAt = nowSeconds(), eventId) {
54
59
  const pk = pubkey.toLowerCase();
55
60
  const prev = this.#lookup(pk) ?? emptyRoutes();
56
61
  if (prev.updatedAt > updatedAt) return false;
@@ -70,8 +75,8 @@ var Gossip = class {
70
75
  } catch {
71
76
  continue;
72
77
  }
73
- if (item.write && !write.includes(url)) write.push(url);
74
- if (item.read && !read.includes(url)) read.push(url);
78
+ if (item.marker !== "read" && !write.includes(url)) write.push(url);
79
+ if (item.marker !== "write" && !read.includes(url)) read.push(url);
75
80
  }
76
81
  this.#put(pk, {
77
82
  write: write.slice(0, this.#maxRelays),
@@ -84,7 +89,7 @@ var Gossip = class {
84
89
  });
85
90
  return true;
86
91
  }
87
- setDmRoutes(pubkey, relays, updatedAt = Math.floor(Date.now() / 1e3), eventId) {
92
+ setDmRoutes(pubkey, relays, updatedAt = nowSeconds(), eventId) {
88
93
  const pk = pubkey.toLowerCase();
89
94
  const prev = this.#lookup(pk) ?? emptyRoutes();
90
95
  if (prev.dmUpdatedAt > updatedAt) return false;
@@ -95,16 +100,7 @@ var Gossip = class {
95
100
  created_at: prev.dmUpdatedAt,
96
101
  id: prev.dmListId
97
102
  })) return false;
98
- const dm = [];
99
- for (const raw of relays) {
100
- let url;
101
- try {
102
- url = normalizeURL(raw);
103
- } catch {
104
- continue;
105
- }
106
- if (!dm.includes(url)) dm.push(url);
107
- }
103
+ const dm = normalizeRelayUrls(relays);
108
104
  this.#put(pk, {
109
105
  write: prev.write,
110
106
  read: prev.read,
@@ -137,10 +133,12 @@ var Gossip = class {
137
133
  return this.#routes.size;
138
134
  }
139
135
  /**
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
136
+ * Route a user-facing filter into per-relay sub-filters plus leftover.
137
+ *
138
+ * - Authors → outbox relays, filter narrowed per relay's authors
139
+ * - #p only → inbox relays of those pubkeys
140
+ * - Neither / all unrouted → remainder is the original filter
141
+ * - Mixed → remainder is the narrowed leftover; all routed → no remainder
144
142
  */
145
143
  route(filter) {
146
144
  const authors = filter.authors?.map((a) => a.toLowerCase());
@@ -215,24 +213,16 @@ var Gossip = class {
215
213
  /** Read that refreshes LRU recency. */
216
214
  #lookup(pk) {
217
215
  const routes = this.#routes.get(pk);
218
- if (routes !== void 0) {
219
- this.#routes.delete(pk);
220
- this.#routes.set(pk, routes);
221
- }
216
+ if (routes !== void 0) touchKey(this.#routes, pk, routes);
222
217
  return routes;
223
218
  }
224
219
  /** Write at the newest LRU end, then trim the oldest beyond the cap. */
225
220
  #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
- }
221
+ touchKey(this.#routes, pk, routes);
222
+ trimOldest(this.#routes, this.#maxPubkeys);
233
223
  }
234
224
  };
235
225
  //#endregion
236
226
  export { Gossip as t };
237
227
 
238
- //# sourceMappingURL=gossip-oloDMWEj.mjs.map
228
+ //# sourceMappingURL=gossip-DFxIBlsr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gossip-DFxIBlsr.mjs","names":[],"sources":["../src/gossip/gossip.ts"],"sourcesContent":["import { touchKey, trimOldest } from \"../core/collections.ts\";\nimport 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 { normalizeRelayUrls, normalizeURL, nowSeconds } 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 readonly write: ReadonlyArray<string>;\n /** Relays the user reads from (inbox). NIP-65. */\n readonly read: ReadonlyArray<string>;\n /** Relays for NIP-17 gift-wrap delivery. Kind 10050. */\n readonly dm: ReadonlyArray<string>;\n /** `created_at` of the last accepted kind:10002 list. */\n readonly updatedAt: number;\n /** `created_at` of the last accepted kind:10050 list. */\n readonly dmUpdatedAt: number;\n /** Event id of the last accepted kind:10002 (NIP-01 equal-timestamp tie-break). */\n readonly relayListId?: string | undefined;\n /** Event id of the last accepted kind:10050. */\n readonly 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 readonly perRelay: ReadonlyMap<string, Filter>;\n /**\n * Unrouted work for the caller:\n *\n * - No authors and no #p: original filter (\"generic\")\n * - Authors/#p all unrouted: original filter (\"orphan\")\n * - Mixed: narrowed leftover (\"fallback\")\n * - All routed: undefined\n */\n readonly remainder?: Filter | undefined;\n};\n\nexport type GossipOptions = {\n /** Max relays to keep per direction when ranking. Default 4. */\n maxRelaysPerPubkey?: number | undefined;\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 | undefined;\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.\n *\n * - Kind:10002 → write/read (NIP-65)\n * - Kind:10050 → dm (NIP-17)\n *\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: ReadonlyArray<RelayListItem>,\n updatedAt: number = nowSeconds(),\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.marker !== \"read\" && !write.includes(url)) {\n write.push(url);\n }\n if (item.marker !== \"write\" && !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 = nowSeconds(),\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 = normalizeRelayUrls(relays);\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): Readonly<PubkeyRoutes> | undefined {\n return this.#lookup(pubkey.toLowerCase());\n }\n\n outboxRelays(pubkey: string): ReadonlyArray<string> {\n return this.#lookup(pubkey.toLowerCase())?.write ?? [];\n }\n\n inboxRelays(pubkey: string): ReadonlyArray<string> {\n return this.#lookup(pubkey.toLowerCase())?.read ?? [];\n }\n\n /** NIP-17 kind:10050 delivery relays for gift-wraps. */\n dmRelays(pubkey: string): ReadonlyArray<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.\n *\n * - Authors → outbox relays, filter narrowed per relay's authors\n * - #p only → inbox relays of those pubkeys\n * - Neither / all unrouted → remainder is the original filter\n * - Mixed → remainder is the narrowed leftover; all 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 touchKey(this.#routes, 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 touchKey(this.#routes, pk, routes);\n trimOldest(this.#routes, this.#maxPubkeys);\n }\n}\n"],"mappings":"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"}
@@ -1,43 +1,46 @@
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-CjgmdpPB.mjs";
1
+ import { t as Event } from "./event-DJeb_DIL.mjs";
2
+ import { t as Filter } from "./filter-jI_9htF7.mjs";
3
+ import { t as RelayListItem } from "./nip65-D1fbmhOg.mjs";
4
4
  //#region src/gossip/gossip.d.ts
5
5
  /** Relay routing state for one pubkey: NIP-65 outbox/inbox plus NIP-17 DM relays. */
6
6
  type PubkeyRoutes = {
7
7
  /** Relays the user writes to (outbox). NIP-65. */
8
- write: string[];
8
+ readonly write: ReadonlyArray<string>;
9
9
  /** Relays the user reads from (inbox). NIP-65. */
10
- read: string[];
10
+ readonly read: ReadonlyArray<string>;
11
11
  /** Relays for NIP-17 gift-wrap delivery. Kind 10050. */
12
- dm: string[];
12
+ readonly dm: ReadonlyArray<string>;
13
13
  /** `created_at` of the last accepted kind:10002 list. */
14
- updatedAt: number;
14
+ readonly updatedAt: number;
15
15
  /** `created_at` of the last accepted kind:10050 list. */
16
- dmUpdatedAt: number;
16
+ readonly dmUpdatedAt: number;
17
17
  /** Event id of the last accepted kind:10002 (NIP-01 equal-timestamp tie-break). */
18
- relayListId?: string | undefined;
18
+ readonly relayListId?: string | undefined;
19
19
  /** Event id of the last accepted kind:10050. */
20
- dmListId?: string | undefined;
20
+ readonly dmListId?: string | undefined;
21
21
  };
22
22
  /** A filter split by gossip routes: per-relay narrowed filters plus the unrouted remainder. */
23
23
  type RoutedFilter = {
24
24
  /** Url → already-narrowed filter. Empty when nothing routed. */
25
- perRelay: Map<string, Filter>;
25
+ readonly perRelay: ReadonlyMap<string, Filter>;
26
26
  /**
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
27
+ * Unrouted work for the caller:
28
+ *
29
+ * - No authors and no #p: original filter ("generic")
30
+ * - Authors/#p all unrouted: original filter ("orphan")
31
+ * - Mixed: narrowed leftover ("fallback")
32
+ * - All routed: undefined
30
33
  */
31
- remainder?: Filter;
34
+ readonly remainder?: Filter | undefined;
32
35
  };
33
36
  type GossipOptions = {
34
37
  /** Max relays to keep per direction when ranking. Default 4. */
35
- maxRelaysPerPubkey?: number;
38
+ maxRelaysPerPubkey?: number | undefined;
36
39
  /**
37
40
  * Max pubkeys with tracked routes; the map is LRU — writes and lookups refresh recency, and
38
41
  * inserting beyond the cap drops the oldest entry. Default 10_000.
39
42
  */
40
- maxPubkeys?: number;
43
+ maxPubkeys?: number | undefined;
41
44
  };
42
45
  /**
43
46
  * Routing table for NIP-65 (10002) and NIP-17 DM relays (10050). Ingest replaceable list events,
@@ -47,27 +50,33 @@ declare class Gossip {
47
50
  #private;
48
51
  constructor(opts?: GossipOptions);
49
52
  /**
50
- * Ingest a routing list event. - kind:10002 → write/read (NIP-65) - kind:10050 → dm (NIP-17)
53
+ * Ingest a routing list event.
54
+ *
55
+ * - Kind:10002 → write/read (NIP-65)
56
+ * - Kind:10050 → dm (NIP-17)
57
+ *
51
58
  * Returns true if routes for that list type were updated.
52
59
  */
53
60
  ingest(event: Event): boolean;
54
- setRoutes(pubkey: string, items: RelayListItem[], updatedAt?: number, eventId?: string): boolean;
61
+ setRoutes(pubkey: string, items: ReadonlyArray<RelayListItem>, updatedAt?: number, eventId?: string): boolean;
55
62
  setDmRoutes(pubkey: string, relays: ReadonlyArray<string>, updatedAt?: number, eventId?: string): boolean;
56
- getRoutes(pubkey: string): PubkeyRoutes | undefined;
57
- outboxRelays(pubkey: string): string[];
58
- inboxRelays(pubkey: string): string[];
63
+ getRoutes(pubkey: string): Readonly<PubkeyRoutes> | undefined;
64
+ outboxRelays(pubkey: string): ReadonlyArray<string>;
65
+ inboxRelays(pubkey: string): ReadonlyArray<string>;
59
66
  /** NIP-17 kind:10050 delivery relays for gift-wraps. */
60
- dmRelays(pubkey: string): string[];
67
+ dmRelays(pubkey: string): ReadonlyArray<string>;
61
68
  clear(pubkey?: string): void;
62
69
  get size(): number;
63
70
  /**
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
71
+ * Route a user-facing filter into per-relay sub-filters plus leftover.
72
+ *
73
+ * - Authors → outbox relays, filter narrowed per relay's authors
74
+ * - #p only → inbox relays of those pubkeys
75
+ * - Neither / all unrouted → remainder is the original filter
76
+ * - Mixed → remainder is the narrowed leftover; all routed → no remainder
68
77
  */
69
78
  route(filter: Filter): RoutedFilter;
70
79
  }
71
80
  //#endregion
72
81
  export { RoutedFilter as i, GossipOptions as n, PubkeyRoutes as r, Gossip as t };
73
- //# sourceMappingURL=gossip-DpIvkBuj.d.mts.map
82
+ //# sourceMappingURL=gossip-OOeeFzG5.d.mts.map
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-DpIvkBuj.mjs";
1
+ import { i as RoutedFilter, n as GossipOptions, r as PubkeyRoutes, t as Gossip } from "./gossip-OOeeFzG5.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-oloDMWEj.mjs";
1
+ import { t as Gossip } from "./gossip-DFxIBlsr.mjs";
2
2
  export { Gossip };
@@ -1,6 +1,6 @@
1
- import { t as Event } from "./event-fU3Y01PR.mjs";
2
- import { t as Filter } from "./filter-C0IMByE3.mjs";
3
- import { i as PutResult, n as NegentropyItem, r as OutboxBound, t as EventStore } from "./types-2pCUprRU.mjs";
1
+ import { t as Event } from "./event-DJeb_DIL.mjs";
2
+ import { t as Filter } from "./filter-jI_9htF7.mjs";
3
+ import { i as PutResult, n as NegentropyItem, r as OutboxBound, t as EventStore } from "./types-BacwnDtU.mjs";
4
4
  //#region src/storage/memory-index.d.ts
5
5
  type MemoryIndexOptions = {
6
6
  /**
@@ -8,7 +8,7 @@ type MemoryIndexOptions = {
8
8
  * e-tag ids, and coordinate tombstones. Default unbounded. Trade-off: once an entry is trimmed, a
9
9
  * re-arriving old deleted event or replaceable version can be accepted again.
10
10
  */
11
- maxTombstones?: number;
11
+ maxTombstones?: number | undefined;
12
12
  /**
13
13
  * FIFO cap on replaceable/addressable winner watermarks recorded by {@link evict}. A watermark
14
14
  * keeps only `{ id, created_at }` per address so stale versions stay rejected after the winner's
@@ -16,11 +16,11 @@ type MemoryIndexOptions = {
16
16
  * retention); callers that evict should pass a bound. Once a watermark is trimmed, an older
17
17
  * evicted version can be accepted again — the same trade-off as deletion tombstones.
18
18
  */
19
- maxWatermarks?: number;
19
+ maxWatermarks?: number | undefined;
20
20
  /** Fires after every physical index insert (accept, replace, deletion event). */
21
- onInsert?: (event: Event) => void;
21
+ onInsert?: ((event: Event) => void) | undefined;
22
22
  /** Fires after every physical index remove (replace, delete, evict, remove, clear). */
23
- onRemove?: (event: Event) => void;
23
+ onRemove?: ((event: Event) => void) | undefined;
24
24
  };
25
25
  /**
26
26
  * Synchronous in-memory event index with NIP-01 replaceable / addressable / ephemeral handling and
@@ -68,10 +68,10 @@ declare class MemoryEventStore implements EventStore {
68
68
  /** Sequential `put` in input order. No transaction: a throw leaves earlier events applied. */
69
69
  putMany(events: ReadonlyArray<Event>): Promise<PutResult[]>;
70
70
  get(id: string): Promise<Event | undefined>;
71
- query(filters: Filter[]): Promise<Event[]>;
72
- count(filters: Filter[]): Promise<number>;
71
+ query(filters: ReadonlyArray<Filter>): Promise<Event[]>;
72
+ count(filters: ReadonlyArray<Filter>): Promise<number>;
73
73
  negentropyItems(filter: Filter): Promise<NegentropyItem[]>;
74
- remove(ids: string[]): Promise<number>;
74
+ remove(ids: ReadonlyArray<string>): Promise<number>;
75
75
  getOutboxBound(pubkey: string, kind: number): Promise<OutboxBound | undefined>;
76
76
  setOutboxBound(pubkey: string, kind: number, bound: OutboxBound): Promise<void>;
77
77
  clear(): Promise<void>;
@@ -82,7 +82,7 @@ declare class MemoryEventStore implements EventStore {
82
82
  /** Options for {@link IndexedDbEventStore}. */
83
83
  type IndexedDbEventStoreOptions = {
84
84
  /** IndexedDB database name. */
85
- dbName?: string;
85
+ dbName?: string | undefined;
86
86
  };
87
87
  /**
88
88
  * Browser IndexedDB event store with the same replaceable / deletion semantics as
@@ -100,12 +100,12 @@ declare class IndexedDbEventStore implements EventStore {
100
100
  /** One readwrite transaction; abort rejects the whole batch with no partial persist. */
101
101
  putMany(events: ReadonlyArray<Event>): Promise<PutResult[]>;
102
102
  get(id: string): Promise<Event | undefined>;
103
- query(filters: Filter[]): Promise<Event[]>;
104
- count(filters: Filter[]): Promise<number>;
103
+ query(filters: ReadonlyArray<Filter>): Promise<Event[]>;
104
+ count(filters: ReadonlyArray<Filter>): Promise<number>;
105
105
  negentropyItems(filter: Filter): Promise<NegentropyItem[]>;
106
106
  getOutboxBound(pubkey: string, kind: number): Promise<OutboxBound | undefined>;
107
107
  setOutboxBound(pubkey: string, kind: number, bound: OutboxBound): Promise<void>;
108
- remove(ids: string[]): Promise<number>;
108
+ remove(ids: ReadonlyArray<string>): Promise<number>;
109
109
  clear(): Promise<void>;
110
110
  close(): void;
111
111
  }
@@ -175,14 +175,14 @@ declare class SqliteEventStore implements EventStore {
175
175
  put(event: Event): Promise<PutResult>;
176
176
  putMany(events: ReadonlyArray<Event>): Promise<PutResult[]>;
177
177
  get(id: string): Promise<Event | undefined>;
178
- query(filters: Filter[]): Promise<Event[]>;
179
- count(filters: Filter[]): Promise<number>;
178
+ query(filters: ReadonlyArray<Filter>): Promise<Event[]>;
179
+ count(filters: ReadonlyArray<Filter>): Promise<number>;
180
180
  negentropyItems(filter: Filter): Promise<NegentropyItem[]>;
181
181
  getOutboxBound(pubkey: string, kind: number): Promise<OutboxBound | undefined>;
182
182
  setOutboxBound(pubkey: string, kind: number, bound: OutboxBound): Promise<void>;
183
- remove(ids: string[]): Promise<number>;
183
+ remove(ids: ReadonlyArray<string>): Promise<number>;
184
184
  clear(): Promise<void>;
185
185
  }
186
186
  //#endregion
187
187
  export { IndexedDbEventStoreOptions as a, MemoryIndexOptions as c, IndexedDbEventStore as i, SqlValue as n, MemoryEventStore as o, SqliteEventStore as r, MemoryIndex as s, SqlDriver as t };
188
- //# sourceMappingURL=index-D1bqFHKB.d.mts.map
188
+ //# sourceMappingURL=index-BxCBX-8R.d.mts.map
@@ -1,12 +1,13 @@
1
- import { t as Event } from "./event-fU3Y01PR.mjs";
2
- import { n as ProfileMetadata } from "./builder-sSflu6nB.mjs";
3
- import { t as RelayListItem } from "./nip65-CjgmdpPB.mjs";
4
- import { t as Gossip } from "./gossip-DpIvkBuj.mjs";
5
- import { a as NostrError } from "./error-CR8Urc84.mjs";
6
- import { n as Pool } from "./pool-DBIYMtwy.mjs";
7
- import { r as OutboxBound, t as EventStore } from "./types-2pCUprRU.mjs";
8
- import { t as ReactiveEventStore } from "./reactive-7aqeip4A.mjs";
9
- import { i as EventPointer, t as AddressPointer } from "./nip19-BevCJZsp.mjs";
1
+ import { t as Event } from "./event-DJeb_DIL.mjs";
2
+ import { n as ProfileMetadata } from "./builder-CTwkB2zM.mjs";
3
+ import { t as RelayListItem } from "./nip65-D1fbmhOg.mjs";
4
+ import { t as Gossip } from "./gossip-OOeeFzG5.mjs";
5
+ import { a as NostrError } from "./error-BquXDmIN.mjs";
6
+ import { _ as Closer, n as Pool } from "./pool-CqQvUnsq.mjs";
7
+ import { r as OutboxBound, t as EventStore } from "./types-BacwnDtU.mjs";
8
+ import { t as ReactiveEventStore } from "./reactive-gGqUrzW8.mjs";
9
+ import { i as EventPointer, t as AddressPointer } from "./nip19-DpPN17bY.mjs";
10
+ import { t as MuteItem } from "./nip51-CR0Q8eym.mjs";
10
11
  //#region src/loaders/event.d.ts
11
12
  type EventRef = string | EventPointer | AddressPointer;
12
13
  /**
@@ -21,8 +22,8 @@ type EventLoader = {
21
22
  //#region src/loaders/replaceable.d.ts
22
23
  /** Result of a replaceable load: the winning event (or none) and freshness. */
23
24
  type ReplaceableLoadResult = {
24
- event: Event | undefined;
25
- fresh: boolean;
25
+ readonly event: Event | undefined;
26
+ readonly fresh: boolean;
26
27
  };
27
28
  /** `default`: fetch when stale or unfetched; `force`: always fetch; `cache-only`: index only. */
28
29
  type LoadStyle = "default" | "force" | "cache-only";
@@ -35,23 +36,9 @@ type ReplaceableLoader = (pubkey: string, opts?: {
35
36
  //#region src/loaders/lists.d.ts
36
37
  /** Result of a list loader: the source event, its decoded items, and freshness. */
37
38
  type ListResult<T> = {
38
- event: Event | undefined;
39
- items: T[];
40
- fresh: boolean;
41
- };
42
- /** One muted entity decoded from a kind:10000 mute list. */
43
- type MutedEntity = {
44
- label: "pubkey";
45
- value: string;
46
- } | {
47
- label: "thread";
48
- value: string;
49
- } | {
50
- label: "hashtag";
51
- value: string;
52
- } | {
53
- label: "word";
54
- value: string;
39
+ readonly event: Event | undefined;
40
+ readonly items: ReadonlyArray<T>;
41
+ readonly fresh: boolean;
55
42
  };
56
43
  type ListLoaderOpts = {
57
44
  hints?: string[] | undefined;
@@ -59,7 +46,7 @@ type ListLoaderOpts = {
59
46
  };
60
47
  type ListLoaders = {
61
48
  follows: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<string>>;
62
- muteList: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<MutedEntity>>;
49
+ muteList: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<MuteItem>>;
63
50
  relayList: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<RelayListItem>>;
64
51
  dmRelayList: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<string>>;
65
52
  };
@@ -67,14 +54,14 @@ type ListLoaders = {
67
54
  //#region src/loaders/profile.d.ts
68
55
  /** A profile-card view of a pubkey: identity fields plus the kind:0 event. */
69
56
  type NostrUser = {
70
- pubkey: string;
71
- npub: string;
72
- shortName: string;
73
- image?: string;
74
- metadata: ProfileMetadata;
75
- lastUpdated: number;
76
- event: Event | undefined;
77
- fresh: boolean;
57
+ readonly pubkey: string;
58
+ readonly npub: string;
59
+ readonly shortName: string;
60
+ readonly image?: string | undefined;
61
+ readonly metadata: ProfileMetadata;
62
+ readonly lastUpdated: number;
63
+ readonly event: Event | undefined;
64
+ readonly fresh: boolean;
78
65
  };
79
66
  /** A {@link NostrUser} with no metadata — used when no kind:0 event exists. */
80
67
  declare function bareNostrUser(pubkey: string): NostrUser;
@@ -90,7 +77,7 @@ type ProfileLoader = {
90
77
  declare class OutboxError extends NostrError {
91
78
  name: string;
92
79
  }
93
- /** Options for {@link createOutboxFeed}. */
80
+ /** Options for {@link OutboxFeed}. */
94
81
  type OutboxFeedOptions = {
95
82
  pool: Pool;
96
83
  gossip: Gossip;
@@ -156,21 +143,16 @@ declare class OutboxFeed {
156
143
  startLive(opts?: {
157
144
  signal?: AbortSignal | undefined;
158
145
  since?: number | undefined;
159
- }): {
160
- close: (reason?: string) => void;
161
- };
146
+ }): Closer;
162
147
  /** Convenience: hydrate + sync + startLive. */
163
148
  start(opts?: {
164
149
  limit?: number | undefined;
165
150
  signal?: AbortSignal | undefined;
166
- }): Promise<{
167
- close: (reason?: string) => void;
151
+ }): Promise<Closer & {
168
152
  events: Event[];
169
153
  }>;
170
154
  close(): void;
171
155
  }
172
- /** Factory matching other loaders helpers. */
173
- declare function createOutboxFeed(opts: OutboxFeedOptions): OutboxFeed;
174
156
  //#endregion
175
157
  //#region src/loaders/index.d.ts
176
158
  /** The loader surface returned by {@link createLoaders}. */
@@ -196,12 +178,12 @@ type CreateLoadersOptions = {
196
178
  * Inbound-event sink for fetched events; defaults to `index.add`. Client wires its single ingest
197
179
  * path so loader fetches get gossip meta and persistence like every other inbound event.
198
180
  */
199
- ingest?: (event: Event, relayUrl: string) => void;
200
- staleAfterSec?: number;
201
- fetchTimeoutMs?: number;
181
+ ingest?: ((event: Event, relayUrl: string) => void) | undefined;
182
+ staleAfterSec?: number | undefined;
183
+ fetchTimeoutMs?: number | undefined;
202
184
  };
203
185
  /** Build an instance-scoped loader suite (no module globals). */
204
186
  declare function createLoaders(opts: CreateLoadersOptions): Loaders;
205
187
  //#endregion
206
- export { ReplaceableLoader as _, OutboxFeed as a, groupAuthorsByOutboxRelay as c, bareNostrUser as d, ListLoaders as f, ReplaceableLoadResult as g, LoadStyle as h, OutboxError as i, NostrUser as l, MutedEntity as m, Loaders as n, OutboxFeedOptions as o, ListResult as p, createLoaders as r, createOutboxFeed as s, CreateLoadersOptions as t, ProfileLoader as u, EventLoader as v, EventRef as y };
207
- //# sourceMappingURL=index-lvXeER5t.d.mts.map
188
+ export { EventRef as _, OutboxFeed as a, NostrUser as c, ListLoaders as d, ListResult as f, EventLoader as g, ReplaceableLoader as h, OutboxError as i, ProfileLoader as l, ReplaceableLoadResult as m, Loaders as n, OutboxFeedOptions as o, LoadStyle as p, createLoaders as r, groupAuthorsByOutboxRelay as s, CreateLoadersOptions as t, bareNostrUser as u };
189
+ //# sourceMappingURL=index-CPVEyzNX.d.mts.map
@@ -1,9 +1,9 @@
1
- import { n as EventTemplate, r as UnsignedEvent, t as Event } from "./event-fU3Y01PR.mjs";
2
- import { r as SecretKey, t as Keys } from "./key-Cv4_pN3x.mjs";
3
- import { t as Filter } from "./filter-C0IMByE3.mjs";
4
- import { a as NostrError } from "./error-CR8Urc84.mjs";
5
- import { t as NostrSigner } from "./types-CRQEk0Oi.mjs";
6
- import { n as BunkerPointer, r as ClientMetadata } from "./nip46-DDV4dC56.mjs";
1
+ import { n as EventTemplate, r as UnsignedEvent, t as Event } from "./event-DJeb_DIL.mjs";
2
+ import { i as SecretKeyInput, t as Keys } from "./key-D_5OgGT7.mjs";
3
+ import { t as Filter } from "./filter-jI_9htF7.mjs";
4
+ import { a as NostrError } from "./error-BquXDmIN.mjs";
5
+ import { t as NostrSigner } from "./types-DNmiscfd.mjs";
6
+ import { n as ClientMetadata, t as BunkerPointer } from "./nip46-BHaxC9TZ.mjs";
7
7
  //#region src/signer/error.d.ts
8
8
  /**
9
9
  * Thrown by a lazy NIP-42 AUTH sign function when no signer is configured at challenge time.
@@ -18,7 +18,7 @@ declare class NoSignerError extends NostrError {
18
18
  /** Local secret-key signer with NIP-04 (legacy) and NIP-44 support. */
19
19
  declare class KeysSigner implements NostrSigner {
20
20
  #private;
21
- constructor(secretKey: SecretKey | Uint8Array | string | Keys);
21
+ constructor(secretKey: SecretKeyInput | Keys);
22
22
  get keys(): Keys;
23
23
  getPublicKey(): Promise<string>;
24
24
  signEvent(unsigned: UnsignedEvent): Promise<Event>;
@@ -77,49 +77,47 @@ type Nip46SubscribeOptions = {
77
77
  * constructed above the signer layer so `signer` never imports `relay` (ADR-0001).
78
78
  */
79
79
  type Nip46Transport = {
80
- subscribe: (relays: string[], filters: Filter[], opts?: Nip46SubscribeOptions) => {
80
+ subscribe: (relays: ReadonlyArray<string>, filters: ReadonlyArray<Filter>, opts?: Nip46SubscribeOptions) => {
81
81
  close: (reason?: string) => void;
82
82
  };
83
- publish: (relays: string[], event: Event) => Promise<ReadonlyArray<{
84
- result?: {
85
- ok: boolean;
86
- message: string;
87
- };
88
- error?: string;
83
+ publish: (relays: ReadonlyArray<string>, event: Event) => Promise<ReadonlyArray<{
84
+ readonly status: "ok" | "rejected" | "failed";
85
+ readonly message?: string;
86
+ readonly error?: Error;
89
87
  }>>;
90
- close: (urls?: string[]) => void;
88
+ close: () => void;
91
89
  };
92
90
  /** Options for {@link Nip46Signer}: transport, timeouts, and relay hints. */
93
91
  type Nip46SignerOptions = {
94
92
  /** Shared transport. When set, the signer does not close it on {@link Nip46Signer.close}. */
95
- pool?: Nip46Transport;
93
+ pool?: Nip46Transport | undefined;
96
94
  /**
97
95
  * Factory for a private transport when `pool` is omitted. Typical: `() => new Pool({
98
96
  * websocketImplementation, enableReconnect: true })`.
99
97
  */
100
- createPool?: () => Nip46Transport;
98
+ createPool?: (() => Nip46Transport) | undefined;
101
99
  /**
102
100
  * Relays used when the bunker pointer has none, and merged uniquely onto a nonempty pointer
103
101
  * (pointer first).
104
102
  */
105
- relays?: string[];
103
+ relays?: ReadonlyArray<string> | undefined;
106
104
  /** Bunker connection secret when the pointer or bunker:// URL has none. */
107
105
  secret?: string | undefined;
108
106
  /** Local client key used to encrypt RPC (not the remote user key). */
109
- clientSecretKey?: SecretKey | Uint8Array | string;
107
+ clientSecretKey?: SecretKeyInput | undefined;
110
108
  /** Called when bunker returns `auth_url` for a pending request. */
111
- onAuthUrl?: (url: string) => void;
109
+ onAuthUrl?: ((url: string) => void) | undefined;
112
110
  /** Per-request timeout in ms. Default 30s. */
113
- timeoutMs?: number;
111
+ timeoutMs?: number | undefined;
114
112
  /**
115
113
  * Timeout in ms applied after the bunker replies `auth_url`: the request keeps waiting for the
116
114
  * real response until this elapses. Default 300s.
117
115
  */
118
- authTimeoutMs?: number;
116
+ authTimeoutMs?: number | undefined;
119
117
  /** Requested permissions sent with `connect` (`method[:kind]` list). */
120
- perms?: string[];
118
+ perms?: ReadonlyArray<string> | undefined;
121
119
  /** Client metadata sent with bunker-initiated `connect`. */
122
- metadata?: ClientMetadata;
120
+ metadata?: ClientMetadata | undefined;
123
121
  };
124
122
  /**
125
123
  * NIP-46 remote signer (bunker / nostrconnect). Implements {@link NostrSigner}; never holds the
@@ -136,7 +134,7 @@ declare class Nip46Signer implements NostrSigner {
136
134
  * identity.
137
135
  */
138
136
  static fromBunker(pointer: BunkerPointer, opts: Nip46SignerOptions & {
139
- clientSecretKey: SecretKey | Uint8Array | string;
137
+ clientSecretKey: SecretKeyInput;
140
138
  }): Nip46Signer;
141
139
  /**
142
140
  * Connect using a `bunker://` URL or pre-parsed pointer. Invalid strings throw. A NIP-05
@@ -150,13 +148,13 @@ declare class Nip46Signer implements NostrSigner {
150
148
  * {@link createNostrConnectURI} after generating keys).
151
149
  */
152
150
  static fromNostrConnectURI(connectionURI: string, opts: Nip46SignerOptions & {
153
- clientSecretKey: SecretKey | Uint8Array | string;
151
+ clientSecretKey: SecretKeyInput;
154
152
  signal?: AbortSignal;
155
153
  handshakeTimeoutMs?: number;
156
154
  }): Promise<Nip46Signer>;
157
155
  connectRemote(overrides?: {
158
- metadata?: ClientMetadata;
159
- perms?: string[];
156
+ metadata?: ClientMetadata | undefined;
157
+ perms?: ReadonlyArray<string> | undefined;
160
158
  }): Promise<void>;
161
159
  /**
162
160
  * Ask the bunker for its preferred relay list and resubscribe when it changes. Spec result is a
@@ -176,4 +174,4 @@ declare class Nip46Signer implements NostrSigner {
176
174
  }
177
175
  //#endregion
178
176
  export { Nip07Signer as a, isNip07Available as c, Nip46Transport as i, KeysSigner as l, Nip46SignerOptions as n, WindowNostr as o, Nip46SubscribeOptions as r, getWindowNostr as s, Nip46Signer as t, NoSignerError as u };
179
- //# sourceMappingURL=index-MxC28S4P.d.mts.map
177
+ //# sourceMappingURL=index-C_w2WfVz.d.mts.map