@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,89 +1,83 @@
1
- import { a as NostrError } from "../error-WEFS-R-4.mjs";
2
- import { f as ProfilePointer } from "../nip19-D7905oIv.mjs";
3
- import { t as ManualFetch } from "../http-6vevbBlu.mjs";
1
+ import { a as NostrError } from "../error-CR8Urc84.mjs";
2
+ import { f as ProfilePointer } from "../nip19-BevCJZsp.mjs";
3
+ import { t as ManualFetch } from "../http-C4HwIu4B.mjs";
4
4
  //#region src/nips/nip05.d.ts
5
5
  /** Root local-part (`_@domain` rendered as just the domain). */
6
- declare const NIP05_ROOT_LOCAL = "_";
7
- declare const WELL_KNOWN_PATH = "/.well-known/nostr.json";
6
+ export declare const NIP05_ROOT_LOCAL = "_";
7
+ export declare const WELL_KNOWN_PATH = "/.well-known/nostr.json";
8
8
  /**
9
9
  * NIP-05 identifier string.
10
+ *
10
11
  * - Full: `name@domain`
11
12
  * - Root: `domain` or `_@domain`
12
13
  */
13
- type Nip05 = string;
14
- type Nip05Address = {
14
+ export type Nip05 = string;
15
+ export type Nip05Address = {
15
16
  /** Local part (lowercased). `_` for domain-only identifiers. */
16
17
  local: string;
17
18
  /** Domain (lowercased). */
18
19
  domain: string;
19
20
  };
20
- /**
21
- * 46.md appendix discovery metadata (`{relays, nostrconnect_url}`).
22
- * Not a bunker pointer.
23
- */
24
- type Nip05Nip46 = {
21
+ /** 46.md appendix discovery metadata (`{relays, nostrconnect_url}`). Not a bunker pointer. */
22
+ export type Nip05Nip46 = {
25
23
  relays?: string[];
26
24
  nostrconnectUrl?: string;
27
25
  };
28
- type Nip05Document = {
26
+ export type Nip05Document = {
29
27
  names: Record<string, string>;
30
28
  /** NIP-05 profile relay hints */
31
29
  relays?: Record<string, string[]>;
32
30
  nip46?: Nip05Nip46;
33
31
  };
34
- type Nip05Fetch = ManualFetch;
35
- declare class Nip05Error extends NostrError {
32
+ export type Nip05Fetch = ManualFetch;
33
+ export declare class Nip05Error extends NostrError {
34
+ name: string;
36
35
  constructor(message: string, options?: ErrorOptions);
37
36
  }
37
+ /** Matches optional local@domain. Groups: 1=local (optional), 2=domain. */
38
+ export declare const NIP05_REGEX: RegExp;
39
+ export declare function isNip05(value: unknown): value is string;
38
40
  /**
39
- * Matches optional local@domain.
40
- * Groups: 1=local (optional), 2=domain.
41
- */
42
- declare const NIP05_REGEX: RegExp;
43
- declare function isNip05(value: unknown): value is string;
44
- /**
45
- * Parse an identifier into local + domain.
46
- * Accepts `name@domain`, `_@domain`, or bare `domain` (local becomes `_`).
41
+ * Parse an identifier into local + domain. Accepts `name@domain`, `_@domain`, or bare `domain`
42
+ * (local becomes `_`).
47
43
  */
48
- declare function parseNip05(input: string): Nip05Address;
44
+ export declare function parseNip05(input: string): Nip05Address;
49
45
  /** Build the well-known HTTPS URL for an address. */
50
- declare function wellKnownUrl(address: Nip05Address): string;
46
+ export declare function wellKnownUrl(address: Nip05Address): string;
51
47
  /**
52
- * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`.
53
- * Hex-pubkey maps and other keys are ignored.
48
+ * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`. Hex-pubkey maps and other
49
+ * keys are ignored.
54
50
  */
55
- declare function parseNip05Nip46(raw: unknown): Nip05Nip46 | undefined;
51
+ export declare function parseNip05Nip46(raw: unknown): Nip05Nip46 | undefined;
56
52
  /** Parse and validate a nostr.json document body. */
57
- declare function parseNip05Document(json: unknown): Nip05Document;
53
+ export declare function parseNip05Document(json: unknown): Nip05Document;
58
54
  /** Resolve local name from an already-parsed document. */
59
- declare function lookupFromDocument(doc: Nip05Document, address: Nip05Address): ProfilePointer | undefined;
55
+ export declare function lookupFromDocument(doc: Nip05Document, address: Nip05Address): ProfilePointer | undefined;
60
56
  /**
61
- * Fetch and parse `/.well-known/nostr.json`.
62
- * Returns `null` on network/parse failure (does not throw for those).
63
- * Rejects HTTP redirects (non-200) per NIP-05 security constraints.
64
- * AbortError rethrows; it is not mapped to `null`.
57
+ * Fetch and parse `/.well-known/nostr.json`. Returns `undefined` on network/parse failure (does not
58
+ * throw for those). Rejects HTTP redirects (non-200) per NIP-05 security constraints. AbortError
59
+ * rethrows; it is not mapped to `undefined`.
65
60
  */
66
- declare function queryNip05Document(identifier: string, opts?: {
61
+ export declare function queryNip05Document(identifier: string, opts?: {
67
62
  fetch?: Nip05Fetch;
68
63
  signal?: AbortSignal;
69
64
  }): Promise<{
70
65
  address: Nip05Address;
71
66
  doc: Nip05Document;
72
- } | null>;
67
+ } | undefined>;
73
68
  /**
74
- * Query `/.well-known/nostr.json` for an identifier.
75
- * Returns `null` on network/parse/lookup failure (does not throw for those).
76
- * Profile `relays` only. `nip46` is discovery metadata, not a bunker pointer.
69
+ * Query `/.well-known/nostr.json` for an identifier. Returns `undefined` on network/parse/lookup
70
+ * failure (does not throw for those). Profile `relays` only. `nip46` is discovery metadata, not a
71
+ * bunker pointer.
77
72
  */
78
- declare function queryProfile(identifier: string, opts?: {
73
+ export declare function queryProfile(identifier: string, opts?: {
79
74
  fetch?: Nip05Fetch;
80
75
  signal?: AbortSignal;
81
- }): Promise<ProfilePointer | null>;
76
+ }): Promise<ProfilePointer | undefined>;
82
77
  /** True when the identifier resolves to exactly `pubkey`. */
83
- declare function verifyNip05(pubkey: string, identifier: string, opts?: {
78
+ export declare function verifyNip05(pubkey: string, identifier: string, opts?: {
84
79
  fetch?: Nip05Fetch;
85
80
  signal?: AbortSignal;
86
81
  }): Promise<boolean>;
87
82
  //#endregion
88
- export { NIP05_REGEX, NIP05_ROOT_LOCAL, Nip05, Nip05Address, Nip05Document, Nip05Error, Nip05Fetch, Nip05Nip46, WELL_KNOWN_PATH, isNip05, lookupFromDocument, parseNip05, parseNip05Document, parseNip05Nip46, queryNip05Document, queryProfile, verifyNip05, wellKnownUrl };
89
83
  //# sourceMappingURL=nip05.d.mts.map
@@ -1,42 +1,42 @@
1
- import { a as isHex32 } from "../util-6tfLQ9JF.mjs";
2
- import { a as NostrError } from "../error-DZEs5OuZ.mjs";
3
- import { n as requireGlobalFetch, t as fetchManual } from "../http-D2rhokZo.mjs";
1
+ import { c as isRecord, g as NostrError, o as isHex32 } from "../util-LfQirgDk.mjs";
2
+ import { n as requireGlobalFetch, t as fetchManual } from "../http-CuazNRIP.mjs";
4
3
  //#region src/nips/nip05.ts
5
4
  /**
6
5
  * NIP-05: Mapping Nostr keys to DNS-based internet identifiers
6
+ *
7
7
  * @see https://github.com/nostr-protocol/nips/blob/master/05.md
8
8
  */
9
9
  /** Root local-part (`_@domain` rendered as just the domain). */
10
10
  const NIP05_ROOT_LOCAL = "_";
11
11
  const WELL_KNOWN_PATH = "/.well-known/nostr.json";
12
12
  var Nip05Error = class extends NostrError {
13
+ name = "Nip05Error";
13
14
  constructor(message, options) {
14
15
  super(message, options);
15
16
  }
16
17
  };
17
- /**
18
- * Matches optional local@domain.
19
- * Groups: 1=local (optional), 2=domain.
20
- */
21
- const NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w-]+(?:\.[\w-]+)+)$/;
18
+ /** Matches optional local@domain. Groups: 1=local (optional), 2=domain. */
19
+ const NIP05_REGEX = /^(?:([a-z0-9._-]+)@)?([a-z0-9-]+(?:\.[a-z0-9-]+)+)$/i;
22
20
  function isNip05(value) {
23
- return typeof value === "string" && NIP05_REGEX.test(value);
21
+ if (typeof value !== "string") return false;
22
+ try {
23
+ parseNip05(value);
24
+ return true;
25
+ } catch {
26
+ return false;
27
+ }
24
28
  }
25
29
  /**
26
- * Parse an identifier into local + domain.
27
- * Accepts `name@domain`, `_@domain`, or bare `domain` (local becomes `_`).
30
+ * Parse an identifier into local + domain. Accepts `name@domain`, `_@domain`, or bare `domain`
31
+ * (local becomes `_`).
28
32
  */
29
33
  function parseNip05(input) {
30
- const match = input.trim().match(NIP05_REGEX);
31
- if (!match?.[2]) throw new Nip05Error(`invalid NIP-05 identifier: ${input}`);
32
- const localRaw = match[1] ?? "_";
33
- const local = localRaw.toLowerCase();
34
- const domain = match[2].toLowerCase();
35
- if (!/^[a-z0-9._-]+$/.test(local)) throw new Nip05Error(`invalid NIP-05 local-part: ${localRaw}`);
36
- if (!domain) throw new Nip05Error("NIP-05 domain must not be empty");
34
+ const match = NIP05_REGEX.exec(input.trim());
35
+ const domain = match?.at(2);
36
+ if (match === null || domain === void 0 || domain === "") throw new Nip05Error(`invalid NIP-05 identifier: ${input}`);
37
37
  return {
38
- local,
39
- domain
38
+ local: (match.at(1) ?? "_").toLowerCase(),
39
+ domain: domain.toLowerCase()
40
40
  };
41
41
  }
42
42
  /** Build the well-known HTTPS URL for an address. */
@@ -46,100 +46,100 @@ function wellKnownUrl(address) {
46
46
  return url.toString();
47
47
  }
48
48
  function stringUrls(list) {
49
- if (!Array.isArray(list)) return void 0;
49
+ if (!Array.isArray(list)) return;
50
50
  return list.filter((u) => typeof u === "string" && u.length > 0);
51
51
  }
52
52
  /**
53
- * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`.
54
- * Hex-pubkey maps and other keys are ignored.
53
+ * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`. Hex-pubkey maps and other
54
+ * keys are ignored.
55
55
  */
56
56
  function parseNip05Nip46(raw) {
57
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
57
+ if (!isRecord(raw)) return;
58
58
  const obj = raw;
59
59
  const result = {};
60
- if (Array.isArray(obj.relays)) result.relays = stringUrls(obj.relays) ?? [];
61
- if (typeof obj.nostrconnect_url === "string" && obj.nostrconnect_url.length > 0) result.nostrconnectUrl = obj.nostrconnect_url;
60
+ if (Array.isArray(obj["relays"])) result.relays = stringUrls(obj["relays"]) ?? [];
61
+ if (typeof obj["nostrconnect_url"] === "string" && obj["nostrconnect_url"].length > 0) result.nostrconnectUrl = obj["nostrconnect_url"];
62
62
  if (result.relays === void 0 && result.nostrconnectUrl === void 0) return;
63
63
  return result;
64
64
  }
65
65
  /** Parse and validate a nostr.json document body. */
66
66
  function parseNip05Document(json) {
67
- if (!json || typeof json !== "object") throw new Nip05Error("NIP-05 document must be a JSON object");
67
+ if (!isRecord(json)) throw new Nip05Error("NIP-05 document must be a JSON object");
68
68
  const raw = json;
69
- if (!raw.names || typeof raw.names !== "object" || Array.isArray(raw.names)) throw new Nip05Error("NIP-05 document missing names map");
69
+ if (!isRecord(raw["names"])) throw new Nip05Error("NIP-05 document missing names map");
70
70
  const names = {};
71
- for (const [k, v] of Object.entries(raw.names)) {
72
- if (typeof v !== "string" || !isHex32(v)) continue;
71
+ for (const [k, v] of Object.entries(raw["names"])) {
72
+ if (typeof v !== "string" || !isHex32(v.toLowerCase())) continue;
73
73
  names[k.toLowerCase()] = v.toLowerCase();
74
74
  }
75
+ const rawRelays = raw["relays"];
75
76
  let relays;
76
- if (raw.relays && typeof raw.relays === "object" && !Array.isArray(raw.relays)) {
77
+ if (isRecord(rawRelays)) {
77
78
  relays = {};
78
- for (const [pk, list] of Object.entries(raw.relays)) {
79
- if (!isHex32(pk)) continue;
79
+ for (const [pk, list] of Object.entries(rawRelays)) {
80
+ if (!isHex32(pk.toLowerCase())) continue;
80
81
  const urls = stringUrls(list);
81
- if (urls?.length) relays[pk.toLowerCase()] = urls;
82
+ if (urls !== void 0 && urls.length > 0) relays[pk.toLowerCase()] = urls;
82
83
  }
83
84
  }
84
- return {
85
- names,
86
- relays,
87
- nip46: parseNip05Nip46(raw.nip46)
88
- };
85
+ const doc = { names };
86
+ if (relays !== void 0) doc.relays = relays;
87
+ const nip46 = parseNip05Nip46(raw["nip46"]);
88
+ if (nip46 !== void 0) doc.nip46 = nip46;
89
+ return doc;
89
90
  }
90
91
  /** Resolve local name from an already-parsed document. */
91
92
  function lookupFromDocument(doc, address) {
92
93
  const pubkey = doc.names[address.local];
93
- if (!pubkey) return void 0;
94
+ if (pubkey === void 0) return;
94
95
  const relays = doc.relays?.[pubkey];
95
- return relays?.length ? {
96
+ return relays !== void 0 && relays.length > 0 ? {
96
97
  pubkey,
97
98
  relays: [...relays]
98
99
  } : { pubkey };
99
100
  }
100
101
  /**
101
- * Fetch and parse `/.well-known/nostr.json`.
102
- * Returns `null` on network/parse failure (does not throw for those).
103
- * Rejects HTTP redirects (non-200) per NIP-05 security constraints.
104
- * AbortError rethrows; it is not mapped to `null`.
102
+ * Fetch and parse `/.well-known/nostr.json`. Returns `undefined` on network/parse failure (does not
103
+ * throw for those). Rejects HTTP redirects (non-200) per NIP-05 security constraints. AbortError
104
+ * rethrows; it is not mapped to `undefined`.
105
105
  */
106
106
  async function queryNip05Document(identifier, opts) {
107
107
  let address;
108
108
  try {
109
109
  address = parseNip05(identifier);
110
110
  } catch {
111
- return null;
111
+ return;
112
112
  }
113
113
  const url = wellKnownUrl(address);
114
114
  const fetchImpl = opts?.fetch ?? requireGlobalFetch(() => new Nip05Error("no fetch implementation available; pass opts.fetch"));
115
115
  try {
116
116
  const res = await fetchManual(fetchImpl, url, { signal: opts?.signal }, (err) => err instanceof Error ? err : /* @__PURE__ */ new Error("NIP-05 request failed"));
117
- if (res.status !== 200) return null;
117
+ if (res.status !== 200) return;
118
118
  const json = await res.json();
119
119
  return {
120
120
  address,
121
121
  doc: parseNip05Document(json)
122
122
  };
123
- } catch (err) {
124
- if (err instanceof Error && err.name === "AbortError") throw err;
125
- return null;
123
+ } catch (error) {
124
+ if (error instanceof Error && error.name === "AbortError") throw error;
125
+ return;
126
126
  }
127
127
  }
128
128
  /**
129
- * Query `/.well-known/nostr.json` for an identifier.
130
- * Returns `null` on network/parse/lookup failure (does not throw for those).
131
- * Profile `relays` only. `nip46` is discovery metadata, not a bunker pointer.
129
+ * Query `/.well-known/nostr.json` for an identifier. Returns `undefined` on network/parse/lookup
130
+ * failure (does not throw for those). Profile `relays` only. `nip46` is discovery metadata, not a
131
+ * bunker pointer.
132
132
  */
133
133
  async function queryProfile(identifier, opts) {
134
134
  const fetched = await queryNip05Document(identifier, opts);
135
- if (!fetched) return null;
136
- return lookupFromDocument(fetched.doc, fetched.address) ?? null;
135
+ if (fetched === void 0) return;
136
+ return lookupFromDocument(fetched.doc, fetched.address);
137
137
  }
138
138
  /** True when the identifier resolves to exactly `pubkey`. */
139
139
  async function verifyNip05(pubkey, identifier, opts) {
140
- if (!isHex32(pubkey)) return false;
140
+ if (!isHex32(pubkey.toLowerCase())) return false;
141
141
  const profile = await queryProfile(identifier, opts);
142
- return profile !== null && profile.pubkey === pubkey.toLowerCase();
142
+ return profile !== void 0 && profile.pubkey === pubkey.toLowerCase();
143
143
  }
144
144
  //#endregion
145
145
  export { NIP05_REGEX, NIP05_ROOT_LOCAL, Nip05Error, WELL_KNOWN_PATH, isNip05, lookupFromDocument, parseNip05, parseNip05Document, parseNip05Nip46, queryNip05Document, queryProfile, verifyNip05, wellKnownUrl };
@@ -1 +1 @@
1
- {"version":3,"file":"nip05.mjs","names":[],"sources":["../../src/nips/nip05.ts"],"sourcesContent":["/**\n * NIP-05: Mapping Nostr keys to DNS-based internet identifiers\n * @see https://github.com/nostr-protocol/nips/blob/master/05.md\n */\nimport { NostrError } from \"../core/error.ts\";\nimport { isHex32 } from \"../core/util.ts\";\nimport { fetchManual, requireGlobalFetch, type ManualFetch } from \"./http.ts\";\nimport type { ProfilePointer } from \"./nip19.ts\";\n\n/** Root local-part (`_@domain` rendered as just the domain). */\nexport const NIP05_ROOT_LOCAL = \"_\";\n\nexport const WELL_KNOWN_PATH = \"/.well-known/nostr.json\";\n\n/**\n * NIP-05 identifier string.\n * - Full: `name@domain`\n * - Root: `domain` or `_@domain`\n */\nexport type Nip05 = string;\n\nexport type Nip05Address = {\n /** Local part (lowercased). `_` for domain-only identifiers. */\n local: string;\n /** Domain (lowercased). */\n domain: string;\n};\n\n/**\n * 46.md appendix discovery metadata (`{relays, nostrconnect_url}`).\n * Not a bunker pointer.\n */\nexport type Nip05Nip46 = {\n relays?: string[];\n nostrconnectUrl?: string;\n};\n\nexport type Nip05Document = {\n names: Record<string, string>;\n /** NIP-05 profile relay hints */\n relays?: Record<string, string[]>;\n nip46?: Nip05Nip46;\n};\n\nexport type Nip05Fetch = ManualFetch;\n\nexport class Nip05Error extends NostrError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n\n/**\n * Matches optional local@domain.\n * Groups: 1=local (optional), 2=domain.\n */\nexport const NIP05_REGEX = /^(?:([\\w.+-]+)@)?([\\w-]+(?:\\.[\\w-]+)+)$/;\n\nexport function isNip05(value: unknown): value is string {\n return typeof value === \"string\" && NIP05_REGEX.test(value);\n}\n\n/**\n * Parse an identifier into local + domain.\n * Accepts `name@domain`, `_@domain`, or bare `domain` (local becomes `_`).\n */\nexport function parseNip05(input: string): Nip05Address {\n const match = input.trim().match(NIP05_REGEX);\n if (!match?.[2]) {\n throw new Nip05Error(`invalid NIP-05 identifier: ${input}`);\n }\n const localRaw = match[1] ?? NIP05_ROOT_LOCAL;\n const local = localRaw.toLowerCase();\n const domain = match[2].toLowerCase();\n\n // NIP-05 local-part: a-z0-9-_.\n if (!/^[a-z0-9._-]+$/.test(local)) {\n throw new Nip05Error(`invalid NIP-05 local-part: ${localRaw}`);\n }\n if (!domain) {\n throw new Nip05Error(\"NIP-05 domain must not be empty\");\n }\n\n return { local, domain };\n}\n\n/** Build the well-known HTTPS URL for an address. */\nexport function wellKnownUrl(address: Nip05Address): string {\n const url = new URL(`https://${address.domain}${WELL_KNOWN_PATH}`);\n url.searchParams.set(\"name\", address.local);\n return url.toString();\n}\n\nfunction stringUrls(list: unknown): string[] | undefined {\n if (!Array.isArray(list)) return undefined;\n return list.filter((u): u is string => typeof u === \"string\" && u.length > 0);\n}\n\n/**\n * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`.\n * Hex-pubkey maps and other keys are ignored.\n */\nexport function parseNip05Nip46(raw: unknown): Nip05Nip46 | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const obj = raw as Record<string, unknown>;\n const result: Nip05Nip46 = {};\n\n if (Array.isArray(obj.relays)) {\n result.relays = stringUrls(obj.relays) ?? [];\n }\n\n if (typeof obj.nostrconnect_url === \"string\" && obj.nostrconnect_url.length > 0) {\n result.nostrconnectUrl = obj.nostrconnect_url;\n }\n\n if (result.relays === undefined && result.nostrconnectUrl === undefined) {\n return undefined;\n }\n return result;\n}\n\n/** Parse and validate a nostr.json document body. */\nexport function parseNip05Document(json: unknown): Nip05Document {\n if (!json || typeof json !== \"object\") {\n throw new Nip05Error(\"NIP-05 document must be a JSON object\");\n }\n const raw = json as { names?: unknown; relays?: unknown; nip46?: unknown };\n if (!raw.names || typeof raw.names !== \"object\" || Array.isArray(raw.names)) {\n throw new Nip05Error(\"NIP-05 document missing names map\");\n }\n\n const names: Record<string, string> = {};\n for (const [k, v] of Object.entries(raw.names as Record<string, unknown>)) {\n if (typeof v !== \"string\" || !isHex32(v)) continue;\n names[k.toLowerCase()] = v.toLowerCase();\n }\n\n let relays: Record<string, string[]> | undefined;\n if (raw.relays && typeof raw.relays === \"object\" && !Array.isArray(raw.relays)) {\n relays = {};\n for (const [pk, list] of Object.entries(raw.relays as Record<string, unknown>)) {\n if (!isHex32(pk)) continue;\n const urls = stringUrls(list);\n if (urls?.length) relays[pk.toLowerCase()] = urls;\n }\n }\n\n return { names, relays, nip46: parseNip05Nip46(raw.nip46) };\n}\n\n/** Resolve local name from an already-parsed document. */\nexport function lookupFromDocument(\n doc: Nip05Document,\n address: Nip05Address,\n): ProfilePointer | undefined {\n const pubkey = doc.names[address.local];\n if (!pubkey) return undefined;\n const relays = doc.relays?.[pubkey];\n return relays?.length ? { pubkey, relays: [...relays] } : { pubkey };\n}\n\n/**\n * Fetch and parse `/.well-known/nostr.json`.\n * Returns `null` on network/parse failure (does not throw for those).\n * Rejects HTTP redirects (non-200) per NIP-05 security constraints.\n * AbortError rethrows; it is not mapped to `null`.\n */\nexport async function queryNip05Document(\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<{ address: Nip05Address; doc: Nip05Document } | null> {\n let address: Nip05Address;\n try {\n address = parseNip05(identifier);\n } catch {\n return null;\n }\n\n const url = wellKnownUrl(address);\n const fetchImpl =\n opts?.fetch ??\n requireGlobalFetch(() => new Nip05Error(\"no fetch implementation available; pass opts.fetch\"));\n\n try {\n const res = await fetchManual(fetchImpl, url, { signal: opts?.signal }, (err) =>\n err instanceof Error ? err : new Error(\"NIP-05 request failed\"),\n );\n // Redirects and errors must not be trusted (NIP-05 security).\n if (res.status !== 200) return null;\n const json = await res.json();\n return { address, doc: parseNip05Document(json) };\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") throw err;\n return null;\n }\n}\n\n/**\n * Query `/.well-known/nostr.json` for an identifier.\n * Returns `null` on network/parse/lookup failure (does not throw for those).\n * Profile `relays` only. `nip46` is discovery metadata, not a bunker pointer.\n */\nexport async function queryProfile(\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<ProfilePointer | null> {\n const fetched = await queryNip05Document(identifier, opts);\n if (!fetched) return null;\n return lookupFromDocument(fetched.doc, fetched.address) ?? null;\n}\n\n/** True when the identifier resolves to exactly `pubkey`. */\nexport async function verifyNip05(\n pubkey: string,\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<boolean> {\n if (!isHex32(pubkey)) return false;\n const profile = await queryProfile(identifier, opts);\n return profile !== null && profile.pubkey === pubkey.toLowerCase();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nip05.mjs","names":[],"sources":["../../src/nips/nip05.ts"],"sourcesContent":["/**\n * NIP-05: Mapping Nostr keys to DNS-based internet identifiers\n *\n * @see https://github.com/nostr-protocol/nips/blob/master/05.md\n */\nimport { NostrError } from \"../core/error.ts\";\nimport { isHex32, isRecord } from \"../core/util.ts\";\nimport { fetchManual, requireGlobalFetch } from \"./http.ts\";\nimport type { ManualFetch } from \"./http.ts\";\nimport type { ProfilePointer } from \"./nip19.ts\";\n\n/** Root local-part (`_@domain` rendered as just the domain). */\nexport const NIP05_ROOT_LOCAL = \"_\";\n\nexport const WELL_KNOWN_PATH = \"/.well-known/nostr.json\";\n\n/**\n * NIP-05 identifier string.\n *\n * - Full: `name@domain`\n * - Root: `domain` or `_@domain`\n */\nexport type Nip05 = string;\n\nexport type Nip05Address = {\n /** Local part (lowercased). `_` for domain-only identifiers. */\n local: string;\n /** Domain (lowercased). */\n domain: string;\n};\n\n/** 46.md appendix discovery metadata (`{relays, nostrconnect_url}`). Not a bunker pointer. */\nexport type Nip05Nip46 = {\n relays?: string[];\n nostrconnectUrl?: string;\n};\n\nexport type Nip05Document = {\n names: Record<string, string>;\n /** NIP-05 profile relay hints */\n relays?: Record<string, string[]>;\n nip46?: Nip05Nip46;\n};\n\nexport type Nip05Fetch = ManualFetch;\n\nexport class Nip05Error extends NostrError {\n override name = \"Nip05Error\";\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n\n/** Matches optional local@domain. Groups: 1=local (optional), 2=domain. */\n// oxlint-disable-next-line no-inferrable-types -- isolatedDeclarations requires the annotation for dts emit\nexport const NIP05_REGEX: RegExp = /^(?:([a-z0-9._-]+)@)?([a-z0-9-]+(?:\\.[a-z0-9-]+)+)$/i;\n\nexport function isNip05(value: unknown): value is string {\n if (typeof value !== \"string\") {\n return false;\n }\n try {\n parseNip05(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Parse an identifier into local + domain. Accepts `name@domain`, `_@domain`, or bare `domain`\n * (local becomes `_`).\n */\nexport function parseNip05(input: string): Nip05Address {\n const match = NIP05_REGEX.exec(input.trim());\n const domain = match?.at(2);\n if (match === null || domain === undefined || domain === \"\") {\n throw new Nip05Error(`invalid NIP-05 identifier: ${input}`);\n }\n const localRaw = match.at(1) ?? NIP05_ROOT_LOCAL;\n return { local: localRaw.toLowerCase(), domain: domain.toLowerCase() };\n}\n\n/** Build the well-known HTTPS URL for an address. */\nexport function wellKnownUrl(address: Nip05Address): string {\n const url = new URL(`https://${address.domain}${WELL_KNOWN_PATH}`);\n url.searchParams.set(\"name\", address.local);\n return url.toString();\n}\n\nfunction stringUrls(list: unknown): string[] | undefined {\n if (!Array.isArray(list)) {\n return undefined;\n }\n return list.filter((u): u is string => typeof u === \"string\" && u.length > 0);\n}\n\n/**\n * Parse nostr.json `nip46`: 46.md appendix `{relays, nostrconnect_url}`. Hex-pubkey maps and other\n * keys are ignored.\n */\nexport function parseNip05Nip46(raw: unknown): Nip05Nip46 | undefined {\n if (!isRecord(raw)) {\n return undefined;\n }\n const obj = raw;\n const result: Nip05Nip46 = {};\n\n if (Array.isArray(obj[\"relays\"])) {\n result.relays = stringUrls(obj[\"relays\"]) ?? [];\n }\n\n if (typeof obj[\"nostrconnect_url\"] === \"string\" && obj[\"nostrconnect_url\"].length > 0) {\n result.nostrconnectUrl = obj[\"nostrconnect_url\"];\n }\n\n if (result.relays === undefined && result.nostrconnectUrl === undefined) {\n return undefined;\n }\n return result;\n}\n\n/** Parse and validate a nostr.json document body. */\nexport function parseNip05Document(json: unknown): Nip05Document {\n if (!isRecord(json)) {\n throw new Nip05Error(\"NIP-05 document must be a JSON object\");\n }\n const raw = json;\n if (!isRecord(raw[\"names\"])) {\n throw new Nip05Error(\"NIP-05 document missing names map\");\n }\n\n const names: Record<string, string> = {};\n for (const [k, v] of Object.entries(raw[\"names\"])) {\n if (typeof v !== \"string\" || !isHex32(v.toLowerCase())) {\n continue;\n }\n names[k.toLowerCase()] = v.toLowerCase();\n }\n\n const rawRelays = raw[\"relays\"];\n let relays: Record<string, string[]> | undefined;\n if (isRecord(rawRelays)) {\n relays = {};\n for (const [pk, list] of Object.entries(rawRelays)) {\n if (!isHex32(pk.toLowerCase())) {\n continue;\n }\n const urls = stringUrls(list);\n if (urls !== undefined && urls.length > 0) {\n relays[pk.toLowerCase()] = urls;\n }\n }\n }\n\n const doc: Nip05Document = { names };\n if (relays !== undefined) {\n doc.relays = relays;\n }\n const nip46 = parseNip05Nip46(raw[\"nip46\"]);\n if (nip46 !== undefined) {\n doc.nip46 = nip46;\n }\n return doc;\n}\n\n/** Resolve local name from an already-parsed document. */\nexport function lookupFromDocument(\n doc: Nip05Document,\n address: Nip05Address,\n): ProfilePointer | undefined {\n const pubkey = doc.names[address.local];\n if (pubkey === undefined) {\n return undefined;\n }\n const relays = doc.relays?.[pubkey];\n return relays !== undefined && relays.length > 0 ? { pubkey, relays: [...relays] } : { pubkey };\n}\n\n/**\n * Fetch and parse `/.well-known/nostr.json`. Returns `undefined` on network/parse failure (does not\n * throw for those). Rejects HTTP redirects (non-200) per NIP-05 security constraints. AbortError\n * rethrows; it is not mapped to `undefined`.\n */\nexport async function queryNip05Document(\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<{ address: Nip05Address; doc: Nip05Document } | undefined> {\n let address: Nip05Address;\n try {\n address = parseNip05(identifier);\n } catch {\n return undefined;\n }\n\n const url = wellKnownUrl(address);\n const fetchImpl =\n opts?.fetch ??\n requireGlobalFetch(() => new Nip05Error(\"no fetch implementation available; pass opts.fetch\"));\n\n try {\n const res = await fetchManual(fetchImpl, url, { signal: opts?.signal }, (err) =>\n err instanceof Error ? err : new Error(\"NIP-05 request failed\"),\n );\n // Redirects and errors must not be trusted (NIP-05 security).\n if (res.status !== 200) {\n return undefined;\n }\n const json = await res.json();\n return { address, doc: parseNip05Document(json) };\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n throw error;\n }\n return undefined;\n }\n}\n\n/**\n * Query `/.well-known/nostr.json` for an identifier. Returns `undefined` on network/parse/lookup\n * failure (does not throw for those). Profile `relays` only. `nip46` is discovery metadata, not a\n * bunker pointer.\n */\nexport async function queryProfile(\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<ProfilePointer | undefined> {\n const fetched = await queryNip05Document(identifier, opts);\n if (fetched === undefined) {\n return undefined;\n }\n return lookupFromDocument(fetched.doc, fetched.address);\n}\n\n/** True when the identifier resolves to exactly `pubkey`. */\nexport async function verifyNip05(\n pubkey: string,\n identifier: string,\n opts?: { fetch?: Nip05Fetch; signal?: AbortSignal },\n): Promise<boolean> {\n if (!isHex32(pubkey.toLowerCase())) {\n return false;\n }\n const profile = await queryProfile(identifier, opts);\n return profile !== undefined && profile.pubkey === pubkey.toLowerCase();\n}\n"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import { t as Event, v as Tag } from "../event-B5D2jxt_.mjs";
2
- import { t as EventBuilder } from "../builder-BphJa-Y-.mjs";
3
- import { f as ProfilePointer, i as EventPointer, t as AddressPointer } from "../nip19-D7905oIv.mjs";
1
+ import { _ as Tag, t as Event } from "../event-fU3Y01PR.mjs";
2
+ import { t as EventBuilder } from "../builder-BWn55Paf.mjs";
3
+ import { f as ProfilePointer, i as EventPointer, t as AddressPointer } from "../nip19-BevCJZsp.mjs";
4
4
  //#region src/nips/nip10.d.ts
5
- type ThreadReferences = {
5
+ /** Parsed NIP-10 thread references from an event's `e`/`q`/`p` tags. */
6
+ export type ThreadReferences = {
6
7
  /** Pointer to the root of the thread. */
7
8
  root: EventPointer | undefined;
8
9
  /** Pointer to the parent event this note replies to. */
@@ -11,33 +12,31 @@ type ThreadReferences = {
11
12
  mentions: EventPointer[];
12
13
  /** Quoted events (`q` tags): event ids or addresses. Discriminate with `"id" in q`. */
13
14
  quotes: Array<EventPointer | AddressPointer>;
14
- /** p-tagged profiles involved in the thread. */
15
+ /** P-tagged profiles involved in the thread. */
15
16
  profiles: ProfilePointer[];
16
17
  };
17
18
  type ReplyParent = Pick<Event, "id" | "pubkey" | "tags" | "kind">;
18
19
  type QuoteInput = string | EventPointer | AddressPointer;
19
- /**
20
- * Parse NIP-10 thread markers and legacy positional e-tags from an event.
21
- */
22
- declare function parseThreadTags(event: Pick<Event, "tags">): ThreadReferences;
23
- type ReplyTagsOptions = {
20
+ /** Parse NIP-10 thread markers and legacy positional e-tags from an event. */
21
+ export declare function parseThreadTags(event: Pick<Event, "tags">): ThreadReferences;
22
+ /** Options for {@link buildReplyTags}. */
23
+ export type ReplyTagsOptions = {
24
24
  /** Parent event being replied to. */
25
25
  parent: ReplyParent;
26
26
  /** Optional relay hint for the parent e-tag. */
27
- relayHint?: string;
27
+ relayHint?: string | undefined;
28
28
  /** Quoted events (`q` tags): hex ids, `kind:pubkey:d` coords, or pointers. */
29
- quotes?: QuoteInput[];
29
+ quotes?: QuoteInput[] | undefined;
30
30
  };
31
31
  /**
32
- * Build NIP-10 e/p tags for a reply to `parent`.
33
- * Uses marked tags (`root` / `reply`) per preferred modern style.
32
+ * Build NIP-10 e/p tags for a reply to `parent`. Uses marked tags (`root` / `reply`) per preferred
33
+ * modern style.
34
34
  */
35
- declare function buildReplyTags(opts: ReplyTagsOptions): Tag[];
35
+ export declare function buildReplyTags(opts: ReplyTagsOptions): Tag[];
36
36
  /**
37
- * Build an {@link EventBuilder} reply with NIP-10 tags.
38
- * Lives here (not on EventBuilder) so core does not depend on nips.
37
+ * Build an {@link EventBuilder} reply with NIP-10 tags. Lives here (not on EventBuilder) so core
38
+ * does not depend on nips.
39
39
  */
40
- declare function replyTo(parent: ReplyParent, content: string, opts?: Pick<ReplyTagsOptions, "relayHint" | "quotes">): EventBuilder;
40
+ export declare function replyTo(parent: ReplyParent, content: string, opts?: Pick<ReplyTagsOptions, "relayHint" | "quotes">): EventBuilder;
41
41
  //#endregion
42
- export { ReplyTagsOptions, ThreadReferences, buildReplyTags, parseThreadTags, replyTo };
43
42
  //# sourceMappingURL=nip10.d.mts.map