@welshman/net 0.0.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.
- package/README.md +20 -0
- package/build/Connection.cjs +89 -0
- package/build/Connection.cjs.map +1 -0
- package/build/Connection.d.ts +26 -0
- package/build/Connection.mjs +85 -0
- package/build/Connection.mjs.map +1 -0
- package/build/ConnectionMeta.cjs +162 -0
- package/build/ConnectionMeta.cjs.map +1 -0
- package/build/ConnectionMeta.d.ts +57 -0
- package/build/ConnectionMeta.mjs +158 -0
- package/build/ConnectionMeta.mjs.map +1 -0
- package/build/Context.cjs +27 -0
- package/build/Context.cjs.map +1 -0
- package/build/Context.d.ts +16 -0
- package/build/Context.mjs +23 -0
- package/build/Context.mjs.map +1 -0
- package/build/Executor.cjs +64 -0
- package/build/Executor.cjs.map +1 -0
- package/build/Executor.d.ts +33 -0
- package/build/Executor.mjs +60 -0
- package/build/Executor.mjs.map +1 -0
- package/build/Pool.cjs +44 -0
- package/build/Pool.cjs.map +1 -0
- package/build/Pool.d.ts +13 -0
- package/build/Pool.mjs +40 -0
- package/build/Pool.mjs.map +1 -0
- package/build/Publish.cjs +70 -0
- package/build/Publish.cjs.map +1 -0
- package/build/Publish.d.ts +40 -0
- package/build/Publish.mjs +65 -0
- package/build/Publish.mjs.map +1 -0
- package/build/Socket.cjs +98 -0
- package/build/Socket.cjs.map +1 -0
- package/build/Socket.d.ts +37 -0
- package/build/Socket.mjs +89 -0
- package/build/Socket.mjs.map +1 -0
- package/build/Subscribe.cjs +215 -0
- package/build/Subscribe.cjs.map +1 -0
- package/build/Subscribe.d.ts +52 -0
- package/build/Subscribe.mjs +206 -0
- package/build/Subscribe.mjs.map +1 -0
- package/build/Tracker.cjs +45 -0
- package/build/Tracker.cjs.map +1 -0
- package/build/Tracker.d.ts +9 -0
- package/build/Tracker.mjs +41 -0
- package/build/Tracker.mjs.map +1 -0
- package/build/index.cjs +30 -0
- package/build/index.cjs.map +1 -0
- package/build/index.d.ts +13 -0
- package/build/index.mjs +14 -0
- package/build/index.mjs.map +1 -0
- package/build/target/Multi.cjs +25 -0
- package/build/target/Multi.cjs.map +1 -0
- package/build/target/Multi.d.ts +10 -0
- package/build/target/Multi.mjs +21 -0
- package/build/target/Multi.mjs.map +1 -0
- package/build/target/Plex.cjs +27 -0
- package/build/target/Plex.cjs.map +1 -0
- package/build/target/Plex.d.ts +12 -0
- package/build/target/Plex.mjs +23 -0
- package/build/target/Plex.mjs.map +1 -0
- package/build/target/Relay.cjs +26 -0
- package/build/target/Relay.cjs.map +1 -0
- package/build/target/Relay.d.ts +11 -0
- package/build/target/Relay.mjs +22 -0
- package/build/target/Relay.mjs.map +1 -0
- package/build/target/Relays.cjs +29 -0
- package/build/target/Relays.cjs.map +1 -0
- package/build/target/Relays.d.ts +10 -0
- package/build/target/Relays.mjs +25 -0
- package/build/target/Relays.mjs.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Socket.cjs","sourceRoot":"","sources":["../Socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import WebSocket from "isomorphic-ws";
|
|
2
|
+
import { Deferred } from '@welshman/lib';
|
|
3
|
+
import type { Message } from '@welshman/util';
|
|
4
|
+
export type PlexMessage = [{
|
|
5
|
+
relays: string[];
|
|
6
|
+
}, Message];
|
|
7
|
+
export type SocketMessage = Message | PlexMessage;
|
|
8
|
+
export declare const isMessage: (m: SocketMessage) => boolean;
|
|
9
|
+
export declare const asMessage: (m: SocketMessage) => Message;
|
|
10
|
+
export type SocketOpts = {
|
|
11
|
+
onOpen: () => void;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
onError: () => void;
|
|
14
|
+
onMessage: (message: SocketMessage) => void;
|
|
15
|
+
};
|
|
16
|
+
export declare class Socket {
|
|
17
|
+
readonly opts: SocketOpts;
|
|
18
|
+
url: string;
|
|
19
|
+
ws?: WebSocket;
|
|
20
|
+
ready: Deferred<boolean>;
|
|
21
|
+
failedToConnect: boolean;
|
|
22
|
+
constructor(url: string, opts: SocketOpts);
|
|
23
|
+
isPending(): boolean;
|
|
24
|
+
isConnecting(): boolean;
|
|
25
|
+
isReady(): boolean;
|
|
26
|
+
isClosing(): boolean;
|
|
27
|
+
isClosed(): boolean;
|
|
28
|
+
isHealthy(): boolean;
|
|
29
|
+
onOpen: () => void;
|
|
30
|
+
onError: () => void;
|
|
31
|
+
onMessage: (event: {
|
|
32
|
+
data: string;
|
|
33
|
+
}) => void;
|
|
34
|
+
send: (message: any) => void;
|
|
35
|
+
connect: () => void;
|
|
36
|
+
disconnect: () => void;
|
|
37
|
+
}
|
package/build/Socket.mjs
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import WebSocket from "isomorphic-ws";
|
|
2
|
+
import { defer } from '@welshman/lib';
|
|
3
|
+
export const isMessage = (m) => typeof m[0] === 'string';
|
|
4
|
+
export const asMessage = (m) => isMessage(m) ? m : m[1];
|
|
5
|
+
export class Socket {
|
|
6
|
+
constructor(url, opts) {
|
|
7
|
+
this.opts = opts;
|
|
8
|
+
this.failedToConnect = false;
|
|
9
|
+
this.onOpen = () => {
|
|
10
|
+
this.ready.resolve(true);
|
|
11
|
+
this.opts.onOpen();
|
|
12
|
+
};
|
|
13
|
+
this.onError = () => {
|
|
14
|
+
this.opts.onError();
|
|
15
|
+
this.disconnect();
|
|
16
|
+
};
|
|
17
|
+
this.onMessage = (event) => {
|
|
18
|
+
try {
|
|
19
|
+
const message = JSON.parse(event.data);
|
|
20
|
+
if (Array.isArray(message)) {
|
|
21
|
+
this.opts.onMessage(message);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.warn("Invalid messages received:", message);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
// pass
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
this.send = (message) => {
|
|
32
|
+
if (!this.ws) {
|
|
33
|
+
throw new Error('Send attempted before socket was opened');
|
|
34
|
+
}
|
|
35
|
+
this.ws.send(JSON.stringify(message));
|
|
36
|
+
};
|
|
37
|
+
this.connect = () => {
|
|
38
|
+
if (this.ws) {
|
|
39
|
+
throw new Error(`Already attempted connection for ${this.url}`);
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
this.ws = new WebSocket(this.url);
|
|
43
|
+
this.ws.onopen = this.onOpen;
|
|
44
|
+
this.ws.onerror = this.onError;
|
|
45
|
+
this.ws.onmessage = this.onMessage;
|
|
46
|
+
this.ws.onclose = this.disconnect;
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
this.failedToConnect = true;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
this.disconnect = () => {
|
|
53
|
+
if (this.ws) {
|
|
54
|
+
const currentWs = this.ws;
|
|
55
|
+
this.ready.then(() => currentWs.close());
|
|
56
|
+
this.ready = defer();
|
|
57
|
+
this.opts.onClose();
|
|
58
|
+
this.ws = undefined;
|
|
59
|
+
// Resolve a different instance of the promise
|
|
60
|
+
this.ready.resolve(false);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
this.url = url;
|
|
64
|
+
this.ready = defer();
|
|
65
|
+
}
|
|
66
|
+
isPending() {
|
|
67
|
+
return !this.ws && !this.failedToConnect;
|
|
68
|
+
}
|
|
69
|
+
isConnecting() {
|
|
70
|
+
var _a;
|
|
71
|
+
return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.CONNECTING;
|
|
72
|
+
}
|
|
73
|
+
isReady() {
|
|
74
|
+
var _a;
|
|
75
|
+
return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN;
|
|
76
|
+
}
|
|
77
|
+
isClosing() {
|
|
78
|
+
var _a;
|
|
79
|
+
return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.CLOSING;
|
|
80
|
+
}
|
|
81
|
+
isClosed() {
|
|
82
|
+
var _a;
|
|
83
|
+
return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.CLOSED;
|
|
84
|
+
}
|
|
85
|
+
isHealthy() {
|
|
86
|
+
return this.isPending() || this.isConnecting() || this.isReady();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=Socket.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Socket.mjs","sourceRoot":"","sources":["../Socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.subscribe = exports.executeSubscriptionBatched = exports.executeSubscriptions = exports.executeSubscription = exports.mergeSubscriptions = exports.calculateSubscriptionGroup = exports.makeSubscription = exports.SubscriptionEvent = void 0;
|
|
4
|
+
const lib_1 = require("@welshman/lib");
|
|
5
|
+
const util_1 = require("@welshman/util");
|
|
6
|
+
const Tracker_1 = require("./Tracker.cjs");
|
|
7
|
+
const Context_1 = require("./Context.cjs");
|
|
8
|
+
// `subscribe` is a super function that handles batching subscriptions by merging
|
|
9
|
+
// them based on parameters (filters and subscribe opts), then splits them by relay.
|
|
10
|
+
// This results in fewer REQs being opened per connection, fewer duplicate events
|
|
11
|
+
// being downloaded, and therefore less signature validation.
|
|
12
|
+
//
|
|
13
|
+
// Behavior can be further configured using NetworkContext. This can be useful for
|
|
14
|
+
// adding support for querying a local cache like a relay, tracking deleted events,
|
|
15
|
+
// and bypassing validation for trusted relays.
|
|
16
|
+
//
|
|
17
|
+
// Urls that any given event was seen on are tracked using subscription request's `tracker`
|
|
18
|
+
// property. These are merged across all subscription requests, so it is possible that an
|
|
19
|
+
// event may be seen on more relays that were actually requested, in the case of overlapping
|
|
20
|
+
// subscriptions.
|
|
21
|
+
var SubscriptionEvent;
|
|
22
|
+
(function (SubscriptionEvent) {
|
|
23
|
+
SubscriptionEvent["Eose"] = "eose";
|
|
24
|
+
SubscriptionEvent["Close"] = "close";
|
|
25
|
+
SubscriptionEvent["Event"] = "event";
|
|
26
|
+
SubscriptionEvent["Abort"] = "abort";
|
|
27
|
+
SubscriptionEvent["Complete"] = "complete";
|
|
28
|
+
SubscriptionEvent["Duplicate"] = "duplicate";
|
|
29
|
+
SubscriptionEvent["DeletedEvent"] = "deleted-event";
|
|
30
|
+
SubscriptionEvent["FailedFilter"] = "failed-filter";
|
|
31
|
+
SubscriptionEvent["InvalidSignature"] = "invalid-signature";
|
|
32
|
+
})(SubscriptionEvent || (exports.SubscriptionEvent = SubscriptionEvent = {}));
|
|
33
|
+
const makeSubscription = (request) => {
|
|
34
|
+
const id = (0, lib_1.randomId)();
|
|
35
|
+
const emitter = new lib_1.Emitter();
|
|
36
|
+
const tracker = new Tracker_1.Tracker();
|
|
37
|
+
const result = (0, lib_1.defer)();
|
|
38
|
+
const close = () => emitter.emit('abort');
|
|
39
|
+
emitter.setMaxListeners(100);
|
|
40
|
+
return { id, request, emitter, tracker, result, close };
|
|
41
|
+
};
|
|
42
|
+
exports.makeSubscription = makeSubscription;
|
|
43
|
+
const calculateSubscriptionGroup = (sub) => {
|
|
44
|
+
const parts = [];
|
|
45
|
+
if (sub.request.timeout)
|
|
46
|
+
parts.push(`timeout:${sub.request.timeout}`);
|
|
47
|
+
if (sub.request.closeOnEose)
|
|
48
|
+
parts.push('closeOnEose');
|
|
49
|
+
return parts.join('|');
|
|
50
|
+
};
|
|
51
|
+
exports.calculateSubscriptionGroup = calculateSubscriptionGroup;
|
|
52
|
+
const mergeSubscriptions = (subs) => {
|
|
53
|
+
const completedRelays = new Set();
|
|
54
|
+
const mergedSubscriptions = [];
|
|
55
|
+
for (const group of Object.values((0, lib_1.groupBy)(exports.calculateSubscriptionGroup, subs))) {
|
|
56
|
+
for (const relay of (0, lib_1.uniq)(group.flatMap((sub) => sub.request.relays))) {
|
|
57
|
+
const abortedSubs = new Set();
|
|
58
|
+
const callerSubs = group.filter((sub) => sub.request.relays.includes(relay));
|
|
59
|
+
const mergedSub = (0, exports.makeSubscription)({
|
|
60
|
+
relays: [relay],
|
|
61
|
+
timeout: callerSubs[0].request.timeout,
|
|
62
|
+
filters: (0, util_1.mergeFilters)(callerSubs.flatMap((sub) => sub.request.filters)),
|
|
63
|
+
});
|
|
64
|
+
for (const { id, emitter } of callerSubs) {
|
|
65
|
+
// Propagate abort event from the caller to the merged subscription
|
|
66
|
+
emitter.on(SubscriptionEvent.Abort, () => {
|
|
67
|
+
abortedSubs.add(id);
|
|
68
|
+
if (abortedSubs.size === callerSubs.length) {
|
|
69
|
+
mergedSub.close();
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
mergedSub.emitter.on(SubscriptionEvent.Event, (url, event) => {
|
|
74
|
+
for (const sub of callerSubs) {
|
|
75
|
+
if (sub.tracker.track(event.id, url)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (!(0, util_1.matchFilters)(sub.request.filters, event)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
sub.emitter.emit(SubscriptionEvent.Event, url, event);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Pass events back to caller
|
|
85
|
+
const propagateEvent = (type, checkFilter) => mergedSub.emitter.on(type, (url, event) => {
|
|
86
|
+
for (const sub of callerSubs) {
|
|
87
|
+
if (!checkFilter || (0, util_1.matchFilters)(sub.request.filters, event)) {
|
|
88
|
+
sub.emitter.emit(type, url, event);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
propagateEvent(SubscriptionEvent.Duplicate, true);
|
|
93
|
+
propagateEvent(SubscriptionEvent.DeletedEvent, false);
|
|
94
|
+
propagateEvent(SubscriptionEvent.FailedFilter, false);
|
|
95
|
+
propagateEvent(SubscriptionEvent.InvalidSignature, true);
|
|
96
|
+
// Propagate eose
|
|
97
|
+
mergedSub.emitter.on(SubscriptionEvent.Eose, (url) => {
|
|
98
|
+
for (const sub of callerSubs) {
|
|
99
|
+
sub.emitter.emit(SubscriptionEvent.Eose, url);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// Propagate close
|
|
103
|
+
mergedSub.emitter.on(SubscriptionEvent.Close, (url) => {
|
|
104
|
+
for (const sub of callerSubs) {
|
|
105
|
+
sub.emitter.emit(SubscriptionEvent.Close, url);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
// Propagate subscription completion. Since we split subs by relay, we need to wait
|
|
109
|
+
// until all relays are completed before we notify
|
|
110
|
+
mergedSub.emitter.on(SubscriptionEvent.Complete, () => {
|
|
111
|
+
completedRelays.add(relay);
|
|
112
|
+
for (const sub of callerSubs) {
|
|
113
|
+
if (sub.request.relays.every(url => completedRelays.has(url))) {
|
|
114
|
+
sub.emitter.emit(SubscriptionEvent.Complete);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
mergedSub.emitter.removeAllListeners();
|
|
118
|
+
});
|
|
119
|
+
// Propagate promise resolution
|
|
120
|
+
mergedSub.result.then((events) => {
|
|
121
|
+
events = (0, lib_1.uniqBy)((event) => event.id, events);
|
|
122
|
+
for (const sub of callerSubs) {
|
|
123
|
+
sub.result.resolve(events.filter((e) => (0, util_1.matchFilters)(sub.request.filters, e)));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
mergedSubscriptions.push(mergedSub);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return mergedSubscriptions;
|
|
130
|
+
};
|
|
131
|
+
exports.mergeSubscriptions = mergeSubscriptions;
|
|
132
|
+
const executeSubscription = (sub) => {
|
|
133
|
+
const { result, request, emitter, tracker } = sub;
|
|
134
|
+
const { timeout, filters, closeOnEose, relays } = request;
|
|
135
|
+
const executor = Context_1.NetworkContext.getExecutor(relays);
|
|
136
|
+
const events = [];
|
|
137
|
+
const completedRelays = new Set();
|
|
138
|
+
let completed;
|
|
139
|
+
const complete = () => {
|
|
140
|
+
if (completed)
|
|
141
|
+
return;
|
|
142
|
+
// Mark as cleaned upp, unsubscribe our executor
|
|
143
|
+
completed = Date.now();
|
|
144
|
+
executorSub.unsubscribe();
|
|
145
|
+
// Resolve our promise
|
|
146
|
+
result.resolve(events);
|
|
147
|
+
// Notify caller, clean up our event emitter
|
|
148
|
+
emitter.emit(SubscriptionEvent.Complete);
|
|
149
|
+
emitter.removeAllListeners();
|
|
150
|
+
// Remove our onClose handler from connections, since they are shared by many subs
|
|
151
|
+
executor.target.connections.forEach((c) => c.off("close", onClose));
|
|
152
|
+
executor.target.cleanup();
|
|
153
|
+
};
|
|
154
|
+
const onEvent = (url, event) => {
|
|
155
|
+
// Check the signature and filters. If we've seen this event, don't re-validate.
|
|
156
|
+
if (tracker.track(event.id, url)) {
|
|
157
|
+
emitter.emit(SubscriptionEvent.Duplicate, url, event);
|
|
158
|
+
}
|
|
159
|
+
else if (Context_1.NetworkContext.isDeleted(url, event)) {
|
|
160
|
+
emitter.emit(SubscriptionEvent.DeletedEvent, url, event);
|
|
161
|
+
}
|
|
162
|
+
else if (!Context_1.NetworkContext.matchFilters(url, filters, event)) {
|
|
163
|
+
emitter.emit(SubscriptionEvent.FailedFilter, url, event);
|
|
164
|
+
}
|
|
165
|
+
else if (!Context_1.NetworkContext.hasValidSignature(url, event)) {
|
|
166
|
+
emitter.emit(SubscriptionEvent.InvalidSignature, url, event);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
emitter.emit(SubscriptionEvent.Event, url, event);
|
|
170
|
+
events.push(event);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const onEose = (url) => {
|
|
174
|
+
completedRelays.add(url);
|
|
175
|
+
emitter.emit(SubscriptionEvent.Eose, url);
|
|
176
|
+
if (closeOnEose && completedRelays.size === executor.target.connections.length) {
|
|
177
|
+
complete();
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const onClose = (connection) => {
|
|
181
|
+
completedRelays.add(connection.url);
|
|
182
|
+
emitter.emit(SubscriptionEvent.Close, connection.url);
|
|
183
|
+
if (completedRelays.size === executor.target.connections.length) {
|
|
184
|
+
complete();
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
// Allow the caller to cancel the subscription
|
|
188
|
+
emitter.on(SubscriptionEvent.Abort, complete);
|
|
189
|
+
// If we have a timeout, complete the subscription automatically
|
|
190
|
+
if (timeout)
|
|
191
|
+
setTimeout(complete, timeout);
|
|
192
|
+
// If one of our connections gets closed make sure to kill our sub
|
|
193
|
+
executor.target.connections.forEach((c) => c.on('close', onClose));
|
|
194
|
+
// Finally, start our subscription
|
|
195
|
+
const executorSub = executor.subscribe(filters, { onEvent, onEose });
|
|
196
|
+
};
|
|
197
|
+
exports.executeSubscription = executeSubscription;
|
|
198
|
+
const executeSubscriptions = (subs) => (0, exports.mergeSubscriptions)(subs).forEach(exports.executeSubscription);
|
|
199
|
+
exports.executeSubscriptions = executeSubscriptions;
|
|
200
|
+
exports.executeSubscriptionBatched = (0, lib_1.batch)(800, exports.executeSubscriptions);
|
|
201
|
+
const subscribe = (request) => {
|
|
202
|
+
const subscription = (0, exports.makeSubscription)(request);
|
|
203
|
+
if (request.filters.length === 0) {
|
|
204
|
+
throw new Error("Zero filters passed to subscribe");
|
|
205
|
+
}
|
|
206
|
+
if (request.immediate) {
|
|
207
|
+
(0, exports.executeSubscription)(subscription);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
(0, exports.executeSubscriptionBatched)(subscription);
|
|
211
|
+
}
|
|
212
|
+
return subscription;
|
|
213
|
+
};
|
|
214
|
+
exports.subscribe = subscribe;
|
|
215
|
+
//# sourceMappingURL=Subscribe.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Subscribe.cjs","sourceRoot":"","sources":["../Subscribe.ts"],"names":[],"mappings":";;;AACA,uCAAoF;AAEpF,yCAAyD;AAEzD,2CAAiC;AAEjC,2CAAwC;AAExC,iFAAiF;AACjF,oFAAoF;AACpF,iFAAiF;AACjF,6DAA6D;AAC7D,EAAE;AACF,kFAAkF;AAClF,mFAAmF;AACnF,+CAA+C;AAC/C,EAAE;AACF,2FAA2F;AAC3F,yFAAyF;AACzF,4FAA4F;AAC5F,iBAAiB;AAEjB,IAAY,iBAUX;AAVD,WAAY,iBAAiB;IAC3B,kCAAa,CAAA;IACb,oCAAe,CAAA;IACf,oCAAe,CAAA;IACf,oCAAe,CAAA;IACf,0CAAqB,CAAA;IACrB,4CAAuB,CAAA;IACvB,mDAA8B,CAAA;IAC9B,mDAA8B,CAAA;IAC9B,2DAAsC,CAAA;AACxC,CAAC,EAVW,iBAAiB,iCAAjB,iBAAiB,QAU5B;AAmBM,MAAM,gBAAgB,GAAG,CAAC,OAAyB,EAAE,EAAE;IAC5D,MAAM,EAAE,GAAG,IAAA,cAAQ,GAAE,CAAA;IACrB,MAAM,OAAO,GAAG,IAAI,aAAO,EAAE,CAAA;IAC7B,MAAM,OAAO,GAAG,IAAI,iBAAO,EAAE,CAAA;IAC7B,MAAM,MAAM,GAAG,IAAA,WAAK,GAAW,CAAA;IAC/B,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAEzC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;IAE5B,OAAO,EAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAC,CAAA;AACvD,CAAC,CAAA;AAVY,QAAA,gBAAgB,oBAU5B;AAEM,MAAM,0BAA0B,GAAG,CAAC,GAAiB,EAAE,EAAE;IAC9D,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IACrE,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAEtD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC,CAAA;AAPY,QAAA,0BAA0B,8BAOtC;AAEM,MAAM,kBAAkB,GAAG,CAAC,IAAoB,EAAE,EAAE;IACzD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAE,CAAA;IACjC,MAAM,mBAAmB,GAAG,EAAE,CAAA;IAE9B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,IAAA,aAAO,EAAC,kCAA0B,EAAE,IAAI,CAAC,CAAC,EAAE;QAC5E,KAAK,MAAM,KAAK,IAAI,IAAA,UAAI,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAiB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE;YAClF,MAAM,WAAW,GAAG,IAAI,GAAG,EAAE,CAAA;YAC7B,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAiB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;YAC1F,MAAM,SAAS,GAAG,IAAA,wBAAgB,EAAC;gBACjC,MAAM,EAAE,CAAC,KAAK,CAAC;gBACf,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;gBACtC,OAAO,EAAE,IAAA,mBAAY,EAAC,UAAU,CAAC,OAAO,CAAC,CAAC,GAAiB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;aACtF,CAAC,CAAA;YAEF,KAAK,MAAM,EAAC,EAAE,EAAE,OAAO,EAAC,IAAI,UAAU,EAAE;gBACtC,mEAAmE;gBACnE,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE;oBACvC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;oBAEnB,IAAI,WAAW,CAAC,IAAI,KAAK,UAAU,CAAC,MAAM,EAAE;wBAC1C,SAAS,CAAC,KAAK,EAAE,CAAA;qBAClB;gBACH,CAAC,CAAC,CAAA;aACH;YAED,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC,GAAW,EAAE,KAAY,EAAE,EAAE;gBAC1E,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;oBAC5B,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE;wBACpC,SAAQ;qBACT;oBAED,IAAI,CAAC,IAAA,mBAAY,EAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;wBAC7C,SAAQ;qBACT;oBAED,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;iBACtD;YACH,CAAC,CAAC,CAAA;YAEF,6BAA6B;YAC7B,MAAM,cAAc,GAAG,CAAC,IAAuB,EAAE,WAAoB,EAAE,EAAE,CACvE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAG,CAAC,GAAW,EAAE,KAAY,EAAE,EAAE;gBACxD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;oBAC5B,IAAI,CAAC,WAAW,IAAI,IAAA,mBAAY,EAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;wBAC5D,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;qBACnC;iBACF;YACH,CAAC,CAAC,CAAA;YAEJ,cAAc,CAAC,iBAAiB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YACjD,cAAc,CAAC,iBAAiB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;YACrD,cAAc,CAAC,iBAAiB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;YACrD,cAAc,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;YAExD,iBAAiB;YACjB,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE;gBAC3D,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;oBAC5B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;iBAC9C;YACH,CAAC,CAAC,CAAA;YAEF,kBAAkB;YAClB,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE;gBAC5D,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;oBAC5B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;iBAC/C;YACH,CAAC,CAAC,CAAA;YAEF,mFAAmF;YACnF,kDAAkD;YAClD,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACpD,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;gBAE1B,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;oBAC5B,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;wBAC7D,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAA;qBAC7C;iBACF;gBAED,SAAS,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAA;YACxC,CAAC,CAAC,CAAA;YAEF,+BAA+B;YAC/B,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAe,EAAE,EAAE;gBACxC,MAAM,GAAG,IAAA,YAAM,EAAC,CAAC,KAAY,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;gBAEnD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;oBAC5B,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAA,mBAAY,EAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;iBACtF;YACH,CAAC,CAAC,CAAA;YAEF,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;SACpC;KACF;IAED,OAAO,mBAAmB,CAAA;AAC5B,CAAC,CAAA;AAhGY,QAAA,kBAAkB,sBAgG9B;AAEM,MAAM,mBAAmB,GAAG,CAAC,GAAiB,EAAE,EAAE;IACvD,MAAM,EAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAC,GAAG,GAAG,CAAA;IAC/C,MAAM,EAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAC,GAAG,OAAO,CAAA;IACvD,MAAM,QAAQ,GAAG,wBAAc,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IACnD,MAAM,MAAM,GAAY,EAAE,CAAA;IAE1B,MAAM,eAAe,GAAG,IAAI,GAAG,EAAE,CAAA;IACjC,IAAI,SAAiB,CAAA;IAErB,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,IAAI,SAAS;YAAE,OAAM;QAErB,gDAAgD;QAChD,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,WAAW,CAAC,WAAW,EAAE,CAAA;QAEzB,sBAAsB;QACtB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAEtB,4CAA4C;QAC5C,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAA;QACxC,OAAO,CAAC,kBAAkB,EAAE,CAAA;QAE5B,kFAAkF;QAClF,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;QAC/E,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;IAC3B,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,KAAY,EAAE,EAAE;QAC5C,gFAAgF;QAChF,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE;YAChC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;SACtD;aAAM,IAAI,wBAAc,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE;YAC/C,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;SACzD;aAAM,IAAI,CAAC,wBAAc,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE;YAC5D,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;SACzD;aAAM,IAAI,CAAC,wBAAc,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE;YACxD,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;SAC7D;aAAM;YACL,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;YACjD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;SACnB;IACH,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE;QAC7B,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAExB,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAEzC,IAAI,WAAW,IAAI,eAAe,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE;YAC9E,QAAQ,EAAE,CAAA;SACX;IACH,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,CAAC,UAAsB,EAAE,EAAE;QACzC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAEnC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAA;QAErD,IAAI,eAAe,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE;YAC/D,QAAQ,EAAE,CAAA;SACX;IACH,CAAC,CAAA;IAED,8CAA8C;IAC9C,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IAE7C,gEAAgE;IAChE,IAAI,OAAO;QAAE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAE1C,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAE9E,kCAAkC;IAClC,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,EAAC,OAAO,EAAE,MAAM,EAAC,CAAC,CAAA;AACpE,CAAC,CAAA;AA3EY,QAAA,mBAAmB,uBA2E/B;AAEM,MAAM,oBAAoB,GAAG,CAAC,IAAoB,EAAE,EAAE,CAC3D,IAAA,0BAAkB,EAAC,IAAI,CAAC,CAAC,OAAO,CAAC,2BAAmB,CAAC,CAAA;AAD1C,QAAA,oBAAoB,wBACsB;AAE1C,QAAA,0BAA0B,GAAG,IAAA,WAAK,EAAC,GAAG,EAAE,4BAAoB,CAAC,CAAA;AAEnE,MAAM,SAAS,GAAG,CAAC,OAAyB,EAAE,EAAE;IACrD,MAAM,YAAY,GAAiB,IAAA,wBAAgB,EAAC,OAAO,CAAC,CAAA;IAE5D,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QAChC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;KACpD;IAED,IAAI,OAAO,CAAC,SAAS,EAAE;QACrB,IAAA,2BAAmB,EAAC,YAAY,CAAC,CAAA;KAClC;SAAM;QACL,IAAA,kCAA0B,EAAC,YAAY,CAAC,CAAA;KACzC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA;AAdY,QAAA,SAAS,aAcrB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Event } from 'nostr-tools';
|
|
2
|
+
import { Emitter } from '@welshman/lib';
|
|
3
|
+
import type { Deferred } from '@welshman/lib';
|
|
4
|
+
import type { Filter } from '@welshman/util';
|
|
5
|
+
import { Tracker } from "./Tracker";
|
|
6
|
+
export declare enum SubscriptionEvent {
|
|
7
|
+
Eose = "eose",
|
|
8
|
+
Close = "close",
|
|
9
|
+
Event = "event",
|
|
10
|
+
Abort = "abort",
|
|
11
|
+
Complete = "complete",
|
|
12
|
+
Duplicate = "duplicate",
|
|
13
|
+
DeletedEvent = "deleted-event",
|
|
14
|
+
FailedFilter = "failed-filter",
|
|
15
|
+
InvalidSignature = "invalid-signature"
|
|
16
|
+
}
|
|
17
|
+
export type SubscribeRequest = {
|
|
18
|
+
relays: string[];
|
|
19
|
+
filters: Filter[];
|
|
20
|
+
timeout?: number;
|
|
21
|
+
immediate?: boolean;
|
|
22
|
+
closeOnEose?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export type Subscription = {
|
|
25
|
+
id: string;
|
|
26
|
+
emitter: Emitter;
|
|
27
|
+
tracker: Tracker;
|
|
28
|
+
result: Deferred<Event[]>;
|
|
29
|
+
request: SubscribeRequest;
|
|
30
|
+
close: () => void;
|
|
31
|
+
};
|
|
32
|
+
export declare const makeSubscription: (request: SubscribeRequest) => {
|
|
33
|
+
id: string;
|
|
34
|
+
request: SubscribeRequest;
|
|
35
|
+
emitter: Emitter;
|
|
36
|
+
tracker: Tracker;
|
|
37
|
+
result: Deferred<Event[]>;
|
|
38
|
+
close: () => boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare const calculateSubscriptionGroup: (sub: Subscription) => string;
|
|
41
|
+
export declare const mergeSubscriptions: (subs: Subscription[]) => {
|
|
42
|
+
id: string;
|
|
43
|
+
request: SubscribeRequest;
|
|
44
|
+
emitter: Emitter;
|
|
45
|
+
tracker: Tracker;
|
|
46
|
+
result: Deferred<Event[]>;
|
|
47
|
+
close: () => boolean;
|
|
48
|
+
}[];
|
|
49
|
+
export declare const executeSubscription: (sub: Subscription) => void;
|
|
50
|
+
export declare const executeSubscriptions: (subs: Subscription[]) => void;
|
|
51
|
+
export declare const executeSubscriptionBatched: (x: Subscription) => void;
|
|
52
|
+
export declare const subscribe: (request: SubscribeRequest) => Subscription;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { Emitter, randomId, groupBy, batch, defer, uniq, uniqBy } from '@welshman/lib';
|
|
2
|
+
import { matchFilters, mergeFilters } from '@welshman/util';
|
|
3
|
+
import { Tracker } from "./Tracker.mjs";
|
|
4
|
+
import { NetworkContext } from "./Context.mjs";
|
|
5
|
+
// `subscribe` is a super function that handles batching subscriptions by merging
|
|
6
|
+
// them based on parameters (filters and subscribe opts), then splits them by relay.
|
|
7
|
+
// This results in fewer REQs being opened per connection, fewer duplicate events
|
|
8
|
+
// being downloaded, and therefore less signature validation.
|
|
9
|
+
//
|
|
10
|
+
// Behavior can be further configured using NetworkContext. This can be useful for
|
|
11
|
+
// adding support for querying a local cache like a relay, tracking deleted events,
|
|
12
|
+
// and bypassing validation for trusted relays.
|
|
13
|
+
//
|
|
14
|
+
// Urls that any given event was seen on are tracked using subscription request's `tracker`
|
|
15
|
+
// property. These are merged across all subscription requests, so it is possible that an
|
|
16
|
+
// event may be seen on more relays that were actually requested, in the case of overlapping
|
|
17
|
+
// subscriptions.
|
|
18
|
+
export var SubscriptionEvent;
|
|
19
|
+
(function (SubscriptionEvent) {
|
|
20
|
+
SubscriptionEvent["Eose"] = "eose";
|
|
21
|
+
SubscriptionEvent["Close"] = "close";
|
|
22
|
+
SubscriptionEvent["Event"] = "event";
|
|
23
|
+
SubscriptionEvent["Abort"] = "abort";
|
|
24
|
+
SubscriptionEvent["Complete"] = "complete";
|
|
25
|
+
SubscriptionEvent["Duplicate"] = "duplicate";
|
|
26
|
+
SubscriptionEvent["DeletedEvent"] = "deleted-event";
|
|
27
|
+
SubscriptionEvent["FailedFilter"] = "failed-filter";
|
|
28
|
+
SubscriptionEvent["InvalidSignature"] = "invalid-signature";
|
|
29
|
+
})(SubscriptionEvent || (SubscriptionEvent = {}));
|
|
30
|
+
export const makeSubscription = (request) => {
|
|
31
|
+
const id = randomId();
|
|
32
|
+
const emitter = new Emitter();
|
|
33
|
+
const tracker = new Tracker();
|
|
34
|
+
const result = defer();
|
|
35
|
+
const close = () => emitter.emit('abort');
|
|
36
|
+
emitter.setMaxListeners(100);
|
|
37
|
+
return { id, request, emitter, tracker, result, close };
|
|
38
|
+
};
|
|
39
|
+
export const calculateSubscriptionGroup = (sub) => {
|
|
40
|
+
const parts = [];
|
|
41
|
+
if (sub.request.timeout)
|
|
42
|
+
parts.push(`timeout:${sub.request.timeout}`);
|
|
43
|
+
if (sub.request.closeOnEose)
|
|
44
|
+
parts.push('closeOnEose');
|
|
45
|
+
return parts.join('|');
|
|
46
|
+
};
|
|
47
|
+
export const mergeSubscriptions = (subs) => {
|
|
48
|
+
const completedRelays = new Set();
|
|
49
|
+
const mergedSubscriptions = [];
|
|
50
|
+
for (const group of Object.values(groupBy(calculateSubscriptionGroup, subs))) {
|
|
51
|
+
for (const relay of uniq(group.flatMap((sub) => sub.request.relays))) {
|
|
52
|
+
const abortedSubs = new Set();
|
|
53
|
+
const callerSubs = group.filter((sub) => sub.request.relays.includes(relay));
|
|
54
|
+
const mergedSub = makeSubscription({
|
|
55
|
+
relays: [relay],
|
|
56
|
+
timeout: callerSubs[0].request.timeout,
|
|
57
|
+
filters: mergeFilters(callerSubs.flatMap((sub) => sub.request.filters)),
|
|
58
|
+
});
|
|
59
|
+
for (const { id, emitter } of callerSubs) {
|
|
60
|
+
// Propagate abort event from the caller to the merged subscription
|
|
61
|
+
emitter.on(SubscriptionEvent.Abort, () => {
|
|
62
|
+
abortedSubs.add(id);
|
|
63
|
+
if (abortedSubs.size === callerSubs.length) {
|
|
64
|
+
mergedSub.close();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
mergedSub.emitter.on(SubscriptionEvent.Event, (url, event) => {
|
|
69
|
+
for (const sub of callerSubs) {
|
|
70
|
+
if (sub.tracker.track(event.id, url)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (!matchFilters(sub.request.filters, event)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
sub.emitter.emit(SubscriptionEvent.Event, url, event);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// Pass events back to caller
|
|
80
|
+
const propagateEvent = (type, checkFilter) => mergedSub.emitter.on(type, (url, event) => {
|
|
81
|
+
for (const sub of callerSubs) {
|
|
82
|
+
if (!checkFilter || matchFilters(sub.request.filters, event)) {
|
|
83
|
+
sub.emitter.emit(type, url, event);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
propagateEvent(SubscriptionEvent.Duplicate, true);
|
|
88
|
+
propagateEvent(SubscriptionEvent.DeletedEvent, false);
|
|
89
|
+
propagateEvent(SubscriptionEvent.FailedFilter, false);
|
|
90
|
+
propagateEvent(SubscriptionEvent.InvalidSignature, true);
|
|
91
|
+
// Propagate eose
|
|
92
|
+
mergedSub.emitter.on(SubscriptionEvent.Eose, (url) => {
|
|
93
|
+
for (const sub of callerSubs) {
|
|
94
|
+
sub.emitter.emit(SubscriptionEvent.Eose, url);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// Propagate close
|
|
98
|
+
mergedSub.emitter.on(SubscriptionEvent.Close, (url) => {
|
|
99
|
+
for (const sub of callerSubs) {
|
|
100
|
+
sub.emitter.emit(SubscriptionEvent.Close, url);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
// Propagate subscription completion. Since we split subs by relay, we need to wait
|
|
104
|
+
// until all relays are completed before we notify
|
|
105
|
+
mergedSub.emitter.on(SubscriptionEvent.Complete, () => {
|
|
106
|
+
completedRelays.add(relay);
|
|
107
|
+
for (const sub of callerSubs) {
|
|
108
|
+
if (sub.request.relays.every(url => completedRelays.has(url))) {
|
|
109
|
+
sub.emitter.emit(SubscriptionEvent.Complete);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
mergedSub.emitter.removeAllListeners();
|
|
113
|
+
});
|
|
114
|
+
// Propagate promise resolution
|
|
115
|
+
mergedSub.result.then((events) => {
|
|
116
|
+
events = uniqBy((event) => event.id, events);
|
|
117
|
+
for (const sub of callerSubs) {
|
|
118
|
+
sub.result.resolve(events.filter((e) => matchFilters(sub.request.filters, e)));
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
mergedSubscriptions.push(mergedSub);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return mergedSubscriptions;
|
|
125
|
+
};
|
|
126
|
+
export const executeSubscription = (sub) => {
|
|
127
|
+
const { result, request, emitter, tracker } = sub;
|
|
128
|
+
const { timeout, filters, closeOnEose, relays } = request;
|
|
129
|
+
const executor = NetworkContext.getExecutor(relays);
|
|
130
|
+
const events = [];
|
|
131
|
+
const completedRelays = new Set();
|
|
132
|
+
let completed;
|
|
133
|
+
const complete = () => {
|
|
134
|
+
if (completed)
|
|
135
|
+
return;
|
|
136
|
+
// Mark as cleaned upp, unsubscribe our executor
|
|
137
|
+
completed = Date.now();
|
|
138
|
+
executorSub.unsubscribe();
|
|
139
|
+
// Resolve our promise
|
|
140
|
+
result.resolve(events);
|
|
141
|
+
// Notify caller, clean up our event emitter
|
|
142
|
+
emitter.emit(SubscriptionEvent.Complete);
|
|
143
|
+
emitter.removeAllListeners();
|
|
144
|
+
// Remove our onClose handler from connections, since they are shared by many subs
|
|
145
|
+
executor.target.connections.forEach((c) => c.off("close", onClose));
|
|
146
|
+
executor.target.cleanup();
|
|
147
|
+
};
|
|
148
|
+
const onEvent = (url, event) => {
|
|
149
|
+
// Check the signature and filters. If we've seen this event, don't re-validate.
|
|
150
|
+
if (tracker.track(event.id, url)) {
|
|
151
|
+
emitter.emit(SubscriptionEvent.Duplicate, url, event);
|
|
152
|
+
}
|
|
153
|
+
else if (NetworkContext.isDeleted(url, event)) {
|
|
154
|
+
emitter.emit(SubscriptionEvent.DeletedEvent, url, event);
|
|
155
|
+
}
|
|
156
|
+
else if (!NetworkContext.matchFilters(url, filters, event)) {
|
|
157
|
+
emitter.emit(SubscriptionEvent.FailedFilter, url, event);
|
|
158
|
+
}
|
|
159
|
+
else if (!NetworkContext.hasValidSignature(url, event)) {
|
|
160
|
+
emitter.emit(SubscriptionEvent.InvalidSignature, url, event);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
emitter.emit(SubscriptionEvent.Event, url, event);
|
|
164
|
+
events.push(event);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const onEose = (url) => {
|
|
168
|
+
completedRelays.add(url);
|
|
169
|
+
emitter.emit(SubscriptionEvent.Eose, url);
|
|
170
|
+
if (closeOnEose && completedRelays.size === executor.target.connections.length) {
|
|
171
|
+
complete();
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const onClose = (connection) => {
|
|
175
|
+
completedRelays.add(connection.url);
|
|
176
|
+
emitter.emit(SubscriptionEvent.Close, connection.url);
|
|
177
|
+
if (completedRelays.size === executor.target.connections.length) {
|
|
178
|
+
complete();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
// Allow the caller to cancel the subscription
|
|
182
|
+
emitter.on(SubscriptionEvent.Abort, complete);
|
|
183
|
+
// If we have a timeout, complete the subscription automatically
|
|
184
|
+
if (timeout)
|
|
185
|
+
setTimeout(complete, timeout);
|
|
186
|
+
// If one of our connections gets closed make sure to kill our sub
|
|
187
|
+
executor.target.connections.forEach((c) => c.on('close', onClose));
|
|
188
|
+
// Finally, start our subscription
|
|
189
|
+
const executorSub = executor.subscribe(filters, { onEvent, onEose });
|
|
190
|
+
};
|
|
191
|
+
export const executeSubscriptions = (subs) => mergeSubscriptions(subs).forEach(executeSubscription);
|
|
192
|
+
export const executeSubscriptionBatched = batch(800, executeSubscriptions);
|
|
193
|
+
export const subscribe = (request) => {
|
|
194
|
+
const subscription = makeSubscription(request);
|
|
195
|
+
if (request.filters.length === 0) {
|
|
196
|
+
throw new Error("Zero filters passed to subscribe");
|
|
197
|
+
}
|
|
198
|
+
if (request.immediate) {
|
|
199
|
+
executeSubscription(subscription);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
executeSubscriptionBatched(subscription);
|
|
203
|
+
}
|
|
204
|
+
return subscription;
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=Subscribe.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Subscribe.mjs","sourceRoot":"","sources":["../Subscribe.ts"],"names":[],"mappings":"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"}
|