diff --git a/packages/feeds/README.md b/packages/feeds/README.md index b7682dc..90a5729 100644 --- a/packages/feeds/README.md +++ b/packages/feeds/README.md @@ -14,12 +14,15 @@ const loader = new FeedLoader({ }) // Define a feed using set operations -const feed = intersection( - union( - dvm({kind: 5300, pubkey: '19b78ccfa7c5e31e6bacbb3f2a1703f64b62017702e584440bf29a7e16263e8c'}), - list("10003:19ba654f26afd4930fd3d51baf4e26f1413b7aeec7190cd6c0cdf4d2f14cec6b:"), +const feed = intersectionFeed( + unionFeed( + dvmFeed({ + kind: 5300, + pubkey: '19b78ccfa7c5e31e6bacbb3f2a1703f64b62017702e584440bf29a7e16263e8c', + }), + listFeed("10003:19ba654f26afd4930fd3d51baf4e26f1413b7aeec7190cd6c0cdf4d2f14cec6b:"), ) - filter({ + filterFeed({ min_wot: 0.1, scopes: ["global"], }), diff --git a/packages/feeds/compiler.ts b/packages/feeds/compiler.ts index 2524bba..afb800f 100644 --- a/packages/feeds/compiler.ts +++ b/packages/feeds/compiler.ts @@ -1,11 +1,11 @@ import {inc, uniq, now, isNil} from '@coracle.social/lib' import type {Rumor, Filter} from '@coracle.social/util' import {Tags, getIdFilters, mergeFilters} from '@coracle.social/util' -import type {RequestItem, DVMItem, Scope, Feed, DynamicFilter, FeedContext} from './core' +import type {RequestItem, DVMItem, Scope, Feed, DynamicFilter, FeedOptions} from './core' import {FeedType} from './core' export class FeedCompiler { - constructor(readonly context: FeedContext) {} + constructor(readonly options: FeedOptions) {} walk([type, ...feed]: Feed, visit: (feed: Feed) => void) { visit([type, ...feed] as Feed) @@ -88,7 +88,7 @@ export class FeedCompiler { async _compileLists(addresses: string[]): Promise { const events: E[] = [] - await this.context.request({ + await this.options.request({ relays: [], filters: getIdFilters(addresses), onEvent: events.push, @@ -103,7 +103,7 @@ export class FeedCompiler { async _compileLols(addresses: string[]): Promise { const events: E[] = [] - await this.context.request({ + await this.options.request({ relays: [], filters: getIdFilters(addresses), onEvent: events.push, @@ -117,7 +117,7 @@ export class FeedCompiler { await Promise.all( requests.map(request => - this.context.requestDvm({ + this.options.requestDvm({ tags: [], ...request, onEvent: events.push, @@ -135,11 +135,11 @@ export class FeedCompiler { _compileFilter({scopes, min_wot, max_wot, until_ago, since_ago, ...filter}: DynamicFilter) { if (scopes && !filter.authors) { - filter.authors = scopes.flatMap((scope: Scope) => this.context.getPubkeysForScope(scope)) + filter.authors = scopes.flatMap((scope: Scope) => this.options.getPubkeysForScope(scope)) } if ((!isNil(min_wot) || !isNil(max_wot))) { - const authors = this.context.getPubkeysForWotRange(min_wot || 0, max_wot || 1) + const authors = this.options.getPubkeysForWotRange(min_wot || 0, max_wot || 1) if (filter.authors) { const authorsSet = new Set(authors) diff --git a/packages/feeds/core.ts b/packages/feeds/core.ts index 087070e..e074d76 100644 --- a/packages/feeds/core.ts +++ b/packages/feeds/core.ts @@ -52,15 +52,15 @@ export type Feed = LOLFeed | DVMFeed -export const usingRelays = (relays: string[], ...feeds: Feed[]) => [FeedType.Relay, relays, ...feeds] as Feed -export const difference = (...feeds: Feed[]) => [FeedType.Difference, ...feeds] as Feed -export const intersection = (...feeds: Feed[]) => [FeedType.Intersection, ...feeds] as Feed -export const symmetricDifference = (...feeds: Feed[]) => [FeedType.SymmetricDifference, ...feeds] as Feed -export const union = (...feeds: Feed[]) => [FeedType.Union, ...feeds] as Feed -export const filter = (...filters: DynamicFilter[]) => [FeedType.Filter, ...filters] as Feed -export const list = (...addresses: string[]) => [FeedType.List, ...addresses] as Feed -export const lol = (...addresses: string[]) => [FeedType.LOL, ...addresses] as Feed -export const dvm = (...requests: DVMItem[]) => [FeedType.DVM, ...requests] as Feed +export const relayFeed = (relays: string[], ...feeds: Feed[]) => [FeedType.Relay, relays, ...feeds] as Feed +export const differenceFeed = (...feeds: Feed[]) => [FeedType.Difference, ...feeds] as Feed +export const intersectionFeed = (...feeds: Feed[]) => [FeedType.Intersection, ...feeds] as Feed +export const symmetricDifferenceFeed = (...feeds: Feed[]) => [FeedType.SymmetricDifference, ...feeds] as Feed +export const unionFeed = (...feeds: Feed[]) => [FeedType.Union, ...feeds] as Feed +export const filterFeed = (...filters: DynamicFilter[]) => [FeedType.Filter, ...filters] as Feed +export const listFeed = (...addresses: string[]) => [FeedType.List, ...addresses] as Feed +export const lolFeed = (...addresses: string[]) => [FeedType.LOL, ...addresses] as Feed +export const dvmFeed = (...requests: DVMItem[]) => [FeedType.DVM, ...requests] as Feed export type RequestItem = { relays: string[] @@ -80,7 +80,7 @@ export type DVMOpts = DVMItem & { onEvent: (event: E) => void } -export type FeedContext = { +export type FeedOptions = { request: (opts: RequestOpts) => Promise requestDvm: (opts: DVMOpts) => Promise getPubkeysForScope: (scope: Scope) => string[] diff --git a/packages/feeds/loader.ts b/packages/feeds/loader.ts index a6ac665..981918d 100644 --- a/packages/feeds/loader.ts +++ b/packages/feeds/loader.ts @@ -1,13 +1,13 @@ import {inc, max, min, now, isNil} from '@coracle.social/lib' import type {Rumor, Filter} from '@coracle.social/util' import {Tags, EPOCH, getIdFilters, guessFilterDelta, mergeFilters} from '@coracle.social/util' -import type {Scope, Feed, DynamicFilter, RequestOpts, RequestItem, FeedContext} from './core' +import type {Scope, Feed, DynamicFilter, RequestOpts, RequestItem, FeedOptions} from './core' import {FeedType} from './core' import {FeedCompiler} from './compiler' export type LoadOpts = { - onEvent: (event: E) => void - onExhausted: () => void + onEvent?: (event: E) => void + onExhausted?: () => void } export type Loader = (limit: number) => Promise @@ -15,8 +15,8 @@ export type Loader = (limit: number) => Promise export class FeedLoader { compiler: FeedCompiler - constructor(readonly context: FeedContext) { - this.compiler = new FeedCompiler(context) + constructor(readonly options: FeedOptions) { + this.compiler = new FeedCompiler(options) } async getLoader([type, ...feed]: Feed, loadOpts: LoadOpts) { @@ -63,15 +63,17 @@ export class FeedLoader { let count = 0 - await this.context.request({ - relays, - filters: requestFilters, - onEvent: (event: E) => { - count += 1 - since = Math.min(since, event.created_at) - onEvent(event) - }, - }) + if (requestFilters.length > 0) { + await this.options.request({ + relays, + filters: requestFilters, + onEvent: (event: E) => { + count += 1 + until = Math.min(until, event.created_at) + onEvent?.(event) + }, + }) + } // Relays can't be relied upon to return events in descending order, do exponential // windowing to ensure we get the most recent stuff on first load, but eventually find it all @@ -82,7 +84,7 @@ export class FeedLoader { since = Math.max(minSince, since - delta) if (since === minSince) { - onExhausted() + onExhausted?.() } } } @@ -121,13 +123,13 @@ export class FeedLoader { for (const event of events.splice(0)) { if (!skip.has(event.id) && !seen.has(event.id)) { - onEvent(event) + onEvent?.(event) seen.add(event.id) } } if (exhausted.size === loaders.length) { - onExhausted() + onExhausted?.() } } } @@ -163,13 +165,13 @@ export class FeedLoader { for (const event of events.splice(0)) { if (counts.get(event.id) === loaders.length && !seen.has(event.id)) { - onEvent(event) + onEvent?.(event) seen.add(event.id) } } if (exhausted.size === loaders.length) { - onExhausted() + onExhausted?.() } } } @@ -205,13 +207,13 @@ export class FeedLoader { for (const event of events.values()) { if (counts.get(event.id) === 1 && !seen.has(event.id)) { - onEvent(event) + onEvent?.(event) seen.add(event.id) } } if (exhausted.size === loaders.length) { - onExhausted() + onExhausted?.() } } } @@ -226,7 +228,7 @@ export class FeedLoader { onExhausted: () => exhausted.add(i), onEvent: (event: E) => { if (!seen.has(event.id)) { - onEvent(event) + onEvent?.(event) seen.add(event.id) } }, @@ -246,7 +248,7 @@ export class FeedLoader { ) if (exhausted.size === loaders.length) { - onExhausted() + onExhausted?.() } } } diff --git a/packages/network/Subscribe.ts b/packages/network/Subscribe.ts index 42836ca..80ca191 100644 --- a/packages/network/Subscribe.ts +++ b/packages/network/Subscribe.ts @@ -166,12 +166,6 @@ export const mergeSubscriptions = (subs: Subscription[]) => { } } - // console.log( - // `Starting ${mergedSubscriptions.length} subscriptions on ${uniq(mergedSubscriptions.flatMap(s => s.request.relays)).length} relays`, - // uniq(mergedSubscriptions.flatMap(s => s.request.relays)), - // ...mergeFilters(mergedSubscriptions.flatMap(s => s.request.filters)), - // ) - return mergedSubscriptions } @@ -265,12 +259,6 @@ export const subscribe = (request: SubscribeRequest) => { } if (request.immediate) { - // console.log( - // `Starting 1 subscriptions on ${request.relays.length} relays`, - // request.relays, - // ...mergeFilters(request.filters) - // ) - executeSubscription(subscription) } else { executeSubscriptionBatched(subscription) diff --git a/packages/util/Events.ts b/packages/util/Events.ts index f736eee..f7cf618 100644 --- a/packages/util/Events.ts +++ b/packages/util/Events.ts @@ -1,4 +1,5 @@ import type {Event, EventTemplate, UnsignedEvent} from 'nostr-tools' +export type {Event, EventTemplate, UnsignedEvent} from 'nostr-tools' import {verifyEvent, getEventHash} from 'nostr-tools' import {cached, now} from '@coracle.social/lib' import {Tags} from './Tags' diff --git a/packages/util/package.json b/packages/util/package.json index efac2b4..4ab650f 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@coracle.social/util", - "version": "0.0.7", + "version": "0.0.8", "author": "hodlbod", "license": "MIT", "description": "A collection of utilities.",