Files
snort/packages/system/dist/RequestBuilder.js
2023-06-08 12:45:23 +02:00

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