Add memoize and batcher, bump versions
This commit is contained in:
Generated
+23
-39
@@ -2169,9 +2169,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nostr-tools": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.7.0.tgz",
|
||||
"integrity": "sha512-jJoL2J1CBiKDxaXZww27nY/Wsuxzx7AULxmGKFce4sskDu1tohNyfnzYQ8BvDyvkstU8kNZUAXPL32tre33uig==",
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.7.2.tgz",
|
||||
"integrity": "sha512-Bq3Ug0SZFtgtL1+0wCnAe8AJtI7yx/00/a2nUug9SkhfOwlKS92Tef12iCK9FdwXw+oFZWMtRnSwcLayQso+xA==",
|
||||
"dependencies": {
|
||||
"@noble/ciphers": "^0.5.1",
|
||||
"@noble/curves": "1.2.0",
|
||||
@@ -3283,12 +3283,12 @@
|
||||
},
|
||||
"packages/dvm": {
|
||||
"name": "@welshman/dvm",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.13",
|
||||
"@welshman/net": "0.0.16",
|
||||
"@welshman/util": "0.0.24",
|
||||
"@welshman/lib": "0.0.14",
|
||||
"@welshman/net": "0.0.18",
|
||||
"@welshman/util": "0.0.25",
|
||||
"nostr-tools": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -3297,29 +3297,11 @@
|
||||
"typescript": "~5.1.6"
|
||||
}
|
||||
},
|
||||
"packages/dvm/node_modules/@scure/base": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz",
|
||||
"integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==",
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"packages/dvm/node_modules/@welshman/net": {
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@welshman/net/-/net-0.0.16.tgz",
|
||||
"integrity": "sha512-9NoNKs3BxMs7biyfhLtQFs0rJP5e8raMMjCXYL0+WaHTSPi1VaKBzXGlsikF713pJ0xm5kigAxa6wquonsWHtg==",
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.12",
|
||||
"@welshman/util": "0.0.23",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"ws": "^8.16.0"
|
||||
}
|
||||
},
|
||||
"packages/dvm/node_modules/@welshman/net/node_modules/@welshman/lib": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@welshman/lib/-/lib-0.0.12.tgz",
|
||||
"integrity": "sha512-865dbPRbXdpZXNkAXz0KDgW0Yq6krC9Pz59cycfe6k75fDO1w4jA30UlW4E1mJuGQycmBtyi9sAkUPP9LG4Srw==",
|
||||
"extraneous": true,
|
||||
"dependencies": {
|
||||
"@scure/base": "^1.1.6",
|
||||
"@types/events": "^3.0.3",
|
||||
@@ -3332,6 +3314,7 @@
|
||||
"version": "0.0.23",
|
||||
"resolved": "https://registry.npmjs.org/@welshman/util/-/util-0.0.23.tgz",
|
||||
"integrity": "sha512-xV9RnPvO3XZ163TD/5ga/vCnLtejMpkIu9JlfiO/iyHJ1DdObq9WkyuHTgVDNxkrPBf74KuoF9gnub9rLMCj/w==",
|
||||
"extraneous": true,
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.12",
|
||||
"nostr-tools": "^2.3.2"
|
||||
@@ -3339,10 +3322,10 @@
|
||||
},
|
||||
"packages/feeds": {
|
||||
"name": "@welshman/feeds",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@welshman/util": "0.0.24"
|
||||
"@welshman/util": "0.0.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gts": "^5.0.1",
|
||||
@@ -3352,7 +3335,7 @@
|
||||
},
|
||||
"packages/lib": {
|
||||
"name": "@welshman/lib",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@scure/base": "^1.1.6",
|
||||
@@ -3376,11 +3359,11 @@
|
||||
},
|
||||
"packages/net": {
|
||||
"name": "@welshman/net",
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.18",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.13",
|
||||
"@welshman/util": "0.0.24",
|
||||
"@welshman/lib": "0.0.14",
|
||||
"@welshman/util": "0.0.25",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"ws": "^8.16.0"
|
||||
},
|
||||
@@ -3392,12 +3375,13 @@
|
||||
},
|
||||
"packages/signer": {
|
||||
"name": "@welshman/signer",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@welshman/lib": "^0.0.13",
|
||||
"@welshman/net": "^0.0.17",
|
||||
"@welshman/util": "^0.0.24"
|
||||
"@welshman/lib": "0.0.14",
|
||||
"@welshman/net": "0.0.18",
|
||||
"@welshman/util": "0.0.25",
|
||||
"nostr-tools": "^2.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gts": "^5.0.1",
|
||||
@@ -3407,7 +3391,7 @@
|
||||
},
|
||||
"packages/store": {
|
||||
"name": "@welshman/store",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"svelte": "^4.2.18"
|
||||
@@ -3420,10 +3404,10 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@welshman/util",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.25",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.13",
|
||||
"@welshman/lib": "0.0.14",
|
||||
"nostr-tools": "^2.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/content",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "A collection of utilities for parsing nostr note content.",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/dvm",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "A collection of utilities for building nostr DVMs.",
|
||||
@@ -31,9 +31,9 @@
|
||||
"typescript": "~5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.13",
|
||||
"@welshman/net": "0.0.16",
|
||||
"@welshman/util": "0.0.24",
|
||||
"@welshman/lib": "0.0.14",
|
||||
"@welshman/net": "0.0.18",
|
||||
"@welshman/util": "0.0.25",
|
||||
"nostr-tools": "^2.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/feeds",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "Utilities for building dynamic nostr feeds.",
|
||||
@@ -31,6 +31,6 @@
|
||||
"typescript": "~5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/util": "0.0.24"
|
||||
"@welshman/util": "0.0.25"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/lib",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "A collection of utilities.",
|
||||
|
||||
@@ -355,6 +355,20 @@ export const once = (f: (...args: any) => void) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const memoize = <T>(f: (...args: any[]) => T) => {
|
||||
let prevArgs: any[]
|
||||
let result: T
|
||||
|
||||
return (...args: any[]) => {
|
||||
if (!equals(prevArgs, args)) {
|
||||
prevArgs = args
|
||||
result = f(...args)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
export const batch = <T>(t: number, f: (xs: T[]) => void) => {
|
||||
const xs: T[] = []
|
||||
const cb = throttle(t, () => xs.length > 0 && f(xs.splice(0)))
|
||||
@@ -365,6 +379,30 @@ export const batch = <T>(t: number, f: (xs: T[]) => void) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const batcher = <T, U>(t: number, execute: (request: T[]) => U[] | Promise<U[]>) => {
|
||||
const queue: {request: T, resolve: (x: U) => void}[] = []
|
||||
|
||||
const _execute = async () => {
|
||||
const items = queue.splice(0)
|
||||
const results = await execute(items.map(item => item.request))
|
||||
|
||||
if (results.length !== items.length) {
|
||||
throw new Error("Execute must return a promise for each request")
|
||||
}
|
||||
|
||||
results.forEach(async (r, i) => items[i].resolve(await r))
|
||||
}
|
||||
|
||||
return (request: T): Promise<U> =>
|
||||
new Promise(resolve => {
|
||||
if (queue.length === 0) {
|
||||
setTimeout(_execute, t)
|
||||
}
|
||||
|
||||
queue.push({request, resolve})
|
||||
})
|
||||
}
|
||||
|
||||
export const addToKey = <T>(m: Record<string, Set<T>>, k: string, v: T) => {
|
||||
const s = m[k] || new Set<T>()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/net",
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.18",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "Utilities for connecting with nostr relays.",
|
||||
@@ -31,8 +31,8 @@
|
||||
"typescript": "~5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.13",
|
||||
"@welshman/util": "0.0.24",
|
||||
"@welshman/lib": "0.0.14",
|
||||
"@welshman/util": "0.0.25",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"ws": "^8.16.0"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import {Emitter} from '@welshman/lib'
|
||||
import type {TrustedEvent} from '@welshman/util'
|
||||
import {Relay, LOCAL_RELAY_URL} from '@welshman/util'
|
||||
import type {Message} from '../Socket'
|
||||
|
||||
export class Local extends Emitter {
|
||||
constructor(readonly relay: Relay) {
|
||||
export class Local<T extends TrustedEvent> extends Emitter {
|
||||
constructor(readonly relay: Relay<T>) {
|
||||
super()
|
||||
|
||||
relay.on('*', this.onMessage)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/signer",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "A nostr signer implemenation supporting several login methods.",
|
||||
@@ -31,8 +31,9 @@
|
||||
"typescript": "~5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "^0.0.13",
|
||||
"@welshman/net": "^0.0.17",
|
||||
"@welshman/util": "^0.0.24"
|
||||
"@welshman/lib": "0.0.14",
|
||||
"@welshman/net": "0.0.18",
|
||||
"@welshman/util": "0.0.25",
|
||||
"nostr-tools": "^2.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export class Nip46Broker extends Emitter {
|
||||
this.#sub = this.subscribe()
|
||||
}
|
||||
|
||||
subscribe() {
|
||||
subscribe = () => {
|
||||
const sub = subscribe({
|
||||
relays: this.handler.relays,
|
||||
filters: [
|
||||
@@ -91,7 +91,7 @@ export class Nip46Broker extends Emitter {
|
||||
return sub
|
||||
}
|
||||
|
||||
async request(method: string, params: string[], admin = false) {
|
||||
request = async (method: string, params: string[], admin = false) => {
|
||||
// nsecbunker has a race condition
|
||||
await this.#ready
|
||||
|
||||
@@ -105,7 +105,7 @@ export class Nip46Broker extends Emitter {
|
||||
publish({event, relays: this.handler.relays})
|
||||
|
||||
this.once(`auth-${id}`, res => {
|
||||
window.open(res.result, "Coracle", "width=600,height=800,popup=yes")
|
||||
window.open(res.error, "Coracle", "width=600,height=800,popup=yes")
|
||||
})
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
@@ -119,7 +119,7 @@ export class Nip46Broker extends Emitter {
|
||||
})
|
||||
}
|
||||
|
||||
createAccount(username: string) {
|
||||
createAccount = (username: string) => {
|
||||
if (!this.handler.domain) {
|
||||
throw new Error("Unable to create an account without a handler domain")
|
||||
}
|
||||
@@ -127,7 +127,7 @@ export class Nip46Broker extends Emitter {
|
||||
return this.request("create_account", [username, this.handler.domain, "", Perms], true)
|
||||
}
|
||||
|
||||
async connect(token = "") {
|
||||
connect = async (token = "") => {
|
||||
if (!this.#connectResult) {
|
||||
const params = [this.pubkey, token, Perms]
|
||||
|
||||
@@ -137,27 +137,27 @@ export class Nip46Broker extends Emitter {
|
||||
return this.#connectResult === "ack"
|
||||
}
|
||||
|
||||
async signEvent(event: EventTemplate) {
|
||||
signEvent = async (event: EventTemplate) => {
|
||||
return JSON.parse(await this.request("sign_event", [JSON.stringify(event)]) as string)
|
||||
}
|
||||
|
||||
nip04Encrypt(pk: string, message: string) {
|
||||
nip04Encrypt = (pk: string, message: string) => {
|
||||
return this.request("nip04_encrypt", [pk, message])
|
||||
}
|
||||
|
||||
nip04Decrypt(pk: string, message: string) {
|
||||
nip04Decrypt = (pk: string, message: string) => {
|
||||
return this.request("nip04_decrypt", [pk, message])
|
||||
}
|
||||
|
||||
nip44Encrypt(pk: string, message: string) {
|
||||
nip44Encrypt = (pk: string, message: string) => {
|
||||
return this.request("nip44_encrypt", [pk, message])
|
||||
}
|
||||
|
||||
nip44Decrypt(pk: string, message: string) {
|
||||
nip44Decrypt = (pk: string, message: string) => {
|
||||
return this.request("nip44_decrypt", [pk, message])
|
||||
}
|
||||
|
||||
teardown() {
|
||||
teardown = () => {
|
||||
this.#closed = true
|
||||
this.#sub?.close()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/store",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "A collection of utilities based on svelte/store for use with welshman",
|
||||
|
||||
+14
-14
@@ -68,8 +68,8 @@ export function withGetter<T>(store: Readable<T> | Writable<T>) {
|
||||
export const throttled = <T>(delay: number, store: Readable<T>) =>
|
||||
custom(set => store.subscribe(throttle(delay, set)))
|
||||
|
||||
export const createEventStore = (repository: Repository) => {
|
||||
let subs: Sub<TrustedEvent[]>[] = []
|
||||
export const createEventStore = <E extends TrustedEvent>(repository: Repository<E>) => {
|
||||
let subs: Sub<E[]>[] = []
|
||||
|
||||
const onUpdate = throttle(300, () => {
|
||||
const $events = repository.dump()
|
||||
@@ -81,8 +81,8 @@ export const createEventStore = (repository: Repository) => {
|
||||
|
||||
return {
|
||||
get: () => repository.dump(),
|
||||
set: (events: TrustedEvent[]) => repository.load(events),
|
||||
subscribe: (f: Sub<TrustedEvent[]>) => {
|
||||
set: (events: E[]) => repository.load(events),
|
||||
subscribe: (f: Sub<E[]>) => {
|
||||
f(repository.dump())
|
||||
|
||||
subs.push(f)
|
||||
@@ -102,7 +102,7 @@ export const createEventStore = (repository: Repository) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const deriveEventsMapped = <T>({
|
||||
export const deriveEventsMapped = <T, E extends TrustedEvent>({
|
||||
filters,
|
||||
repository,
|
||||
eventToItem,
|
||||
@@ -110,9 +110,9 @@ export const deriveEventsMapped = <T>({
|
||||
includeDeleted = false,
|
||||
}: {
|
||||
filters: Filter[]
|
||||
repository: Repository,
|
||||
eventToItem: (event: TrustedEvent) => T
|
||||
itemToEvent: (item: T) => TrustedEvent
|
||||
repository: Repository<E>,
|
||||
eventToItem: (event: E) => T
|
||||
itemToEvent: (item: T) => E
|
||||
includeDeleted?: boolean
|
||||
}) =>
|
||||
custom<T[]>(setter => {
|
||||
@@ -120,7 +120,7 @@ export const deriveEventsMapped = <T>({
|
||||
|
||||
setter(data)
|
||||
|
||||
const onUpdate = batch(300, (updates: {added: TrustedEvent[]; removed: Set<string>}[]) => {
|
||||
const onUpdate = batch(300, (updates: {added: E[]; removed: Set<string>}[]) => {
|
||||
const removed = new Set()
|
||||
const added = new Map()
|
||||
|
||||
@@ -150,7 +150,7 @@ export const deriveEventsMapped = <T>({
|
||||
|
||||
if (!includeDeleted && removed.size > 0) {
|
||||
const [deleted, ok] = partition(
|
||||
(item: T) => getIdAndAddress(itemToEvent(item)).some(id => removed.has(id)),
|
||||
(item: T) => getIdAndAddress(itemToEvent(item)).some((id: string) => removed.has(id)),
|
||||
data,
|
||||
)
|
||||
|
||||
@@ -170,15 +170,15 @@ export const deriveEventsMapped = <T>({
|
||||
return () => repository.off("update", onUpdate)
|
||||
})
|
||||
|
||||
export const deriveEvents = (repository: Repository, opts: {filters: Filter[]; includeDeleted?: boolean}) =>
|
||||
deriveEventsMapped<TrustedEvent>({
|
||||
export const deriveEvents = <E extends TrustedEvent>(repository: Repository<E>, opts: {filters: Filter[]; includeDeleted?: boolean}) =>
|
||||
deriveEventsMapped<E, E>({
|
||||
...opts,
|
||||
repository,
|
||||
eventToItem: identity,
|
||||
itemToEvent: identity,
|
||||
})
|
||||
|
||||
export const deriveEvent = (repository: Repository, idOrAddress: string) =>
|
||||
export const deriveEvent = <E extends TrustedEvent>(repository: Repository<E>, idOrAddress: string) =>
|
||||
derived(
|
||||
deriveEvents(repository, {
|
||||
filters: getIdFilters([idOrAddress]),
|
||||
@@ -187,7 +187,7 @@ export const deriveEvent = (repository: Repository, idOrAddress: string) =>
|
||||
first
|
||||
)
|
||||
|
||||
export const deriveIsDeletedByAddress = (repository: Repository, event: TrustedEvent) =>
|
||||
export const deriveIsDeletedByAddress = <E extends TrustedEvent>(repository: Repository<E>, event: E) =>
|
||||
custom<boolean>(setter => {
|
||||
setter(repository.isDeletedByAddress(event))
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/util",
|
||||
"version": "0.0.24",
|
||||
"version": "0.0.25",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "A collection of nostr-related utilities.",
|
||||
@@ -31,7 +31,7 @@
|
||||
"typescript": "~5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@welshman/lib": "0.0.13",
|
||||
"@welshman/lib": "0.0.14",
|
||||
"nostr-tools": "^2.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,22 +48,22 @@ export const normalizeRelayUrl = (url: string, {allowInsecure = false}: Normaliz
|
||||
return prefix + url
|
||||
}
|
||||
|
||||
export class Relay extends Emitter {
|
||||
export class Relay<T extends TrustedEvent> extends Emitter {
|
||||
subs = new Map<string, Filter[]>()
|
||||
|
||||
constructor(readonly repository: Repository) {
|
||||
constructor(readonly repository: Repository<T>) {
|
||||
super()
|
||||
}
|
||||
|
||||
send(type: string, ...message: any[]) {
|
||||
switch(type) {
|
||||
case 'EVENT': return this.handleEVENT(message as [TrustedEvent])
|
||||
case 'EVENT': return this.handleEVENT(message as [T])
|
||||
case 'CLOSE': return this.handleCLOSE(message as [string])
|
||||
case 'REQ': return this.handleREQ(message as [string, ...Filter[]])
|
||||
}
|
||||
}
|
||||
|
||||
handleEVENT([event]: [TrustedEvent]) {
|
||||
handleEVENT([event]: [T]) {
|
||||
this.repository.publish(event)
|
||||
|
||||
// Callers generally expect async relays
|
||||
|
||||
@@ -10,13 +10,13 @@ export const DAY = 86400
|
||||
|
||||
const getDay = (ts: number) => Math.floor(ts / DAY)
|
||||
|
||||
export class Repository extends Emitter {
|
||||
eventsById = new Map<string, TrustedEvent>()
|
||||
eventsByWrap = new Map<string, TrustedEvent>()
|
||||
eventsByAddress = new Map<string, TrustedEvent>()
|
||||
eventsByTag = new Map<string, TrustedEvent[]>()
|
||||
eventsByDay = new Map<number, TrustedEvent[]>()
|
||||
eventsByAuthor = new Map<string, TrustedEvent[]>()
|
||||
export class Repository<T extends TrustedEvent> extends Emitter {
|
||||
eventsById = new Map<string, T>()
|
||||
eventsByWrap = new Map<string, T>()
|
||||
eventsByAddress = new Map<string, T>()
|
||||
eventsByTag = new Map<string, T[]>()
|
||||
eventsByDay = new Map<number, T[]>()
|
||||
eventsByAuthor = new Map<string, T[]>()
|
||||
deletes = new Map<string, number>()
|
||||
|
||||
// Dump/load/clear
|
||||
@@ -25,7 +25,7 @@ export class Repository extends Emitter {
|
||||
return Array.from(this.eventsById.values())
|
||||
}
|
||||
|
||||
load = async (events: TrustedEvent[], chunkSize = 1000) => {
|
||||
load = async (events: T[], chunkSize = 1000) => {
|
||||
this.clear()
|
||||
|
||||
const added = []
|
||||
@@ -69,7 +69,7 @@ export class Repository extends Emitter {
|
||||
: this.eventsById.get(idOrAddress)
|
||||
}
|
||||
|
||||
hasEvent = (event: TrustedEvent) => {
|
||||
hasEvent = (event: T) => {
|
||||
const duplicate = (
|
||||
this.eventsById.get(event.id) ||
|
||||
this.eventsByAddress.get(getAddress(event))
|
||||
@@ -79,12 +79,12 @@ export class Repository extends Emitter {
|
||||
}
|
||||
|
||||
query = (filters: Filter[], {includeDeleted = false} = {}) => {
|
||||
const result: TrustedEvent[][] = []
|
||||
const result: T[][] = []
|
||||
for (let filter of filters) {
|
||||
let events: TrustedEvent[] = Array.from(this.eventsById.values())
|
||||
let events: T[] = Array.from(this.eventsById.values())
|
||||
|
||||
if (filter.ids) {
|
||||
events = filter.ids!.map(id => this.eventsById.get(id)).filter(identity) as TrustedEvent[]
|
||||
events = filter.ids!.map(id => this.eventsById.get(id)).filter(identity) as T[]
|
||||
filter = omit(['ids'], filter)
|
||||
} else if (filter.authors) {
|
||||
events = uniq(filter.authors!.flatMap(pubkey => this.eventsByAuthor.get(pubkey) || []))
|
||||
@@ -112,8 +112,8 @@ export class Repository extends Emitter {
|
||||
}
|
||||
}
|
||||
|
||||
const chunk: TrustedEvent[] = []
|
||||
for (const event of sortBy((e: TrustedEvent) => -e.created_at, events)) {
|
||||
const chunk: T[] = []
|
||||
for (const event of sortBy((e: T) => -e.created_at, events)) {
|
||||
if (filter.limit && chunk.length >= filter.limit) {
|
||||
break
|
||||
}
|
||||
@@ -133,7 +133,7 @@ export class Repository extends Emitter {
|
||||
return uniq(flatten(result))
|
||||
}
|
||||
|
||||
publish = (event: TrustedEvent, {shouldNotify = true} = {}): boolean => {
|
||||
publish = (event: T, {shouldNotify = true} = {}): boolean => {
|
||||
if (!isTrustedEvent(event)) {
|
||||
throw new Error("Invalid event published to Repository", event)
|
||||
}
|
||||
@@ -203,19 +203,19 @@ export class Repository extends Emitter {
|
||||
return true
|
||||
}
|
||||
|
||||
isDeletedByAddress = (event: TrustedEvent) => (this.deletes.get(getAddress(event)) || 0) > event.created_at
|
||||
isDeletedByAddress = (event: T) => (this.deletes.get(getAddress(event)) || 0) > event.created_at
|
||||
|
||||
isDeletedById = (event: TrustedEvent) => (this.deletes.get(event.id) || 0) > event.created_at
|
||||
isDeletedById = (event: T) => (this.deletes.get(event.id) || 0) > event.created_at
|
||||
|
||||
isDeleted = (event: TrustedEvent) => this.isDeletedByAddress(event) || this.isDeletedById(event)
|
||||
isDeleted = (event: T) => this.isDeletedByAddress(event) || this.isDeletedById(event)
|
||||
|
||||
// Utilities
|
||||
|
||||
_updateIndex<K>(m: Map<K, TrustedEvent[]>, k: K, e: TrustedEvent, duplicate?: TrustedEvent) {
|
||||
_updateIndex<K>(m: Map<K, T[]>, k: K, e: T, duplicate?: T) {
|
||||
let a = m.get(k) || []
|
||||
|
||||
if (duplicate) {
|
||||
a = a.filter((x: TrustedEvent) => x !== duplicate)
|
||||
a = a.filter((x: T) => x !== duplicate)
|
||||
}
|
||||
|
||||
a.push(e)
|
||||
|
||||
Reference in New Issue
Block a user