include node_modules so release .zip is deployable
This commit is contained in:
+747
@@ -0,0 +1,747 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// pool.ts
|
||||
var pool_exports = {};
|
||||
__export(pool_exports, {
|
||||
SimplePool: () => SimplePool
|
||||
});
|
||||
module.exports = __toCommonJS(pool_exports);
|
||||
|
||||
// event.ts
|
||||
var import_secp256k1 = require("@noble/curves/secp256k1");
|
||||
var import_sha256 = require("@noble/hashes/sha256");
|
||||
var import_utils = require("@noble/hashes/utils");
|
||||
|
||||
// utils.ts
|
||||
var utf8Decoder = new TextDecoder("utf-8");
|
||||
var utf8Encoder = new TextEncoder();
|
||||
function normalizeURL(url) {
|
||||
let p = new URL(url);
|
||||
p.pathname = p.pathname.replace(/\/+/g, "/");
|
||||
if (p.pathname.endsWith("/"))
|
||||
p.pathname = p.pathname.slice(0, -1);
|
||||
if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
|
||||
p.port = "";
|
||||
p.searchParams.sort();
|
||||
p.hash = "";
|
||||
return p.toString();
|
||||
}
|
||||
var MessageNode = class {
|
||||
_value;
|
||||
_next;
|
||||
get value() {
|
||||
return this._value;
|
||||
}
|
||||
set value(message) {
|
||||
this._value = message;
|
||||
}
|
||||
get next() {
|
||||
return this._next;
|
||||
}
|
||||
set next(node) {
|
||||
this._next = node;
|
||||
}
|
||||
constructor(message) {
|
||||
this._value = message;
|
||||
this._next = null;
|
||||
}
|
||||
};
|
||||
var MessageQueue = class {
|
||||
_first;
|
||||
_last;
|
||||
get first() {
|
||||
return this._first;
|
||||
}
|
||||
set first(messageNode) {
|
||||
this._first = messageNode;
|
||||
}
|
||||
get last() {
|
||||
return this._last;
|
||||
}
|
||||
set last(messageNode) {
|
||||
this._last = messageNode;
|
||||
}
|
||||
_size;
|
||||
get size() {
|
||||
return this._size;
|
||||
}
|
||||
set size(v) {
|
||||
this._size = v;
|
||||
}
|
||||
constructor() {
|
||||
this._first = null;
|
||||
this._last = null;
|
||||
this._size = 0;
|
||||
}
|
||||
enqueue(message) {
|
||||
const newNode = new MessageNode(message);
|
||||
if (this._size === 0 || !this._last) {
|
||||
this._first = newNode;
|
||||
this._last = newNode;
|
||||
} else {
|
||||
this._last.next = newNode;
|
||||
this._last = newNode;
|
||||
}
|
||||
this._size++;
|
||||
return true;
|
||||
}
|
||||
dequeue() {
|
||||
if (this._size === 0 || !this._first)
|
||||
return null;
|
||||
let prev = this._first;
|
||||
this._first = prev.next;
|
||||
prev.next = null;
|
||||
this._size--;
|
||||
return prev.value;
|
||||
}
|
||||
};
|
||||
|
||||
// event.ts
|
||||
var verifiedSymbol = Symbol("verified");
|
||||
function serializeEvent(evt) {
|
||||
if (!validateEvent(evt))
|
||||
throw new Error("can't serialize event with wrong or missing properties");
|
||||
return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);
|
||||
}
|
||||
function getEventHash(event) {
|
||||
let eventHash = (0, import_sha256.sha256)(utf8Encoder.encode(serializeEvent(event)));
|
||||
return (0, import_utils.bytesToHex)(eventHash);
|
||||
}
|
||||
var isRecord = (obj) => obj instanceof Object;
|
||||
function validateEvent(event) {
|
||||
if (!isRecord(event))
|
||||
return false;
|
||||
if (typeof event.kind !== "number")
|
||||
return false;
|
||||
if (typeof event.content !== "string")
|
||||
return false;
|
||||
if (typeof event.created_at !== "number")
|
||||
return false;
|
||||
if (typeof event.pubkey !== "string")
|
||||
return false;
|
||||
if (!event.pubkey.match(/^[a-f0-9]{64}$/))
|
||||
return false;
|
||||
if (!Array.isArray(event.tags))
|
||||
return false;
|
||||
for (let i = 0; i < event.tags.length; i++) {
|
||||
let tag = event.tags[i];
|
||||
if (!Array.isArray(tag))
|
||||
return false;
|
||||
for (let j = 0; j < tag.length; j++) {
|
||||
if (typeof tag[j] === "object")
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function verifySignature(event) {
|
||||
if (typeof event[verifiedSymbol] === "boolean")
|
||||
return event[verifiedSymbol];
|
||||
const hash = getEventHash(event);
|
||||
if (hash !== event.id) {
|
||||
return event[verifiedSymbol] = false;
|
||||
}
|
||||
try {
|
||||
return event[verifiedSymbol] = import_secp256k1.schnorr.verify(event.sig, hash, event.pubkey);
|
||||
} catch (err) {
|
||||
return event[verifiedSymbol] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// filter.ts
|
||||
function matchFilter(filter, event) {
|
||||
if (filter.ids && filter.ids.indexOf(event.id) === -1) {
|
||||
if (!filter.ids.some((prefix) => event.id.startsWith(prefix))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (filter.kinds && filter.kinds.indexOf(event.kind) === -1)
|
||||
return false;
|
||||
if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {
|
||||
if (!filter.authors.some((prefix) => event.pubkey.startsWith(prefix))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (let f in filter) {
|
||||
if (f[0] === "#") {
|
||||
let tagName = f.slice(1);
|
||||
let values = filter[`#${tagName}`];
|
||||
if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (filter.since && event.created_at < filter.since)
|
||||
return false;
|
||||
if (filter.until && event.created_at > filter.until)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
function matchFilters(filters, event) {
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
if (matchFilter(filters[i], event))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function mergeFilters(...filters) {
|
||||
let result = {};
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
let filter = filters[i];
|
||||
Object.entries(filter).forEach(([property, values]) => {
|
||||
if (property === "kinds" || property === "ids" || property === "authors" || property[0] === "#") {
|
||||
result[property] = result[property] || [];
|
||||
for (let v = 0; v < values.length; v++) {
|
||||
let value = values[v];
|
||||
if (!result[property].includes(value))
|
||||
result[property].push(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (filter.limit && (!result.limit || filter.limit > result.limit))
|
||||
result.limit = filter.limit;
|
||||
if (filter.until && (!result.until || filter.until > result.until))
|
||||
result.until = filter.until;
|
||||
if (filter.since && (!result.since || filter.since < result.since))
|
||||
result.since = filter.since;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// fakejson.ts
|
||||
function getHex64(json, field) {
|
||||
let len = field.length + 3;
|
||||
let idx = json.indexOf(`"${field}":`) + len;
|
||||
let s = json.slice(idx).indexOf(`"`) + idx + 1;
|
||||
return json.slice(s, s + 64);
|
||||
}
|
||||
function getSubscriptionId(json) {
|
||||
let idx = json.slice(0, 22).indexOf(`"EVENT"`);
|
||||
if (idx === -1)
|
||||
return null;
|
||||
let pstart = json.slice(idx + 7 + 1).indexOf(`"`);
|
||||
if (pstart === -1)
|
||||
return null;
|
||||
let start = idx + 7 + 1 + pstart;
|
||||
let pend = json.slice(start + 1, 80).indexOf(`"`);
|
||||
if (pend === -1)
|
||||
return null;
|
||||
let end = start + 1 + pend;
|
||||
return json.slice(start + 1, end);
|
||||
}
|
||||
|
||||
// relay.ts
|
||||
var newListeners = () => ({
|
||||
connect: [],
|
||||
disconnect: [],
|
||||
error: [],
|
||||
notice: [],
|
||||
auth: []
|
||||
});
|
||||
function relayInit(url, options = {}) {
|
||||
let { listTimeout = 3e3, getTimeout = 3e3, countTimeout = 3e3 } = options;
|
||||
var ws;
|
||||
var openSubs = {};
|
||||
var listeners = newListeners();
|
||||
var subListeners = {};
|
||||
var pubListeners = {};
|
||||
var connectionPromise;
|
||||
async function connectRelay() {
|
||||
if (connectionPromise)
|
||||
return connectionPromise;
|
||||
connectionPromise = new Promise((resolve, reject) => {
|
||||
try {
|
||||
ws = new WebSocket(url);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
ws.onopen = () => {
|
||||
listeners.connect.forEach((cb) => cb());
|
||||
resolve();
|
||||
};
|
||||
ws.onerror = () => {
|
||||
connectionPromise = void 0;
|
||||
listeners.error.forEach((cb) => cb());
|
||||
reject();
|
||||
};
|
||||
ws.onclose = async () => {
|
||||
connectionPromise = void 0;
|
||||
listeners.disconnect.forEach((cb) => cb());
|
||||
};
|
||||
let incomingMessageQueue = new MessageQueue();
|
||||
let handleNextInterval;
|
||||
ws.onmessage = (e) => {
|
||||
incomingMessageQueue.enqueue(e.data);
|
||||
if (!handleNextInterval) {
|
||||
handleNextInterval = setInterval(handleNext, 0);
|
||||
}
|
||||
};
|
||||
function handleNext() {
|
||||
if (incomingMessageQueue.size === 0) {
|
||||
clearInterval(handleNextInterval);
|
||||
handleNextInterval = null;
|
||||
return;
|
||||
}
|
||||
var json = incomingMessageQueue.dequeue();
|
||||
if (!json)
|
||||
return;
|
||||
let subid = getSubscriptionId(json);
|
||||
if (subid) {
|
||||
let so = openSubs[subid];
|
||||
if (so && so.alreadyHaveEvent && so.alreadyHaveEvent(getHex64(json, "id"), url)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
let data = JSON.parse(json);
|
||||
switch (data[0]) {
|
||||
case "EVENT": {
|
||||
let id2 = data[1];
|
||||
let event = data[2];
|
||||
if (validateEvent(event) && openSubs[id2] && (openSubs[id2].skipVerification || verifySignature(event)) && matchFilters(openSubs[id2].filters, event)) {
|
||||
openSubs[id2];
|
||||
(subListeners[id2]?.event || []).forEach((cb) => cb(event));
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "COUNT":
|
||||
let id = data[1];
|
||||
let payload = data[2];
|
||||
if (openSubs[id]) {
|
||||
;
|
||||
(subListeners[id]?.count || []).forEach((cb) => cb(payload));
|
||||
}
|
||||
return;
|
||||
case "EOSE": {
|
||||
let id2 = data[1];
|
||||
if (id2 in subListeners) {
|
||||
subListeners[id2].eose.forEach((cb) => cb());
|
||||
subListeners[id2].eose = [];
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "OK": {
|
||||
let id2 = data[1];
|
||||
let ok = data[2];
|
||||
let reason = data[3] || "";
|
||||
if (id2 in pubListeners) {
|
||||
let { resolve: resolve2, reject: reject2 } = pubListeners[id2];
|
||||
if (ok)
|
||||
resolve2(null);
|
||||
else
|
||||
reject2(new Error(reason));
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "NOTICE":
|
||||
let notice = data[1];
|
||||
listeners.notice.forEach((cb) => cb(notice));
|
||||
return;
|
||||
case "AUTH": {
|
||||
let challenge = data[1];
|
||||
listeners.auth?.forEach((cb) => cb(challenge));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
return connectionPromise;
|
||||
}
|
||||
function connected() {
|
||||
return ws?.readyState === 1;
|
||||
}
|
||||
async function connect() {
|
||||
if (connected())
|
||||
return;
|
||||
await connectRelay();
|
||||
}
|
||||
async function trySend(params) {
|
||||
let msg = JSON.stringify(params);
|
||||
if (!connected()) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
||||
if (!connected()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
ws.send(msg);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
const sub = (filters, {
|
||||
verb = "REQ",
|
||||
skipVerification = false,
|
||||
alreadyHaveEvent = null,
|
||||
id = Math.random().toString().slice(2)
|
||||
} = {}) => {
|
||||
let subid = id;
|
||||
openSubs[subid] = {
|
||||
id: subid,
|
||||
filters,
|
||||
skipVerification,
|
||||
alreadyHaveEvent
|
||||
};
|
||||
trySend([verb, subid, ...filters]);
|
||||
let subscription = {
|
||||
sub: (newFilters, newOpts = {}) => sub(newFilters || filters, {
|
||||
skipVerification: newOpts.skipVerification || skipVerification,
|
||||
alreadyHaveEvent: newOpts.alreadyHaveEvent || alreadyHaveEvent,
|
||||
id: subid
|
||||
}),
|
||||
unsub: () => {
|
||||
delete openSubs[subid];
|
||||
delete subListeners[subid];
|
||||
trySend(["CLOSE", subid]);
|
||||
},
|
||||
on: (type, cb) => {
|
||||
subListeners[subid] = subListeners[subid] || {
|
||||
event: [],
|
||||
count: [],
|
||||
eose: []
|
||||
};
|
||||
subListeners[subid][type].push(cb);
|
||||
},
|
||||
off: (type, cb) => {
|
||||
let listeners2 = subListeners[subid];
|
||||
let idx = listeners2[type].indexOf(cb);
|
||||
if (idx >= 0)
|
||||
listeners2[type].splice(idx, 1);
|
||||
},
|
||||
get events() {
|
||||
return eventsGenerator(subscription);
|
||||
}
|
||||
};
|
||||
return subscription;
|
||||
};
|
||||
function _publishEvent(event, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!event.id) {
|
||||
reject(new Error(`event ${event} has no id`));
|
||||
return;
|
||||
}
|
||||
let id = event.id;
|
||||
trySend([type, event]);
|
||||
pubListeners[id] = { resolve, reject };
|
||||
});
|
||||
}
|
||||
return {
|
||||
url,
|
||||
sub,
|
||||
on: (type, cb) => {
|
||||
listeners[type].push(cb);
|
||||
if (type === "connect" && ws?.readyState === 1) {
|
||||
;
|
||||
cb();
|
||||
}
|
||||
},
|
||||
off: (type, cb) => {
|
||||
let index = listeners[type].indexOf(cb);
|
||||
if (index !== -1)
|
||||
listeners[type].splice(index, 1);
|
||||
},
|
||||
list: (filters, opts) => new Promise((resolve) => {
|
||||
let s = sub(filters, opts);
|
||||
let events = [];
|
||||
let timeout = setTimeout(() => {
|
||||
s.unsub();
|
||||
resolve(events);
|
||||
}, listTimeout);
|
||||
s.on("eose", () => {
|
||||
s.unsub();
|
||||
clearTimeout(timeout);
|
||||
resolve(events);
|
||||
});
|
||||
s.on("event", (event) => {
|
||||
events.push(event);
|
||||
});
|
||||
}),
|
||||
get: (filter, opts) => new Promise((resolve) => {
|
||||
let s = sub([filter], opts);
|
||||
let timeout = setTimeout(() => {
|
||||
s.unsub();
|
||||
resolve(null);
|
||||
}, getTimeout);
|
||||
s.on("event", (event) => {
|
||||
s.unsub();
|
||||
clearTimeout(timeout);
|
||||
resolve(event);
|
||||
});
|
||||
}),
|
||||
count: (filters) => new Promise((resolve) => {
|
||||
let s = sub(filters, { ...sub, verb: "COUNT" });
|
||||
let timeout = setTimeout(() => {
|
||||
s.unsub();
|
||||
resolve(null);
|
||||
}, countTimeout);
|
||||
s.on("count", (event) => {
|
||||
s.unsub();
|
||||
clearTimeout(timeout);
|
||||
resolve(event);
|
||||
});
|
||||
}),
|
||||
async publish(event) {
|
||||
await _publishEvent(event, "EVENT");
|
||||
},
|
||||
async auth(event) {
|
||||
await _publishEvent(event, "AUTH");
|
||||
},
|
||||
connect,
|
||||
close() {
|
||||
listeners = newListeners();
|
||||
subListeners = {};
|
||||
pubListeners = {};
|
||||
if (ws?.readyState === WebSocket.OPEN) {
|
||||
ws.close();
|
||||
}
|
||||
},
|
||||
get status() {
|
||||
return ws?.readyState ?? 3;
|
||||
}
|
||||
};
|
||||
}
|
||||
async function* eventsGenerator(sub) {
|
||||
let nextResolve;
|
||||
const eventQueue = [];
|
||||
const pushToQueue = (event) => {
|
||||
if (nextResolve) {
|
||||
nextResolve(event);
|
||||
nextResolve = void 0;
|
||||
} else {
|
||||
eventQueue.push(event);
|
||||
}
|
||||
};
|
||||
sub.on("event", pushToQueue);
|
||||
try {
|
||||
while (true) {
|
||||
if (eventQueue.length > 0) {
|
||||
yield eventQueue.shift();
|
||||
} else {
|
||||
const event = await new Promise((resolve) => {
|
||||
nextResolve = resolve;
|
||||
});
|
||||
yield event;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
sub.off("event", pushToQueue);
|
||||
}
|
||||
}
|
||||
|
||||
// pool.ts
|
||||
var SimplePool = class {
|
||||
_conn;
|
||||
_seenOn = {};
|
||||
batchedByKey = {};
|
||||
eoseSubTimeout;
|
||||
getTimeout;
|
||||
seenOnEnabled = true;
|
||||
batchInterval = 100;
|
||||
constructor(options = {}) {
|
||||
this._conn = {};
|
||||
this.eoseSubTimeout = options.eoseSubTimeout || 3400;
|
||||
this.getTimeout = options.getTimeout || 3400;
|
||||
this.seenOnEnabled = options.seenOnEnabled !== false;
|
||||
this.batchInterval = options.batchInterval || 100;
|
||||
}
|
||||
close(relays) {
|
||||
relays.forEach((url) => {
|
||||
let relay = this._conn[normalizeURL(url)];
|
||||
if (relay)
|
||||
relay.close();
|
||||
});
|
||||
}
|
||||
async ensureRelay(url) {
|
||||
const nm = normalizeURL(url);
|
||||
if (!this._conn[nm]) {
|
||||
this._conn[nm] = relayInit(nm, {
|
||||
getTimeout: this.getTimeout * 0.9,
|
||||
listTimeout: this.getTimeout * 0.9
|
||||
});
|
||||
}
|
||||
const relay = this._conn[nm];
|
||||
await relay.connect();
|
||||
return relay;
|
||||
}
|
||||
sub(relays, filters, opts) {
|
||||
let _knownIds = /* @__PURE__ */ new Set();
|
||||
let modifiedOpts = { ...opts || {} };
|
||||
modifiedOpts.alreadyHaveEvent = (id, url) => {
|
||||
if (opts?.alreadyHaveEvent?.(id, url)) {
|
||||
return true;
|
||||
}
|
||||
if (this.seenOnEnabled) {
|
||||
let set = this._seenOn[id] || /* @__PURE__ */ new Set();
|
||||
set.add(url);
|
||||
this._seenOn[id] = set;
|
||||
}
|
||||
return _knownIds.has(id);
|
||||
};
|
||||
let subs = [];
|
||||
let eventListeners = /* @__PURE__ */ new Set();
|
||||
let eoseListeners = /* @__PURE__ */ new Set();
|
||||
let eosesMissing = relays.length;
|
||||
let eoseSent = false;
|
||||
let eoseTimeout = setTimeout(
|
||||
() => {
|
||||
eoseSent = true;
|
||||
for (let cb of eoseListeners.values())
|
||||
cb();
|
||||
},
|
||||
opts?.eoseSubTimeout || this.eoseSubTimeout
|
||||
);
|
||||
relays.filter((r, i, a) => a.indexOf(r) === i).forEach(async (relay) => {
|
||||
let r;
|
||||
try {
|
||||
r = await this.ensureRelay(relay);
|
||||
} catch (err) {
|
||||
handleEose();
|
||||
return;
|
||||
}
|
||||
if (!r)
|
||||
return;
|
||||
let s = r.sub(filters, modifiedOpts);
|
||||
s.on("event", (event) => {
|
||||
_knownIds.add(event.id);
|
||||
for (let cb of eventListeners.values())
|
||||
cb(event);
|
||||
});
|
||||
s.on("eose", () => {
|
||||
if (eoseSent)
|
||||
return;
|
||||
handleEose();
|
||||
});
|
||||
subs.push(s);
|
||||
function handleEose() {
|
||||
eosesMissing--;
|
||||
if (eosesMissing === 0) {
|
||||
clearTimeout(eoseTimeout);
|
||||
for (let cb of eoseListeners.values())
|
||||
cb();
|
||||
}
|
||||
}
|
||||
});
|
||||
let greaterSub = {
|
||||
sub(filters2, opts2) {
|
||||
subs.forEach((sub) => sub.sub(filters2, opts2));
|
||||
return greaterSub;
|
||||
},
|
||||
unsub() {
|
||||
subs.forEach((sub) => sub.unsub());
|
||||
},
|
||||
on(type, cb) {
|
||||
if (type === "event") {
|
||||
eventListeners.add(cb);
|
||||
} else if (type === "eose") {
|
||||
eoseListeners.add(cb);
|
||||
}
|
||||
},
|
||||
off(type, cb) {
|
||||
if (type === "event") {
|
||||
eventListeners.delete(cb);
|
||||
} else if (type === "eose")
|
||||
eoseListeners.delete(cb);
|
||||
},
|
||||
get events() {
|
||||
return eventsGenerator(greaterSub);
|
||||
}
|
||||
};
|
||||
return greaterSub;
|
||||
}
|
||||
get(relays, filter, opts) {
|
||||
return new Promise((resolve) => {
|
||||
let sub = this.sub(relays, [filter], opts);
|
||||
let timeout = setTimeout(() => {
|
||||
sub.unsub();
|
||||
resolve(null);
|
||||
}, this.getTimeout);
|
||||
sub.on("event", (event) => {
|
||||
resolve(event);
|
||||
clearTimeout(timeout);
|
||||
sub.unsub();
|
||||
});
|
||||
});
|
||||
}
|
||||
list(relays, filters, opts) {
|
||||
return new Promise((resolve) => {
|
||||
let events = [];
|
||||
let sub = this.sub(relays, filters, opts);
|
||||
sub.on("event", (event) => {
|
||||
events.push(event);
|
||||
});
|
||||
sub.on("eose", () => {
|
||||
sub.unsub();
|
||||
resolve(events);
|
||||
});
|
||||
});
|
||||
}
|
||||
batchedList(batchKey, relays, filters) {
|
||||
return new Promise((resolve) => {
|
||||
if (!this.batchedByKey[batchKey]) {
|
||||
this.batchedByKey[batchKey] = [
|
||||
{
|
||||
filters,
|
||||
relays,
|
||||
resolve,
|
||||
events: []
|
||||
}
|
||||
];
|
||||
setTimeout(() => {
|
||||
Object.keys(this.batchedByKey).forEach(async (batchKey2) => {
|
||||
const batchedRequests = this.batchedByKey[batchKey2];
|
||||
const filters2 = [];
|
||||
const relays2 = [];
|
||||
batchedRequests.forEach((br) => {
|
||||
filters2.push(...br.filters);
|
||||
relays2.push(...br.relays);
|
||||
});
|
||||
const sub = this.sub(relays2, [mergeFilters(...filters2)]);
|
||||
sub.on("event", (event) => {
|
||||
batchedRequests.forEach((br) => matchFilters(br.filters, event) && br.events.push(event));
|
||||
});
|
||||
sub.on("eose", () => {
|
||||
sub.unsub();
|
||||
batchedRequests.forEach((br) => br.resolve(br.events));
|
||||
});
|
||||
delete this.batchedByKey[batchKey2];
|
||||
});
|
||||
}, this.batchInterval);
|
||||
} else {
|
||||
this.batchedByKey[batchKey].push({
|
||||
filters,
|
||||
relays,
|
||||
resolve,
|
||||
events: []
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
publish(relays, event) {
|
||||
return relays.map(async (relay) => {
|
||||
let r = await this.ensureRelay(relay);
|
||||
return r.publish(event);
|
||||
});
|
||||
}
|
||||
seenOn(id) {
|
||||
return Array.from(this._seenOn[id]?.values?.() || []);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user