Remove tsc-multi, re-install gts, apply autoformatting and linting

This commit is contained in:
Jon Staab
2024-12-17 10:59:27 -08:00
parent 0b86613161
commit f33e03740e
122 changed files with 2243 additions and 2178 deletions
+10 -11
View File
@@ -1,4 +1,4 @@
import {nip19} from "nostr-tools"
import {decode, naddrEncode} from "nostr-tools/nip19"
// Define this locally to avoid circular dependencies
type AddressableEvent = {
@@ -12,7 +12,7 @@ export class Address {
readonly kind: number,
readonly pubkey: string,
readonly identifier: string,
readonly relays: string[] = []
readonly relays: string[] = [],
) {}
static isAddress(address: string) {
@@ -26,22 +26,21 @@ export class Address {
}
static fromNaddr(naddr: string) {
let type
let data = {} as any
let decoded: any
try {
({type, data} = nip19.decode(naddr) as {
type: "naddr"
data: any
})
decoded = decode(naddr)
} catch (e) {
// pass
}
if (type !== "naddr") {
if (decoded?.type !== "naddr") {
throw new Error(`Invalid naddr ${naddr}`)
}
return new Address(data.kind, data.pubkey, data.identifier, data.relays)
const {kind, pubkey, identifier, relays} = decoded.data
return new Address(kind, pubkey, identifier, relays)
}
static fromEvent(event: AddressableEvent, relays: string[] = []) {
@@ -52,7 +51,7 @@ export class Address {
toString = () => [this.kind, this.pubkey, this.identifier].join(":")
toNaddr = () => nip19.naddrEncode(this)
toNaddr = () => naddrEncode(this)
}
// Utils
+6 -3
View File
@@ -1,4 +1,4 @@
import type {EventContent, TrustedEvent, EventTemplate} from './Events'
import type {EventContent, TrustedEvent, EventTemplate} from "./Events.js"
export type Encrypt = (x: string) => Promise<string>
@@ -27,7 +27,10 @@ export class Encryptable<T extends EventTemplate> {
* const eventTemplate = await encryptable.reconcile(myEncryptFunction)
* ```
*/
constructor(readonly event: Partial<T>, readonly updates: EncryptableUpdates) {}
constructor(
readonly event: Partial<T>,
readonly updates: EncryptableUpdates,
) {}
/**
* Encrypts plaintext updates and merges them into the event template.
@@ -49,7 +52,7 @@ export class Encryptable<T extends EventTemplate> {
tag[1] = await encrypt(tag[1])
return tag
})
}),
)
}
+29 -21
View File
@@ -1,8 +1,13 @@
import {verifiedSymbol, getEventHash, verifyEvent} from 'nostr-tools'
import {cached, pick, now} from '@welshman/lib'
import {getAncestorTagValues} from './Tags'
import {getAddress} from './Address'
import {isEphemeralKind, isReplaceableKind, isPlainReplaceableKind, isParameterizedReplaceableKind} from './Kinds'
import {verifiedSymbol, getEventHash, verifyEvent} from "nostr-tools/pure"
import {cached, pick, now} from "@welshman/lib"
import {getAncestorTagValues} from "./Tags.js"
import {getAddress} from "./Address.js"
import {
isEphemeralKind,
isReplaceableKind,
isPlainReplaceableKind,
isParameterizedReplaceableKind,
} from "./Kinds.js"
export type EventContent = {
tags: string[][]
@@ -46,8 +51,10 @@ export type CreateEventOpts = {
created_at?: number
}
export const createEvent = (kind: number, {content = "", tags = [], created_at = now()}: CreateEventOpts) =>
({kind, content, tags, created_at})
export const createEvent = (
kind: number,
{content = "", tags = [], created_at = now()}: CreateEventOpts,
) => ({kind, content, tags, created_at})
export const isEventTemplate = (e: EventTemplate): e is EventTemplate =>
Boolean(typeof e.kind === "number" && Array.isArray(e.tags) && typeof e.content === "string")
@@ -58,8 +65,7 @@ export const isStampedEvent = (e: StampedEvent): e is StampedEvent =>
export const isOwnedEvent = (e: OwnedEvent): e is OwnedEvent =>
Boolean(isStampedEvent(e) && e.pubkey)
export const isHashedEvent = (e: HashedEvent): e is HashedEvent =>
Boolean(isOwnedEvent(e) && e.id)
export const isHashedEvent = (e: HashedEvent): e is HashedEvent => Boolean(isOwnedEvent(e) && e.id)
export const isSignedEvent = (e: TrustedEvent): e is SignedEvent =>
Boolean(isHashedEvent(e) && e.sig)
@@ -71,25 +77,25 @@ export const isTrustedEvent = (e: TrustedEvent): e is TrustedEvent =>
isSignedEvent(e) || isUnwrappedEvent(e)
export const asEventTemplate = (e: EventTemplate): EventTemplate =>
pick(['kind', 'tags', 'content'], e)
pick(["kind", "tags", "content"], e)
export const asStampedEvent = (e: StampedEvent): StampedEvent =>
pick(['kind', 'tags', 'content', 'created_at'], e)
pick(["kind", "tags", "content", "created_at"], e)
export const asOwnedEvent = (e: OwnedEvent): OwnedEvent =>
pick(['kind', 'tags', 'content', 'created_at', 'pubkey'], e)
pick(["kind", "tags", "content", "created_at", "pubkey"], e)
export const asHashedEvent = (e: HashedEvent): HashedEvent =>
pick(['kind', 'tags', 'content', 'created_at', 'pubkey', 'id'], e)
pick(["kind", "tags", "content", "created_at", "pubkey", "id"], e)
export const asSignedEvent = (e: SignedEvent): SignedEvent =>
pick(['kind', 'tags', 'content', 'created_at', 'pubkey', 'id', 'sig'], e)
pick(["kind", "tags", "content", "created_at", "pubkey", "id", "sig"], e)
export const asUnwrappedEvent = (e: UnwrappedEvent): UnwrappedEvent =>
pick(['kind', 'tags', 'content', 'created_at', 'pubkey', 'id', 'wrap'], e)
pick(["kind", "tags", "content", "created_at", "pubkey", "id", "wrap"], e)
export const asTrustedEvent = (e: TrustedEvent): TrustedEvent =>
pick(['kind', 'tags', 'content', 'created_at', 'pubkey', 'id', 'sig', 'wrap'], e)
pick(["kind", "tags", "content", "created_at", "pubkey", "id", "sig", "wrap"], e)
const _hasValidSignature = cached<string, boolean, [SignedEvent]>({
maxSize: 10000,
@@ -97,7 +103,7 @@ const _hasValidSignature = cached<string, boolean, [SignedEvent]>({
try {
return [getEventHash(e), e.sig].join(":")
} catch (err) {
return 'invalid'
return "invalid"
}
},
getValue: ([e]: [SignedEvent]) => {
@@ -113,11 +119,12 @@ const _hasValidSignature = cached<string, boolean, [SignedEvent]>({
export const hasValidSignature = (e: SignedEvent) => e[verifiedSymbol] || _hasValidSignature(e)
export const getIdentifier = (e: EventTemplate) => e.tags.find(t => t[0] === 'd')?.[1]
export const getIdentifier = (e: EventTemplate) => e.tags.find(t => t[0] === "d")?.[1]
export const getIdOrAddress = (e: HashedEvent) => isReplaceable(e) ? getAddress(e) : e.id
export const getIdOrAddress = (e: HashedEvent) => (isReplaceable(e) ? getAddress(e) : e.id)
export const getIdAndAddress = (e: HashedEvent) => isReplaceable(e) ? [e.id, getAddress(e)] : [e.id]
export const getIdAndAddress = (e: HashedEvent) =>
isReplaceable(e) ? [e.id, getAddress(e)] : [e.id]
export const isEphemeral = (e: EventTemplate) => isEphemeralKind(e.kind)
@@ -125,7 +132,8 @@ export const isReplaceable = (e: EventTemplate) => isReplaceableKind(e.kind)
export const isPlainReplaceable = (e: EventTemplate) => isPlainReplaceableKind(e.kind)
export const isParameterizedReplaceable = (e: EventTemplate) => isParameterizedReplaceableKind(e.kind)
export const isParameterizedReplaceable = (e: EventTemplate) =>
isParameterizedReplaceableKind(e.kind)
export const isChildOf = (child: EventContent, parent: HashedEvent) => {
const {roots, replies} = getAncestorTagValues(child.tags)
+27 -14
View File
@@ -1,8 +1,19 @@
import {matchFilter as nostrToolsMatchFilter} from 'nostr-tools'
import {without, uniqBy, prop, mapVals, shuffle, avg, hash, groupBy, randomId, uniq} from '@welshman/lib'
import type {HashedEvent, TrustedEvent, SignedEvent} from './Events'
import {isReplaceableKind} from './Kinds'
import {Address, getAddress} from './Address'
import {matchFilter as nostrToolsMatchFilter} from "nostr-tools/filter"
import {
without,
uniqBy,
prop,
mapVals,
shuffle,
avg,
hash,
groupBy,
randomId,
uniq,
} from "@welshman/lib"
import type {HashedEvent, TrustedEvent, SignedEvent} from "./Events.js"
import {isReplaceableKind} from "./Kinds.js"
import {Address, getAddress} from "./Address.js"
export const EPOCH = 1609459200
@@ -58,12 +69,12 @@ export const getFilterId = (filter: Filter) => {
const parts = []
for (const k of keys) {
const v = filter[k as keyof Filter]
const s = Array.isArray(v) ? v.join(',') : v
const s = Array.isArray(v) ? v.join(",") : v
parts.push([k, s].join(':'))
parts.push([k, s].join(":"))
}
return hash(parts.join('|'))
return hash(parts.join("|"))
}
export const calculateFilterGroup = ({since, until, limit, search, ...filter}: Filter) => {
@@ -107,13 +118,13 @@ export const intersectFilters = (groups: Filter[][]) => {
const f3: Filter = {}
for (const k of uniq([...Object.keys(f1), ...Object.keys(f2)]) as (keyof Filter)[]) {
if (k === 'since' || k === 'limit') {
if (k === "since" || k === "limit") {
f3[k] = Math.max(f1[k] || 0, f2[k] || 0)
} else if (k === 'until') {
} else if (k === "until") {
f3[k] = Math.min(f1[k] || f2[k] || 0, f2[k] || f1[k] || 0)
} else if (k === 'search') {
} else if (k === "search") {
if (f1[k] && f2[k] && f1[k] !== f2[k]) {
f3[k] = [f1[k], f2[k]].join(' ')
f3[k] = [f1[k], f2[k]].join(" ")
} else {
f3[k] = f1[k] || f2[k]
}
@@ -186,7 +197,6 @@ export const getReplyFilters = (events: TrustedEvent[], filter: Filter = {}) =>
return filters
}
export const addRepostFilters = (filters: Filter[]) =>
filters.flatMap(original => {
const filterChunk = [original]
@@ -239,6 +249,9 @@ export const getFilterResultCardinality = (filter: Filter) => {
}
export const trimFilter = (filter: Filter): Filter =>
mapVals(v => Array.isArray(v) && v.length > 1000 ? shuffle(v as string[]).slice(0, 1000) : v, filter) as Filter
mapVals(
v => (Array.isArray(v) && v.length > 1000 ? shuffle(v as string[]).slice(0, 1000) : v),
filter,
) as Filter
export const trimFilters = (filters: Filter[]) => filters.map(trimFilter)
+9 -5
View File
@@ -1,7 +1,7 @@
import {fromPairs, last, first, parseJson} from "@welshman/lib"
import {getAddress} from "./Address"
import {getAddressTags, getKindTagValues} from "./Tags"
import type {TrustedEvent} from "./Events"
import {getAddress} from "./Address.js"
import {getAddressTags, getKindTagValues} from "./Tags.js"
import type {TrustedEvent} from "./Events.js"
export type Handler = {
kind: number
@@ -32,8 +32,12 @@ export const readHandlers = (event: TrustedEvent) => {
return []
}
return getKindTagValues(event.tags)
.map(kind => ({...normalizedMeta, kind, identifier, event})) as Handler[]
return getKindTagValues(event.tags).map(kind => ({
...normalizedMeta,
kind,
identifier,
event,
})) as Handler[]
}
export const getHandlerKey = (handler: Handler) => `${handler.kind}:${getAddress(handler.event)}`
+10 -7
View File
@@ -1,12 +1,16 @@
import {kinds} from 'nostr-tools'
import {between} from '@welshman/lib'
import {
isRegularKind,
isEphemeralKind,
isReplaceableKind as isPlainReplaceableKind,
isParameterizedReplaceableKind,
} from "nostr-tools/kinds"
import {between} from "@welshman/lib"
export {isRegularKind, isEphemeralKind, isPlainReplaceableKind, isParameterizedReplaceableKind}
export const isRegularKind = kinds.isRegularKind
export const isEphemeralKind = kinds.isEphemeralKind
export const isPlainReplaceableKind = kinds.isReplaceableKind
export const isParameterizedReplaceableKind = kinds.isParameterizedReplaceableKind
export const isReplaceableKind = (kind: number) =>
isPlainReplaceableKind(kind) || isParameterizedReplaceableKind(kind)
export const isDVMKind = (kind: number) => between([4999, 7001], kind)
export const PROFILE = 0
@@ -162,4 +166,3 @@ export const GROUP_ADMINS = 39001
export const DEPRECATED_RELAY_RECOMMENDATION = 2
export const DEPRECATED_DIRECT_MESSAGE = 4
export const DEPRECATED_NAMED_GENERIC = 30001
+1 -1
View File
@@ -1,3 +1,3 @@
export const fromNostrURI = (s: string) => s.replace(/^nostr:\/?\/?/, "")
export const toNostrURI = (s: string) => s.startsWith('nostr:') ? s : `nostr:${s}`
export const toNostrURI = (s: string) => (s.startsWith("nostr:") ? s : `nostr:${s}`)
+14 -9
View File
@@ -1,9 +1,9 @@
import {parseJson, nthEq} from "@welshman/lib"
import {Address} from "./Address"
import {uniqTags} from "./Tags"
import {isShareableRelayUrl} from "./Relay"
import {Encryptable, DecryptedEvent} from "./Encryptable"
import type {EncryptableUpdates} from "./Encryptable"
import {Address} from "./Address.js"
import {uniqTags} from "./Tags.js"
import {isShareableRelayUrl} from "./Relay.js"
import {Encryptable, DecryptedEvent} from "./Encryptable.js"
import type {EncryptableUpdates} from "./Encryptable.js"
export type ListParams = {
kind: number
@@ -19,8 +19,11 @@ export type PublishedList = Omit<List, "event"> & {
event: DecryptedEvent
}
export const makeList = (list: ListParams & Partial<List>): List =>
({publicTags: [], privateTags: [], ...list})
export const makeList = (list: ListParams & Partial<List>): List => ({
publicTags: [],
privateTags: [],
...list,
})
const isValidTag = (tag: string[]) => {
if (tag[0] === "p") return tag[1]?.length === 64
@@ -41,8 +44,10 @@ export const readList = (event: DecryptedEvent): PublishedList => {
return {event, kind: event.kind, publicTags, privateTags}
}
export const getListTags = (list: List | undefined) =>
[...list?.publicTags || [], ...list?.privateTags || []]
export const getListTags = (list: List | undefined) => [
...(list?.publicTags || []),
...(list?.privateTags || []),
]
export const removeFromListByPredicate = (list: List, pred: (t: string[]) => boolean) => {
const plaintext: EncryptableUpdates = {}
+10 -8
View File
@@ -1,8 +1,8 @@
import {nip19} from "nostr-tools"
import {npubEncode} from "nostr-tools/nip19"
import {ellipsize, parseJson} from "@welshman/lib"
import {TrustedEvent} from "./Events"
import {getLnUrl} from './Zaps'
import {PROFILE} from "./Kinds"
import {TrustedEvent} from "./Events.js"
import {getLnUrl} from "./Zaps.js"
import {PROFILE} from "./Kinds.js"
export type Profile = {
name?: string
@@ -27,13 +27,15 @@ export const isPublishedProfile = (profile: Profile): profile is PublishedProfil
export const makeProfile = (profile: Partial<Profile> = {}): Profile => {
const address = profile.lud06 || profile.lud16
const lnurl = typeof address === 'string' ? getLnUrl(address) : null
const lnurl = typeof address === "string" ? getLnUrl(address) : null
return lnurl ? {lnurl, ...profile} : profile
}
export const readProfile = (event: TrustedEvent): PublishedProfile =>
({...makeProfile(parseJson(event.content) || {}), event})
export const readProfile = (event: TrustedEvent): PublishedProfile => ({
...makeProfile(parseJson(event.content) || {}),
event,
})
export const createProfile = ({event, ...profile}: Profile) => ({
kind: PROFILE,
@@ -47,7 +49,7 @@ export const editProfile = ({event, ...profile}: PublishedProfile) => ({
})
export const displayPubkey = (pubkey: string) => {
const d = nip19.npubEncode(pubkey)
const d = npubEncode(pubkey)
return d.slice(0, 8) + "…" + d.slice(-5)
}
+32 -28
View File
@@ -1,8 +1,8 @@
import {last, Emitter, normalizeUrl, sleep, stripProtocol} from '@welshman/lib'
import {matchFilters} from './Filters'
import type {Repository} from './Repository'
import type {Filter} from './Filters'
import type {HashedEvent, TrustedEvent} from './Events'
import {last, Emitter, normalizeUrl, sleep, stripProtocol} from "@welshman/lib"
import {matchFilters} from "./Filters.js"
import type {Repository} from "./Repository.js"
import type {Filter} from "./Filters.js"
import type {HashedEvent, TrustedEvent} from "./Events.js"
// Constants and types
@@ -31,8 +31,8 @@ export type RelayProfile = {
// Utils related to bare urls
export const isRelayUrl = (url: string) => {
if (!url.includes('://')) {
url = 'wss://' + url
if (!url.includes("://")) {
url = "wss://" + url
}
try {
@@ -47,16 +47,16 @@ export const isRelayUrl = (url: string) => {
export const isShareableRelayUrl = (url: string) =>
Boolean(
isRelayUrl(url) &&
// Is it actually a websocket url and has a dot
url.match(/^wss:\/\/.+\..+/) &&
// Don't match stuff with a port number
!url.slice(6).match(/:\d+/) &&
// Don't match stuff with a numeric tld
!url.slice(6).match(/\.\d+\b/) &&
// Don't match raw ip addresses
!url.slice(6).match(/\d+\.\d+\.\d+\.\d+/) &&
// Skip nostr.wine's virtual relays
!url.slice(6).match(/\/npub/)
// Is it actually a websocket url and has a dot
url.match(/^wss:\/\/.+\..+/) &&
// Don't match stuff with a port number
!url.slice(6).match(/:\d+/) &&
// Don't match stuff with a numeric tld
!url.slice(6).match(/\.\d+\b/) &&
// Don't match raw ip addresses
!url.slice(6).match(/\d+\.\d+\.\d+\.\d+/) &&
// Skip nostr.wine's virtual relays
!url.slice(6).match(/\/npub/),
)
export const normalizeRelayUrl = (url: string) => {
@@ -78,7 +78,8 @@ export const normalizeRelayUrl = (url: string) => {
export const displayRelayUrl = (url: string) => last(url.split("://")).replace(/\/$/, "")
export const displayRelayProfile = (profile?: RelayProfile, fallback = "") => profile?.name || fallback
export const displayRelayProfile = (profile?: RelayProfile, fallback = "") =>
profile?.name || fallback
// In-memory relay implementation backed by Repository
@@ -90,10 +91,13 @@ export class Relay<E extends HashedEvent = TrustedEvent> extends Emitter {
}
send(type: string, ...message: any[]) {
switch(type) {
case 'EVENT': return this.handleEVENT(message as [E])
case 'CLOSE': return this.handleCLOSE(message as [string])
case 'REQ': return this.handleREQ(message as [string, ...Filter[]])
switch (type) {
case "EVENT":
return this.handleEVENT(message as [E])
case "CLOSE":
return this.handleCLOSE(message as [string])
case "REQ":
return this.handleREQ(message as [string, ...Filter[]])
}
}
@@ -101,13 +105,13 @@ export class Relay<E extends HashedEvent = TrustedEvent> extends Emitter {
this.repository.publish(event)
// Callers generally expect async relays
sleep(1).then(() => {
this.emit('OK', event.id, true, "")
void sleep(1).then(() => {
this.emit("OK", event.id, true, "")
if (!this.repository.isDeleted(event)) {
for (const [subId, filters] of this.subs.entries()) {
if (matchFilters(filters, event)) {
this.emit('EVENT', subId, event)
this.emit("EVENT", subId, event)
}
}
}
@@ -122,12 +126,12 @@ export class Relay<E extends HashedEvent = TrustedEvent> extends Emitter {
this.subs.set(subId, filters)
// Callers generally expect async relays
sleep(1).then(() => {
void sleep(1).then(() => {
for (const event of this.repository.query(filters)) {
this.emit('EVENT', subId, event)
this.emit("EVENT", subId, event)
}
this.emit('EOSE', subId)
this.emit("EOSE", subId)
})
}
}
+20 -22
View File
@@ -1,10 +1,10 @@
import {flatten, Emitter, sortBy, inc, chunk, uniq, omit, now, range, identity} from '@welshman/lib'
import {DELETE} from './Kinds'
import {EPOCH, matchFilter} from './Filters'
import {isReplaceable, isUnwrappedEvent} from './Events'
import {getAddress} from './Address'
import type {Filter} from './Filters'
import type {TrustedEvent, HashedEvent} from './Events'
import {flatten, Emitter, sortBy, inc, chunk, uniq, omit, now, range, identity} from "@welshman/lib"
import {DELETE} from "./Kinds.js"
import {EPOCH, matchFilter} from "./Filters.js"
import {isReplaceable, isUnwrappedEvent} from "./Events.js"
import {getAddress} from "./Address.js"
import type {Filter} from "./Filters.js"
import type {TrustedEvent, HashedEvent} from "./Events.js"
export const DAY = 86400
@@ -69,22 +69,19 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
removed.add(id)
}
this.emit('update', {added, removed})
this.emit("update", {added, removed})
}
// API
getEvent = (idOrAddress: string) => {
return idOrAddress.includes(':')
return idOrAddress.includes(":")
? this.eventsByAddress.get(idOrAddress)
: this.eventsById.get(idOrAddress)
}
hasEvent = (event: E) => {
const duplicate = (
this.eventsById.get(event.id) ||
this.eventsByAddress.get(getAddress(event))
)
const duplicate = this.eventsById.get(event.id) || this.eventsByAddress.get(getAddress(event))
return duplicate && duplicate.created_at >= event.created_at
}
@@ -110,7 +107,7 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
this._updateIndex(this.eventsByDay, getDay(event.created_at), undefined, event)
this._updateIndex(this.eventsByAuthor, event.pubkey, undefined, event)
this.emit('update', {added: [], removed: [event.id]})
this.emit("update", {added: [], removed: [event.id]})
}
}
@@ -121,27 +118,28 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
if (filter.ids) {
events = filter.ids!.map(id => this.eventsById.get(id)).filter(identity) as E[]
filter = omit(['ids'], filter)
filter = omit(["ids"], filter)
} else if (filter.authors) {
events = uniq(filter.authors!.flatMap(pubkey => this.eventsByAuthor.get(pubkey) || []))
filter = omit(['authors'], filter)
filter = omit(["authors"], filter)
} else if (filter.since || filter.until) {
const sinceDay = getDay(filter.since || EPOCH)
const untilDay = getDay(filter.until || now())
events = uniq(
Array.from(range(sinceDay, inc(untilDay)))
.flatMap((day: number) => this.eventsByDay.get(day) || [])
Array.from(range(sinceDay, inc(untilDay))).flatMap(
(day: number) => this.eventsByDay.get(day) || [],
),
)
} else {
for (const [k, values] of Object.entries(filter)) {
if (!k.startsWith('#') || k.length !== 2) {
if (!k.startsWith("#") || k.length !== 2) {
continue
}
filter = omit([k], filter)
events = uniq(
(values as string[]).flatMap(v => this.eventsByTag.get(`${k[1]}:${v}`) || [])
(values as string[]).flatMap(v => this.eventsByTag.get(`${k[1]}:${v}`) || []),
)
break
@@ -218,7 +216,7 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
// Update our tag indexes
for (const tag of event.tags) {
if (tag[0]?.length === 1) {
this._updateIndex(this.eventsByTag, tag.slice(0, 2).join(':'), event, duplicate)
this._updateIndex(this.eventsByTag, tag.slice(0, 2).join(":"), event, duplicate)
// If this is a delete event, the tag value is an id or address. Track when it was
// deleted so that replaceables can be restored.
@@ -235,7 +233,7 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
}
if (shouldNotify) {
this.emit('update', {added: [event], removed})
this.emit("update", {added: [event], removed})
}
return true
+5 -5
View File
@@ -1,6 +1,6 @@
import {uniq, uniqBy, mapVals, nth, nthEq, ensurePlural} from "@welshman/lib"
import {isRelayUrl, isShareableRelayUrl} from "./Relay"
import {Address} from "./Address"
import {isRelayUrl, isShareableRelayUrl} from "./Relay.js"
import {Address} from "./Address.js"
export const getTags = (types: string | string[], tags: string[][]) => {
types = ensurePlural(types)
@@ -17,8 +17,7 @@ export const getTag = (types: string | string[], tags: string[][]) => {
export const getTagValues = (types: string | string[], tags: string[][]) =>
getTags(types, tags).map(nth(1))
export const getTagValue = (types: string | string[], tags: string[][]) =>
getTag(types, tags)?.[1]
export const getTagValue = (types: string | string[], tags: string[][]) => getTag(types, tags)?.[1]
export const getEventTags = (tags: string[][]) =>
tags.filter(t => ["e"].includes(t[0]) && t[1].length === 64)
@@ -37,7 +36,8 @@ export const getPubkeyTagValues = (tags: string[][]) => getPubkeyTags(tags).map(
export const getTopicTags = (tags: string[][]) => tags.filter(nthEq(0, "t"))
export const getTopicTagValues = (tags: string[][]) => getTopicTags(tags).map(t => t[1].replace(/^#/, ''))
export const getTopicTagValues = (tags: string[][]) =>
getTopicTags(tags).map(t => t[1].replace(/^#/, ""))
export const getRelayTags = (tags: string[][]) =>
tags.filter(t => ["r", "relay"].includes(t[0]) && isRelayUrl(t[1] || ""))
+4 -4
View File
@@ -1,5 +1,5 @@
import {hexToBech32, fromPairs} from '@welshman/lib'
import type {TrustedEvent} from './Events'
import {hexToBech32, fromPairs} from "@welshman/lib"
import type {TrustedEvent} from "./Events.js"
const DIVISORS = {
m: BigInt(1e3),
@@ -71,7 +71,7 @@ export const getLnUrl = (address: string) => {
export type Zapper = {
lnurl: string
pubkey?: string,
pubkey?: string
callback?: string
minSendable?: number
maxSendable?: number
@@ -81,7 +81,7 @@ export type Zapper = {
export type Zap = {
request: TrustedEvent
response: TrustedEvent,
response: TrustedEvent
invoiceAmount: number
}
+13 -13
View File
@@ -1,13 +1,13 @@
export * from './Address'
export * from './Encryptable'
export * from './Events'
export * from './Filters'
export * from './Handler'
export * from './Kinds'
export * from './Links'
export * from './List'
export * from './Profile'
export * from './Relay'
export * from './Repository'
export * from './Tags'
export * from './Zaps'
export * from "./Address.js"
export * from "./Encryptable.js"
export * from "./Events.js"
export * from "./Filters.js"
export * from "./Handler.js"
export * from "./Kinds.js"
export * from "./Links.js"
export * from "./List.js"
export * from "./Profile.js"
export * from "./Relay.js"
export * from "./Repository.js"
export * from "./Tags.js"
export * from "./Zaps.js"