Break down relay utils, replace removeNil with removeUndefined
This commit is contained in:
@@ -19,14 +19,14 @@ import {get} from "svelte/store"
|
|||||||
import type {Writable} from "svelte/store"
|
import type {Writable} from "svelte/store"
|
||||||
import type {NodeViewProps} from "@tiptap/core"
|
import type {NodeViewProps} from "@tiptap/core"
|
||||||
import {Router} from "@welshman/router"
|
import {Router} from "@welshman/router"
|
||||||
import {removeNil} from "@welshman/lib"
|
import {removeUndefined} from "@welshman/lib"
|
||||||
import type {FileAttributes} from "@welshman/editor"
|
import type {FileAttributes} from "@welshman/editor"
|
||||||
import {Editor, MentionSuggestion, WelshmanExtension} from "@welshman/editor"
|
import {Editor, MentionSuggestion, WelshmanExtension} from "@welshman/editor"
|
||||||
import {profileSearch, deriveProfileDisplay} from "@welshman/app"
|
import {profileSearch, deriveProfileDisplay} from "@welshman/app"
|
||||||
|
|
||||||
export const MentionNodeView = ({node}: NodeViewProps) => {
|
export const MentionNodeView = ({node}: NodeViewProps) => {
|
||||||
const dom = document.createElement("span")
|
const dom = document.createElement("span")
|
||||||
const display = deriveProfileDisplay(node.attrs.pubkey, removeNil([url]))
|
const display = deriveProfileDisplay(node.attrs.pubkey, removeUndefined([url]))
|
||||||
|
|
||||||
dom.classList.add("tiptap-object")
|
dom.classList.add("tiptap-object")
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -324,7 +324,7 @@ export declare const toIterable: (x: any) => any;
|
|||||||
export declare const ensurePlural: <T>(x: T | T[]) => T[];
|
export declare const ensurePlural: <T>(x: T | T[]) => T[];
|
||||||
|
|
||||||
// Ensures values are not undefined
|
// Ensures values are not undefined
|
||||||
export declare const removeNil: <T>(xs: T[]) => (T & {})[];
|
export declare const removeUndefined: <T>(xs: T[]) => (T & {})[];
|
||||||
|
|
||||||
// Returns a list of overlapping pairs of elements in xs
|
// Returns a list of overlapping pairs of elements in xs
|
||||||
export declare const overlappingPairs: <T>(xs: T[]) => T[][];
|
export declare const overlappingPairs: <T>(xs: T[]) => T[][];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {get} from "svelte/store"
|
import {get} from "svelte/store"
|
||||||
import {uniq, nthNe, removeNil, nthEq} from "@welshman/lib"
|
import {uniq, nthNe, removeUndefined, nthEq} from "@welshman/lib"
|
||||||
import {
|
import {
|
||||||
sendManagementRequest,
|
sendManagementRequest,
|
||||||
ManagementRequest,
|
ManagementRequest,
|
||||||
@@ -75,7 +75,7 @@ export const addRelay = async (url: string, mode: RelayMode) => {
|
|||||||
|
|
||||||
const list = get(userRelaySelections) || makeList({kind: RELAYS})
|
const list = get(userRelaySelections) || makeList({kind: RELAYS})
|
||||||
const dup = getRelayTags(getListTags(list)).find(nthEq(1, url))
|
const dup = getRelayTags(getListTags(list)).find(nthEq(1, url))
|
||||||
const tag = removeNil(["r", url, dup && dup[2] !== mode ? undefined : mode])
|
const tag = removeUndefined(["r", url, dup && dup[2] !== mode ? undefined : mode])
|
||||||
const tags = [...list.publicTags.filter(nthNe(1, url)), tag]
|
const tags = [...list.publicTags.filter(nthNe(1, url)), tag]
|
||||||
const event = {kind: list.kind, content: list.event?.content || "", tags}
|
const event = {kind: list.kind, content: list.event?.content || "", tags}
|
||||||
const relays = Router.get().FromUser().policy(addMaximalFallbacks).getUrls()
|
const relays = Router.get().FromUser().policy(addMaximalFallbacks).getUrls()
|
||||||
|
|||||||
+52
-24
@@ -1,6 +1,15 @@
|
|||||||
import {writable, derived} from "svelte/store"
|
import {writable, derived} from "svelte/store"
|
||||||
|
import {
|
||||||
|
uniq,
|
||||||
|
removeUndefined,
|
||||||
|
prop,
|
||||||
|
indexBy,
|
||||||
|
batcher,
|
||||||
|
fetchJson,
|
||||||
|
postJson,
|
||||||
|
Maybe,
|
||||||
|
} from "@welshman/lib"
|
||||||
import {withGetter} from "@welshman/store"
|
import {withGetter} from "@welshman/store"
|
||||||
import {uniq, batcher, postJson} from "@welshman/lib"
|
|
||||||
import {RelayProfile} from "@welshman/util"
|
import {RelayProfile} from "@welshman/util"
|
||||||
import {normalizeRelayUrl, displayRelayUrl, displayRelayProfile, isRelayUrl} from "@welshman/util"
|
import {normalizeRelayUrl, displayRelayUrl, displayRelayProfile, isRelayUrl} from "@welshman/util"
|
||||||
import {collection} from "@welshman/store"
|
import {collection} from "@welshman/store"
|
||||||
@@ -8,36 +17,55 @@ import {appContext} from "./context.js"
|
|||||||
|
|
||||||
export const relays = withGetter(writable<RelayProfile[]>([]))
|
export const relays = withGetter(writable<RelayProfile[]>([]))
|
||||||
|
|
||||||
export const fetchRelayProfiles = async (urls: string[]) => {
|
export const fetchRelayProfileDirectly = async (url: string): Promise<Maybe<RelayProfile>> => {
|
||||||
|
try {
|
||||||
|
return fetchJson(url.replace(/^ws/, "http"), {
|
||||||
|
headers: {
|
||||||
|
Accept: "application/nostr+json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchRelayProfilesDirectly = async (
|
||||||
|
urls: string[],
|
||||||
|
): Promise<Map<string, RelayProfile>> =>
|
||||||
|
indexBy(
|
||||||
|
prop("url"),
|
||||||
|
removeUndefined(
|
||||||
|
await Promise.all(
|
||||||
|
urls.map(async url => {
|
||||||
|
const profile = await fetchRelayProfileDirectly(url)
|
||||||
|
|
||||||
|
if (profile) {
|
||||||
|
return {...profile, url}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
export const fetchRelayProfilesUsingProxy = async (
|
||||||
|
proxy: string,
|
||||||
|
urls: string[],
|
||||||
|
): Promise<Map<string, RelayProfile>> => {
|
||||||
const profilesByUrl = new Map<string, RelayProfile>()
|
const profilesByUrl = new Map<string, RelayProfile>()
|
||||||
|
const res: any = await postJson(`${proxy}/relay/info`, {urls})
|
||||||
|
|
||||||
if (appContext.dufflepudUrl) {
|
for (const {url, info} of res?.data || []) {
|
||||||
const res: any = await postJson(`${appContext.dufflepudUrl}/relay/info`, {urls})
|
profilesByUrl.set(url, info)
|
||||||
|
|
||||||
for (const {url, info} of res?.data || []) {
|
|
||||||
profilesByUrl.set(url, info)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await Promise.all(
|
|
||||||
urls.map(async url => {
|
|
||||||
try {
|
|
||||||
const res = await fetch(url.replace(/^ws/, "http"), {
|
|
||||||
headers: {
|
|
||||||
Accept: "application/nostr+json",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
profilesByUrl.set(url, await res.json())
|
|
||||||
} catch (e) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return profilesByUrl
|
return profilesByUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const fetchRelayProfiles = (urls: string[]) =>
|
||||||
|
appContext.dufflepudUrl
|
||||||
|
? fetchRelayProfilesUsingProxy(appContext.dufflepudUrl, urls)
|
||||||
|
: fetchRelayProfilesDirectly(urls)
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
indexStore: relaysByUrl,
|
indexStore: relaysByUrl,
|
||||||
deriveItem: deriveRelay,
|
deriveItem: deriveRelay,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {writable, derived} from "svelte/store"
|
import {writable, derived} from "svelte/store"
|
||||||
import {Zapper, TrustedEvent, Zap, getTagValues, getLnUrl, zapFromEvent} from "@welshman/util"
|
import {Zapper, TrustedEvent, Zap, getTagValues, getLnUrl, zapFromEvent} from "@welshman/util"
|
||||||
import {
|
import {
|
||||||
removeNil,
|
removeUndefined,
|
||||||
fetchJson,
|
fetchJson,
|
||||||
uniq,
|
uniq,
|
||||||
bech32ToHex,
|
bech32ToHex,
|
||||||
@@ -22,7 +22,7 @@ export const fetchZappers = async (lnurls: string[]) => {
|
|||||||
|
|
||||||
// Use dufflepud if we it's set up to protect user privacy, otherwise fetch directly
|
// Use dufflepud if we it's set up to protect user privacy, otherwise fetch directly
|
||||||
if (base) {
|
if (base) {
|
||||||
const hexUrls = removeNil(lnurls.map(lnurl => tryCatch(() => bech32ToHex(lnurl))))
|
const hexUrls = removeUndefined(lnurls.map(lnurl => tryCatch(() => bech32ToHex(lnurl))))
|
||||||
|
|
||||||
if (hexUrls.length > 0) {
|
if (hexUrls.length > 0) {
|
||||||
const res: any = await tryCatch(
|
const res: any = await tryCatch(
|
||||||
@@ -102,7 +102,7 @@ export const deriveZapperForPubkey = (pubkey: string, relays: string[] = []) =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const getLnUrlsForEvent = async (event: TrustedEvent) => {
|
export const getLnUrlsForEvent = async (event: TrustedEvent) => {
|
||||||
const lnurls = removeNil(getTagValues("zap", event.tags).map(getLnUrl))
|
const lnurls = removeUndefined(getTagValues("zap", event.tags).map(getLnUrl))
|
||||||
|
|
||||||
if (lnurls.length > 0) {
|
if (lnurls.length > 0) {
|
||||||
return lnurls
|
return lnurls
|
||||||
@@ -110,7 +110,7 @@ export const getLnUrlsForEvent = async (event: TrustedEvent) => {
|
|||||||
|
|
||||||
const profile = await loadProfile(event.pubkey)
|
const profile = await loadProfile(event.pubkey)
|
||||||
|
|
||||||
return removeNil([profile?.lnurl])
|
return removeUndefined([profile?.lnurl])
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getZapperForZap = async (zap: TrustedEvent, parent: TrustedEvent) => {
|
export const getZapperForZap = async (zap: TrustedEvent, parent: TrustedEvent) => {
|
||||||
@@ -126,7 +126,7 @@ export const getValidZap = async (zap: TrustedEvent, parent: TrustedEvent) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getValidZaps = async (zaps: TrustedEvent[], parent: TrustedEvent) =>
|
export const getValidZaps = async (zaps: TrustedEvent[], parent: TrustedEvent) =>
|
||||||
removeNil(await Promise.all(zaps.map(zap => getValidZap(zap, parent))))
|
removeUndefined(await Promise.all(zaps.map(zap => getValidZap(zap, parent))))
|
||||||
|
|
||||||
export const deriveValidZaps = (zaps: TrustedEvent[], parent: TrustedEvent) => {
|
export const deriveValidZaps = (zaps: TrustedEvent[], parent: TrustedEvent) => {
|
||||||
const store = writable<Zap[]>([])
|
const store = writable<Zap[]>([])
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
inc,
|
inc,
|
||||||
removeNil,
|
removeUndefined,
|
||||||
call,
|
call,
|
||||||
defer,
|
defer,
|
||||||
Deferred,
|
Deferred,
|
||||||
@@ -130,9 +130,10 @@ export class FeedController {
|
|||||||
let delta = initialDelta
|
let delta = initialDelta
|
||||||
let since = this.options.useWindowing ? maxUntil - delta : 0
|
let since = this.options.useWindowing ? maxUntil - delta : 0
|
||||||
let until = maxUntil
|
let until = maxUntil
|
||||||
|
let exhausted = false
|
||||||
|
|
||||||
return async (limit: number) => {
|
return async (limit: number) => {
|
||||||
if (promise) {
|
if (promise || exhausted) {
|
||||||
return promise
|
return promise
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +174,7 @@ export class FeedController {
|
|||||||
|
|
||||||
if (this.options.useWindowing) {
|
if (this.options.useWindowing) {
|
||||||
if (since === minSince) {
|
if (since === minSince) {
|
||||||
|
exhausted = true
|
||||||
onExhausted?.()
|
onExhausted?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +187,7 @@ export class FeedController {
|
|||||||
|
|
||||||
since = Math.max(minSince, until - delta)
|
since = Math.max(minSince, until - delta)
|
||||||
} else if (count === 0) {
|
} else if (count === 0) {
|
||||||
|
exhausted = true
|
||||||
onExhausted?.()
|
onExhausted?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +354,7 @@ export class FeedController {
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
const signal = AbortSignal.any(removeNil([controller.signal, this.options.signal]))
|
const signal = AbortSignal.any(removeUndefined([controller.signal, this.options.signal]))
|
||||||
const requestFilters = filters!.map((filter: Filter) => ({...filter, limit: 0}))
|
const requestFilters = filters!.map((filter: Filter) => ({...filter, limit: 0}))
|
||||||
|
|
||||||
requestPage(
|
requestPage(
|
||||||
|
|||||||
@@ -776,7 +776,7 @@ export const toIterable = (x: any) => (isIterable(x) ? x : [x])
|
|||||||
export const ensurePlural = <T>(x: T | T[]) => (x instanceof Array ? x : [x])
|
export const ensurePlural = <T>(x: T | T[]) => (x instanceof Array ? x : [x])
|
||||||
|
|
||||||
/** Ensures values are not undefined */
|
/** Ensures values are not undefined */
|
||||||
export const removeNil = <T>(xs: T[]) => xs.filter(isDefined).map(assertDefined)
|
export const removeUndefined = <T>(xs: T[]) => xs.filter(isDefined).map(assertDefined)
|
||||||
|
|
||||||
/** Returns a list of overlapping pairs of elements in xs */
|
/** Returns a list of overlapping pairs of elements in xs */
|
||||||
export const overlappingPairs = <T>(xs: T[]): T[][] => {
|
export const overlappingPairs = <T>(xs: T[]): T[][] => {
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import {derived} from "svelte/store"
|
import {derived} from "svelte/store"
|
||||||
import {sortBy, identity, ensurePlural, removeNil, batch, partition, first} from "@welshman/lib"
|
import {
|
||||||
|
sortBy,
|
||||||
|
identity,
|
||||||
|
ensurePlural,
|
||||||
|
removeUndefined,
|
||||||
|
batch,
|
||||||
|
partition,
|
||||||
|
first,
|
||||||
|
} from "@welshman/lib"
|
||||||
import {matchFilters, getIdAndAddress, getIdFilters, Filter, TrustedEvent} from "@welshman/util"
|
import {matchFilters, getIdAndAddress, getIdFilters, Filter, TrustedEvent} from "@welshman/util"
|
||||||
import {Repository} from "@welshman/net"
|
import {Repository} from "@welshman/net"
|
||||||
import {custom} from "./custom.js"
|
import {custom} from "./custom.js"
|
||||||
@@ -34,7 +42,7 @@ export const deriveEventsMapped = <T>(
|
|||||||
if (deferred.has(event.id)) {
|
if (deferred.has(event.id)) {
|
||||||
deferred.delete(event.id)
|
deferred.delete(event.id)
|
||||||
|
|
||||||
for (const item of removeNil(ensurePlural(items))) {
|
for (const item of removeUndefined(ensurePlural(items))) {
|
||||||
data.push(item)
|
data.push(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +61,7 @@ export const deriveEventsMapped = <T>(
|
|||||||
if (items instanceof Promise) {
|
if (items instanceof Promise) {
|
||||||
defer(event, items)
|
defer(event, items)
|
||||||
} else {
|
} else {
|
||||||
for (const item of removeNil(ensurePlural(items))) {
|
for (const item of removeUndefined(ensurePlural(items))) {
|
||||||
data.push(item)
|
data.push(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +97,7 @@ export const deriveEventsMapped = <T>(
|
|||||||
} else if (items) {
|
} else if (items) {
|
||||||
dirty = true
|
dirty = true
|
||||||
|
|
||||||
for (const item of removeNil(ensurePlural(items))) {
|
for (const item of removeUndefined(ensurePlural(items))) {
|
||||||
data.push(item as T)
|
data.push(item as T)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user