225 lines
9.4 KiB
JavaScript
225 lines
9.4 KiB
JavaScript
"use strict";
|
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
};
|
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
};
|
|
var _RequestBuilder_instances, _RequestBuilder_builders, _RequestBuilder_options, _RequestBuilder_groupByRelay, _RequestFilterBuilder_filter, _RequestFilterBuilder_relayHints;
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.RequestFilterBuilder = exports.RequestBuilder = exports.RequestStrategy = void 0;
|
|
const Util_1 = require("./Util");
|
|
const RequestSplitter_1 = require("./RequestSplitter");
|
|
const GossipModel_1 = require("./GossipModel");
|
|
const RequestMerger_1 = require("./RequestMerger");
|
|
/**
|
|
* Which strategy is used when building REQ filters
|
|
*/
|
|
var RequestStrategy;
|
|
(function (RequestStrategy) {
|
|
/**
|
|
* Use the users default relays to fetch events,
|
|
* this is the fallback option when there is no better way to query a given filter set
|
|
*/
|
|
RequestStrategy[RequestStrategy["DefaultRelays"] = 1] = "DefaultRelays";
|
|
/**
|
|
* Using a cached copy of the authors relay lists NIP-65, split a given set of request filters by pubkey
|
|
*/
|
|
RequestStrategy[RequestStrategy["AuthorsRelays"] = 2] = "AuthorsRelays";
|
|
/**
|
|
* Relay hints are usually provided when using replies
|
|
*/
|
|
RequestStrategy[RequestStrategy["RelayHintedEventIds"] = 3] = "RelayHintedEventIds";
|
|
})(RequestStrategy = exports.RequestStrategy || (exports.RequestStrategy = {}));
|
|
/**
|
|
* Nostr REQ builder
|
|
*/
|
|
class RequestBuilder {
|
|
constructor(id) {
|
|
_RequestBuilder_instances.add(this);
|
|
_RequestBuilder_builders.set(this, void 0);
|
|
_RequestBuilder_options.set(this, void 0);
|
|
this.id = id;
|
|
__classPrivateFieldSet(this, _RequestBuilder_builders, [], "f");
|
|
}
|
|
get numFilters() {
|
|
return __classPrivateFieldGet(this, _RequestBuilder_builders, "f").length;
|
|
}
|
|
get options() {
|
|
return __classPrivateFieldGet(this, _RequestBuilder_options, "f");
|
|
}
|
|
withFilter() {
|
|
const ret = new RequestFilterBuilder();
|
|
__classPrivateFieldGet(this, _RequestBuilder_builders, "f").push(ret);
|
|
return ret;
|
|
}
|
|
withOptions(opt) {
|
|
__classPrivateFieldSet(this, _RequestBuilder_options, {
|
|
...__classPrivateFieldGet(this, _RequestBuilder_options, "f"),
|
|
...opt,
|
|
}, "f");
|
|
return this;
|
|
}
|
|
buildRaw() {
|
|
return __classPrivateFieldGet(this, _RequestBuilder_builders, "f").map(f => f.filter);
|
|
}
|
|
build(relays) {
|
|
const expanded = __classPrivateFieldGet(this, _RequestBuilder_builders, "f").flatMap(a => a.build(relays, this.id));
|
|
return __classPrivateFieldGet(this, _RequestBuilder_instances, "m", _RequestBuilder_groupByRelay).call(this, expanded);
|
|
}
|
|
/**
|
|
* Detects a change in request from a previous set of filters
|
|
* @param q All previous filters merged
|
|
* @returns
|
|
*/
|
|
buildDiff(relays, filters) {
|
|
const next = this.buildRaw();
|
|
const diff = (0, RequestSplitter_1.diffFilters)(filters, next);
|
|
if (diff.changed) {
|
|
return (0, GossipModel_1.splitAllByWriteRelays)(relays, diff.added).map(a => {
|
|
return {
|
|
strategy: RequestStrategy.AuthorsRelays,
|
|
filters: a.filters,
|
|
relay: a.relay,
|
|
};
|
|
});
|
|
}
|
|
return [];
|
|
}
|
|
}
|
|
exports.RequestBuilder = RequestBuilder;
|
|
_RequestBuilder_builders = new WeakMap(), _RequestBuilder_options = new WeakMap(), _RequestBuilder_instances = new WeakSet(), _RequestBuilder_groupByRelay = function _RequestBuilder_groupByRelay(expanded) {
|
|
const relayMerged = expanded.reduce((acc, v) => {
|
|
const existing = acc.get(v.relay);
|
|
if (existing) {
|
|
existing.push(v);
|
|
}
|
|
else {
|
|
acc.set(v.relay, [v]);
|
|
}
|
|
return acc;
|
|
}, new Map());
|
|
const filtersSquashed = [...relayMerged.values()].map(a => {
|
|
return {
|
|
filters: (0, RequestMerger_1.mergeSimilar)(a.flatMap(b => b.filters)),
|
|
relay: a[0].relay,
|
|
strategy: a[0].strategy,
|
|
};
|
|
});
|
|
return filtersSquashed;
|
|
};
|
|
/**
|
|
* Builder class for a single request filter
|
|
*/
|
|
class RequestFilterBuilder {
|
|
constructor() {
|
|
_RequestFilterBuilder_filter.set(this, {});
|
|
_RequestFilterBuilder_relayHints.set(this, new Map());
|
|
}
|
|
get filter() {
|
|
return { ...__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f") };
|
|
}
|
|
get relayHints() {
|
|
return new Map(__classPrivateFieldGet(this, _RequestFilterBuilder_relayHints, "f"));
|
|
}
|
|
ids(ids) {
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").ids = (0, Util_1.appendDedupe)(__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").ids, ids);
|
|
return this;
|
|
}
|
|
id(id, relay) {
|
|
if (relay) {
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_relayHints, "f").set(id, (0, Util_1.appendDedupe)(__classPrivateFieldGet(this, _RequestFilterBuilder_relayHints, "f").get(id), [relay]));
|
|
}
|
|
return this.ids([id]);
|
|
}
|
|
authors(authors) {
|
|
if (!authors)
|
|
return this;
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").authors = (0, Util_1.appendDedupe)(__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").authors, authors);
|
|
return this;
|
|
}
|
|
kinds(kinds) {
|
|
if (!kinds)
|
|
return this;
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").kinds = (0, Util_1.appendDedupe)(__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").kinds, kinds);
|
|
return this;
|
|
}
|
|
since(since) {
|
|
if (!since)
|
|
return this;
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").since = since;
|
|
return this;
|
|
}
|
|
until(until) {
|
|
if (!until)
|
|
return this;
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").until = until;
|
|
return this;
|
|
}
|
|
limit(limit) {
|
|
if (!limit)
|
|
return this;
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").limit = limit;
|
|
return this;
|
|
}
|
|
tag(key, value) {
|
|
if (!value)
|
|
return this;
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f")[`#${key}`] = value;
|
|
return this;
|
|
}
|
|
search(keyword) {
|
|
if (!keyword)
|
|
return this;
|
|
__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").search = keyword;
|
|
return this;
|
|
}
|
|
/**
|
|
* Build/expand this filter into a set of relay specific queries
|
|
*/
|
|
build(relays, id) {
|
|
// when querying for specific event ids with relay hints
|
|
// take the first approach which is to split the filter by relay
|
|
if (__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").ids && __classPrivateFieldGet(this, _RequestFilterBuilder_relayHints, "f").size > 0) {
|
|
const relays = (0, Util_1.dedupe)([...__classPrivateFieldGet(this, _RequestFilterBuilder_relayHints, "f").values()].flat());
|
|
return relays.map(r => {
|
|
return {
|
|
filters: [
|
|
{
|
|
...__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f"),
|
|
ids: [...__classPrivateFieldGet(this, _RequestFilterBuilder_relayHints, "f").entries()].filter(([, v]) => v.includes(r)).map(([k]) => k),
|
|
},
|
|
],
|
|
relay: r,
|
|
strategy: RequestStrategy.RelayHintedEventIds,
|
|
};
|
|
});
|
|
}
|
|
// If any authors are set use the gossip model to fetch data for each author
|
|
if (__classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f").authors) {
|
|
const split = (0, GossipModel_1.splitByWriteRelays)(relays, __classPrivateFieldGet(this, _RequestFilterBuilder_filter, "f"));
|
|
return split.map(a => {
|
|
return {
|
|
filters: [a.filter],
|
|
relay: a.relay,
|
|
strategy: RequestStrategy.AuthorsRelays,
|
|
};
|
|
});
|
|
}
|
|
return [
|
|
{
|
|
filters: [this.filter],
|
|
relay: "",
|
|
strategy: RequestStrategy.DefaultRelays,
|
|
},
|
|
];
|
|
}
|
|
}
|
|
exports.RequestFilterBuilder = RequestFilterBuilder;
|
|
_RequestFilterBuilder_filter = new WeakMap(), _RequestFilterBuilder_relayHints = new WeakMap();
|
|
//# sourceMappingURL=RequestBuilder.js.map
|