@nostrify/nostrify 0.49.1 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +22 -22
- package/.turbo/turbo-test.log +113 -113
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +12 -0
- package/NRelay1.test.ts +32 -0
- package/NRelay1.ts +76 -3
- package/NSchema.ts +95 -84
- package/dist/NRelay1.d.ts +10 -1
- package/dist/NRelay1.d.ts.map +1 -1
- package/dist/NRelay1.js +64 -2
- package/dist/NSchema.d.ts +231 -23
- package/dist/NSchema.d.ts.map +1 -1
- package/dist/NSchema.js +55 -11
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
|
|
2
|
-
> @nostrify/nostrify@0.
|
|
2
|
+
> @nostrify/nostrify@0.50.0 build /home/alex/Projects/nostrify/packages/nostrify
|
|
3
3
|
> npx tsc -p tsconfig.json && node ../../esbuild.config.js --package ./
|
|
4
4
|
|
|
5
5
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
|
6
6
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
|
7
7
|
Building with esbuild...
|
|
8
8
|
|
|
9
|
-
dist/NRelay1.js
|
|
10
|
-
dist/NSchema.js
|
|
11
|
-
dist/NPool.js
|
|
12
|
-
dist/test/TestRelayServer.js
|
|
13
|
-
dist/NSet.js
|
|
14
|
-
dist/NConnectSigner.js
|
|
15
|
-
dist/ln/LNURL.js
|
|
16
|
-
dist/NIP98.js
|
|
17
|
-
dist/NBrowserSigner.js
|
|
18
|
-
dist/uploaders/BlossomUploader.js
|
|
19
|
-
dist/uploaders/NostrBuildUploader.js
|
|
20
|
-
dist/test/MockRelay.js
|
|
21
|
-
dist/BunkerURI.js
|
|
22
|
-
dist/NKinds.js
|
|
23
|
-
dist/NIP05.js
|
|
24
|
-
dist/NSecSigner.js
|
|
25
|
-
dist/utils/Machina.js
|
|
26
|
-
dist/NCache.js
|
|
27
|
-
dist/mod.js
|
|
28
|
-
dist/test/mod.js
|
|
9
|
+
dist/NRelay1.js 10.7kb
|
|
10
|
+
dist/NSchema.js 8.2kb
|
|
11
|
+
dist/NPool.js 5.4kb
|
|
12
|
+
dist/test/TestRelayServer.js 4.4kb
|
|
13
|
+
dist/NSet.js 4.1kb
|
|
14
|
+
dist/NConnectSigner.js 3.9kb
|
|
15
|
+
dist/ln/LNURL.js 3.3kb
|
|
16
|
+
dist/NIP98.js 2.7kb
|
|
17
|
+
dist/NBrowserSigner.js 2.6kb
|
|
18
|
+
dist/uploaders/BlossomUploader.js 1.9kb
|
|
19
|
+
dist/uploaders/NostrBuildUploader.js 1.9kb
|
|
20
|
+
dist/test/MockRelay.js 1.4kb
|
|
21
|
+
dist/BunkerURI.js 1.4kb
|
|
22
|
+
dist/NKinds.js 1.1kb
|
|
23
|
+
dist/NIP05.js 1.1kb
|
|
24
|
+
dist/NSecSigner.js 1.1kb
|
|
25
|
+
dist/utils/Machina.js 925b
|
|
26
|
+
dist/NCache.js 828b
|
|
27
|
+
dist/mod.js 815b
|
|
28
|
+
dist/test/mod.js 701b
|
|
29
29
|
...and 11 more output files...
|
|
30
30
|
|
|
31
|
-
⚡ Done in
|
|
31
|
+
⚡ Done in 16ms
|
|
32
32
|
Done!
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
▶ NRelay1 idleTimeout
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
test at uploaders/NostrBuildUploader.test.ts:12:7
|
|
106
|
-
|
|
107
|
-
Error: nostr.build with default uploader requires a secret key to be configured
|
|
108
|
-
at TestContext.<anonymous>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
at async
|
|
113
|
-
|
|
1
|
+
|
|
2
|
+
> @nostrify/nostrify@0.49.2 test /home/alex/Projects/nostrify/packages/nostrify
|
|
3
|
+
> node --test "**/*.test.ts"
|
|
4
|
+
|
|
5
|
+
✔ BunkerURI (3.395047ms)
|
|
6
|
+
✔ BunkerURI.fromJSON (0.74187ms)
|
|
7
|
+
✔ NBrowserSigner - without extension (6.198276ms)
|
|
8
|
+
✔ NBrowserSigner - with extension polyfill (190.009587ms)
|
|
9
|
+
✔ NBrowserSigner.nip44 - with extension polyfill (37.935911ms)
|
|
10
|
+
✔ NBrowserSigner.nip04 - with extension polyfill (25.129052ms)
|
|
11
|
+
✔ NBrowserSigner.getRelays - with extension polyfill (2.053194ms)
|
|
12
|
+
✔ NBrowserSigner - missing nip44 support (0.917462ms)
|
|
13
|
+
✔ NBrowserSigner - missing nip04 support (0.459447ms)
|
|
14
|
+
✔ NBrowserSigner - feature detection (0.765374ms)
|
|
15
|
+
✔ NCache (12.840903ms)
|
|
16
|
+
✔ NConnectSigner.signEvent with nip04 encryption (271.624777ms)
|
|
17
|
+
✔ NConnectSigner.signEvent with nip44 encryption (71.743781ms)
|
|
18
|
+
✔ NIP05.lookup (136.606498ms)
|
|
19
|
+
✔ NIP05.lookup with invalid values but valid profile pointer (26.791359ms)
|
|
20
|
+
✔ NIP05.lookup with invalid document (12.007099ms)
|
|
21
|
+
✔ NIP50.parseInput (3.937501ms)
|
|
22
|
+
✔ NIP50.parseInput with negated token (0.560007ms)
|
|
23
|
+
✔ NIP98.template (6.37427ms)
|
|
24
|
+
✔ NIP98.template with payload (26.999101ms)
|
|
25
|
+
✔ NIP98.verify (179.4453ms)
|
|
26
|
+
✔ NIP98.verify fails with missing header (3.242699ms)
|
|
27
|
+
✔ NIP98.verify fails with missing token (1.904625ms)
|
|
28
|
+
✔ NIP98.verify fails with invalid token (2.465312ms)
|
|
29
|
+
✔ NIP98.verify fails with invalid event (22.614687ms)
|
|
30
|
+
✔ NIP98.verify fails with wrong event kind (32.449507ms)
|
|
31
|
+
✔ NIP98.verify fails with wrong request URL (21.092385ms)
|
|
32
|
+
✔ NIP98.verify fails with wrong request method (29.362892ms)
|
|
33
|
+
✔ NIP98.verify fails with expired event (18.052067ms)
|
|
34
|
+
✔ NIP98.verify fails with invalid payload (31.823746ms)
|
|
35
|
+
✔ NIP98Client.fetch - basic GET request (203.916982ms)
|
|
36
|
+
✔ NIP98Client.fetch - POST request with body (53.60961ms)
|
|
37
|
+
✔ NIP98Client.fetch - with Request object input (20.893399ms)
|
|
38
|
+
✔ NIP98Client.fetch - with URL object input (11.890279ms)
|
|
39
|
+
✔ NIP98Client.fetch - uses default fetch when not provided (9.503144ms)
|
|
40
|
+
✔ NIP98Client.fetch - preserves existing headers (14.925967ms)
|
|
41
|
+
✔ NIP98Client.fetch - event can be verified with NIP98.verify (24.239093ms)
|
|
42
|
+
✔ NIP98Client.fetch - handles different HTTP methods (62.95163ms)
|
|
43
|
+
✔ NKinds (2.673706ms)
|
|
44
|
+
✔ NPool.query (340.485108ms)
|
|
45
|
+
✔ NPool.req (83.109821ms)
|
|
46
|
+
✔ NPool.event (39.765323ms)
|
|
47
|
+
✔ NPool.query with eoseTimeout (589.053675ms)
|
|
48
|
+
✔ NPool.query with eoseTimeout disabled (517.784379ms)
|
|
49
|
+
✔ NRelay1.query (327.416455ms)
|
|
50
|
+
✔ NRelay1.query with NIP-50 search preserves relay order (54.456828ms)
|
|
51
|
+
✔ NRelay1.query mismatched filter (24.4706ms)
|
|
52
|
+
✔ NRelay1.req (70.307922ms)
|
|
53
|
+
✔ NRelay1.event (25.854061ms)
|
|
54
|
+
﹣ NRelay1 backoff (0.278776ms) # SKIP
|
|
55
|
+
▶ NRelay1 idleTimeout
|
|
56
|
+
✔ websocket opens (2.814902ms)
|
|
57
|
+
✔ websocket closes after idleTimeout (150.342419ms)
|
|
58
|
+
✔ websocket wakes up during activity (16.192178ms)
|
|
59
|
+
✔ NRelay1 idleTimeout (172.377473ms)
|
|
60
|
+
✔ NRelay1.count rejects when the server sends CLOSED (6.414255ms)
|
|
61
|
+
✔ NRelay1 closes when it receives a binary message (4.879718ms)
|
|
62
|
+
✔ n.id (13.224767ms)
|
|
63
|
+
✔ n.bech32 (4.952717ms)
|
|
64
|
+
✔ n.filter (59.599323ms)
|
|
65
|
+
✔ n.event (50.481827ms)
|
|
66
|
+
✔ n.metadata (79.798873ms)
|
|
67
|
+
✔ NSecSigner (174.438973ms)
|
|
68
|
+
✔ NSecSigner.nip44 (40.880438ms)
|
|
69
|
+
✔ NSet (32.904085ms)
|
|
70
|
+
✔ NSet.add (replaceable) (0.611303ms)
|
|
71
|
+
✔ NSet.add (parameterized) (0.78409ms)
|
|
72
|
+
✔ NSet.add (deletion) (0.528828ms)
|
|
73
|
+
✔ Construct a RelayError from the reason message (2.522901ms)
|
|
74
|
+
✔ Throw a new RelayError if the OK message is false (0.555108ms)
|
|
75
|
+
✔ LNURL.fromString (9.215922ms)
|
|
76
|
+
✔ LNURL.fromLightningAddress (2.004964ms)
|
|
77
|
+
✔ LNURL.toString (0.956956ms)
|
|
78
|
+
✔ LNURL.getDetails (77.433128ms)
|
|
79
|
+
✔ LNURL.getInvoice (11.77437ms)
|
|
80
|
+
✔ ErrorRelay (108.988137ms)
|
|
81
|
+
✔ MockRelay (4.248918ms)
|
|
82
|
+
✔ BlossomUploader.upload (667.499053ms)
|
|
83
|
+
✖ NostrBuildUploader.upload (15.830003ms)
|
|
84
|
+
✔ CircularSet (3.14234ms)
|
|
85
|
+
✔ push, iterate, & close (103.279174ms)
|
|
86
|
+
✔ close & reopen (0.623095ms)
|
|
87
|
+
✔ aborts with signal (51.133076ms)
|
|
88
|
+
✔ already aborted signal in constructor (0.404423ms)
|
|
89
|
+
✔ push after abort (0.54578ms)
|
|
90
|
+
✔ multiple messages in queue (0.272634ms)
|
|
91
|
+
✔ N64 (11.53621ms)
|
|
92
|
+
✔ N64.encodeEvent (0.261664ms)
|
|
93
|
+
✔ N64.decodeEvent (2.938024ms)
|
|
94
|
+
ℹ tests 88
|
|
95
|
+
ℹ suites 0
|
|
96
|
+
ℹ pass 86
|
|
97
|
+
ℹ fail 1
|
|
98
|
+
ℹ cancelled 0
|
|
99
|
+
ℹ skipped 1
|
|
100
|
+
ℹ todo 0
|
|
101
|
+
ℹ duration_ms 3268.962193
|
|
102
|
+
|
|
103
|
+
✖ failing tests:
|
|
104
|
+
|
|
105
|
+
test at uploaders/NostrBuildUploader.test.ts:12:7
|
|
106
|
+
✖ NostrBuildUploader.upload (15.830003ms)
|
|
107
|
+
Error: nostr.build with default uploader requires a secret key to be configured
|
|
108
|
+
at TestContext.<anonymous> (file:///home/alex/Projects/nostrify/packages/nostrify/uploaders/NostrBuildUploader.test.ts:25:13)
|
|
109
|
+
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
|
110
|
+
at async Test.run (node:internal/test_runner/test:1102:7)
|
|
111
|
+
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:358:3)
|
|
112
|
+
at async file:///home/alex/Projects/nostrify/packages/nostrify/uploaders/NostrBuildUploader.test.ts:12:1
|
|
113
|
+
ELIFECYCLE Test failed. See above for more details.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @nostrify/nostrify@0.
|
|
2
|
+
> @nostrify/nostrify@0.50.0 typecheck /home/alex/Projects/nostrify/packages/nostrify
|
|
3
3
|
> npx tsc --noEmit
|
|
4
4
|
|
|
5
5
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.50.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add NIP-11 relay information document support to NRelay1 with `getRelayInfo()` method and `NSchema.relayInfo()` validation schema. Fix NRelay1.query to preserve relay-provided ordering for NIP-50 search filters instead of sorting by created_at.
|
|
8
|
+
|
|
9
|
+
## 0.49.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Simplify NSchema by removing explicit zod type annotations and leveraging type inference
|
|
14
|
+
|
|
3
15
|
## 0.49.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/NRelay1.test.ts
CHANGED
|
@@ -36,6 +36,38 @@ await test("NRelay1.query", async () => {
|
|
|
36
36
|
clearTimeout(tid);
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
+
await test("NRelay1.query with NIP-50 search preserves relay order", async () => {
|
|
40
|
+
// Create events with different timestamps. The relay will send them
|
|
41
|
+
// in "relevance" order (oldest first), not chronological order.
|
|
42
|
+
const sk = generateSecretKey();
|
|
43
|
+
const oldest = genEvent({ kind: 1, content: "most relevant", created_at: 1000 }, sk);
|
|
44
|
+
const middle = genEvent({ kind: 1, content: "somewhat relevant", created_at: 2000 }, sk);
|
|
45
|
+
const newest = genEvent({ kind: 1, content: "least relevant", created_at: 3000 }, sk);
|
|
46
|
+
|
|
47
|
+
// Relay sends in relevance order: oldest, middle, newest.
|
|
48
|
+
// Without the fix, NSet would sort them newest-first by created_at.
|
|
49
|
+
await using server = await TestRelayServer.create({
|
|
50
|
+
handleMessage(socket, msg) {
|
|
51
|
+
if (msg[0] === "REQ") {
|
|
52
|
+
const [, subId] = msg;
|
|
53
|
+
socket.send(JSON.stringify(["EVENT", subId, oldest]));
|
|
54
|
+
socket.send(JSON.stringify(["EVENT", subId, middle]));
|
|
55
|
+
socket.send(JSON.stringify(["EVENT", subId, newest]));
|
|
56
|
+
socket.send(JSON.stringify(["EOSE", subId]));
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await using relay = new NRelay1(server.url);
|
|
62
|
+
const events = await relay.query([{ kinds: [1], search: "relevant" }]);
|
|
63
|
+
|
|
64
|
+
deepStrictEqual(events.length, 3);
|
|
65
|
+
// Results should preserve relay order (relevance), not be sorted by created_at.
|
|
66
|
+
deepStrictEqual(events[0].id, oldest.id);
|
|
67
|
+
deepStrictEqual(events[1].id, middle.id);
|
|
68
|
+
deepStrictEqual(events[2].id, newest.id);
|
|
69
|
+
});
|
|
70
|
+
|
|
39
71
|
await test("NRelay1.query mismatched filter", async () => {
|
|
40
72
|
await using server = await TestRelayServer.create({
|
|
41
73
|
handleMessage(socket, msg) {
|
package/NRelay1.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
NostrRelayMsg,
|
|
11
11
|
NostrRelayNOTICE,
|
|
12
12
|
NostrRelayOK,
|
|
13
|
+
NostrRelayInfo,
|
|
13
14
|
NRelay,
|
|
14
15
|
} from '@nostrify/types';
|
|
15
16
|
import { getFilterLimit, matchFilters, verifyEvent as _verifyEvent } from 'nostr-tools';
|
|
@@ -28,7 +29,7 @@ type EventMap = {
|
|
|
28
29
|
notice: NostrRelayNOTICE;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
|
-
/** Options used for constructing an `NRelay1` instance. */
|
|
32
|
+
/** Options used for constructing an `NRelay1` instance. */
|
|
32
33
|
export interface NRelay1Opts {
|
|
33
34
|
/** Respond to `AUTH` challenges by producing a signed kind `22242` event. */
|
|
34
35
|
auth?(challenge: string): Promise<NostrEvent>;
|
|
@@ -40,6 +41,8 @@ export interface NRelay1Opts {
|
|
|
40
41
|
verifyEvent?(event: NostrEvent): boolean;
|
|
41
42
|
/** Logger callback. */
|
|
42
43
|
log?(log: NRelay1Log): void;
|
|
44
|
+
/** Custom fetch function for retrieving NIP-11 relay information. Default: `globalThis.fetch`. */
|
|
45
|
+
fetch?: typeof globalThis.fetch;
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
export interface NRelay1Log {
|
|
@@ -58,6 +61,7 @@ export class NRelay1 implements NRelay {
|
|
|
58
61
|
private controller = new AbortController();
|
|
59
62
|
private url: string;
|
|
60
63
|
private opts: NRelay1Opts;
|
|
64
|
+
private relayInfoPromise?: Promise<NostrRelayInfo | undefined>;
|
|
61
65
|
|
|
62
66
|
private ee = new EventTarget();
|
|
63
67
|
|
|
@@ -76,6 +80,69 @@ export class NRelay1 implements NRelay {
|
|
|
76
80
|
this.maybeStartIdleTimer();
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
/** Fetch the NIP-11 relay information document. */
|
|
84
|
+
private async fetchRelayInfo(opts?: { signal?: AbortSignal }): Promise<NostrRelayInfo | undefined> {
|
|
85
|
+
try {
|
|
86
|
+
const { fetch: fetchFn = globalThis.fetch } = this.opts;
|
|
87
|
+
const { signal } = opts || {};
|
|
88
|
+
|
|
89
|
+
const httpUrl = this.url.replace(/^wss?:\/\//, (match) =>
|
|
90
|
+
match === 'ws://' ? 'http://' : 'https://'
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const response = await fetchFn(httpUrl, {
|
|
94
|
+
headers: { Accept: 'application/nostr+json' },
|
|
95
|
+
signal,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
this.log({
|
|
100
|
+
level: 'warn',
|
|
101
|
+
ns: 'relay.nip11',
|
|
102
|
+
status: response.status,
|
|
103
|
+
message: 'Failed to fetch relay info',
|
|
104
|
+
});
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const data = await response.json();
|
|
109
|
+
const result = n.relayInfo().safeParse(data);
|
|
110
|
+
|
|
111
|
+
if (!result.success) {
|
|
112
|
+
this.log({
|
|
113
|
+
level: 'warn',
|
|
114
|
+
ns: 'relay.nip11',
|
|
115
|
+
error: result.error,
|
|
116
|
+
message: 'Invalid relay info format',
|
|
117
|
+
});
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.log({
|
|
122
|
+
level: 'debug',
|
|
123
|
+
ns: 'relay.nip11',
|
|
124
|
+
message: 'Successfully fetched relay info',
|
|
125
|
+
});
|
|
126
|
+
return result.data as NostrRelayInfo;
|
|
127
|
+
} catch (error) {
|
|
128
|
+
this.log({
|
|
129
|
+
level: 'warn',
|
|
130
|
+
ns: 'relay.nip11',
|
|
131
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
132
|
+
message: 'Error fetching relay info',
|
|
133
|
+
});
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Get the NIP-11 relay information document. Fetches on first call and caches the result. */
|
|
139
|
+
async getRelayInfo(opts?: { signal?: AbortSignal }): Promise<NostrRelayInfo | undefined> {
|
|
140
|
+
if (!this.relayInfoPromise) {
|
|
141
|
+
this.relayInfoPromise = this.fetchRelayInfo(opts);
|
|
142
|
+
}
|
|
143
|
+
return this.relayInfoPromise;
|
|
144
|
+
}
|
|
145
|
+
|
|
79
146
|
/** Create (and open) a WebSocket connection with automatic reconnect. */
|
|
80
147
|
private createSocket(): Websocket {
|
|
81
148
|
const { backoff = new ExponentialBackoff(1000) } = this.opts;
|
|
@@ -255,7 +322,8 @@ export class NRelay1 implements NRelay {
|
|
|
255
322
|
filters: NostrFilter[],
|
|
256
323
|
opts?: { signal?: AbortSignal },
|
|
257
324
|
): Promise<NostrEvent[]> {
|
|
258
|
-
const
|
|
325
|
+
const map = new Map<string, NostrEvent>();
|
|
326
|
+
const events = new NSet(map);
|
|
259
327
|
|
|
260
328
|
const limit = filters.reduce(
|
|
261
329
|
(result, filter) => result + getFilterLimit(filter),
|
|
@@ -273,7 +341,12 @@ export class NRelay1 implements NRelay {
|
|
|
273
341
|
}
|
|
274
342
|
}
|
|
275
343
|
|
|
276
|
-
|
|
344
|
+
// Don't sort results of search filters.
|
|
345
|
+
if (filters.some((filter) => typeof filter.search === 'string')) {
|
|
346
|
+
return [...map.values()];
|
|
347
|
+
} else {
|
|
348
|
+
return [...events];
|
|
349
|
+
}
|
|
277
350
|
}
|
|
278
351
|
|
|
279
352
|
async event(
|