@qntx/nostr 0.1.0 → 0.2.1

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 (186) hide show
  1. package/README.md +16 -0
  2. package/dist/abort-Ba8tDrOI.mjs +38 -0
  3. package/dist/abort-Ba8tDrOI.mjs.map +1 -0
  4. package/dist/{builder-BphJa-Y-.d.mts → builder-BWn55Paf.d.mts} +20 -14
  5. package/dist/{builder-q0VsvnYE.mjs → builder-CyrGKRVP.mjs} +32 -16
  6. package/dist/builder-CyrGKRVP.mjs.map +1 -0
  7. package/dist/{client-Bd8B1mYm.mjs → client-5DhgYV7P.mjs} +372 -195
  8. package/dist/client-5DhgYV7P.mjs.map +1 -0
  9. package/dist/client.d.mts +1 -1
  10. package/dist/client.mjs +1 -1
  11. package/dist/core.d.mts +8 -8
  12. package/dist/core.mjs +8 -9
  13. package/dist/error-BW7re1UN.d.mts +9 -0
  14. package/dist/error-B__OMBRY.mjs +14 -0
  15. package/dist/error-B__OMBRY.mjs.map +1 -0
  16. package/dist/{error-WEFS-R-4.d.mts → error-CR8Urc84.d.mts} +20 -8
  17. package/dist/{error-CwBxle6N.mjs → error-DrEIM7FO.mjs} +5 -3
  18. package/dist/error-DrEIM7FO.mjs.map +1 -0
  19. package/dist/{event-CzoQEFMF.mjs → event-D8Nfoh4K.mjs} +40 -32
  20. package/dist/event-D8Nfoh4K.mjs.map +1 -0
  21. package/dist/{event-B5D2jxt_.d.mts → event-fU3Y01PR.d.mts} +23 -20
  22. package/dist/{filter-BxwjEkZp.mjs → filter-BQl3GlHt.mjs} +42 -35
  23. package/dist/filter-BQl3GlHt.mjs.map +1 -0
  24. package/dist/filter-C0IMByE3.d.mts +37 -0
  25. package/dist/{gossip-C5RVB1UB.d.mts → gossip-BRQwIM_q.d.mts} +25 -23
  26. package/dist/{gossip-3xkRRCm_.mjs → gossip-oloDMWEj.mjs} +52 -34
  27. package/dist/gossip-oloDMWEj.mjs.map +1 -0
  28. package/dist/gossip.d.mts +1 -1
  29. package/dist/gossip.mjs +1 -1
  30. package/dist/{http-6vevbBlu.d.mts → http-C4HwIu4B.d.mts} +7 -7
  31. package/dist/{http-D2rhokZo.mjs → http-CuazNRIP.mjs} +10 -6
  32. package/dist/http-CuazNRIP.mjs.map +1 -0
  33. package/dist/index-B-CGNDPS.d.mts +207 -0
  34. package/dist/index-BIhSADwK.d.mts +339 -0
  35. package/dist/{index-BYMnhRIC.d.mts → index-Ba7bJ7DD.d.mts} +68 -50
  36. package/dist/{index-DaRyjo7O.d.mts → index-Boe8FshM.d.mts} +13 -7
  37. package/dist/index-D-TK_KJG.d.mts +84 -0
  38. package/dist/index-D1bqFHKB.d.mts +188 -0
  39. package/dist/index.d.mts +22 -20
  40. package/dist/index.mjs +19 -18
  41. package/dist/{key-Dn-aX4x4.mjs → key-Bbtys6o7.mjs} +22 -14
  42. package/dist/key-Bbtys6o7.mjs.map +1 -0
  43. package/dist/{key-BiGxGLhg.d.mts → key-BlsYhN1V.d.mts} +9 -6
  44. package/dist/{kind-BLl4cLOc.mjs → kind-Cxwhhkx8.mjs} +2 -1
  45. package/dist/kind-Cxwhhkx8.mjs.map +1 -0
  46. package/dist/{loaders-BNQszDAn.mjs → loaders-o6YXB_Ri.mjs} +329 -305
  47. package/dist/loaders-o6YXB_Ri.mjs.map +1 -0
  48. package/dist/loaders.d.mts +3 -3
  49. package/dist/loaders.mjs +2 -2
  50. package/dist/memory-C2EVx0_O.mjs +46 -0
  51. package/dist/memory-C2EVx0_O.mjs.map +1 -0
  52. package/dist/{memory-BCmhZPek.mjs → memory-index-Do1mz0WF.mjs} +212 -82
  53. package/dist/memory-index-Do1mz0WF.mjs.map +1 -0
  54. package/dist/{message-C_Uj-Y-c.mjs → message-DcY6Fi9o.mjs} +38 -24
  55. package/dist/message-DcY6Fi9o.mjs.map +1 -0
  56. package/dist/{message-DJC-Jz6T.d.mts → message-iGPIqnn0.d.mts} +15 -8
  57. package/dist/{nip17-BWq-Kfq5.d.mts → nip17-DNEkz8rM.d.mts} +18 -17
  58. package/dist/{nip19-D7905oIv.d.mts → nip19-BevCJZsp.d.mts} +23 -3
  59. package/dist/{nip46-C_DoxiS_.d.mts → nip46-DDV4dC56.d.mts} +13 -12
  60. package/dist/{nip59-DljW_sYh.d.mts → nip59-zQgdLcEr.d.mts} +28 -25
  61. package/dist/{nip65-Di5hZRuV.d.mts → nip65-DBfh2smt.d.mts} +8 -3
  62. package/dist/{nip77-ByxlgoQO.d.mts → nip77-DH4RhS5r.d.mts} +9 -8
  63. package/dist/nips/blossom.d.mts +37 -37
  64. package/dist/nips/blossom.mjs +67 -52
  65. package/dist/nips/blossom.mjs.map +1 -1
  66. package/dist/nips/nip04.d.mts +2 -3
  67. package/dist/nips/nip04.mjs +6 -10
  68. package/dist/nips/nip04.mjs.map +1 -1
  69. package/dist/nips/nip05.d.mts +37 -43
  70. package/dist/nips/nip05.mjs +57 -57
  71. package/dist/nips/nip05.mjs.map +1 -1
  72. package/dist/nips/nip10.d.mts +18 -19
  73. package/dist/nips/nip10.mjs +76 -61
  74. package/dist/nips/nip10.mjs.map +1 -1
  75. package/dist/nips/nip11.d.mts +9 -8
  76. package/dist/nips/nip11.mjs +14 -11
  77. package/dist/nips/nip11.mjs.map +1 -1
  78. package/dist/nips/nip13.d.mts +9 -9
  79. package/dist/nips/nip13.mjs +15 -17
  80. package/dist/nips/nip13.mjs.map +1 -1
  81. package/dist/nips/nip17.d.mts +1 -1
  82. package/dist/nips/nip17.mjs +17 -12
  83. package/dist/nips/nip17.mjs.map +1 -1
  84. package/dist/nips/nip19.d.mts +1 -1
  85. package/dist/nips/nip19.mjs +52 -29
  86. package/dist/nips/nip19.mjs.map +1 -1
  87. package/dist/nips/nip21.d.mts +5 -6
  88. package/dist/nips/nip21.mjs +8 -7
  89. package/dist/nips/nip21.mjs.map +1 -1
  90. package/dist/nips/nip27.d.mts +7 -8
  91. package/dist/nips/nip27.mjs +26 -25
  92. package/dist/nips/nip27.mjs.map +1 -1
  93. package/dist/nips/nip42.d.mts +5 -6
  94. package/dist/nips/nip42.mjs +3 -3
  95. package/dist/nips/nip42.mjs.map +1 -1
  96. package/dist/nips/nip44.d.mts +24 -7
  97. package/dist/nips/nip44.mjs +25 -15
  98. package/dist/nips/nip44.mjs.map +1 -1
  99. package/dist/nips/nip46.d.mts +1 -1
  100. package/dist/nips/nip46.mjs +52 -49
  101. package/dist/nips/nip46.mjs.map +1 -1
  102. package/dist/nips/nip49.d.mts +8 -7
  103. package/dist/nips/nip49.mjs +16 -12
  104. package/dist/nips/nip49.mjs.map +1 -1
  105. package/dist/nips/nip51.d.mts +25 -27
  106. package/dist/nips/nip51.mjs +47 -36
  107. package/dist/nips/nip51.mjs.map +1 -1
  108. package/dist/nips/nip57.d.mts +12 -13
  109. package/dist/nips/nip57.mjs +35 -38
  110. package/dist/nips/nip57.mjs.map +1 -1
  111. package/dist/nips/nip59.d.mts +1 -1
  112. package/dist/nips/nip59.mjs +14 -18
  113. package/dist/nips/nip59.mjs.map +1 -1
  114. package/dist/nips/nip65.d.mts +1 -1
  115. package/dist/nips/nip65.mjs +11 -8
  116. package/dist/nips/nip65.mjs.map +1 -1
  117. package/dist/nips/nip77.d.mts +1 -1
  118. package/dist/nips/nip77.mjs +56 -34
  119. package/dist/nips/nip77.mjs.map +1 -1
  120. package/dist/nips/nip96.d.mts +21 -12
  121. package/dist/nips/nip96.mjs +59 -36
  122. package/dist/nips/nip96.mjs.map +1 -1
  123. package/dist/nips/nip98.d.mts +12 -12
  124. package/dist/nips/nip98.mjs +18 -19
  125. package/dist/nips/nip98.mjs.map +1 -1
  126. package/dist/pool-B7p_reAm.d.mts +333 -0
  127. package/dist/{pool-C_j1OmBB.mjs → pool-C2xOcsun.mjs} +792 -568
  128. package/dist/pool-C2xOcsun.mjs.map +1 -0
  129. package/dist/reactive-DDlThDSZ.mjs +324 -0
  130. package/dist/reactive-DDlThDSZ.mjs.map +1 -0
  131. package/dist/reactive-DFpqtIf_.d.mts +66 -0
  132. package/dist/relay.d.mts +5 -4
  133. package/dist/relay.mjs +2 -2
  134. package/dist/report-CHld4uWj.mjs +32 -0
  135. package/dist/report-CHld4uWj.mjs.map +1 -0
  136. package/dist/{signer-CZ6K6FUc.mjs → signer-CKR9EHce.mjs} +107 -72
  137. package/dist/signer-CKR9EHce.mjs.map +1 -0
  138. package/dist/signer.d.mts +3 -3
  139. package/dist/signer.mjs +3 -2
  140. package/dist/storage-xXxLGCVb.mjs +1376 -0
  141. package/dist/storage-xXxLGCVb.mjs.map +1 -0
  142. package/dist/storage.d.mts +4 -4
  143. package/dist/storage.mjs +5 -4
  144. package/dist/store.d.mts +2 -0
  145. package/dist/store.mjs +2 -0
  146. package/dist/testing.d.mts +135 -0
  147. package/dist/testing.mjs +963 -0
  148. package/dist/testing.mjs.map +1 -0
  149. package/dist/types-2pCUprRU.d.mts +47 -0
  150. package/dist/types-CRQEk0Oi.d.mts +19 -0
  151. package/dist/util-LfQirgDk.mjs +113 -0
  152. package/dist/util-LfQirgDk.mjs.map +1 -0
  153. package/dist/wasm.d.mts +4 -4
  154. package/dist/wasm.mjs +54 -55
  155. package/dist/wasm.mjs.map +1 -1
  156. package/dist/websocket-CmeqvAkp.d.mts +27 -0
  157. package/package.json +93 -39
  158. package/dist/builder-q0VsvnYE.mjs.map +0 -1
  159. package/dist/client-Bd8B1mYm.mjs.map +0 -1
  160. package/dist/error-B49rbDzT.d.mts +0 -7
  161. package/dist/error-CwBxle6N.mjs.map +0 -1
  162. package/dist/error-DZEs5OuZ.mjs +0 -24
  163. package/dist/error-DZEs5OuZ.mjs.map +0 -1
  164. package/dist/event-CzoQEFMF.mjs.map +0 -1
  165. package/dist/filter-BxwjEkZp.mjs.map +0 -1
  166. package/dist/filter-DUEKP3q1.d.mts +0 -40
  167. package/dist/gossip-3xkRRCm_.mjs.map +0 -1
  168. package/dist/http-D2rhokZo.mjs.map +0 -1
  169. package/dist/index-C0C4e-Gn.d.mts +0 -55
  170. package/dist/index-DgOugrpF.d.mts +0 -275
  171. package/dist/index-EwL6fHLo.d.mts +0 -267
  172. package/dist/index-k2YhCgsh.d.mts +0 -57
  173. package/dist/key-Dn-aX4x4.mjs.map +0 -1
  174. package/dist/kind-BLl4cLOc.mjs.map +0 -1
  175. package/dist/loaders-BNQszDAn.mjs.map +0 -1
  176. package/dist/memory-BCmhZPek.mjs.map +0 -1
  177. package/dist/message-C_Uj-Y-c.mjs.map +0 -1
  178. package/dist/pool-C_j1OmBB.mjs.map +0 -1
  179. package/dist/pool-DhRi7l-b.d.mts +0 -297
  180. package/dist/signer-CZ6K6FUc.mjs.map +0 -1
  181. package/dist/storage-DOy0iLRE.mjs +0 -870
  182. package/dist/storage-DOy0iLRE.mjs.map +0 -1
  183. package/dist/types-BzyADqnw.d.mts +0 -19
  184. package/dist/types-Dn24TPFs.d.mts +0 -43
  185. package/dist/util-6tfLQ9JF.mjs +0 -73
  186. package/dist/util-6tfLQ9JF.mjs.map +0 -1
@@ -1,22 +1,22 @@
1
1
  //#region src/nips/http.d.ts
2
2
  /**
3
- * Shared nips HTTP primitive. Not a pack entry (core has zero network).
4
- * Callers never pass `redirect`; sendManual always sets `"manual"`.
3
+ * Shared nips HTTP primitive. Not a pack entry (core has zero network). Callers never pass
4
+ * `redirect`; sendManual always sets `"manual"`.
5
5
  */
6
6
  type ManualFetch = (url: string, init?: {
7
7
  method?: string;
8
8
  headers?: Record<string, string>;
9
9
  body?: Blob | FormData | string | null;
10
- signal?: AbortSignal;
10
+ signal?: AbortSignal | undefined;
11
11
  }) => Promise<{
12
12
  ok: boolean;
13
13
  status: number;
14
14
  headers: {
15
- get(name: string): string | null;
15
+ get: (name: string) => string | null;
16
16
  };
17
- json(): Promise<unknown>;
18
- arrayBuffer(): Promise<ArrayBuffer>;
17
+ json: () => Promise<unknown>;
18
+ arrayBuffer: () => Promise<ArrayBuffer>;
19
19
  }>;
20
20
  //#endregion
21
21
  export { ManualFetch as t };
22
- //# sourceMappingURL=http-6vevbBlu.d.mts.map
22
+ //# sourceMappingURL=http-C4HwIu4B.d.mts.map
@@ -1,11 +1,15 @@
1
1
  //#region src/nips/http.ts
2
2
  function requireGlobalFetch(missing) {
3
3
  if (typeof globalThis.fetch !== "function") throw missing();
4
- return globalThis.fetch.bind(globalThis);
4
+ const fetchImpl = globalThis.fetch.bind(globalThis);
5
+ return async (url, init) => fetchImpl(url, init === void 0 ? init : {
6
+ ...init,
7
+ signal: init.signal ?? null
8
+ });
5
9
  }
6
10
  /** Always sets redirect:manual. Shared by fetchManual and headStatus. */
7
11
  async function sendManual(fetchImpl, url, init) {
8
- return await fetchImpl(url, {
12
+ return fetchImpl(url, {
9
13
  ...init,
10
14
  redirect: "manual"
11
15
  });
@@ -13,12 +17,12 @@ async function sendManual(fetchImpl, url, init) {
13
17
  async function fetchManual(fetchImpl, url, init, wrapNetwork) {
14
18
  try {
15
19
  return await sendManual(fetchImpl, url, init);
16
- } catch (err) {
17
- if (err instanceof Error && err.name === "AbortError") throw err;
18
- throw wrapNetwork(err);
20
+ } catch (error) {
21
+ if (error instanceof Error && error.name === "AbortError") throw error;
22
+ throw wrapNetwork(error);
19
23
  }
20
24
  }
21
25
  //#endregion
22
26
  export { requireGlobalFetch as n, sendManual as r, fetchManual as t };
23
27
 
24
- //# sourceMappingURL=http-D2rhokZo.mjs.map
28
+ //# sourceMappingURL=http-CuazNRIP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-CuazNRIP.mjs","names":[],"sources":["../src/nips/http.ts"],"sourcesContent":["/**\n * Shared nips HTTP primitive. Not a pack entry (core has zero network). Callers never pass\n * `redirect`; sendManual always sets `\"manual\"`.\n */\n\nexport type ManualFetch = (\n url: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n // oxlint-disable-next-line no-restricted-types -- mirrors RequestInit.body, which is nullable\n body?: Blob | FormData | string | null;\n signal?: AbortSignal | undefined;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n // oxlint-disable-next-line no-restricted-types -- mirrors Headers.get, which returns null\n headers: { get: (name: string) => string | null };\n json: () => Promise<unknown>;\n arrayBuffer: () => Promise<ArrayBuffer>;\n}>;\n\ntype ManualInit = NonNullable<Parameters<ManualFetch>[1]>;\n\nexport function requireGlobalFetch(missing: () => Error): ManualFetch {\n if (typeof globalThis.fetch !== \"function\") {\n throw missing();\n }\n const fetchImpl = globalThis.fetch.bind(globalThis);\n // RequestInit.signal is AbortSignal | null and rejects explicit undefined under\n // exactOptionalPropertyTypes; normalize it for the real fetch.\n return async (url, init) =>\n fetchImpl(url, init === undefined ? init : { ...init, signal: init.signal ?? null });\n}\n\n/** Always sets redirect:manual. Shared by fetchManual and headStatus. */\nexport async function sendManual(\n fetchImpl: ManualFetch,\n url: string,\n init: ManualInit,\n): Promise<Awaited<ReturnType<ManualFetch>>> {\n return fetchImpl(url, { ...init, redirect: \"manual\" } as Parameters<ManualFetch>[1]);\n}\n\nexport async function fetchManual(\n fetchImpl: ManualFetch,\n url: string,\n init: ManualInit,\n wrapNetwork: (err: unknown) => Error,\n): Promise<Awaited<ReturnType<ManualFetch>>> {\n try {\n return await sendManual(fetchImpl, url, init);\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n throw error;\n }\n throw wrapNetwork(error);\n }\n}\n"],"mappings":";AAyBA,SAAgB,mBAAmB,SAAmC;CACpE,IAAI,OAAO,WAAW,UAAU,YAC9B,MAAM,QAAQ;CAEhB,MAAM,YAAY,WAAW,MAAM,KAAK,UAAU;CAGlD,OAAO,OAAO,KAAK,SACjB,UAAU,KAAK,SAAS,KAAA,IAAY,OAAO;EAAE,GAAG;EAAM,QAAQ,KAAK,UAAU;CAAK,CAAC;AACvF;;AAGA,eAAsB,WACpB,WACA,KACA,MAC2C;CAC3C,OAAO,UAAU,KAAK;EAAE,GAAG;EAAM,UAAU;CAAS,CAA+B;AACrF;AAEA,eAAsB,YACpB,WACA,KACA,MACA,aAC2C;CAC3C,IAAI;EACF,OAAO,MAAM,WAAW,WAAW,KAAK,IAAI;CAC9C,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,MAAM,SAAS,cAC3C,MAAM;EAER,MAAM,YAAY,KAAK;CACzB;AACF"}
@@ -0,0 +1,207 @@
1
+ import { t as Event } from "./event-fU3Y01PR.mjs";
2
+ import { n as ProfileMetadata } from "./builder-BWn55Paf.mjs";
3
+ import { t as RelayListItem } from "./nip65-DBfh2smt.mjs";
4
+ import { t as Gossip } from "./gossip-BRQwIM_q.mjs";
5
+ import { a as NostrError } from "./error-CR8Urc84.mjs";
6
+ import { n as Pool } from "./pool-B7p_reAm.mjs";
7
+ import { r as OutboxBound, t as EventStore } from "./types-2pCUprRU.mjs";
8
+ import { t as ReactiveEventStore } from "./reactive-DFpqtIf_.mjs";
9
+ import { i as EventPointer, t as AddressPointer } from "./nip19-BevCJZsp.mjs";
10
+ //#region src/loaders/event.d.ts
11
+ type EventRef = string | EventPointer | AddressPointer;
12
+ /**
13
+ * Resolve an event reference (hex id, note, nevent, naddr, or pointer object) through the reactive
14
+ * index, fetching from relays on a miss. The index is the durable store — the loader keeps only
15
+ * in-flight coalescing, so a miss never blocks a later retry.
16
+ */
17
+ type EventLoader = {
18
+ load: (ref: EventRef) => Promise<Event | undefined>;
19
+ };
20
+ //#endregion
21
+ //#region src/loaders/replaceable.d.ts
22
+ /** Result of a replaceable load: the winning event (or none) and freshness. */
23
+ type ReplaceableLoadResult = {
24
+ event: Event | undefined;
25
+ fresh: boolean;
26
+ };
27
+ /** `default`: fetch when stale or unfetched; `force`: always fetch; `cache-only`: index only. */
28
+ type LoadStyle = "default" | "force" | "cache-only";
29
+ /** Loads the winning replaceable/addressable event of one kind for a pubkey. */
30
+ type ReplaceableLoader = (pubkey: string, opts?: {
31
+ hints?: string[] | undefined;
32
+ style?: LoadStyle | undefined;
33
+ }) => Promise<ReplaceableLoadResult>;
34
+ //#endregion
35
+ //#region src/loaders/lists.d.ts
36
+ /** Result of a list loader: the source event, its decoded items, and freshness. */
37
+ 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;
55
+ };
56
+ type ListLoaderOpts = {
57
+ hints?: string[] | undefined;
58
+ style?: LoadStyle | undefined;
59
+ };
60
+ type ListLoaders = {
61
+ follows: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<string>>;
62
+ muteList: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<MutedEntity>>;
63
+ relayList: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<RelayListItem>>;
64
+ dmRelayList: (pubkey: string, opts?: ListLoaderOpts) => Promise<ListResult<string>>;
65
+ };
66
+ //#endregion
67
+ //#region src/loaders/profile.d.ts
68
+ /** A profile-card view of a pubkey: identity fields plus the kind:0 event. */
69
+ 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;
78
+ };
79
+ /** A {@link NostrUser} with no metadata — used when no kind:0 event exists. */
80
+ declare function bareNostrUser(pubkey: string): NostrUser;
81
+ type ProfileLoader = {
82
+ load: (pubkey: string, opts?: {
83
+ hints?: string[] | undefined;
84
+ style?: LoadStyle | undefined;
85
+ }) => Promise<NostrUser>;
86
+ };
87
+ //#endregion
88
+ //#region src/loaders/outbox.d.ts
89
+ /** Outbox feed lifecycle error (e.g. use after close). */
90
+ declare class OutboxError extends NostrError {
91
+ name: string;
92
+ }
93
+ /** Options for {@link createOutboxFeed}. */
94
+ type OutboxFeedOptions = {
95
+ pool: Pool;
96
+ gossip: Gossip;
97
+ storage: EventStore;
98
+ /** Fallback relays when an author has no known outbox routes. */
99
+ discoveryRelays: ReadonlyArray<string>;
100
+ authors: ReadonlyArray<string>;
101
+ /** Event kinds to fetch. Default `[Kind.TextNote]`. */
102
+ kinds?: ReadonlyArray<number> | undefined;
103
+ /** Max write-relays to use per author. Default 3. */
104
+ maxRelaysPerAuthor?: number | undefined;
105
+ fetchTimeoutMs?: number | undefined;
106
+ /** Called for live events after observe, and for sync events returned by applySync. */
107
+ onEvent?: ((event: Event) => void) | undefined;
108
+ /** Live ingest (e.g. `client.observe`) with the source relay URL. StartLive never putManys. */
109
+ observe?: ((event: Event, relayUrl: string) => void) | undefined;
110
+ /**
111
+ * Every receipt from every relay — live (including duplicates the feed's own dedupe skips) and
112
+ * sync fetch batches — for seenOn bookkeeping.
113
+ */
114
+ seen?: ((event: Event, relayUrl: string) => void) | undefined;
115
+ /**
116
+ * Sync path only. Awaited. Return events that should advance bounds. Throw → sync throws, bounds
117
+ * unchanged.
118
+ */
119
+ applySync?: ((events: ReadonlyArray<Event>) => Promise<ReadonlyArray<Event>>) | undefined;
120
+ /** Load kind:10002 for authors before sync when routes are missing. Requires a relay-list loader. */
121
+ hydrate?: ((pubkeys: ReadonlyArray<string>) => Promise<void>) | undefined;
122
+ };
123
+ /**
124
+ * Group authors by outbox relay (discovery fallback). `prefer` reorders existing candidates only;
125
+ * it never appends a URL that is not already in the author's outbox or discovery list. Returns
126
+ * Map<relayUrl, authors[]>.
127
+ */
128
+ declare function groupAuthorsByOutboxRelay(authors: ReadonlyArray<string>, gossip: Gossip, discoveryRelays: ReadonlyArray<string>, maxRelaysPerAuthor?: number, prefer?: ReadonlyArray<string>): Map<string, string[]>;
129
+ /**
130
+ * Outbox-model feed: history sync + live subscription for a set of authors, routed via NIP-65 write
131
+ * relays (with discovery fallback).
132
+ */
133
+ declare class OutboxFeed {
134
+ #private;
135
+ constructor(opts: OutboxFeedOptions);
136
+ get authors(): ReadonlyArray<string>;
137
+ get kinds(): ReadonlyArray<number>;
138
+ /** Replace the author set (does not auto-restart live). */
139
+ setAuthors(authors: ReadonlyArray<string>): void;
140
+ getBound(pubkey: string, kind: number): OutboxBound | undefined;
141
+ /** Load NIP-65 relay lists for authors that have no outbox routes yet. */
142
+ hydrate(): Promise<void>;
143
+ /** One-shot history pull. Persistence is `applySync`; bounds move only for events it returns. */
144
+ sync(opts?: {
145
+ limit?: number | undefined;
146
+ since?: number | undefined;
147
+ until?: number | undefined;
148
+ signal?: AbortSignal | undefined;
149
+ /** Skip hydrate() even if provided. */
150
+ skipHydrate?: boolean | undefined;
151
+ }): Promise<Event[]>;
152
+ /**
153
+ * Start a live subscription across outbox relays for the current authors. Closes any previous
154
+ * live subscription.
155
+ */
156
+ startLive(opts?: {
157
+ signal?: AbortSignal | undefined;
158
+ since?: number | undefined;
159
+ }): {
160
+ close: (reason?: string) => void;
161
+ };
162
+ /** Convenience: hydrate + sync + startLive. */
163
+ start(opts?: {
164
+ limit?: number | undefined;
165
+ signal?: AbortSignal | undefined;
166
+ }): Promise<{
167
+ close: (reason?: string) => void;
168
+ events: Event[];
169
+ }>;
170
+ close(): void;
171
+ }
172
+ /** Factory matching other loaders helpers. */
173
+ declare function createOutboxFeed(opts: OutboxFeedOptions): OutboxFeed;
174
+ //#endregion
175
+ //#region src/loaders/index.d.ts
176
+ /** The loader surface returned by {@link createLoaders}. */
177
+ type Loaders = {
178
+ follows: ListLoaders["follows"];
179
+ muteList: ListLoaders["muteList"];
180
+ relayList: ListLoaders["relayList"];
181
+ dmRelayList: ListLoaders["dmRelayList"];
182
+ profile: ProfileLoader["load"];
183
+ event: EventLoader["load"];
184
+ /** Generic replaceable loader for any kind; memoized per kind. */
185
+ replaceable: (kind: number) => ReplaceableLoader;
186
+ addRelay: (url: string) => void;
187
+ removeRelay: (url: string) => void;
188
+ };
189
+ /** Options for {@link createLoaders}. */
190
+ type CreateLoadersOptions = {
191
+ pool: Pool;
192
+ relays: ReadonlyArray<string>;
193
+ /** The reactive index loaders read from and feed fetched events into. */
194
+ index: ReactiveEventStore;
195
+ /**
196
+ * Inbound-event sink for fetched events; defaults to `index.add`. Client wires its single ingest
197
+ * path so loader fetches get gossip meta and persistence like every other inbound event.
198
+ */
199
+ ingest?: (event: Event, relayUrl: string) => void;
200
+ staleAfterSec?: number;
201
+ fetchTimeoutMs?: number;
202
+ };
203
+ /** Build an instance-scoped loader suite (no module globals). */
204
+ declare function createLoaders(opts: CreateLoadersOptions): Loaders;
205
+ //#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-B-CGNDPS.d.mts.map
@@ -0,0 +1,339 @@
1
+ import { n as EventTemplate, r as UnsignedEvent, t as Event } from "./event-fU3Y01PR.mjs";
2
+ import { t as EventBuilder } from "./builder-BWn55Paf.mjs";
3
+ import { t as Filter } from "./filter-C0IMByE3.mjs";
4
+ import { t as Gossip } from "./gossip-BRQwIM_q.mjs";
5
+ import { a as NostrError } from "./error-CR8Urc84.mjs";
6
+ import { a as PoolPublishResult, n as Pool, t as InvalidEventPolicy } from "./pool-B7p_reAm.mjs";
7
+ import { t as WebSocketConstructor } from "./websocket-CmeqvAkp.mjs";
8
+ import { t as EventStore } from "./types-2pCUprRU.mjs";
9
+ import { t as ReactiveEventStore } from "./reactive-DFpqtIf_.mjs";
10
+ import { a as OutboxFeed, n as Loaders } from "./index-B-CGNDPS.mjs";
11
+ import { a as Rumor } from "./nip59-zQgdLcEr.mjs";
12
+ import { i as ReplyTo, r as Recipient } from "./nip17-DNEkz8rM.mjs";
13
+ import { t as NostrSigner } from "./types-CRQEk0Oi.mjs";
14
+ import { t as StorageError } from "./error-BW7re1UN.mjs";
15
+ //#region src/client/types.d.ts
16
+ /** Direction of a {@link Client.sync} run: upload, download, or both. */
17
+ declare const SyncDirection: {
18
+ readonly Up: "up";
19
+ readonly Down: "down";
20
+ readonly Both: "both";
21
+ };
22
+ /** Union of the {@link SyncDirection} values. */
23
+ type SyncDirectionName = (typeof SyncDirection)[keyof typeof SyncDirection];
24
+ /** Options for {@link Client.sync} (NIP-77 set reconciliation). */
25
+ type SyncOptions = {
26
+ relays?: ReadonlyArray<string>;
27
+ direction?: SyncDirectionName;
28
+ /**
29
+ * Wall-clock deadline for the Negentropy reconciliation session (`NEG-OPEN` through `NEG-CLOSE`),
30
+ * in milliseconds. One clock for the whole session — not reset per `NEG-MSG`. Default: the relay
31
+ * `publishTimeoutMs`. Upload/download phases reuse this value as their per-call timeout.
32
+ */
33
+ timeoutMs?: number;
34
+ signal?: AbortSignal;
35
+ dryRun?: boolean;
36
+ /** When false, skip observe/storage on downloaded events. Default true. */
37
+ observe?: boolean;
38
+ };
39
+ /** Outcome of a {@link Client.sync} run: ids compared, sent, received, and failures. */
40
+ type SyncSummary = {
41
+ local: string[];
42
+ remote: string[];
43
+ sent: string[];
44
+ received: string[];
45
+ sendFailures: Record<string, string>;
46
+ persistFailures: Record<string, string>;
47
+ };
48
+ /** Options for {@link Client.builder} / `ClientOptions` accepted by the builder. */
49
+ type ClientOptions = {
50
+ signer?: NostrSigner;
51
+ relays?: ReadonlyArray<string>;
52
+ websocketImplementation?: WebSocketConstructor;
53
+ /** Injected EVENT verifier. Default is core BIP-340. */
54
+ verifyEvent?: (event: Event) => boolean;
55
+ connectTimeoutMs?: number;
56
+ publishTimeoutMs?: number;
57
+ /**
58
+ * When true (default), answer NIP-42 AUTH automatically. The signer is read at challenge time, so
59
+ * `setSigner()` applies to live connections; challenges received while no signer is set are
60
+ * ignored.
61
+ */
62
+ automaticAuth?: boolean;
63
+ /** When true (default), relays reconnect with backoff after disconnect. */
64
+ enableReconnect?: boolean;
65
+ /** Keepalive ping. Default false. */
66
+ enablePing?: boolean;
67
+ pingIntervalMs?: number;
68
+ pingTimeoutMs?: number;
69
+ /** Forwarded to the pool: when false (default), `ws://` relays are rejected. */
70
+ allowInsecure?: boolean;
71
+ /** Forwarded to the pool: `ws://` URLs allowed despite `allowInsecure`. */
72
+ trustedInsecureUrls?: ReadonlyArray<string>;
73
+ /** Forwarded to the pool: close idle relays after this many ms. */
74
+ idleTimeoutMs?: number;
75
+ /** Forwarded to the pool: soft cap on connected non-pinned relays. */
76
+ maxRelays?: number;
77
+ /** Forwarded to the pool: relays never closed by idle cleanup or `maxRelays`. */
78
+ pinnedUrls?: ReadonlyArray<string>;
79
+ /**
80
+ * Forwarded to the pool: a relay exceeding `limit` verification failures inside `windowMs` is
81
+ * disconnected and suspended for `cooldownMs`.
82
+ */
83
+ invalidEventPolicy?: InvalidEventPolicy;
84
+ /** Forwarded to the pool: fired once when a relay is suspended, with the lift time. */
85
+ onRelaySuspended?: (url: string, until: number) => void;
86
+ gossip?: Gossip;
87
+ /**
88
+ * Local event store. Defaults to {@link MemoryEventStore}. Browser apps that want persistence must
89
+ * pass {@link IndexedDbEventStore} and `await open()`.
90
+ */
91
+ storage?: EventStore;
92
+ /**
93
+ * Synchronous reactive index that mirrors every ingested event before callbacks and persistence.
94
+ * Defaults to a new {@link ReactiveEventStore}.
95
+ */
96
+ index?: ReactiveEventStore;
97
+ /**
98
+ * When true (default), every ingested event is written to storage. Set false to disable automatic
99
+ * persistence while keeping the store for manual use.
100
+ */
101
+ persistEvents?: boolean;
102
+ /**
103
+ * Storage I/O failures: live `putMany` flush and `fetchEvents({ localFirst: true })` query. Those
104
+ * paths do not throw.
105
+ */
106
+ onstorageerror?: (err: StorageError) => void;
107
+ };
108
+ type FetchEventsOptions = {
109
+ relays?: string[];
110
+ timeoutMs?: number;
111
+ signal?: AbortSignal;
112
+ gossip?: boolean;
113
+ /** When true, query local storage first and merge with network results. Defaults to false. */
114
+ localFirst?: boolean;
115
+ /** When false, skip writing fetched events to storage/observe. Default true. */
116
+ observe?: boolean;
117
+ /**
118
+ * Every event of every relay batch, including duplicates across relays. `relayUrl` is the
119
+ * normalized URL of the relay that delivered it.
120
+ */
121
+ onevent?: (event: Event, relayUrl: string) => void;
122
+ };
123
+ type SubscribeOptions = {
124
+ relays?: string[];
125
+ /**
126
+ * First receipt of each event only (deduped across relays). `relayUrl` is the normalized URL of
127
+ * the relay that delivered it first.
128
+ */
129
+ onevent?: (event: Event, relayUrl: string) => void;
130
+ /** Every receipt from every relay, including duplicates skipped by dedupe. */
131
+ receivedEvent?: (id: string, relayUrl: string) => void;
132
+ oneose?: () => void;
133
+ onclose?: (reason: string) => void;
134
+ signal?: AbortSignal;
135
+ id?: string;
136
+ /**
137
+ * If set, fire `oneose` once after this many ms if not all relays have EOSEd. Does not close the
138
+ * subscription.
139
+ */
140
+ eoseTimeoutMs?: number;
141
+ /** Fan out REQs via NIP-65 gossip routes when available. */
142
+ gossip?: boolean;
143
+ /** When false, skip writing received events to storage/observe. Default true. */
144
+ observe?: boolean;
145
+ };
146
+ type PublishOptions = {
147
+ relays?: string[];
148
+ timeoutMs?: number;
149
+ gossip?: boolean;
150
+ /** When false, skip writing the published event to storage/observe. Default true. */
151
+ observe?: boolean;
152
+ };
153
+ /** Options for sending a NIP-17 private message. */
154
+ type SendPrivateMessageOptions = {
155
+ readonly subject?: string;
156
+ readonly replyTo?: ReplyTo;
157
+ readonly created_at?: number;
158
+ readonly timeoutMs?: number;
159
+ readonly observe?: boolean;
160
+ };
161
+ /** Result of sending a NIP-17 DM: the rumor plus per-recipient wrap publish results. */
162
+ type PrivateMessageSendResult = {
163
+ rumor: Rumor;
164
+ wraps: ReadonlyArray<{
165
+ recipient: string;
166
+ wrap: Event;
167
+ results: PoolPublishResult[];
168
+ }>;
169
+ };
170
+ /** An unwrapped NIP-17 private message: the received gift wrap and its inner rumor. */
171
+ type ReceivedPrivateMessage = {
172
+ wrap: Event;
173
+ rumor: Rumor;
174
+ /** Normalized URL of the relay that delivered the wrap, when known. */
175
+ relayUrl?: string;
176
+ };
177
+ /** Options for fetching NIP-17 private-message history. */
178
+ type FetchPrivateMessagesOptions = {
179
+ readonly since?: number;
180
+ readonly until?: number;
181
+ readonly timeoutMs?: number;
182
+ readonly signal?: AbortSignal;
183
+ readonly observe?: boolean;
184
+ };
185
+ /** Options for a live NIP-17 private-message subscription. */
186
+ type SubscribePrivateMessagesOptions = {
187
+ readonly since?: number;
188
+ readonly onevent?: (msg: ReceivedPrivateMessage) => void;
189
+ readonly oneose?: () => void;
190
+ readonly onclose?: (reason: string) => void;
191
+ readonly signal?: AbortSignal;
192
+ readonly eoseTimeoutMs?: number;
193
+ readonly observe?: boolean;
194
+ };
195
+ /** Client lifecycle, configuration, or abort failure (not cryptographic). */
196
+ declare class ClientError extends NostrError {
197
+ name: string;
198
+ }
199
+ //#endregion
200
+ //#region src/client/builder.d.ts
201
+ /**
202
+ * Fluent constructor for {@link Client}. The constructor is supplied by {@link Client.builder} so
203
+ * this module never imports the `Client` value, keeping the client/builder dependency
204
+ * one-directional.
205
+ */
206
+ declare class ClientBuilder {
207
+ #private;
208
+ constructor(newClient: (opts: ClientOptions) => Client);
209
+ signer(signer: NostrSigner): this;
210
+ relays(urls: ReadonlyArray<string>): this;
211
+ addRelay(url: string): this;
212
+ websocketImplementation(impl: WebSocketConstructor): this;
213
+ verifyEvent(fn: (event: Event) => boolean): this;
214
+ connectTimeoutMs(ms: number): this;
215
+ publishTimeoutMs(ms: number): this;
216
+ automaticAuth(enabled: boolean): this;
217
+ /** Allow `ws://` relays. Default false. */
218
+ allowInsecure(allow: boolean): this;
219
+ /** `ws://` URLs allowed despite `allowInsecure` being off. */
220
+ trustedInsecureUrls(urls: ReadonlyArray<string>): this;
221
+ /** Close idle relays after this many ms. Unset = disabled. */
222
+ idleTimeoutMs(ms: number): this;
223
+ /** Soft cap on connected non-pinned relays. */
224
+ maxRelays(n: number): this;
225
+ /** Relays never closed by idle cleanup or `maxRelays` eviction. */
226
+ pinnedUrls(urls: ReadonlyArray<string>): this;
227
+ /** Forwarded to the pool: suspend a relay delivering too many invalid events. */
228
+ invalidEventPolicy(policy: InvalidEventPolicy): this;
229
+ /** Forwarded to the pool: fired once when a relay is suspended, with the lift time. */
230
+ onRelaySuspended(cb: (url: string, until: number) => void): this;
231
+ enableReconnect(enabled: boolean): this;
232
+ enablePing(enabled: boolean): this;
233
+ pingIntervalMs(ms: number): this;
234
+ pingTimeoutMs(ms: number): this;
235
+ /**
236
+ * Local event store. Defaults to {@link MemoryEventStore}. Browser apps that want persistence must
237
+ * pass {@link IndexedDbEventStore} and `await open()`.
238
+ */
239
+ storage(store: EventStore): this;
240
+ /**
241
+ * Synchronous reactive index mirroring ingested events. Defaults to a new
242
+ * {@link ReactiveEventStore}.
243
+ */
244
+ index(index: ReactiveEventStore): this;
245
+ /** When false, Client will not auto-write events to storage. Default true. */
246
+ persistEvents(enabled: boolean): this;
247
+ gossip(gossip: Gossip): this;
248
+ onstorageerror(fn: (err: StorageError) => void): this;
249
+ build(): Client;
250
+ }
251
+ //#endregion
252
+ //#region src/client/client.d.ts
253
+ /** Layer-5 facade: signer + default relays + pool + loaders + gossip + event store. */
254
+ declare class Client {
255
+ #private;
256
+ readonly pool: Pool;
257
+ readonly loaders: Loaders;
258
+ readonly gossip: Gossip;
259
+ readonly storage: EventStore;
260
+ readonly index: ReactiveEventStore;
261
+ onstorageerror: ((err: StorageError) => void) | undefined;
262
+ constructor(opts?: ClientOptions);
263
+ static builder(): ClientBuilder;
264
+ get signer(): NostrSigner | undefined;
265
+ get relays(): ReadonlyArray<string>;
266
+ get isShutdown(): boolean;
267
+ setSigner(signer: NostrSigner | undefined): void;
268
+ addRelay(url: string): void;
269
+ removeRelay(url: string): void;
270
+ /** Connect all configured relays (best-effort; failures are ignored). */
271
+ connect(opts?: {
272
+ signal?: AbortSignal;
273
+ }): Promise<void>;
274
+ shutdown(): Promise<void>;
275
+ /** Ingest one inbound event: index (with relay URL) → meta → persistence. */
276
+ observe(event: Event, relayUrl?: string): void;
277
+ /** Ingest many events (deduped by id, order preserved) as one persist batch. */
278
+ observeAll(events: ReadonlyArray<Event>): void;
279
+ /**
280
+ * Explicitly load kind:10002 and kind:10050 lists for pubkeys and feed gossip. Does not
281
+ * background-fetch unknown authors on every subscribe (predictable DX).
282
+ */
283
+ hydrateGossip(pubkeys: ReadonlyArray<string>, opts?: {
284
+ hints?: string[];
285
+ force?: boolean;
286
+ }): Promise<void>;
287
+ /**
288
+ * Create an outbox-model feed for the given authors (NIP-65 write relays). Live events go through
289
+ * {@link observe}; sync persists via applySync.
290
+ */
291
+ outbox(opts: {
292
+ authors: ReadonlyArray<string>;
293
+ kinds?: ReadonlyArray<number>;
294
+ onEvent?: (event: Event) => void;
295
+ maxRelaysPerAuthor?: number;
296
+ }): OutboxFeed;
297
+ getPublicKey(): Promise<string>;
298
+ signEvent(unsigned: UnsignedEvent): Promise<Event>;
299
+ signEventBuilder(builder: EventBuilder): Promise<Event>;
300
+ signTemplate(template: EventTemplate): Promise<Event>;
301
+ /**
302
+ * Sign (if builder) and publish to relays. With `gossip: true`, prefers the author's NIP-65
303
+ * outbox relays, tagged `p` inboxes, and up to 5 `e`/`a` tag relay hints when known. On any
304
+ * successful OK, observes the event into storage/gossip.
305
+ */
306
+ publish(eventOrBuilder: Event | EventBuilder, opts?: PublishOptions): Promise<PoolPublishResult[]>;
307
+ /**
308
+ * Fetch events. With `gossip: true`, routes filters by NIP-65 when possible. With `localFirst:
309
+ * true`, merges storage hits with network results.
310
+ */
311
+ fetchEvents(filter: Filter | Filter[], opts?: FetchEventsOptions): Promise<Event[]>;
312
+ /** Query local storage only (no network). */
313
+ queryLocal(filter: Filter | Filter[]): Promise<Event[]>;
314
+ subscribe(filter: Filter | Filter[], opts?: SubscribeOptions): {
315
+ close: (reason?: string) => void;
316
+ };
317
+ /** Publish a kind:10050 NIP-17 DM relay list (`relay` tags). Not kind 10002. */
318
+ setDmRelays(relays: ReadonlyArray<string>, opts?: PublishOptions): Promise<PoolPublishResult[]>;
319
+ sendPrivateMessage(recipients: string | Recipient | ReadonlyArray<string | Recipient>, content: string, opts?: SendPrivateMessageOptions): Promise<PrivateMessageSendResult>;
320
+ fetchPrivateMessages(opts?: FetchPrivateMessagesOptions): Promise<ReceivedPrivateMessage[]>;
321
+ subscribePrivateMessages(opts?: SubscribePrivateMessagesOptions): Promise<{
322
+ close: (reason?: string) => void;
323
+ }>;
324
+ /**
325
+ * NIP-77 sync against one relay: reconcile, then optionally upload local-only events and/or
326
+ * download remote-only events. `observe: false` skips putMany and ingest; received ids are still
327
+ * listed. `persistEvents: false` skips putMany, still ingests when observe is on.
328
+ */
329
+ syncToRelay(url: string, filter: Filter, opts?: Omit<SyncOptions, "relays">): Promise<SyncSummary>;
330
+ /**
331
+ * NIP-77 sync against the given relays (or Client default relays). Independent sessions run in
332
+ * parallel. Fulfilled summaries are merged; if every relay rejects, throws the first rejection in
333
+ * URL order.
334
+ */
335
+ sync(filter: Filter, opts?: SyncOptions): Promise<SyncSummary>;
336
+ }
337
+ //#endregion
338
+ export { FetchEventsOptions as a, PublishOptions as c, SubscribeOptions as d, SubscribePrivateMessagesOptions as f, SyncSummary as g, SyncOptions as h, ClientOptions as i, ReceivedPrivateMessage as l, SyncDirectionName as m, ClientBuilder as n, FetchPrivateMessagesOptions as o, SyncDirection as p, ClientError as r, PrivateMessageSendResult as s, Client as t, SendPrivateMessageOptions as u };
339
+ //# sourceMappingURL=index-BIhSADwK.d.mts.map