@nostrify/nostrify 0.46.4
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 +5 -0
- package/BunkerURI.test.ts +28 -0
- package/BunkerURI.ts +58 -0
- package/CHANGELOG.md +562 -0
- package/LICENSE +21 -0
- package/NBrowserSigner.test.ts +170 -0
- package/NBrowserSigner.ts +100 -0
- package/NCache.bench.ts +81 -0
- package/NCache.test.ts +22 -0
- package/NCache.ts +73 -0
- package/NConnectSigner.test.ts +102 -0
- package/NConnectSigner.ts +189 -0
- package/NIP05.test.ts +67 -0
- package/NIP05.ts +52 -0
- package/NIP50.test.ts +58 -0
- package/NIP50.ts +24 -0
- package/NIP98.test.ts +181 -0
- package/NIP98.ts +97 -0
- package/NKinds.test.ts +42 -0
- package/NKinds.ts +26 -0
- package/NPool.test.ts +117 -0
- package/NPool.ts +224 -0
- package/NRelay1.test.ts +174 -0
- package/NRelay1.ts +440 -0
- package/NSchema.test.ts +94 -0
- package/NSchema.ts +255 -0
- package/NSecSigner.bench.ts +55 -0
- package/NSecSigner.test.ts +26 -0
- package/NSecSigner.ts +60 -0
- package/NSet.bench.ts +10 -0
- package/NSet.test.ts +92 -0
- package/NSet.ts +203 -0
- package/README.md +314 -0
- package/RelayError.test.ts +23 -0
- package/RelayError.ts +22 -0
- package/dist/BunkerURI.d.ts +23 -0
- package/dist/BunkerURI.d.ts.map +1 -0
- package/dist/BunkerURI.js +52 -0
- package/dist/BunkerURI.js.map +1 -0
- package/dist/NBrowserSigner.d.ts +27 -0
- package/dist/NBrowserSigner.d.ts.map +1 -0
- package/dist/NBrowserSigner.js +96 -0
- package/dist/NBrowserSigner.js.map +1 -0
- package/dist/NCache.d.ts +34 -0
- package/dist/NCache.d.ts.map +1 -0
- package/dist/NCache.js +63 -0
- package/dist/NCache.js.map +1 -0
- package/dist/NConnectSigner.d.ts +50 -0
- package/dist/NConnectSigner.d.ts.map +1 -0
- package/dist/NConnectSigner.js +130 -0
- package/dist/NConnectSigner.js.map +1 -0
- package/dist/NIP05.d.ts +15 -0
- package/dist/NIP05.d.ts.map +1 -0
- package/dist/NIP05.js +40 -0
- package/dist/NIP05.js.map +1 -0
- package/dist/NIP50.d.ts +10 -0
- package/dist/NIP50.d.ts.map +1 -0
- package/dist/NIP50.js +26 -0
- package/dist/NIP50.js.map +1 -0
- package/dist/NIP98.d.ts +15 -0
- package/dist/NIP98.d.ts.map +1 -0
- package/dist/NIP98.js +71 -0
- package/dist/NIP98.js.map +1 -0
- package/dist/NKinds.d.ts +13 -0
- package/dist/NKinds.d.ts.map +1 -0
- package/dist/NKinds.js +27 -0
- package/dist/NKinds.js.map +1 -0
- package/dist/NPool.d.ts +91 -0
- package/dist/NPool.d.ts.map +1 -0
- package/dist/NPool.js +185 -0
- package/dist/NPool.js.map +1 -0
- package/dist/NRelay1.d.ts +80 -0
- package/dist/NRelay1.d.ts.map +1 -0
- package/dist/NRelay1.js +336 -0
- package/dist/NRelay1.js.map +1 -0
- package/dist/NSchema.d.ts +73 -0
- package/dist/NSchema.d.ts.map +1 -0
- package/dist/NSchema.js +215 -0
- package/dist/NSchema.js.map +1 -0
- package/dist/NSecSigner.d.ts +29 -0
- package/dist/NSecSigner.d.ts.map +1 -0
- package/dist/NSecSigner.js +52 -0
- package/dist/NSecSigner.js.map +1 -0
- package/dist/NSet.d.ts +76 -0
- package/dist/NSet.d.ts.map +1 -0
- package/dist/NSet.js +174 -0
- package/dist/NSet.js.map +1 -0
- package/dist/RelayError.d.ts +10 -0
- package/dist/RelayError.d.ts.map +1 -0
- package/dist/RelayError.js +23 -0
- package/dist/RelayError.js.map +1 -0
- package/dist/ln/LNURL.d.ts +55 -0
- package/dist/ln/LNURL.d.ts.map +1 -0
- package/dist/ln/LNURL.js +105 -0
- package/dist/ln/LNURL.js.map +1 -0
- package/dist/ln/mod.d.ts +4 -0
- package/dist/ln/mod.d.ts.map +1 -0
- package/dist/ln/mod.js +6 -0
- package/dist/ln/mod.js.map +1 -0
- package/dist/ln/types/LNURLCallback.d.ts +8 -0
- package/dist/ln/types/LNURLCallback.d.ts.map +1 -0
- package/dist/ln/types/LNURLCallback.js +3 -0
- package/dist/ln/types/LNURLCallback.js.map +1 -0
- package/dist/ln/types/LNURLDetails.d.ts +20 -0
- package/dist/ln/types/LNURLDetails.d.ts.map +1 -0
- package/dist/ln/types/LNURLDetails.js +3 -0
- package/dist/ln/types/LNURLDetails.js.map +1 -0
- package/dist/mod.d.ts +16 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +32 -0
- package/dist/mod.js.map +1 -0
- package/dist/test/ErrorRelay.d.ts +21 -0
- package/dist/test/ErrorRelay.d.ts.map +1 -0
- package/dist/test/ErrorRelay.js +26 -0
- package/dist/test/ErrorRelay.js.map +1 -0
- package/dist/test/MockRelay.d.ts +20 -0
- package/dist/test/MockRelay.d.ts.map +1 -0
- package/dist/test/MockRelay.js +66 -0
- package/dist/test/MockRelay.js.map +1 -0
- package/dist/test/TestRelayServer.d.ts +25 -0
- package/dist/test/TestRelayServer.d.ts.map +1 -0
- package/dist/test/TestRelayServer.js +134 -0
- package/dist/test/TestRelayServer.js.map +1 -0
- package/dist/test/mod.d.ts +8 -0
- package/dist/test/mod.d.ts.map +1 -0
- package/dist/test/mod.js +28 -0
- package/dist/test/mod.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/uploaders/BlossomUploader.d.ts +26 -0
- package/dist/uploaders/BlossomUploader.d.ts.map +1 -0
- package/dist/uploaders/BlossomUploader.js +71 -0
- package/dist/uploaders/BlossomUploader.js.map +1 -0
- package/dist/uploaders/NostrBuildUploader.d.ts +24 -0
- package/dist/uploaders/NostrBuildUploader.d.ts.map +1 -0
- package/dist/uploaders/NostrBuildUploader.js +67 -0
- package/dist/uploaders/NostrBuildUploader.js.map +1 -0
- package/dist/uploaders/mod.d.ts +3 -0
- package/dist/uploaders/mod.d.ts.map +1 -0
- package/dist/uploaders/mod.js +8 -0
- package/dist/uploaders/mod.js.map +1 -0
- package/dist/utils/CircularSet.d.ts +13 -0
- package/dist/utils/CircularSet.d.ts.map +1 -0
- package/dist/utils/CircularSet.js +35 -0
- package/dist/utils/CircularSet.js.map +1 -0
- package/dist/utils/Machina.d.ts +36 -0
- package/dist/utils/Machina.d.ts.map +1 -0
- package/dist/utils/Machina.js +66 -0
- package/dist/utils/Machina.js.map +1 -0
- package/dist/utils/N64.d.ts +9 -0
- package/dist/utils/N64.d.ts.map +1 -0
- package/dist/utils/N64.js +23 -0
- package/dist/utils/N64.js.map +1 -0
- package/dist/utils/mod.d.ts +3 -0
- package/dist/utils/mod.d.ts.map +1 -0
- package/dist/utils/mod.js +8 -0
- package/dist/utils/mod.js.map +1 -0
- package/ln/LNURL.test.ts +87 -0
- package/ln/LNURL.ts +146 -0
- package/ln/mod.ts +4 -0
- package/ln/types/LNURLCallback.ts +7 -0
- package/ln/types/LNURLDetails.ts +19 -0
- package/mod.ts +16 -0
- package/package.json +23 -0
- package/test/ErrorRelay.test.ts +19 -0
- package/test/ErrorRelay.ts +40 -0
- package/test/MockRelay.test.ts +20 -0
- package/test/MockRelay.ts +92 -0
- package/test/TestRelayServer.ts +156 -0
- package/test/mod.ts +28 -0
- package/tsconfig.json +14 -0
- package/uploaders/BlossomUploader.test.ts +26 -0
- package/uploaders/BlossomUploader.ts +98 -0
- package/uploaders/NostrBuildUploader.test.ts +22 -0
- package/uploaders/NostrBuildUploader.ts +89 -0
- package/uploaders/mod.ts +2 -0
- package/utils/CircularSet.test.ts +15 -0
- package/utils/CircularSet.ts +34 -0
- package/utils/Machina.test.ts +91 -0
- package/utils/Machina.ts +66 -0
- package/utils/N64.test.ts +27 -0
- package/utils/N64.ts +23 -0
- package/utils/mod.ts +2 -0
package/dist/NPool.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NPool = void 0;
|
|
4
|
+
const nostr_tools_1 = require("nostr-tools");
|
|
5
|
+
const CircularSet_1 = require("./utils/CircularSet");
|
|
6
|
+
const Machina_1 = require("./utils/Machina");
|
|
7
|
+
const NSet_1 = require("./NSet");
|
|
8
|
+
/**
|
|
9
|
+
* The `NPool` class is a `NRelay` implementation for connecting to multiple relays.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const pool = new NPool({
|
|
13
|
+
* open: (url) => new NRelay1(url),
|
|
14
|
+
* reqRouter: async (filters) => new Map([
|
|
15
|
+
* ['wss://relay1.mostr.pub', filters],
|
|
16
|
+
* ['wss://relay2.mostr.pub', filters],
|
|
17
|
+
* ]),
|
|
18
|
+
* eventRouter: async (event) => ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub'],
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Now you can use the pool like a regular relay.
|
|
22
|
+
* for await (const msg of pool.req([{ kinds: [1] }])) {
|
|
23
|
+
* if (msg[0] === 'EVENT') console.log(msg[2]);
|
|
24
|
+
* if (msg[0] === 'EOSE') break;
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* This class is designed with the Outbox model in mind.
|
|
29
|
+
* Instead of passing relay URLs into each method, you pass functions into the contructor that statically-analyze filters and events to determine which relays to use for requesting and publishing events.
|
|
30
|
+
* If a relay wasn't already connected, it will be opened automatically.
|
|
31
|
+
* Defining `open` will also let you use any relay implementation, such as `NRelay1`.
|
|
32
|
+
*
|
|
33
|
+
* Note that `pool.req` may stream duplicate events, while `pool.query` will correctly process replaceable events and deletions within the event set before returning them.
|
|
34
|
+
*
|
|
35
|
+
* `pool.req` will only emit an `EOSE` when all relays in its set have emitted an `EOSE`, and likewise for `CLOSED`.
|
|
36
|
+
*/
|
|
37
|
+
class NPool {
|
|
38
|
+
opts;
|
|
39
|
+
_relays = new Map();
|
|
40
|
+
constructor(opts) {
|
|
41
|
+
this.opts = opts;
|
|
42
|
+
}
|
|
43
|
+
/** Get or create a relay instance for the given URL. */
|
|
44
|
+
relay(url) {
|
|
45
|
+
const relay = this._relays.get(url);
|
|
46
|
+
if (relay) {
|
|
47
|
+
return relay;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const relay = this.opts.open(url);
|
|
51
|
+
this._relays.set(url, relay);
|
|
52
|
+
return relay;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Returns a new pool instance that uses the given relays. Connections are shared with the original pool. */
|
|
56
|
+
group(urls) {
|
|
57
|
+
return new NPool({
|
|
58
|
+
open: (url) => this.relay(url),
|
|
59
|
+
reqRouter: (filters) => new Map(urls.map((url) => [url, filters])),
|
|
60
|
+
eventRouter: () => urls,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
get relays() {
|
|
64
|
+
return this._relays;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Sends a `REQ` to relays based on the configured `reqRouter`.
|
|
68
|
+
*
|
|
69
|
+
* `EVENT` messages from the selected relays are yielded.
|
|
70
|
+
* `EOSE` and `CLOSE` messages are only yielded when all relays have emitted them.
|
|
71
|
+
*
|
|
72
|
+
* Deduplication of `EVENT` messages is attempted, so that each event is only yielded once.
|
|
73
|
+
* A circular set of 1000 is used to track seen event IDs, so it's possible that very
|
|
74
|
+
* long-running subscriptions (with over 1000 results) may yield duplicate events.
|
|
75
|
+
*/
|
|
76
|
+
async *req(filters, opts) {
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
const signal = opts?.signal ? AbortSignal.any([opts.signal, controller.signal]) : controller.signal;
|
|
79
|
+
const routes = opts?.relays
|
|
80
|
+
? new Map(opts.relays.map((url) => [url, filters]))
|
|
81
|
+
: await this.opts.reqRouter(filters);
|
|
82
|
+
if (routes.size < 1) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const machina = new Machina_1.Machina(signal);
|
|
86
|
+
const eoses = new Set();
|
|
87
|
+
const closes = new Set();
|
|
88
|
+
const events = new CircularSet_1.CircularSet(1000);
|
|
89
|
+
for (const [url, filters] of routes.entries()) {
|
|
90
|
+
const relay = this.relay(url);
|
|
91
|
+
(async () => {
|
|
92
|
+
for await (const msg of relay.req(filters, { signal })) {
|
|
93
|
+
if (msg[0] === 'EOSE') {
|
|
94
|
+
eoses.add(url);
|
|
95
|
+
if (eoses.size === routes.size) {
|
|
96
|
+
machina.push(msg);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (msg[0] === 'CLOSED') {
|
|
100
|
+
closes.add(url);
|
|
101
|
+
if (closes.size === routes.size) {
|
|
102
|
+
machina.push(msg);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (msg[0] === 'EVENT') {
|
|
106
|
+
const [, , event] = msg;
|
|
107
|
+
if (!events.has(event.id)) {
|
|
108
|
+
events.add(event.id);
|
|
109
|
+
machina.push(msg);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
})().catch(() => { });
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
for await (const msg of machina) {
|
|
117
|
+
yield msg;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
controller.abort();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Events are sent to relays according to the `eventRouter`.
|
|
126
|
+
* Returns a fulfilled promise if ANY relay accepted the event,
|
|
127
|
+
* or a rejected promise if ALL relays rejected or failed to publish the event.
|
|
128
|
+
*/
|
|
129
|
+
async event(event, opts) {
|
|
130
|
+
const relayUrls = opts?.relays ?? await this.opts.eventRouter(event);
|
|
131
|
+
if (!relayUrls.length) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// @ts-ignore Promise.any exists for sure
|
|
135
|
+
await Promise.any(relayUrls.map((url) => this.relay(url).event(event, opts)));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* This method calls `.req` internally and then post-processes the results.
|
|
139
|
+
* Please read the definition of `.req`.
|
|
140
|
+
*
|
|
141
|
+
* - The strategy is to seek regular events quickly, and to wait to find the latest versions of replaceable events.
|
|
142
|
+
* - Filters for replaceable events will wait for all relays to `EOSE` (or `CLOSE`, or for the signal to be aborted) to ensure the latest event versions are retrieved.
|
|
143
|
+
* - Filters for regular events will stop as soon as the filters are fulfilled.
|
|
144
|
+
* - Events are deduplicated, sorted, and only the latest version of replaceable events is kept.
|
|
145
|
+
* - If the signal is aborted, this method will return partial results instead of throwing.
|
|
146
|
+
*
|
|
147
|
+
* To implement a custom strategy, call `.req` directly.
|
|
148
|
+
*/
|
|
149
|
+
async query(filters, opts) {
|
|
150
|
+
const map = new Map();
|
|
151
|
+
const events = new NSet_1.NSet(map);
|
|
152
|
+
const limit = filters.reduce((result, filter) => result + (0, nostr_tools_1.getFilterLimit)(filter), 0);
|
|
153
|
+
if (limit === 0)
|
|
154
|
+
return [];
|
|
155
|
+
try {
|
|
156
|
+
for await (const msg of this.req(filters, opts)) {
|
|
157
|
+
if (msg[0] === 'EOSE')
|
|
158
|
+
break;
|
|
159
|
+
if (msg[0] === 'EVENT')
|
|
160
|
+
events.add(msg[2]);
|
|
161
|
+
if (msg[0] === 'CLOSED')
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Skip errors, return partial results.
|
|
167
|
+
}
|
|
168
|
+
// Don't sort results of search filters.
|
|
169
|
+
if (filters.some((filter) => typeof filter.search === 'string')) {
|
|
170
|
+
return [...map.values()];
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
return [...events];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/** Close all the relays in the pool. */
|
|
177
|
+
async close() {
|
|
178
|
+
await Promise.all([...this._relays.values()].map((relay) => relay.close()));
|
|
179
|
+
}
|
|
180
|
+
async [Symbol.asyncDispose]() {
|
|
181
|
+
await this.close();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.NPool = NPool;
|
|
185
|
+
//# sourceMappingURL=NPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NPool.js","sourceRoot":"","sources":["../NPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { NostrClientMsg, NostrClientREQ, NostrEvent, NostrFilter, NostrRelayCLOSED, NostrRelayEOSE, NostrRelayEVENT, NostrRelayMsg, NRelay } from '@nostrify/types';
|
|
2
|
+
import { Backoff, Websocket } from 'websocket-ts';
|
|
3
|
+
/** Options used for constructing an `NRelay1` instance. */
|
|
4
|
+
export interface NRelay1Opts {
|
|
5
|
+
/** Respond to `AUTH` challenges by producing a signed kind `22242` event. */
|
|
6
|
+
auth?(challenge: string): Promise<NostrEvent>;
|
|
7
|
+
/** Configure reconnection strategy, or set to `false` to disable. Default: `new ExponentialBackoff(1000)`. */
|
|
8
|
+
backoff?: Backoff | false;
|
|
9
|
+
/** How long to wait (in milliseconds) for the caller to create a subscription before closing the connection. Set to `false` to disable. Default: `30_000`. */
|
|
10
|
+
idleTimeout?: number | false;
|
|
11
|
+
/** Ensure the event is valid before returning it. Default: `nostrTools.verifyEvent`. */
|
|
12
|
+
verifyEvent?(event: NostrEvent): boolean;
|
|
13
|
+
/** Logger callback. */
|
|
14
|
+
log?(log: NRelay1Log): void;
|
|
15
|
+
}
|
|
16
|
+
export interface NRelay1Log {
|
|
17
|
+
level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'critical';
|
|
18
|
+
ns: string;
|
|
19
|
+
[k: string]: JsonValue | undefined | {
|
|
20
|
+
toJSON(): JsonValue;
|
|
21
|
+
} | Error;
|
|
22
|
+
}
|
|
23
|
+
/** Single relay connection over WebSocket. */
|
|
24
|
+
export declare class NRelay1 implements NRelay {
|
|
25
|
+
private url;
|
|
26
|
+
private opts;
|
|
27
|
+
socket: Websocket;
|
|
28
|
+
private subs;
|
|
29
|
+
private closedByUser;
|
|
30
|
+
private idleTimer?;
|
|
31
|
+
private controller;
|
|
32
|
+
private ee;
|
|
33
|
+
get subscriptions(): readonly NostrClientREQ[];
|
|
34
|
+
private log;
|
|
35
|
+
constructor(url: string, opts?: NRelay1Opts);
|
|
36
|
+
/** Create (and open) a WebSocket connection with automatic reconnect. */
|
|
37
|
+
private createSocket;
|
|
38
|
+
/** Handle a NIP-01 relay message. */
|
|
39
|
+
protected receive(msg: NostrRelayMsg): void;
|
|
40
|
+
/** Send a NIP-01 client message to the relay. */
|
|
41
|
+
protected send(msg: NostrClientMsg): void;
|
|
42
|
+
req(filters: NostrFilter[], opts?: {
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
}): AsyncGenerator<NostrRelayEVENT | NostrRelayEOSE | NostrRelayCLOSED>;
|
|
45
|
+
query(filters: NostrFilter[], opts?: {
|
|
46
|
+
signal?: AbortSignal;
|
|
47
|
+
}): Promise<NostrEvent[]>;
|
|
48
|
+
event(event: NostrEvent, opts?: {
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
count(filters: NostrFilter[], opts?: {
|
|
52
|
+
signal?: AbortSignal;
|
|
53
|
+
}): Promise<{
|
|
54
|
+
count: number;
|
|
55
|
+
approximate?: boolean;
|
|
56
|
+
}>;
|
|
57
|
+
/** Get a stream of EE events. */
|
|
58
|
+
private on;
|
|
59
|
+
/** Wait for a single EE event. */
|
|
60
|
+
private once;
|
|
61
|
+
protected abortError(): DOMException;
|
|
62
|
+
/** Start the idle time if applicable. */
|
|
63
|
+
private maybeStartIdleTimer;
|
|
64
|
+
/** Stop the idle timer. */
|
|
65
|
+
private stopIdleTimer;
|
|
66
|
+
/** Make a new WebSocket, but only if it was closed by an idle timeout. */
|
|
67
|
+
private wake;
|
|
68
|
+
/**
|
|
69
|
+
* Close the relay connection and prevent it from reconnecting.
|
|
70
|
+
* After this you should dispose of the `NRelay1` instance and create a new one to connect again.
|
|
71
|
+
*/
|
|
72
|
+
close(): Promise<void>;
|
|
73
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
/** Native JSON primitive value, including objects and arrays. */
|
|
76
|
+
type JsonValue = {
|
|
77
|
+
[key: string]: JsonValue | undefined;
|
|
78
|
+
} | JsonValue[] | string | number | boolean | null;
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=NRelay1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NRelay1.d.ts","sourceRoot":"","sources":["../NRelay1.ts"],"names":[],"mappings":"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"}
|
package/dist/NRelay1.js
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NRelay1 = void 0;
|
|
4
|
+
const nostr_tools_1 = require("nostr-tools");
|
|
5
|
+
const websocket_ts_1 = require("websocket-ts");
|
|
6
|
+
const Machina_1 = require("./utils/Machina");
|
|
7
|
+
const NSchema_1 = require("./NSchema");
|
|
8
|
+
const NSet_1 = require("./NSet");
|
|
9
|
+
/** Single relay connection over WebSocket. */
|
|
10
|
+
class NRelay1 {
|
|
11
|
+
url;
|
|
12
|
+
opts;
|
|
13
|
+
socket;
|
|
14
|
+
subs = new Map();
|
|
15
|
+
closedByUser = false;
|
|
16
|
+
idleTimer;
|
|
17
|
+
controller = new AbortController();
|
|
18
|
+
ee = new EventTarget();
|
|
19
|
+
get subscriptions() {
|
|
20
|
+
return [...this.subs.values()];
|
|
21
|
+
}
|
|
22
|
+
log(log) {
|
|
23
|
+
this.opts.log?.({ ...log, url: this.url });
|
|
24
|
+
}
|
|
25
|
+
constructor(url, opts = {}) {
|
|
26
|
+
this.url = url;
|
|
27
|
+
this.opts = opts;
|
|
28
|
+
this.socket = this.createSocket();
|
|
29
|
+
this.maybeStartIdleTimer();
|
|
30
|
+
}
|
|
31
|
+
/** Create (and open) a WebSocket connection with automatic reconnect. */
|
|
32
|
+
createSocket() {
|
|
33
|
+
const { backoff = new websocket_ts_1.ExponentialBackoff(1000) } = this.opts;
|
|
34
|
+
return new websocket_ts_1.WebsocketBuilder(this.url)
|
|
35
|
+
.withBuffer(new websocket_ts_1.ArrayQueue())
|
|
36
|
+
.withBackoff(backoff === false ? undefined : backoff)
|
|
37
|
+
.onOpen((socket) => {
|
|
38
|
+
this.log({
|
|
39
|
+
level: 'debug',
|
|
40
|
+
ns: 'relay.ws.state',
|
|
41
|
+
state: 'open',
|
|
42
|
+
readyState: socket.readyState,
|
|
43
|
+
});
|
|
44
|
+
for (const req of this.subs.values()) {
|
|
45
|
+
this.send(req);
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.onClose((socket) => {
|
|
49
|
+
this.log({
|
|
50
|
+
level: 'debug',
|
|
51
|
+
ns: 'relay.ws.state',
|
|
52
|
+
state: 'close',
|
|
53
|
+
readyState: socket.readyState,
|
|
54
|
+
});
|
|
55
|
+
// If the connection closes on its own and there are no active subscriptions, let it stay closed.
|
|
56
|
+
if (!this.subs.size) {
|
|
57
|
+
this.socket.close();
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
.onReconnect((socket) => {
|
|
61
|
+
this.log({
|
|
62
|
+
level: 'debug',
|
|
63
|
+
ns: 'relay.ws.state',
|
|
64
|
+
state: 'reconnect',
|
|
65
|
+
readyState: socket.readyState,
|
|
66
|
+
});
|
|
67
|
+
})
|
|
68
|
+
.onRetry((socket, e) => {
|
|
69
|
+
this.log({
|
|
70
|
+
level: 'warn',
|
|
71
|
+
ns: 'relay.ws.retry',
|
|
72
|
+
readyState: socket.readyState,
|
|
73
|
+
backoff: e.detail.backoff,
|
|
74
|
+
});
|
|
75
|
+
})
|
|
76
|
+
.onError((socket) => {
|
|
77
|
+
this.log({
|
|
78
|
+
level: 'error',
|
|
79
|
+
ns: 'relay.ws.error',
|
|
80
|
+
readyState: socket.readyState,
|
|
81
|
+
});
|
|
82
|
+
})
|
|
83
|
+
.onMessage((_socket, e) => {
|
|
84
|
+
if (typeof e.data !== 'string') {
|
|
85
|
+
this.close();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const result = NSchema_1.NSchema.json().pipe(NSchema_1.NSchema.relayMsg()).safeParse(e.data);
|
|
89
|
+
if (result.success) {
|
|
90
|
+
this.log({
|
|
91
|
+
level: 'trace',
|
|
92
|
+
ns: 'relay.ws.message',
|
|
93
|
+
data: result.data,
|
|
94
|
+
});
|
|
95
|
+
this.receive(result.data);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this.log({
|
|
99
|
+
level: 'warn',
|
|
100
|
+
ns: 'relay.ws.message',
|
|
101
|
+
error: result.error,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
.build();
|
|
106
|
+
}
|
|
107
|
+
/** Handle a NIP-01 relay message. */
|
|
108
|
+
receive(msg) {
|
|
109
|
+
const { auth, verifyEvent = nostr_tools_1.verifyEvent } = this.opts;
|
|
110
|
+
switch (msg[0]) {
|
|
111
|
+
case 'EVENT':
|
|
112
|
+
if (!verifyEvent(msg[2]))
|
|
113
|
+
break;
|
|
114
|
+
this.ee.dispatchEvent(new CustomEvent(`sub:${msg[1]}`, { detail: msg }));
|
|
115
|
+
break;
|
|
116
|
+
case 'EOSE':
|
|
117
|
+
this.ee.dispatchEvent(new CustomEvent(`sub:${msg[1]}`, { detail: msg }));
|
|
118
|
+
break;
|
|
119
|
+
case 'CLOSED':
|
|
120
|
+
this.subs.delete(msg[1]);
|
|
121
|
+
this.maybeStartIdleTimer();
|
|
122
|
+
this.ee.dispatchEvent(new CustomEvent(`sub:${msg[1]}`, { detail: msg }));
|
|
123
|
+
this.ee.dispatchEvent(new CustomEvent(`count:${msg[1]}`, { detail: msg }));
|
|
124
|
+
break;
|
|
125
|
+
case 'OK':
|
|
126
|
+
this.ee.dispatchEvent(new CustomEvent(`ok:${msg[1]}`, { detail: msg }));
|
|
127
|
+
break;
|
|
128
|
+
case 'NOTICE':
|
|
129
|
+
this.ee.dispatchEvent(new CustomEvent('notice', { detail: msg }));
|
|
130
|
+
break;
|
|
131
|
+
case 'COUNT':
|
|
132
|
+
this.ee.dispatchEvent(new CustomEvent(`count:${msg[1]}`, { detail: msg }));
|
|
133
|
+
break;
|
|
134
|
+
case 'AUTH':
|
|
135
|
+
auth?.(msg[1]).then((event) => this.send(['AUTH', event])).catch(() => { });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** Send a NIP-01 client message to the relay. */
|
|
139
|
+
send(msg) {
|
|
140
|
+
this.log({ level: 'trace', ns: 'relay.ws.send', data: msg });
|
|
141
|
+
this.wake();
|
|
142
|
+
switch (msg[0]) {
|
|
143
|
+
case 'REQ':
|
|
144
|
+
this.subs.set(msg[1], msg);
|
|
145
|
+
break;
|
|
146
|
+
case 'CLOSE':
|
|
147
|
+
this.subs.delete(msg[1]);
|
|
148
|
+
this.maybeStartIdleTimer();
|
|
149
|
+
break;
|
|
150
|
+
case 'EVENT':
|
|
151
|
+
case 'COUNT':
|
|
152
|
+
return this.socket.send(JSON.stringify(msg));
|
|
153
|
+
}
|
|
154
|
+
if (this.socket.readyState === WebSocket.OPEN) {
|
|
155
|
+
this.socket.send(JSON.stringify(msg));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async *req(filters, opts = {}) {
|
|
159
|
+
const { signal } = opts;
|
|
160
|
+
const subscriptionId = crypto.randomUUID();
|
|
161
|
+
const msgs = this.on(`sub:${subscriptionId}`, signal);
|
|
162
|
+
const req = ['REQ', subscriptionId, ...filters];
|
|
163
|
+
this.send(req);
|
|
164
|
+
try {
|
|
165
|
+
for await (const msg of msgs) {
|
|
166
|
+
if (msg[0] === 'EOSE')
|
|
167
|
+
yield msg;
|
|
168
|
+
if (msg[0] === 'CLOSED')
|
|
169
|
+
break;
|
|
170
|
+
if (msg[0] === 'EVENT') {
|
|
171
|
+
if ((0, nostr_tools_1.matchFilters)(filters, msg[2])) {
|
|
172
|
+
yield msg;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
this.send(['CLOSE', subscriptionId]);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async query(filters, opts) {
|
|
185
|
+
const events = new NSet_1.NSet();
|
|
186
|
+
const limit = filters.reduce((result, filter) => result + (0, nostr_tools_1.getFilterLimit)(filter), 0);
|
|
187
|
+
if (limit === 0)
|
|
188
|
+
return [];
|
|
189
|
+
for await (const msg of this.req(filters, opts)) {
|
|
190
|
+
if (msg[0] === 'EOSE')
|
|
191
|
+
break;
|
|
192
|
+
if (msg[0] === 'EVENT')
|
|
193
|
+
events.add(msg[2]);
|
|
194
|
+
if (msg[0] === 'CLOSED')
|
|
195
|
+
throw new Error('Subscription closed');
|
|
196
|
+
if (events.size >= limit) {
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return [...events];
|
|
201
|
+
}
|
|
202
|
+
async event(event, opts) {
|
|
203
|
+
const result = this.once(`ok:${event.id}`, opts?.signal);
|
|
204
|
+
try {
|
|
205
|
+
this.send(['EVENT', event]);
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
result.catch(() => { });
|
|
209
|
+
throw e;
|
|
210
|
+
}
|
|
211
|
+
const [, , ok, reason] = await result;
|
|
212
|
+
if (!ok) {
|
|
213
|
+
throw new Error(reason);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async count(filters, opts) {
|
|
217
|
+
const subscriptionId = crypto.randomUUID();
|
|
218
|
+
const result = this.once(`count:${subscriptionId}`, opts?.signal);
|
|
219
|
+
try {
|
|
220
|
+
this.send(['COUNT', subscriptionId, ...filters]);
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
result.catch(() => { });
|
|
224
|
+
throw e;
|
|
225
|
+
}
|
|
226
|
+
const msg = await result;
|
|
227
|
+
switch (msg[0]) {
|
|
228
|
+
case 'CLOSED':
|
|
229
|
+
throw new Error('Subscription closed');
|
|
230
|
+
case 'COUNT': {
|
|
231
|
+
const [, , count] = msg;
|
|
232
|
+
return count;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/** Get a stream of EE events. */
|
|
237
|
+
async *on(key, signal) {
|
|
238
|
+
const _signal = signal ? AbortSignal.any([this.controller.signal, signal]) : this.controller.signal;
|
|
239
|
+
if (_signal.aborted)
|
|
240
|
+
throw this.abortError();
|
|
241
|
+
const machina = new Machina_1.Machina(_signal);
|
|
242
|
+
const onMsg = (e) => machina.push(e.detail);
|
|
243
|
+
this.ee.addEventListener(key, onMsg);
|
|
244
|
+
try {
|
|
245
|
+
for await (const msg of machina) {
|
|
246
|
+
yield msg;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
this.ee.removeEventListener(key, onMsg);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/** Wait for a single EE event. */
|
|
254
|
+
async once(key, signal) {
|
|
255
|
+
for await (const msg of this.on(key, signal)) {
|
|
256
|
+
return msg;
|
|
257
|
+
}
|
|
258
|
+
throw new Error('Unreachable');
|
|
259
|
+
}
|
|
260
|
+
abortError() {
|
|
261
|
+
return new DOMException('The signal has been aborted', 'AbortError');
|
|
262
|
+
}
|
|
263
|
+
/** Start the idle time if applicable. */
|
|
264
|
+
maybeStartIdleTimer() {
|
|
265
|
+
const { idleTimeout = 30_000 } = this.opts;
|
|
266
|
+
// If the idle timeout is disabled, do nothing.
|
|
267
|
+
if (idleTimeout === false)
|
|
268
|
+
return;
|
|
269
|
+
// If a timer is already running, let it continue without disruption.
|
|
270
|
+
if (this.idleTimer)
|
|
271
|
+
return;
|
|
272
|
+
// If there are still subscriptions, the connection is not "idle".
|
|
273
|
+
if (this.subs.size)
|
|
274
|
+
return;
|
|
275
|
+
// If the connection was manually closed, there's no need to start a timer.
|
|
276
|
+
if (this.closedByUser)
|
|
277
|
+
return;
|
|
278
|
+
this.log({
|
|
279
|
+
level: 'debug',
|
|
280
|
+
ns: 'relay.idletimer',
|
|
281
|
+
state: 'running',
|
|
282
|
+
timeout: idleTimeout,
|
|
283
|
+
});
|
|
284
|
+
this.idleTimer = setTimeout(() => {
|
|
285
|
+
this.log({
|
|
286
|
+
level: 'debug',
|
|
287
|
+
ns: 'relay.idletimer',
|
|
288
|
+
state: 'aborted',
|
|
289
|
+
timeout: idleTimeout,
|
|
290
|
+
});
|
|
291
|
+
this.socket.close();
|
|
292
|
+
}, idleTimeout);
|
|
293
|
+
}
|
|
294
|
+
/** Stop the idle timer. */
|
|
295
|
+
stopIdleTimer() {
|
|
296
|
+
this.log({ level: 'debug', ns: 'relay.idletimer', state: 'stopped' });
|
|
297
|
+
clearTimeout(this.idleTimer);
|
|
298
|
+
this.idleTimer = undefined;
|
|
299
|
+
}
|
|
300
|
+
/** Make a new WebSocket, but only if it was closed by an idle timeout. */
|
|
301
|
+
wake() {
|
|
302
|
+
this.stopIdleTimer();
|
|
303
|
+
if (!this.closedByUser && this.socket.closedByUser) {
|
|
304
|
+
this.log({ level: 'debug', ns: 'relay.wake', state: 'awoken' });
|
|
305
|
+
this.socket = this.createSocket();
|
|
306
|
+
}
|
|
307
|
+
else if (this.closedByUser || this.socket.closedByUser) {
|
|
308
|
+
this.log({ level: 'debug', ns: 'relay.wake', state: 'closed' });
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
this.log({ level: 'debug', ns: 'relay.wake', state: 'awake' });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Close the relay connection and prevent it from reconnecting.
|
|
316
|
+
* After this you should dispose of the `NRelay1` instance and create a new one to connect again.
|
|
317
|
+
*/
|
|
318
|
+
async close() {
|
|
319
|
+
this.closedByUser = true;
|
|
320
|
+
this.socket.close();
|
|
321
|
+
this.stopIdleTimer();
|
|
322
|
+
this.controller.abort();
|
|
323
|
+
if (this.socket.readyState !== WebSocket.CLOSED) {
|
|
324
|
+
await new Promise((resolve) => {
|
|
325
|
+
this.socket.addEventListener(websocket_ts_1.WebsocketEvent.close, resolve, {
|
|
326
|
+
once: true,
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async [Symbol.asyncDispose]() {
|
|
332
|
+
await this.close();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
exports.NRelay1 = NRelay1;
|
|
336
|
+
//# sourceMappingURL=NRelay1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NRelay1.js","sourceRoot":"","sources":["../NRelay1.ts"],"names":[],"mappings":"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"}
|