Fix relay profile loading, add getTopicTags, allow mapping events to multiple items
This commit is contained in:
@@ -80,20 +80,18 @@ export const {
|
|||||||
load: batcher(800, async (nip05s: string[]) => {
|
load: batcher(800, async (nip05s: string[]) => {
|
||||||
const fresh = await fetchHandles(uniq(nip05s))
|
const fresh = await fetchHandles(uniq(nip05s))
|
||||||
const stale = handlesByNip05.get()
|
const stale = handlesByNip05.get()
|
||||||
const items: Handle[] = nip05s.map(nip05 => {
|
|
||||||
|
for (const nip05 of nip05s) {
|
||||||
const newHandle = fresh.get(nip05)
|
const newHandle = fresh.get(nip05)
|
||||||
const oldHandle = stale.get(nip05)
|
|
||||||
|
|
||||||
if (newHandle) {
|
if (newHandle) {
|
||||||
stale.set(nip05, {...newHandle, nip05})
|
stale.set(nip05, {...newHandle, nip05})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {...oldHandle, ...newHandle, nip05}
|
|
||||||
})
|
|
||||||
|
|
||||||
handles.set(Array.from(stale.values()))
|
handles.set(Array.from(stale.values()))
|
||||||
|
|
||||||
return items
|
return nip05s
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
+15
-12
@@ -1,6 +1,6 @@
|
|||||||
import {writable, derived} from 'svelte/store'
|
import {writable, derived} from 'svelte/store'
|
||||||
import {withGetter} from '@welshman/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 type {RelayProfile} from "@welshman/util"
|
||||||
import {AuthStatus, asMessage, type Connection, type SocketMessage} from '@welshman/net'
|
import {AuthStatus, asMessage, type Connection, type SocketMessage} from '@welshman/net'
|
||||||
import {createSearch} from './util'
|
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!
|
const base = ctx.app.dufflepudUrl!
|
||||||
|
|
||||||
if (!base) {
|
if (!base) {
|
||||||
throw new Error("ctx.app.dufflepudUrl is required to fetch relay metadata")
|
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<string, RelayProfile>()
|
const profilesByUrl = new Map<string, RelayProfile>()
|
||||||
|
|
||||||
for (const {url, info} of res?.data || []) {
|
for (const {url, info} of res?.data || []) {
|
||||||
@@ -69,18 +69,21 @@ export const {
|
|||||||
store: relays,
|
store: relays,
|
||||||
getKey: (relay: Relay) => relay.url,
|
getKey: (relay: Relay) => relay.url,
|
||||||
load: batcher(800, async (urls: string[]) => {
|
load: batcher(800, async (urls: string[]) => {
|
||||||
const profilesByUrl = await fetchRelayProfiles(uniq(urls))
|
const fresh = await fetchRelayProfiles(uniq(urls))
|
||||||
const index = relaysByUrl.get()
|
const stale = relaysByUrl.get()
|
||||||
const items: Relay[] = urls.map(url => {
|
|
||||||
const relay = index.get(url)
|
|
||||||
const profile = profilesByUrl.get(url) || relay?.profile
|
|
||||||
|
|
||||||
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
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -131,4 +131,14 @@ export const storageAdapters = {
|
|||||||
fromPairs(data.map(({key, value}) => [key, value])),
|
fromPairs(data.map(({key, value}) => [key, value])),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
fromMapStore: <T>(store: Writable<Map<string, T>>) => ({
|
||||||
|
keyPath: "key",
|
||||||
|
store: adapter({
|
||||||
|
store: store,
|
||||||
|
forward: ($data: Map<string, T>) =>
|
||||||
|
Array.from($data.entries()).map(([key, value]) => ({key, value})),
|
||||||
|
backward: (data: {key: string, value: T}[]) =>
|
||||||
|
new Map(data.map(({key, value}) => [key, value])),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,20 +54,18 @@ export const {
|
|||||||
load: batcher(800, async (lnurls: string[]) => {
|
load: batcher(800, async (lnurls: string[]) => {
|
||||||
const fresh = await fetchZappers(uniq(lnurls))
|
const fresh = await fetchZappers(uniq(lnurls))
|
||||||
const stale = zappersByLnurl.get()
|
const stale = zappersByLnurl.get()
|
||||||
const items: Zapper[] = lnurls.map(lnurl => {
|
|
||||||
|
for (const lnurl of lnurls) {
|
||||||
const newZapper = fresh.get(lnurl)
|
const newZapper = fresh.get(lnurl)
|
||||||
const oldZapper = stale.get(lnurl)
|
|
||||||
|
|
||||||
if (newZapper) {
|
if (newZapper) {
|
||||||
stale.set(lnurl, {...newZapper, lnurl})
|
stale.set(lnurl, {...newZapper, lnurl})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {...oldZapper, ...newZapper, lnurl}
|
|
||||||
})
|
|
||||||
|
|
||||||
zappers.set(Array.from(stale.values()))
|
zappers.set(Array.from(stale.values()))
|
||||||
|
|
||||||
return items
|
return lnurls
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ export const batcher = <T, U>(t: number, execute: (request: T[]) => U[] | Promis
|
|||||||
const results = await execute(items.map(item => item.request))
|
const results = await execute(items.map(item => item.request))
|
||||||
|
|
||||||
if (results.length !== items.length) {
|
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))
|
results.forEach(async (r, i) => items[i].resolve(await r))
|
||||||
|
|||||||
+24
-15
@@ -1,7 +1,7 @@
|
|||||||
import {throttle} from "throttle-debounce"
|
import {throttle} from "throttle-debounce"
|
||||||
import {derived, writable} from "svelte/store"
|
import {derived, writable} from "svelte/store"
|
||||||
import type {Readable, Updater, Writable, Subscriber, Unsubscriber} 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 {Maybe} from "@welshman/lib"
|
||||||
import type {Repository} from "@welshman/util"
|
import type {Repository} from "@welshman/util"
|
||||||
import {matchFilters, getIdAndAddress, getIdFilters} from "@welshman/util"
|
import {matchFilters, getIdAndAddress, getIdFilters} from "@welshman/util"
|
||||||
@@ -150,7 +150,7 @@ export const deriveEventsMapped = <T>(repository: Repository, {
|
|||||||
includeDeleted = false,
|
includeDeleted = false,
|
||||||
}: {
|
}: {
|
||||||
filters: Filter[]
|
filters: Filter[]
|
||||||
eventToItem: (event: TrustedEvent) => Maybe<T | Promise<T>>
|
eventToItem: (event: TrustedEvent) => Maybe<T | T[] | Promise<T | T[]>>
|
||||||
itemToEvent: (item: T) => TrustedEvent
|
itemToEvent: (item: T) => TrustedEvent
|
||||||
throttle?: number
|
throttle?: number
|
||||||
includeDeleted?: boolean
|
includeDeleted?: boolean
|
||||||
@@ -159,29 +159,35 @@ export const deriveEventsMapped = <T>(repository: Repository, {
|
|||||||
let data: T[] = []
|
let data: T[] = []
|
||||||
const deferred = new Set()
|
const deferred = new Set()
|
||||||
|
|
||||||
const defer = (event: TrustedEvent, item: Promise<T>) => {
|
const defer = (event: TrustedEvent, promise: Promise<T | T[]>) => {
|
||||||
deferred.add(event.id)
|
deferred.add(event.id)
|
||||||
|
|
||||||
item.then($item => {
|
promise.then(items => {
|
||||||
if (deferred.has(event.id)) {
|
if (deferred.has(event.id)) {
|
||||||
deferred.delete(event.id)
|
deferred.delete(event.id)
|
||||||
data.push($item)
|
|
||||||
|
for (const item of ensurePlural(items)) {
|
||||||
|
data.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
setter(data)
|
setter(data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const event of repository.query(filters, {includeDeleted})) {
|
for (const event of repository.query(filters, {includeDeleted})) {
|
||||||
const item = eventToItem(event)
|
const items = eventToItem(event)
|
||||||
|
|
||||||
if (!item) {
|
if (!items) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item instanceof Promise) {
|
if (items instanceof Promise) {
|
||||||
defer(event, item)
|
defer(event, items)
|
||||||
} else {
|
} else {
|
||||||
data.push(item)
|
for (const item of ensurePlural(items)) {
|
||||||
|
data.push(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,13 +213,16 @@ export const deriveEventsMapped = <T>(repository: Repository, {
|
|||||||
let dirty = false
|
let dirty = false
|
||||||
for (const event of added.values()) {
|
for (const event of added.values()) {
|
||||||
if (matchFilters(filters, event)) {
|
if (matchFilters(filters, event)) {
|
||||||
const item = eventToItem(event)
|
const items = eventToItem(event)
|
||||||
|
|
||||||
if (item instanceof Promise) {
|
if (items instanceof Promise) {
|
||||||
defer(event, item)
|
defer(event, items)
|
||||||
} else if (item) {
|
} else if (items) {
|
||||||
dirty = true
|
dirty = true
|
||||||
data.push(item as T)
|
|
||||||
|
for (const item of ensurePlural(items)) {
|
||||||
|
data.push(item as T)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,6 +195,10 @@ export const getPubkeyTags = (tags: string[][]) =>
|
|||||||
|
|
||||||
export const getPubkeyTagValues = (tags: string[][]) => getPubkeyTags(tags).map(nth(1))
|
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[][]) =>
|
export const getRelayTags = (tags: string[][]) =>
|
||||||
tags.filter(t => ["r", "relay"].includes(t[0]) && isRelayUrl(t[1]))
|
tags.filter(t => ["r", "relay"].includes(t[0]) && isRelayUrl(t[1]))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user