Fix encryptable, fix async deriveEventsMapped
This commit is contained in:
@@ -100,7 +100,7 @@ export class ConnectionMeta {
|
||||
if (ok) {
|
||||
this.authStatus = AuthStatus.Ok
|
||||
} else if (notice?.startsWith('auth-required:')) {
|
||||
// Re-enqueue pending reqs when auth challenge is received
|
||||
// Re-enqueue pending events when auth challenge is received
|
||||
const pub = this.pendingPublishes.get(eventId)
|
||||
|
||||
if (pub) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {hexToBytes} from '@noble/hashes/utils'
|
||||
import {Emitter, tryCatch, randomId, sleep, equals, now} from "@welshman/lib"
|
||||
import {createEvent, TrustedEvent, EventTemplate, NOSTR_CONNECT} from "@welshman/util"
|
||||
import {subscribe, publish, Subscription} from "@welshman/net"
|
||||
import {ISigner, decrypt} from '../util'
|
||||
import {ISigner, decrypt, hash, own} from '../util'
|
||||
import {Nip01Signer} from './nip01'
|
||||
|
||||
export type Nip46Handler = {
|
||||
@@ -168,7 +168,8 @@ export class Nip46Signer implements ISigner {
|
||||
|
||||
getPubkey = async () => this.broker.pubkey
|
||||
|
||||
sign = (event: EventTemplate) => this.broker.signEvent(event)
|
||||
sign = (template: EventTemplate) =>
|
||||
this.broker.signEvent(hash(own(this.broker.pubkey, template)))
|
||||
|
||||
nip04 = {
|
||||
encrypt: this.broker.nip04Encrypt,
|
||||
|
||||
+31
-16
@@ -110,18 +110,46 @@ export const deriveEventsMapped = <T>({
|
||||
repository,
|
||||
eventToItem,
|
||||
itemToEvent,
|
||||
throttle = 300,
|
||||
includeDeleted = false,
|
||||
}: {
|
||||
filters: Filter[]
|
||||
repository: Repository,
|
||||
eventToItem: (event: CustomEvent) => T | Promise<T>
|
||||
itemToEvent: (item: T) => CustomEvent
|
||||
throttle?: number
|
||||
includeDeleted?: boolean
|
||||
}) =>
|
||||
custom<T[]>(setter => {
|
||||
let data = repository.query(filters, {includeDeleted}).map(eventToItem).filter(identity) as T[]
|
||||
let data: T[] = []
|
||||
const deferred = new Set()
|
||||
|
||||
const defer = (event: CustomEvent, item: Promise<T>) => {
|
||||
deferred.add(event.id)
|
||||
|
||||
item.then($item => {
|
||||
if (deferred.has(event.id)) {
|
||||
deferred.delete(event.id)
|
||||
data.push($item)
|
||||
setter(data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (const event of repository.query(filters, {includeDeleted})) {
|
||||
const item = eventToItem(event)
|
||||
|
||||
if (!item) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (item instanceof Promise) {
|
||||
defer(event, item)
|
||||
} else {
|
||||
data.push(item)
|
||||
}
|
||||
}
|
||||
|
||||
setter(data)
|
||||
|
||||
const onUpdate = batch(300, (updates: {added: CustomEvent[]; removed: Set<string>}[]) => {
|
||||
@@ -147,18 +175,7 @@ export const deriveEventsMapped = <T>({
|
||||
const item = eventToItem(event)
|
||||
|
||||
if (item instanceof Promise) {
|
||||
// If it's a promise, resolve it before adding it to data
|
||||
deferred.add(event.id)
|
||||
|
||||
// Wait for the promise to resolve. If it hasn't since been removed,
|
||||
// we're clear to add it
|
||||
item.then($item => {
|
||||
if (deferred.has(event.id)) {
|
||||
deferred.delete(event.id)
|
||||
data.push($item)
|
||||
setter(data)
|
||||
}
|
||||
})
|
||||
defer(event, item)
|
||||
} else if (item) {
|
||||
dirty = true
|
||||
data.push(item as T)
|
||||
@@ -186,9 +203,7 @@ export const deriveEventsMapped = <T>({
|
||||
repository.on("update", onUpdate)
|
||||
|
||||
return () => repository.off("update", onUpdate)
|
||||
}, {
|
||||
throttle: 300,
|
||||
})
|
||||
}, {throttle})
|
||||
|
||||
export const deriveEvents = (opts: {repository: Repository, filters: Filter[], includeDeleted?: boolean}) =>
|
||||
deriveEventsMapped<CustomEvent>({
|
||||
|
||||
@@ -2,6 +2,18 @@ import type {EventContent, CustomEvent} from './Events'
|
||||
|
||||
export type Encrypt = (x: string) => Promise<string>
|
||||
|
||||
export type EncryptableParams = {
|
||||
kind: number,
|
||||
tags?: string[][]
|
||||
content?: string
|
||||
}
|
||||
|
||||
export type EncryptableResult = {
|
||||
kind: number,
|
||||
tags: string[][]
|
||||
content: string
|
||||
}
|
||||
|
||||
export type DecryptedEvent = CustomEvent & {
|
||||
plaintext: Partial<EventContent>
|
||||
}
|
||||
@@ -9,10 +21,10 @@ export type DecryptedEvent = CustomEvent & {
|
||||
export const asDecryptedEvent = (event: CustomEvent, plaintext: Partial<EventContent>) =>
|
||||
({...event, plaintext}) as DecryptedEvent
|
||||
|
||||
export class Encryptable<E extends Partial<EventContent>> {
|
||||
constructor(readonly event: E, readonly updates: E) {}
|
||||
export class Encryptable {
|
||||
constructor(readonly event: EncryptableParams, readonly updates: Partial<EventContent>) {}
|
||||
|
||||
async reconcile(encrypt: Encrypt) {
|
||||
async reconcile(encrypt: Encrypt): Promise<EncryptableResult> {
|
||||
const encryptContent = () => {
|
||||
if (!this.updates.content) return null
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const readHandlers = (event: CustomEvent) => {
|
||||
}
|
||||
|
||||
return getKindTagValues(event.tags)
|
||||
.map(kind => ({...normalizedMeta, kind: parseInt(kind), identifier, event})) as Handler[]
|
||||
.map(kind => ({...normalizedMeta, kind, identifier, event})) as Handler[]
|
||||
}
|
||||
|
||||
export const getHandlerKey = (handler: Handler) => `${handler.kind}:${getAddress(handler.event)}`
|
||||
|
||||
+19
-30
@@ -1,6 +1,6 @@
|
||||
import {EventTemplate} from 'nostr-tools'
|
||||
import type {OmitStatics} from '@welshman/lib'
|
||||
import {Fluent, ensurePlural} from '@welshman/lib'
|
||||
import {Fluent, nth, ensurePlural} from '@welshman/lib'
|
||||
import {isRelayUrl, normalizeRelayUrl} from './Relay'
|
||||
import {Address, isContextAddress} from './Address'
|
||||
import {GROUP, COMMUNITY} from './Kinds'
|
||||
@@ -208,46 +208,35 @@ export class Tags extends (Fluent<Tag> as OmitStatics<typeof Fluent<Tag>, 'from'
|
||||
|
||||
// New, simpler version
|
||||
|
||||
export const getTags =
|
||||
(types: string[], testValue?: (v: string) => boolean) =>
|
||||
(tags: string[][]) =>
|
||||
tags.filter(t => types.includes(t[0]) && (!testValue || testValue(t[1] || "")))
|
||||
export const getEventTags = (tags: string[][]) =>
|
||||
tags.filter(t => ["e"].includes(t[0]) && t[1].length === 64)
|
||||
|
||||
export const getTagValues = (types: string[], testValue?: (v: string) => boolean) => {
|
||||
const _getTags = getTags(types, testValue)
|
||||
export const getEventTagValues = (tags: string[][]) => getEventTags(tags).map(nth(1))
|
||||
|
||||
return (tags: string[][]) => _getTags(tags).map(t => t[1] || "")
|
||||
}
|
||||
export const getAddressTags = (tags: string[][]) =>
|
||||
tags.filter(t => ["a"].includes(t[0]) && Address.isAddress(t[1]))
|
||||
|
||||
export const getTagValue = (types: string[], testValue?: (v: string) => boolean) => {
|
||||
const _getTagValues = getTagValues(types, testValue)
|
||||
|
||||
return (tags: string[][]) => _getTagValues(tags)[0]
|
||||
}
|
||||
|
||||
export const getEventTags = getTags(["e"], id => id.length === 64)
|
||||
|
||||
export const getEventTagValues = getTagValues(["e"], id => id.length === 64)
|
||||
|
||||
export const getAddressTags = getTags(["a"], Address.isAddress)
|
||||
|
||||
export const getAddressTagValues = getTagValues(["a"], Address.isAddress)
|
||||
export const getAddressTagValues = (tags: string[][]) => getAddressTags(tags).map(nth(1))
|
||||
|
||||
export const getContextTagValues = (tags: string[][]) =>
|
||||
getAddressTagValues(tags).filter(isContextAddress)
|
||||
|
||||
export const getPubkeyTags = getTags(["p"], pk => pk.length === 64)
|
||||
export const getPubkeyTags = (tags: string[][]) =>
|
||||
tags.filter(t => ["p"].includes(t[0]) && t[1].length === 64)
|
||||
|
||||
export const getPubkeyTagValues = getTagValues(["p"], pk => pk.length === 64)
|
||||
export const getPubkeyTagValues = (tags: string[][]) => getPubkeyTags(tags).map(nth(1))
|
||||
|
||||
export const getRelayTags = getTags(["r", "relay"], isRelayUrl)
|
||||
export const getRelayTags = (tags: string[][]) =>
|
||||
tags.filter(t => ["r", "relay"].includes(t[0]) && isRelayUrl(t[1]))
|
||||
|
||||
export const getRelayTagValues = getTagValues(["r", "relay"], isRelayUrl)
|
||||
export const getRelayTagValues = (tags: string[][]) => getRelayTags(tags).map(nth(1))
|
||||
|
||||
export const getGroupTags = getTags(["h", "group"], h => Boolean(h.match(/^(.+)'(.+)$/)))
|
||||
export const getGroupTags = (tags: string[][]) =>
|
||||
tags.filter(t => ["h", "group"].includes(t[0]) && t[1] && isRelayUrl(t[2]))
|
||||
|
||||
export const getGroupTagValues = getTagValues(["h", "group"], h => Boolean(h.match(/^(.+)'(.+)$/)))
|
||||
export const getGroupTagValues = (tags: string[][]) => getGroupTags(tags).map(nth(1))
|
||||
|
||||
export const getKindTags = getTags(["k"], h => Boolean(h.match(/^\d+$/)))
|
||||
export const getKindTags = (tags: string[][]) =>
|
||||
tags.filter(t => ["k"].includes(t[0]) && t[1].match(/^\d+$/))
|
||||
|
||||
export const getKindTagValues = getTagValues(["k"], h => Boolean(h.match(/^\d+$/)))
|
||||
export const getKindTagValues = (tags: string[][]) => getKindTags(tags).map(t => parseInt(t[1]))
|
||||
|
||||
Reference in New Issue
Block a user