Slim down some things

This commit is contained in:
Jon Staab
2024-10-07 13:26:58 -07:00
parent eb2b078a39
commit 944ee61b88
11 changed files with 75 additions and 85 deletions
+4 -5
View File
@@ -15,12 +15,11 @@ export const collection = <T, LoadArgs extends any[]>({
load: (key: string, ...args: LoadArgs) => Promise<any> load: (key: string, ...args: LoadArgs) => Promise<any>
}) => { }) => {
const indexStore = withGetter(derived(store, $items => indexBy(getKey, $items))) const indexStore = withGetter(derived(store, $items => indexBy(getKey, $items)))
const getItem = (key: string) => indexStore.get().get(key)
const pending = new Map<string, Promise<Maybe<T>>>() const pending = new Map<string, Promise<Maybe<T>>>()
const loadAttempts = new Map<string, number>() const loadAttempts = new Map<string, number>()
const loadItem = async (key: string, ...args: LoadArgs) => { const loadItem = async (key: string, ...args: LoadArgs) => {
const stale = getItem(key) const stale = indexStore.get().get(key)
const freshness = getFreshness(name, key) const freshness = getFreshness(name, key)
// If we have an item, reload if it's stale // If we have an item, reload if it's stale
@@ -30,7 +29,7 @@ export const collection = <T, LoadArgs extends any[]>({
// If we already are loading, await and return // If we already are loading, await and return
if (pending.has(key)) { if (pending.has(key)) {
return pending.get(key)!.then(() => getItem(key)) return pending.get(key)!.then(() => indexStore.get().get(key))
} }
const attempt = loadAttempts.get(key) || 0 const attempt = loadAttempts.get(key) || 0
@@ -52,7 +51,7 @@ export const collection = <T, LoadArgs extends any[]>({
pending.delete(key) pending.delete(key)
const fresh = getItem(key) const fresh = indexStore.get().get(key)
if (fresh) { if (fresh) {
loadAttempts.delete(key) loadAttempts.delete(key)
@@ -73,5 +72,5 @@ export const collection = <T, LoadArgs extends any[]>({
return derived(indexStore, $index => $index.get(key)) return derived(indexStore, $index => $index.get(key))
} }
return {indexStore, deriveItem, loadItem, getItem} return {indexStore, deriveItem, loadItem}
} }
+8 -18
View File
@@ -1,24 +1,17 @@
import {FOLLOWS, getListValues, asDecryptedEvent, readList} from '@welshman/util' import {FOLLOWS, asDecryptedEvent, readList} from '@welshman/util'
import {type TrustedEvent, type PublishedList} from '@welshman/util' import {type TrustedEvent, type PublishedList} from '@welshman/util'
import {type SubscribeRequestWithHandlers} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEventsMapped, withGetter} from '@welshman/store' import {deriveEventsMapped} from '@welshman/store'
import {repository, load} from './core' import {repository, load} from './core'
import {collection} from './collection' import {collection} from './collection'
import {ensurePlaintext} from './plaintext'
import {loadRelaySelections} from './relaySelections' import {loadRelaySelections} from './relaySelections'
export const follows = withGetter( export const follows = deriveEventsMapped<PublishedList>(repository, {
deriveEventsMapped<PublishedList>(repository, { filters: [{kinds: [FOLLOWS]}],
filters: [{kinds: [FOLLOWS]}], itemToEvent: item => item.event,
itemToEvent: item => item.event, eventToItem: (event: TrustedEvent) =>
eventToItem: async (event: TrustedEvent) => readList(asDecryptedEvent(event)),
readList( })
asDecryptedEvent(event, {
content: await ensurePlaintext(event),
}),
),
})
)
export const { export const {
indexStore: followsByPubkey, indexStore: followsByPubkey,
@@ -33,6 +26,3 @@ export const {
await load({...request, filters: [{kinds: [FOLLOWS], authors: [pubkey]}]}) await load({...request, filters: [{kinds: [FOLLOWS], authors: [pubkey]}]})
}, },
}) })
export const getFollows = (pubkey: string) =>
getListValues("p", followsByPubkey.get().get(pubkey))
+1 -2
View File
@@ -1,5 +1,4 @@
import {writable, derived} from 'svelte/store' import {writable, derived} from 'svelte/store'
import {withGetter} from '@welshman/store'
import {type SubscribeRequestWithHandlers} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {ctx, tryCatch, fetchJson, uniq, batcher, postJson, last} from '@welshman/lib' import {ctx, tryCatch, fetchJson, uniq, batcher, postJson, last} from '@welshman/lib'
import {collection} from './collection' import {collection} from './collection'
@@ -41,7 +40,7 @@ export async function queryProfile(nip05: string) {
} }
} }
export const handles = withGetter(writable<Handle[]>([])) export const handles = writable<Handle[]>([])
export const fetchHandles = async (nip05s: string[]) => { export const fetchHandles = async (nip05s: string[]) => {
const base = ctx.app.dufflepudUrl! const base = ctx.app.dufflepudUrl!
+12 -18
View File
@@ -1,24 +1,22 @@
import {MUTES, getListValues, asDecryptedEvent, readList} from '@welshman/util' import {MUTES, asDecryptedEvent, readList} from '@welshman/util'
import {type TrustedEvent, type PublishedList} from '@welshman/util' import {type TrustedEvent, type PublishedList} from '@welshman/util'
import {type SubscribeRequestWithHandlers} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEventsMapped, withGetter} from '@welshman/store' import {deriveEventsMapped} from '@welshman/store'
import {repository, load} from './core' import {repository, load} from './core'
import {collection} from './collection' import {collection} from './collection'
import {ensurePlaintext} from './plaintext' import {ensurePlaintext} from './plaintext'
import {loadRelaySelections} from './relaySelections' import {loadRelaySelections} from './relaySelections'
export const mutes = withGetter( export const mutes = deriveEventsMapped<PublishedList>(repository, {
deriveEventsMapped<PublishedList>(repository, { filters: [{kinds: [MUTES]}],
filters: [{kinds: [MUTES]}], itemToEvent: item => item.event,
itemToEvent: item => item.event, eventToItem: async (event: TrustedEvent) =>
eventToItem: async (event: TrustedEvent) => readList(
readList( asDecryptedEvent(event, {
asDecryptedEvent(event, { content: await ensurePlaintext(event),
content: await ensurePlaintext(event), }),
}), ),
), })
})
)
export const { export const {
indexStore: mutesByPubkey, indexStore: mutesByPubkey,
@@ -34,7 +32,3 @@ export const {
}, },
}) })
export const getMutes = (pubkey: string) =>
getListValues("p", mutesByPubkey.get().get(pubkey))
-1
View File
@@ -19,7 +19,6 @@ export const {
indexStore: profilesByPubkey, indexStore: profilesByPubkey,
deriveItem: deriveProfile, deriveItem: deriveProfile,
loadItem: loadProfile, loadItem: loadProfile,
getItem: getProfile,
} = collection({ } = collection({
name: "profiles", name: "profiles",
store: profiles, store: profiles,
+24 -18
View File
@@ -1,56 +1,62 @@
import {uniq} from '@welshman/lib' import {uniq} from '@welshman/lib'
import {INBOX_RELAYS, RELAYS, getRelayTags, normalizeRelayUrl, type TrustedEvent} from '@welshman/util' import {INBOX_RELAYS, RELAYS, normalizeRelayUrl, asDecryptedEvent, readList, getListTags, getRelayTags, getRelayTagValues} from '@welshman/util'
import {type SubscribeRequestWithHandlers} from "@welshman/net" import type {TrustedEvent, PublishedList, List} from '@welshman/util'
import {deriveEvents, withGetter} from '@welshman/store' import type {SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEventsMapped} from '@welshman/store'
import {load, repository} from './core' import {load, repository} from './core'
import {collection} from './collection' import {collection} from './collection'
export const getRelayUrls = (event?: TrustedEvent): string[] => export const getRelayUrls = (list?: List): string[] =>
uniq( uniq(getRelayTagValues(getListTags(list)).map(normalizeRelayUrl))
getRelayTags(event?.tags || [])
.map((t: string[]) => normalizeRelayUrl(t[1]))
)
export const getReadRelayUrls = (event?: TrustedEvent): string[] => export const getReadRelayUrls = (list?: List): string[] =>
uniq( uniq(
getRelayTags(event?.tags || []) getRelayTags(getListTags(list))
.filter((t: string[]) => !t[2] || t[2] === "read") .filter((t: string[]) => !t[2] || t[2] === "read")
.map((t: string[]) => normalizeRelayUrl(t[1])) .map((t: string[]) => normalizeRelayUrl(t[1]))
) )
export const getWriteRelayUrls = (event?: TrustedEvent): string[] => export const getWriteRelayUrls = (list?: List): string[] =>
uniq( uniq(
getRelayTags(event?.tags || []) getRelayTags(getListTags(list))
.filter((t: string[]) => !t[2] || t[2] === "write") .filter((t: string[]) => !t[2] || t[2] === "write")
.map((t: string[]) => normalizeRelayUrl(t[1])) .map((t: string[]) => normalizeRelayUrl(t[1]))
) )
export const relaySelections = withGetter(deriveEvents(repository, {filters: [{kinds: [RELAYS]}]})) export const relaySelections = deriveEventsMapped<PublishedList>(repository, {
filters: [{kinds: [RELAYS]}],
itemToEvent: item => item.event,
eventToItem: (event: TrustedEvent) =>
readList(asDecryptedEvent(event)),
})
export const { export const {
indexStore: relaySelectionsByPubkey, indexStore: relaySelectionsByPubkey,
deriveItem: deriveRelaySelections, deriveItem: deriveRelaySelections,
loadItem: loadRelaySelections, loadItem: loadRelaySelections,
getItem: getRelaySelections,
} = collection({ } = collection({
name: "relaySelections", name: "relaySelections",
store: relaySelections, store: relaySelections,
getKey: relaySelections => relaySelections.pubkey, getKey: relaySelections => relaySelections.event.pubkey,
load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) => load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
load({...request, filters: [{kinds: [RELAYS], authors: [pubkey]}]}), load({...request, filters: [{kinds: [RELAYS], authors: [pubkey]}]}),
}) })
export const inboxRelaySelections = withGetter(deriveEvents(repository, {filters: [{kinds: [INBOX_RELAYS]}]})) export const inboxRelaySelections = deriveEventsMapped<PublishedList>(repository, {
filters: [{kinds: [INBOX_RELAYS]}],
itemToEvent: item => item.event,
eventToItem: (event: TrustedEvent) =>
readList(asDecryptedEvent(event)),
})
export const { export const {
indexStore: inboxRelaySelectionsByPubkey, indexStore: inboxRelaySelectionsByPubkey,
deriveItem: deriveInboxRelaySelections, deriveItem: deriveInboxRelaySelections,
loadItem: loadInboxRelaySelections, loadItem: loadInboxRelaySelections,
getItem: getInboxRelaySelections,
} = collection({ } = collection({
name: "inboxRelaySelections", name: "inboxRelaySelections",
store: inboxRelaySelections, store: inboxRelaySelections,
getKey: inboxRelaySelections => inboxRelaySelections.pubkey, getKey: inboxRelaySelections => inboxRelaySelections.event.pubkey,
load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) => load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
load({...request, filters: [{kinds: [INBOX_RELAYS], authors: [pubkey]}]}), load({...request, filters: [{kinds: [INBOX_RELAYS], authors: [pubkey]}]}),
}) })
+11 -5
View File
@@ -1,11 +1,17 @@
import {throttle} from 'throttle-debounce' import {throttle} from 'throttle-debounce'
import {derived, writable} from 'svelte/store' import {derived, writable} from 'svelte/store'
import {addToMapKey, inc, dec} from '@welshman/lib' import {addToMapKey, inc, dec} from '@welshman/lib'
import {getListValues} from '@welshman/util' import {getListTags, getPubkeyTagValues} from '@welshman/util'
import {throttled, withGetter} from '@welshman/store' import {throttled, withGetter} from '@welshman/store'
import {pubkey} from './session' import {pubkey} from './session'
import {follows, getFollows, followsByPubkey} from './follows' import {follows, followsByPubkey} from './follows'
import {mutes, getMutes} from './mutes' import {mutes, mutesByPubkey} from './mutes'
export const getFollows = (pubkey: string) =>
getPubkeyTagValues(getListTags(followsByPubkey.get().get(pubkey)))
export const getMutes = (pubkey: string) =>
getPubkeyTagValues(getListTags(mutesByPubkey.get().get(pubkey)))
export const followersByPubkey = withGetter( export const followersByPubkey = withGetter(
derived( derived(
@@ -14,7 +20,7 @@ export const followersByPubkey = withGetter(
const $followersByPubkey = new Map<string, Set<string>>() const $followersByPubkey = new Map<string, Set<string>>()
for (const list of lists) { for (const list of lists) {
for (const pubkey of getListValues("p", list)) { for (const pubkey of getPubkeyTagValues(getListTags(list))) {
addToMapKey($followersByPubkey, pubkey, list.event.pubkey) addToMapKey($followersByPubkey, pubkey, list.event.pubkey)
} }
} }
@@ -31,7 +37,7 @@ export const mutersByPubkey = withGetter(
const $mutersByPubkey = new Map<string, Set<string>>() const $mutersByPubkey = new Map<string, Set<string>>()
for (const list of lists) { for (const list of lists) {
for (const pubkey of getListValues("p", list)) { for (const pubkey of getPubkeyTagValues(getListTags(list))) {
addToMapKey($mutersByPubkey, pubkey, list.event.pubkey) addToMapKey($mutersByPubkey, pubkey, list.event.pubkey)
} }
} }
+1 -2
View File
@@ -1,12 +1,11 @@
import {writable, derived} from 'svelte/store' import {writable, derived} from 'svelte/store'
import {withGetter} from '@welshman/store'
import {type Zapper} from '@welshman/util' import {type Zapper} from '@welshman/util'
import {type SubscribeRequestWithHandlers} from "@welshman/net" import {type SubscribeRequestWithHandlers} from "@welshman/net"
import {ctx, identity, fetchJson, uniq, bech32ToHex, hexToBech32, tryCatch, batcher, postJson} from '@welshman/lib' import {ctx, identity, fetchJson, uniq, bech32ToHex, hexToBech32, tryCatch, batcher, postJson} from '@welshman/lib'
import {collection} from './collection' import {collection} from './collection'
import {deriveProfile} from './profiles' import {deriveProfile} from './profiles'
export const zappers = withGetter(writable<Zapper[]>([])) export const zappers = writable<Zapper[]>([])
export const fetchZappers = async (lnurls: string[]) => { export const fetchZappers = async (lnurls: string[]) => {
const base = ctx.app.dufflepudUrl! const base = ctx.app.dufflepudUrl!
+1 -1
View File
@@ -18,7 +18,7 @@ export type DecryptedEvent = TrustedEvent & {
plaintext: Partial<EventContent> plaintext: Partial<EventContent>
} }
export const asDecryptedEvent = (event: TrustedEvent, plaintext: Partial<EventContent>) => export const asDecryptedEvent = (event: TrustedEvent, plaintext: Partial<EventContent> = {}) =>
({...event, plaintext}) as DecryptedEvent ({...event, plaintext}) as DecryptedEvent
export class Encryptable { export class Encryptable {
+4 -15
View File
@@ -1,7 +1,7 @@
import {parseJson, ensurePlural, nth} from "@welshman/lib" import {parseJson} from "@welshman/lib"
import {Address} from "./Address" import {Address} from "./Address"
import {isShareableRelayUrl} from "./Relay" import {isShareableRelayUrl} from "./Relay"
import {Encryptable, DecryptedEvent} from "./Encryptable" import {DecryptedEvent} from "./Encryptable"
export type ListParams = { export type ListParams = {
kind: number kind: number
@@ -39,16 +39,5 @@ export const readList = (event: DecryptedEvent): PublishedList => {
return {event, kind: event.kind, publicTags, privateTags} return {event, kind: event.kind, publicTags, privateTags}
} }
export const createList = ({kind, publicTags = [], privateTags = []}: List) => export const getListTags = (list: List | undefined) =>
new Encryptable({kind, tags: publicTags}, {content: JSON.stringify(privateTags)}) [...list?.publicTags || [], ...list?.privateTags || []]
export const editList = ({kind, publicTags = [], privateTags = []}: PublishedList) =>
new Encryptable({kind, tags: publicTags}, {content: JSON.stringify(privateTags)})
export const getListValues = (tagName: string | string[], list: List | undefined) => {
const tagNames = ensurePlural(tagName)
const allTags = [...list?.publicTags || [], ...list?.privateTags || []]
const filteredTags = allTags.filter(t => tagNames.includes(t[0])).map(nth(1))
return filteredTags
}
+9
View File
@@ -177,6 +177,15 @@ export class Tags extends (Fluent<Tag> as OmitStatics<typeof Fluent<Tag>, 'from'
// New, simpler version // New, simpler version
export const getTags = (types: string | string[], tags: string[][]) => {
types = ensurePlural(types)
return tags.filter(t => types.includes(t[0]))
}
export const getTagValues = (types: string | string[], tags: string[][]) =>
getTags(types, tags).map(nth(1))
export const getEventTags = (tags: string[][]) => export const getEventTags = (tags: string[][]) =>
tags.filter(t => ["e"].includes(t[0]) && t[1].length === 64) tags.filter(t => ["e"].includes(t[0]) && t[1].length === 64)