Slim down some things
This commit is contained in:
@@ -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}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,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
@@ -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))
|
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
@@ -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,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!
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user