@nostrify/nostrify 0.46.8 → 0.46.10

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 (47) hide show
  1. package/.turbo/turbo-build.log +19 -28
  2. package/.turbo/turbo-test.log +91 -123
  3. package/CHANGELOG.md +16 -0
  4. package/NIP05.ts +6 -6
  5. package/NSchema.ts +71 -30
  6. package/dist/BunkerURI.ts +58 -0
  7. package/dist/NBrowserSigner.ts +100 -0
  8. package/dist/NCache.ts +73 -0
  9. package/dist/NConnectSigner.ts +188 -0
  10. package/dist/NIP05.d.ts +1 -1
  11. package/dist/NIP05.ts +51 -0
  12. package/dist/NIP50.ts +24 -0
  13. package/dist/NIP98.ts +97 -0
  14. package/dist/NKinds.ts +26 -0
  15. package/dist/NPool.ts +243 -0
  16. package/dist/NRelay1.ts +447 -0
  17. package/dist/NSchema.d.ts +2 -2
  18. package/dist/NSchema.d.ts.map +1 -1
  19. package/dist/NSchema.js +35 -6
  20. package/dist/NSchema.ts +291 -0
  21. package/dist/NSecSigner.ts +62 -0
  22. package/dist/NSet.ts +210 -0
  23. package/dist/RelayError.ts +22 -0
  24. package/dist/ln/LNURL.ts +146 -0
  25. package/dist/ln/mod.ts +4 -0
  26. package/dist/ln/types/LNURLCallback.ts +7 -0
  27. package/dist/ln/types/LNURLDetails.ts +19 -0
  28. package/dist/mod.ts +16 -0
  29. package/dist/test/ErrorRelay.ts +52 -0
  30. package/dist/test/MockRelay.ts +92 -0
  31. package/dist/test/TestRelayServer.ts +185 -0
  32. package/dist/test/mod.ts +28 -0
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/dist/uploaders/BlossomUploader.ts +98 -0
  35. package/dist/uploaders/NostrBuildUploader.ts +89 -0
  36. package/dist/uploaders/mod.ts +2 -0
  37. package/dist/utils/CircularSet.ts +36 -0
  38. package/dist/utils/Machina.ts +66 -0
  39. package/dist/utils/N64.ts +23 -0
  40. package/dist/utils/mod.ts +2 -0
  41. package/package.json +3 -3
  42. package/tsconfig.json +1 -2
  43. package/dist/ln/mod.js.map +0 -7
  44. package/dist/mod.js.map +0 -7
  45. package/dist/test/mod.js.map +0 -7
  46. package/dist/uploaders/mod.js.map +0 -7
  47. package/dist/utils/mod.js.map +0 -7
@@ -1,28 +1,19 @@
1
-
2
- > @nostrify/nostrify@0.46.7 build /home/sid/repos/nostrify/packages/nostrify
3
- > tsc -p tsconfig.json && node ../../esbuild.config.js --package ./
4
-
5
-
6
- dist/NRelay1.js 8.9kb
7
- dist/NSchema.js 5.6kb
8
- dist/NPool.js 5.0kb
9
- dist/test/TestRelayServer.js 4.4kb
10
- dist/NSet.js 4.1kb
11
- dist/NConnectSigner.js 3.9kb
12
- dist/ln/LNURL.js 3.3kb
13
- dist/NBrowserSigner.js 2.6kb
14
- dist/NIP98.js 2.4kb
15
- dist/uploaders/NostrBuildUploader.js 1.9kb
16
- dist/uploaders/BlossomUploader.js 1.8kb
17
- dist/test/MockRelay.js 1.4kb
18
- dist/BunkerURI.js 1.4kb
19
- dist/NKinds.js 1.1kb
20
- dist/NIP05.js 1.1kb
21
- dist/NSecSigner.js 1.1kb
22
- dist/utils/Machina.js 925b
23
- dist/NCache.js 828b
24
- dist/mod.js 752b
25
- dist/test/mod.js 701b
26
- ...and 10 more output files...
27
-
28
- ⚡ Done in 22ms
1
+
2
+
3
+ > @nostrify/nostrify@0.46.9 build /home/sid/repos/nostrify/packages/nostrify
4
+ > npx tsc -p tsconfig.json && node ../../esbuild.config.js --package ./
5
+
6
+ npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
7
+ npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
8
+ ⠙Building with esbuild...
9
+
10
+ dist/NRelay1.js 8.9kb
11
+ dist/NSchema.js 5.8kb
12
+ dist/NPool.js 5.0kb
13
+ dist/test/TestRelayServer.js 4.4kb
14
+ dist/NSet.js 4.1kb
15
+ ...and 25 more output files...
16
+
17
+ ⚡ Done in 24ms
18
+ Copying source files...
19
+ Done!
@@ -1,123 +1,91 @@
1
-
2
- > @nostrify/nostrify@0.46.7 test /home/sid/repos/nostrify/packages/nostrify
3
- > node --test "**/*.test.ts"
4
-
5
- ✔ BunkerURI (3.139394ms)
6
- ✔ BunkerURI.fromJSON (1.078848ms)
7
- NBrowserSigner - without extension (6.464847ms)
8
- ✔ NBrowserSigner - with extension polyfill (234.080428ms)
9
- ✔ NBrowserSigner.nip44 - with extension polyfill (91.327807ms)
10
- ✔ NBrowserSigner.nip04 - with extension polyfill (83.997199ms)
11
- ✔ NBrowserSigner.getRelays - with extension polyfill (1.347041ms)
12
- ✔ NBrowserSigner - missing nip44 support (7.24135ms)
13
- ✔ NBrowserSigner - missing nip04 support (0.957463ms)
14
- ✔ NBrowserSigner - feature detection (0.630183ms)
15
- NCache (7.515339ms)
16
- NConnectSigner.signEvent with nip04 encryption (279.362646ms)
17
- ✔ NConnectSigner.signEvent with nip44 encryption (108.072198ms)
18
- NIP05.lookup (127.775302ms)
19
- ✔ NIP05.lookup with invalid values but valid profile pointer (11.722058ms)
20
- ✔ NIP05.lookup with invalid document (13.281978ms)
21
- NIP50.parseInput (3.655177ms)
22
- ✔ NIP50.parseInput with negated token (0.487567ms)
23
- NIP98.template (24.095253ms)
24
- ✔ NIP98.template with payload (53.842113ms)
25
- ✔ NIP98.verify (281.757944ms)
26
- ✔ NIP98.verify fails with missing header (7.416304ms)
27
- ✔ NIP98.verify fails with missing token (4.561446ms)
28
- ✔ NIP98.verify fails with invalid token (9.659557ms)
29
- ✔ NIP98.verify fails with invalid event (37.684884ms)
30
- ✔ NIP98.verify fails with wrong event kind (62.228241ms)
31
- ✔ NIP98.verify fails with wrong request URL (32.012672ms)
32
- ✔ NIP98.verify fails with wrong request method (61.338176ms)
33
- ✔ NIP98.verify fails with expired event (33.697888ms)
34
- ✔ NIP98.verify fails with invalid payload (73.713885ms)
35
- NKinds (2.137233ms)
36
- NPool.query (1002.066008ms)
37
- ✔ NPool.req (97.498969ms)
38
- ✔ NPool.event (267.305626ms)
39
- NRelay1.query (746.453455ms)
40
- ✔ NRelay1.query mismatched filter (259.123715ms)
41
- ✔ NRelay1.req (297.033979ms)
42
- ✔ NRelay1.event (246.217138ms)
43
- NRelay1 backoff (1.75855ms) # SKIP
44
- NRelay1 idleTimeout
45
- websocket opens (43.318751ms)
46
- ✔ websocket closes after idleTimeout (151.53622ms)
47
- ✔ websocket wakes up during activity (20.337967ms)
48
- NRelay1 idleTimeout (429.224616ms)
49
- ✔ NRelay1.count rejects when the server sends CLOSED (223.243687ms)
50
- ✔ NRelay1 closes when it receives a binary message (221.917598ms)
51
- n.id (19.246617ms)
52
- ✔ n.bech32 (5.666764ms)
53
- ✔ n.filter (41.374213ms)
54
- ✔ n.event (5.833826ms)
55
- ✔ n.metadata (22.364081ms)
56
- NSecSigner (265.119504ms)
57
- ✔ NSecSigner.nip44 (70.579379ms)
58
- NSet (36.583337ms)
59
- ✔ NSet.add (replaceable) (0.930993ms)
60
- ✔ NSet.add (parameterized) (1.035127ms)
61
- ✔ NSet.add (deletion) (0.479884ms)
62
- Construct a RelayError from the reason message (2.876998ms)
63
- Throw a new RelayError if the OK message is false (0.544837ms)
64
- LNURL.fromString (7.092726ms)
65
- ✔ LNURL.fromLightningAddress (1.072702ms)
66
- ✔ LNURL.toString (1.514522ms)
67
- ✔ LNURL.getDetails (94.441569ms)
68
- ✔ LNURL.getInvoice (8.24442ms)
69
- ErrorRelay (123.796477ms)
70
- MockRelay (3.191496ms)
71
- BlossomUploader.upload (1004.663359ms)
72
- {
73
- status: 'error',
74
- message: 'Unauthorized, please provide a valid nip-98 token',
75
- data: {}
76
- }
77
- NostrBuildUploader.upload (1590.593336ms)
78
- CircularSet (7.081691ms)
79
- ✔ push, iterate, & close (104.057684ms)
80
- close & reopen (0.858706ms)
81
- aborts with signal (52.838065ms)
82
- already aborted signal in constructor (0.887341ms)
83
- push after abort (1.140029ms)
84
- multiple messages in queue (0.695626ms)
85
- N64 (8.897581ms)
86
- N64.encodeEvent (0.552799ms)
87
- N64.decodeEvent (1.49315ms)
88
- tests 77
89
- suites 0
90
- pass 75
91
- fail 1
92
- ℹ cancelled 0
93
- ℹ skipped 1
94
- ℹ todo 0
95
- ℹ duration_ms 3317.855572
96
-
97
- ✖ failing tests:
98
-
99
- test at uploaders/NostrBuildUploader.test.ts:10:7
100
- ✖ NostrBuildUploader.upload (1590.593336ms)
101
- Error [ZodError]: [
102
- {
103
- "code": "invalid_type",
104
- "expected": "array",
105
- "received": "object",
106
- "path": [
107
- "data"
108
- ],
109
- "message": "Expected array, received object"
110
- }
111
- ]
112
- at get error (file:///home/sid/repos/nostrify/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js:39:31)
113
- at ZodObject.parse (file:///home/sid/repos/nostrify/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js:114:22)
114
- at NostrBuildUploader.upload (file:///home/sid/repos/nostrify/packages/nostrify/uploaders/NostrBuildUploader.ts:51:48)
115
- at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
116
- at async TestContext.<anonymous> (file:///home/sid/repos/nostrify/packages/nostrify/uploaders/NostrBuildUploader.test.ts:22:18)
117
- at async Test.run (node:internal/test_runner/test:1088:7)
118
- at async startSubtestAfterBootstrap (node:internal/test_runner/harness:332:3)
119
- at async file:///home/sid/repos/nostrify/packages/nostrify/uploaders/NostrBuildUploader.test.ts:10:1 {
120
- issues: [ { code: 'invalid_type', expected: 'array', received: 'object', path: [Array], message: 'Expected array, received object' } ],
121
- [errors]: [ { code: 'invalid_type', expected: 'array', received: 'object', path: [Array], message: 'Expected array, received object' } ]
122
- }
123
-  ELIFECYCLE  Test failed. See above for more details.
1
+
2
+
3
+ > @nostrify/nostrify@0.46.8 test /home/sid/repos/nostrify/packages/nostrify
4
+ > node --test "**/*.test.ts"
5
+
6
+ ✔ BunkerURI (2.901722ms)
7
+ BunkerURI.fromJSON (0.681727ms)
8
+ ✔ NBrowserSigner - without extension (2.955361ms)
9
+ ✔ NBrowserSigner - with extension polyfill (142.479686ms)
10
+ ✔ NBrowserSigner.nip44 - with extension polyfill (63.176698ms)
11
+ ✔ NBrowserSigner.nip04 - with extension polyfill (94.046199ms)
12
+ ✔ NBrowserSigner.getRelays - with extension polyfill (1.225726ms)
13
+ ✔ NBrowserSigner - missing nip44 support (0.470316ms)
14
+ ✔ NBrowserSigner - missing nip04 support (0.596869ms)
15
+ NBrowserSigner - feature detection (0.692134ms)
16
+ NCache (4.463457ms)
17
+ ✔ NConnectSigner.signEvent with nip04 encryption (264.497854ms)
18
+ NConnectSigner.signEvent with nip44 encryption (151.108865ms)
19
+ ✔ NIP05.lookup (82.449297ms)
20
+ ✔ NIP05.lookup with invalid values but valid profile pointer (5.343535ms)
21
+ NIP05.lookup with invalid document (5.910931ms)
22
+ ✔ NIP50.parseInput (6.388441ms)
23
+ NIP50.parseInput with negated token (0.443007ms)
24
+ ✔ NIP98.template (3.769298ms)
25
+ ✔ NIP98.template with payload (18.668676ms)
26
+ ✔ NIP98.verify (102.562862ms)
27
+ ✔ NIP98.verify fails with missing header (4.419038ms)
28
+ ✔ NIP98.verify fails with missing token (2.752191ms)
29
+ ✔ NIP98.verify fails with invalid token (4.587427ms)
30
+ ✔ NIP98.verify fails with invalid event (16.989187ms)
31
+ ✔ NIP98.verify fails with wrong event kind (40.621459ms)
32
+ ✔ NIP98.verify fails with wrong request URL (41.071101ms)
33
+ ✔ NIP98.verify fails with wrong request method (62.625645ms)
34
+ ✔ NIP98.verify fails with expired event (20.760162ms)
35
+ NIP98.verify fails with invalid payload (51.97091ms)
36
+ NKinds (3.308412ms)
37
+ ✔ NPool.query (368.093259ms)
38
+ ✔ NPool.req (266.969001ms)
39
+ NPool.event (232.161184ms)
40
+ ✔ NRelay1.query (280.362725ms)
41
+ ✔ NRelay1.query mismatched filter (245.542477ms)
42
+ ✔ NRelay1.req (247.658198ms)
43
+ NRelay1.event (216.357493ms)
44
+ NRelay1 backoff (0.334682ms) # SKIP
45
+ NRelay1 idleTimeout
46
+ ✔ websocket opens (40.531572ms)
47
+ ✔ websocket closes after idleTimeout (150.405626ms)
48
+ websocket wakes up during activity (14.544161ms)
49
+ ✔ NRelay1 idleTimeout (209.795356ms)
50
+ ✔ NRelay1.count rejects when the server sends CLOSED (6.440892ms)
51
+ NRelay1 closes when it receives a binary message (5.03225ms)
52
+ ✔ n.id (3.950608ms)
53
+ ✔ n.bech32 (1.817636ms)
54
+ ✔ n.filter (10.95275ms)
55
+ ✔ n.event (2.561941ms)
56
+ n.metadata (11.862022ms)
57
+ ✔ NSecSigner (178.164717ms)
58
+ NSecSigner.nip44 (31.935079ms)
59
+ ✔ NSet (19.978352ms)
60
+ ✔ NSet.add (replaceable) (0.615308ms)
61
+ ✔ NSet.add (parameterized) (0.985888ms)
62
+ NSet.add (deletion) (0.380918ms)
63
+ Construct a RelayError from the reason message (1.717692ms)
64
+ Throw a new RelayError if the OK message is false (0.750801ms)
65
+ ✔ LNURL.fromString (7.817616ms)
66
+ ✔ LNURL.fromLightningAddress (0.932529ms)
67
+ ✔ LNURL.toString (1.933713ms)
68
+ ✔ LNURL.getDetails (111.66131ms)
69
+ LNURL.getInvoice (13.562812ms)
70
+ ErrorRelay (112.209428ms)
71
+ MockRelay (3.019126ms)
72
+ ﹣ BlossomUploader.upload (1.127947ms) # SKIP
73
+ NostrBuildUploader.upload (2.842008ms) # SKIP
74
+ CircularSet (2.247513ms)
75
+ push, iterate, & close (103.751782ms)
76
+ ✔ close & reopen (0.982257ms)
77
+ aborts with signal (51.656203ms)
78
+ already aborted signal in constructor (1.251916ms)
79
+ ✔ push after abort (0.906129ms)
80
+ multiple messages in queue (0.531637ms)
81
+ N64 (8.171994ms)
82
+ N64.encodeEvent (0.513338ms)
83
+ N64.decodeEvent (1.449988ms)
84
+ tests 77
85
+ suites 0
86
+ pass 74
87
+ fail 0
88
+ cancelled 0
89
+ skipped 3
90
+ todo 0
91
+ duration_ms 2192.909865
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.46.10
4
+
5
+ ### Patch Changes
6
+
7
+ - distribute ts files
8
+ - Updated dependencies
9
+ - @nostrify/types@0.36.6
10
+
11
+ ## 0.46.9
12
+
13
+ ### Patch Changes
14
+
15
+ - tests should pass now
16
+ - Updated dependencies
17
+ - @nostrify/types@0.36.5
18
+
3
19
  ## 0.46.8
4
20
 
5
21
  ### Patch Changes
package/NIP05.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { NProfilePointer } from '@nostrify/types';
1
+ import type { NProfilePointer } from "@nostrify/types";
2
2
 
3
- import { NSchema as n, z } from './NSchema.ts';
3
+ import { NSchema as n, z } from "./NSchema.ts";
4
4
 
5
5
  interface LookupOpts {
6
6
  fetch?: typeof fetch;
@@ -18,7 +18,7 @@ export class NIP05 {
18
18
  return z.object({
19
19
  pubkey: n.id(),
20
20
  relays: n.relayUrl().array().optional(),
21
- });
21
+ }) as z.ZodType<NProfilePointer>;
22
22
  }
23
23
 
24
24
  /** Resolve NIP-05 name to a profile pointer. */
@@ -31,10 +31,10 @@ export class NIP05 {
31
31
  const match = nip05.match(NIP05.regex());
32
32
  if (!match) throw new Error(`NIP-05: invalid name ${nip05}`);
33
33
 
34
- const [_, name = '_', domain] = match;
34
+ const [_, name = "_", domain] = match;
35
35
 
36
- const url = new URL('/.well-known/nostr.json', `https://${domain}/`);
37
- url.searchParams.set('name', name);
36
+ const url = new URL("/.well-known/nostr.json", `https://${domain}/`);
37
+ url.searchParams.set("name", name);
38
38
 
39
39
  const response = await fetch(url, { signal });
40
40
  const json = await response.json();
package/NSchema.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { z } from 'zod';
1
+ import { z } from "zod";
2
2
 
3
3
  import type {
4
4
  NostrClientAUTH,
@@ -20,7 +20,7 @@ import type {
20
20
  NostrRelayMsg,
21
21
  NostrRelayNOTICE,
22
22
  NostrRelayOK,
23
- } from '@nostrify/types';
23
+ } from "@nostrify/types";
24
24
 
25
25
  /**
26
26
  * A suite of [zod](https://github.com/colinhacks/zod) schemas for Nostr.
@@ -50,7 +50,15 @@ class NSchema {
50
50
  content: z.string(),
51
51
  created_at: z.number().int().nonnegative(),
52
52
  sig: z.string(),
53
- });
53
+ }).required({
54
+ id: true,
55
+ kind: true,
56
+ pubkey: true,
57
+ tags: true,
58
+ content: true,
59
+ created_at: true,
60
+ sig: true,
61
+ }) as z.ZodType<NostrEvent>;
54
62
  }
55
63
 
56
64
  /** Nostr filter schema. */
@@ -67,16 +75,16 @@ class NSchema {
67
75
  .passthrough()
68
76
  .transform((value) => {
69
77
  const keys = [
70
- 'kinds',
71
- 'ids',
72
- 'authors',
73
- 'since',
74
- 'until',
75
- 'limit',
76
- 'search',
78
+ "kinds",
79
+ "ids",
80
+ "authors",
81
+ "since",
82
+ "until",
83
+ "limit",
84
+ "search",
77
85
  ];
78
86
  return Object.entries(value).reduce((acc, [key, val]) => {
79
- if (keys.includes(key) || key.startsWith('#')) {
87
+ if (keys.includes(key) || key.startsWith("#")) {
80
88
  acc[key] = val;
81
89
  }
82
90
  return acc;
@@ -92,7 +100,9 @@ class NSchema {
92
100
  return z
93
101
  .string()
94
102
  .regex(/^[\x21-\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}$/)
95
- .refine((value) => prefix ? value.startsWith(`${prefix}1`) : true) as z.ZodType<`${P}1${string}`>;
103
+ .refine((value) =>
104
+ prefix ? value.startsWith(`${prefix}1`) : true
105
+ ) as z.ZodType<`${P}1${string}`>;
96
106
  }
97
107
 
98
108
  /** WebSocket URL starting with `ws://` or `wss://`. */
@@ -105,27 +115,39 @@ class NSchema {
105
115
 
106
116
  /** NIP-01 `EVENT` message from client to relay. */
107
117
  static clientEVENT(): z.ZodType<NostrClientEVENT> {
108
- return z.tuple([z.literal('EVENT'), NSchema.event()]);
118
+ return z.tuple([
119
+ z.literal("EVENT"),
120
+ NSchema.event(),
121
+ ]) as unknown as z.ZodType<
122
+ NostrClientEVENT
123
+ >;
109
124
  }
110
125
 
111
126
  /** NIP-01 `REQ` message from client to relay. */
112
127
  static clientREQ(): z.ZodType<NostrClientREQ> {
113
- return z.tuple([z.literal('REQ'), z.string()]).rest(NSchema.filter());
128
+ return z.tuple([z.literal("REQ"), z.string()]).rest(NSchema.filter());
114
129
  }
115
130
 
116
131
  /** NIP-45 `COUNT` message from client to relay. */
117
132
  static clientCOUNT(): z.ZodType<NostrClientCOUNT> {
118
- return z.tuple([z.literal('COUNT'), z.string()]).rest(NSchema.filter());
133
+ return z.tuple([z.literal("COUNT"), z.string()]).rest(NSchema.filter());
119
134
  }
120
135
 
121
136
  /** NIP-01 `CLOSE` message from client to relay. */
122
137
  static clientCLOSE(): z.ZodType<NostrClientCLOSE> {
123
- return z.tuple([z.literal('CLOSE'), z.string()]);
138
+ return z.tuple([z.literal("CLOSE"), z.string()]) as unknown as z.ZodType<
139
+ NostrClientCLOSE
140
+ >;
124
141
  }
125
142
 
126
143
  /** NIP-42 `AUTH` message from client to relay. */
127
144
  static clientAUTH(): z.ZodType<NostrClientAUTH> {
128
- return z.tuple([z.literal('AUTH'), NSchema.event()]);
145
+ return z.tuple([
146
+ z.literal("AUTH"),
147
+ NSchema.event(),
148
+ ]) as unknown as z.ZodType<
149
+ NostrClientAUTH
150
+ >;
129
151
  }
130
152
 
131
153
  /** NIP-01 message from client to relay. */
@@ -136,49 +158,68 @@ class NSchema {
136
158
  NSchema.clientCOUNT(),
137
159
  NSchema.clientCLOSE(),
138
160
  NSchema.clientAUTH(),
139
- ]);
161
+ ]) as z.ZodType<NostrClientMsg>;
140
162
  }
141
163
 
142
164
  /** NIP-01 `EVENT` message from relay to client. */
143
165
  static relayEVENT(): z.ZodType<NostrRelayEVENT> {
144
- return z.tuple([z.literal('EVENT'), z.string(), NSchema.event()]);
166
+ return z.tuple([
167
+ z.literal("EVENT"),
168
+ z.string(),
169
+ NSchema.event(),
170
+ ]) as unknown as z.ZodType<NostrRelayEVENT>;
145
171
  }
146
172
 
147
173
  /** NIP-01 `OK` message from relay to client. */
148
174
  static relayOK(): z.ZodType<NostrRelayOK> {
149
- return z.tuple([z.literal('OK'), NSchema.id(), z.boolean(), z.string()]);
175
+ return z.tuple([
176
+ z.literal("OK"),
177
+ NSchema.id(),
178
+ z.boolean(),
179
+ z.string(),
180
+ ]) as unknown as z.ZodType<NostrRelayOK>;
150
181
  }
151
182
 
152
183
  /** NIP-01 `EOSE` message from relay to client. */
153
184
  static relayEOSE(): z.ZodType<NostrRelayEOSE> {
154
- return z.tuple([z.literal('EOSE'), z.string()]);
185
+ return z.tuple([z.literal("EOSE"), z.string()]) as unknown as z.ZodType<
186
+ NostrRelayEOSE
187
+ >;
155
188
  }
156
189
 
157
190
  /** NIP-01 `NOTICE` message from relay to client. */
158
191
  static relayNOTICE(): z.ZodType<NostrRelayNOTICE> {
159
- return z.tuple([z.literal('NOTICE'), z.string()]);
192
+ return z.tuple([z.literal("NOTICE"), z.string()]) as unknown as z.ZodType<
193
+ NostrRelayNOTICE
194
+ >;
160
195
  }
161
196
 
162
197
  /** NIP-01 `CLOSED` message from relay to client. */
163
198
  static relayCLOSED(): z.ZodType<NostrRelayCLOSED> {
164
- return z.tuple([z.literal('CLOSED'), z.string(), z.string()]);
199
+ return z.tuple([
200
+ z.literal("CLOSED"),
201
+ z.string(),
202
+ z.string(),
203
+ ]) as unknown as z.ZodType<NostrRelayCLOSED>;
165
204
  }
166
205
 
167
206
  /** NIP-42 `AUTH` message from relay to client. */
168
207
  static relayAUTH(): z.ZodType<NostrRelayAUTH> {
169
- return z.tuple([z.literal('AUTH'), z.string()]);
208
+ return z.tuple([z.literal("AUTH"), z.string()]) as unknown as z.ZodType<
209
+ NostrRelayAUTH
210
+ >;
170
211
  }
171
212
 
172
213
  /** NIP-45 `COUNT` message from relay to client. */
173
214
  static relayCOUNT(): z.ZodType<NostrRelayCOUNT> {
174
215
  return z.tuple([
175
- z.literal('COUNT'),
216
+ z.literal("COUNT"),
176
217
  z.string(),
177
218
  z.object({
178
219
  count: z.number().int().nonnegative(),
179
220
  approximate: z.boolean().optional(),
180
221
  }),
181
- ]);
222
+ ]) as unknown as z.ZodType<NostrRelayCOUNT>;
182
223
  }
183
224
 
184
225
  /** NIP-01 message from relay to client. */
@@ -201,7 +242,7 @@ class NSchema {
201
242
  banner: z.string().url().optional().catch(undefined),
202
243
  bot: z.boolean().optional().catch(undefined),
203
244
  display_name: z.string().optional().catch(undefined),
204
- lud06: NSchema.bech32('lnurl').optional().catch(undefined),
245
+ lud06: NSchema.bech32("lnurl").optional().catch(undefined),
205
246
  lud16: z.string().email().optional().catch(undefined),
206
247
  name: z.string().optional().catch(undefined),
207
248
  nip05: z.string().email().optional().catch(undefined),
@@ -216,7 +257,7 @@ class NSchema {
216
257
  id: z.string(),
217
258
  method: z.string(),
218
259
  params: z.string().array(),
219
- });
260
+ }) as z.ZodType<NostrConnectRequest>;
220
261
  }
221
262
 
222
263
  /** NIP-46 response content schema. */
@@ -225,7 +266,7 @@ class NSchema {
225
266
  id: z.string(),
226
267
  result: z.string(),
227
268
  error: z.string().optional(),
228
- });
269
+ }) as z.ZodType<NostrConnectResponse>;
229
270
  }
230
271
 
231
272
  /**
@@ -240,7 +281,7 @@ class NSchema {
240
281
  try {
241
282
  return JSON.parse(value) as unknown;
242
283
  } catch (_e) {
243
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid JSON' });
284
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Invalid JSON" });
244
285
  return z.NEVER;
245
286
  }
246
287
  });
@@ -0,0 +1,58 @@
1
+ /** Construct a [NIP-46](https://github.com/nostr-protocol/nips/blob/master/46.md) bunker URI. */
2
+ export class BunkerURI {
3
+ /** Remote signer pubkey. */
4
+ pubkey: string;
5
+ /** Relay URLs on which the client is listening for responses from the remote-signer. */
6
+ relays: string[];
7
+ /** A short random string that the remote-signer should return as the `result` field of its response. */
8
+ secret?: string;
9
+
10
+ constructor(uri: string) {
11
+ const url = new URL(uri);
12
+ const params = new URLSearchParams(url.search);
13
+
14
+ // https://github.com/denoland/deno/issues/26440
15
+ const pubkey = url.hostname || url.pathname.slice(2);
16
+ const relays = params.getAll('relay');
17
+ const secret = params.get('secret') ?? undefined;
18
+
19
+ if (!pubkey) {
20
+ throw new Error('Invalid bunker URI');
21
+ }
22
+
23
+ this.pubkey = pubkey;
24
+ this.relays = relays;
25
+ this.secret = secret;
26
+ }
27
+
28
+ /** Convert into a `bunker://` URI string. */
29
+ get href(): string {
30
+ return this.toString();
31
+ }
32
+
33
+ /** Convert into a `bunker://` URI string. */
34
+ toString(): string {
35
+ return BunkerURI.toString(this);
36
+ }
37
+
38
+ /** Convert a bunker data object into a `BunkerURI` instance. */
39
+ static fromJSON(data: { pubkey: string; relays: string[]; secret?: string }): BunkerURI {
40
+ const uri = BunkerURI.toString(data);
41
+ return new BunkerURI(uri);
42
+ }
43
+
44
+ /** Convert a bunker data object into a bunker URI string. */
45
+ private static toString(data: { pubkey: string; relays: string[]; secret?: string }): string {
46
+ const search = new URLSearchParams();
47
+
48
+ for (const relay of data.relays) {
49
+ search.append('relay', relay);
50
+ }
51
+
52
+ if (data.secret) {
53
+ search.set('secret', data.secret);
54
+ }
55
+
56
+ return `bunker://${data.pubkey}?${search.toString()}`;
57
+ }
58
+ }