From 4e113faa1ada27ad37a8439f831b68f3a0faebed Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Wed, 11 Sep 2024 09:15:03 -0700 Subject: [PATCH] Fix relay profile loading, add getTopicTags, allow mapping events to multiple items --- packages/app/src/handles.ts | 10 ++++------ packages/app/src/relays.ts | 27 +++++++++++++------------ packages/app/src/storage.ts | 10 ++++++++++ packages/app/src/zappers.ts | 10 ++++------ packages/lib/src/Tools.ts | 2 +- packages/store/src/index.ts | 39 +++++++++++++++++++++++-------------- packages/util/src/Tags.ts | 4 ++++ 7 files changed, 62 insertions(+), 40 deletions(-) diff --git a/packages/app/src/handles.ts b/packages/app/src/handles.ts index 4a77170..a1d70db 100644 --- a/packages/app/src/handles.ts +++ b/packages/app/src/handles.ts @@ -80,20 +80,18 @@ export const { load: batcher(800, async (nip05s: string[]) => { const fresh = await fetchHandles(uniq(nip05s)) const stale = handlesByNip05.get() - const items: Handle[] = nip05s.map(nip05 => { + + for (const nip05 of nip05s) { const newHandle = fresh.get(nip05) - const oldHandle = stale.get(nip05) if (newHandle) { stale.set(nip05, {...newHandle, nip05}) } - - return {...oldHandle, ...newHandle, nip05} - }) + } handles.set(Array.from(stale.values())) - return items + return nip05s }), }) diff --git a/packages/app/src/relays.ts b/packages/app/src/relays.ts index c4d8616..f1614f7 100644 --- a/packages/app/src/relays.ts +++ b/packages/app/src/relays.ts @@ -1,6 +1,6 @@ import {writable, derived} from 'svelte/store' import {withGetter} from '@welshman/store' -import {ctx, groupBy, indexBy, batch, now, uniq, uniqBy, batcher, postJson} from '@welshman/lib' +import {ctx, groupBy, indexBy, batch, now, uniq, batcher, postJson} from '@welshman/lib' import type {RelayProfile} from "@welshman/util" import {AuthStatus, asMessage, type Connection, type SocketMessage} from '@welshman/net' import {createSearch} from './util' @@ -43,14 +43,14 @@ export const relaysByPubkey = derived(relays, $relays => ), ) -export const fetchRelayProfiles = (urls: string[]) => { +export const fetchRelayProfiles = async (urls: string[]) => { const base = ctx.app.dufflepudUrl! if (!base) { throw new Error("ctx.app.dufflepudUrl is required to fetch relay metadata") } - const res: any = postJson(`${base}/relay/info`, {urls}) + const res: any = await postJson(`${base}/relay/info`, {urls}) const profilesByUrl = new Map() for (const {url, info} of res?.data || []) { @@ -69,18 +69,21 @@ export const { store: relays, getKey: (relay: Relay) => relay.url, load: batcher(800, async (urls: string[]) => { - const profilesByUrl = await fetchRelayProfiles(uniq(urls)) - const index = relaysByUrl.get() - const items: Relay[] = urls.map(url => { - const relay = index.get(url) - const profile = profilesByUrl.get(url) || relay?.profile + const fresh = await fetchRelayProfiles(uniq(urls)) + const stale = relaysByUrl.get() - return {...relay, profile, url} - }) + for (const url of urls) { + const relay = stale.get(url) + const profile = fresh.get(url) - relays.update($relays => uniqBy($relay => $relay.url, [...$relays, ...items])) + if (profile) { + stale.set(url, {...relay, profile, url}) + } + } - return items + relays.set(Array.from(stale.values())) + + return urls }), }) diff --git a/packages/app/src/storage.ts b/packages/app/src/storage.ts index aca46a8..f331a07 100644 --- a/packages/app/src/storage.ts +++ b/packages/app/src/storage.ts @@ -131,4 +131,14 @@ export const storageAdapters = { fromPairs(data.map(({key, value}) => [key, value])), }), }), + fromMapStore: (store: Writable>) => ({ + keyPath: "key", + store: adapter({ + store: store, + forward: ($data: Map) => + Array.from($data.entries()).map(([key, value]) => ({key, value})), + backward: (data: {key: string, value: T}[]) => + new Map(data.map(({key, value}) => [key, value])), + }), + }), } diff --git a/packages/app/src/zappers.ts b/packages/app/src/zappers.ts index 19fea74..c74d988 100644 --- a/packages/app/src/zappers.ts +++ b/packages/app/src/zappers.ts @@ -54,20 +54,18 @@ export const { load: batcher(800, async (lnurls: string[]) => { const fresh = await fetchZappers(uniq(lnurls)) const stale = zappersByLnurl.get() - const items: Zapper[] = lnurls.map(lnurl => { + + for (const lnurl of lnurls) { const newZapper = fresh.get(lnurl) - const oldZapper = stale.get(lnurl) if (newZapper) { stale.set(lnurl, {...newZapper, lnurl}) } - - return {...oldZapper, ...newZapper, lnurl} - }) + } zappers.set(Array.from(stale.values())) - return items + return lnurls }), }) diff --git a/packages/lib/src/Tools.ts b/packages/lib/src/Tools.ts index 460d697..bb14fa5 100644 --- a/packages/lib/src/Tools.ts +++ b/packages/lib/src/Tools.ts @@ -479,7 +479,7 @@ export const batcher = (t: number, execute: (request: T[]) => U[] | Promis const results = await execute(items.map(item => item.request)) if (results.length !== items.length) { - throw new Error("Execute must return a promise for each request") + throw new Error("Execute must return a result for each request") } results.forEach(async (r, i) => items[i].resolve(await r)) diff --git a/packages/store/src/index.ts b/packages/store/src/index.ts index 3eecb58..cb314ce 100644 --- a/packages/store/src/index.ts +++ b/packages/store/src/index.ts @@ -1,7 +1,7 @@ import {throttle} from "throttle-debounce" import {derived, writable} from "svelte/store" import type {Readable, Updater, Writable, Subscriber, Unsubscriber} from "svelte/store" -import {identity, getJson, setJson, batch, partition, first} from "@welshman/lib" +import {identity, ensurePlural, getJson, setJson, batch, partition, first} from "@welshman/lib" import type {Maybe} from "@welshman/lib" import type {Repository} from "@welshman/util" import {matchFilters, getIdAndAddress, getIdFilters} from "@welshman/util" @@ -150,7 +150,7 @@ export const deriveEventsMapped = (repository: Repository, { includeDeleted = false, }: { filters: Filter[] - eventToItem: (event: TrustedEvent) => Maybe> + eventToItem: (event: TrustedEvent) => Maybe> itemToEvent: (item: T) => TrustedEvent throttle?: number includeDeleted?: boolean @@ -159,29 +159,35 @@ export const deriveEventsMapped = (repository: Repository, { let data: T[] = [] const deferred = new Set() - const defer = (event: TrustedEvent, item: Promise) => { + const defer = (event: TrustedEvent, promise: Promise) => { deferred.add(event.id) - item.then($item => { + promise.then(items => { if (deferred.has(event.id)) { deferred.delete(event.id) - data.push($item) + + for (const item of ensurePlural(items)) { + data.push(item) + } + setter(data) } }) } for (const event of repository.query(filters, {includeDeleted})) { - const item = eventToItem(event) + const items = eventToItem(event) - if (!item) { + if (!items) { continue } - if (item instanceof Promise) { - defer(event, item) + if (items instanceof Promise) { + defer(event, items) } else { - data.push(item) + for (const item of ensurePlural(items)) { + data.push(item) + } } } @@ -207,13 +213,16 @@ export const deriveEventsMapped = (repository: Repository, { let dirty = false for (const event of added.values()) { if (matchFilters(filters, event)) { - const item = eventToItem(event) + const items = eventToItem(event) - if (item instanceof Promise) { - defer(event, item) - } else if (item) { + if (items instanceof Promise) { + defer(event, items) + } else if (items) { dirty = true - data.push(item as T) + + for (const item of ensurePlural(items)) { + data.push(item as T) + } } } } diff --git a/packages/util/src/Tags.ts b/packages/util/src/Tags.ts index a59d454..d90f46f 100644 --- a/packages/util/src/Tags.ts +++ b/packages/util/src/Tags.ts @@ -195,6 +195,10 @@ export const getPubkeyTags = (tags: string[][]) => export const getPubkeyTagValues = (tags: string[][]) => getPubkeyTags(tags).map(nth(1)) +export const getTopicTags = (tags: string[][]) => tags.filter(t => ["t"].includes(t[0])) + +export const getTopicTagValues = (tags: string[][]) => getTopicTags(tags).map(nth(1)) + export const getRelayTags = (tags: string[][]) => tags.filter(t => ["r", "relay"].includes(t[0]) && isRelayUrl(t[1]))