Add parameter to optimize repository.query, auto-connect when sending, optimize storage adapters
This commit is contained in:
Generated
+21
-4
@@ -1487,6 +1487,12 @@
|
|||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/events": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/hast": {
|
"node_modules/@types/hast": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -2649,6 +2655,15 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/events": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/execa": {
|
"node_modules/execa": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -5783,7 +5798,7 @@
|
|||||||
},
|
},
|
||||||
"packages/editor": {
|
"packages/editor": {
|
||||||
"name": "@welshman/editor",
|
"name": "@welshman/editor",
|
||||||
"version": "0.0.1",
|
"version": "0.0.3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/package": "^2.0.0",
|
"@sveltejs/package": "^2.0.0",
|
||||||
@@ -5802,7 +5817,7 @@
|
|||||||
"@tiptap/pm": "^2.9.1",
|
"@tiptap/pm": "^2.9.1",
|
||||||
"@welshman/lib": "^0.0.36",
|
"@welshman/lib": "^0.0.36",
|
||||||
"@welshman/util": "^0.0.53",
|
"@welshman/util": "^0.0.53",
|
||||||
"nostr-editor": "github:cesardeazevedo/nostr-editor#069fdde",
|
"nostr-editor": "github:cesardeazevedo/nostr-editor#a211491c",
|
||||||
"nostr-tools": "^2.10.4",
|
"nostr-tools": "^2.10.4",
|
||||||
"publint": "^0.2.0",
|
"publint": "^0.2.0",
|
||||||
"svelte": "^4.0.0",
|
"svelte": "^4.0.0",
|
||||||
@@ -5828,7 +5843,7 @@
|
|||||||
"@tiptap/suggestion": "^2.9.1",
|
"@tiptap/suggestion": "^2.9.1",
|
||||||
"@welshman/lib": "^0.0.36",
|
"@welshman/lib": "^0.0.36",
|
||||||
"@welshman/util": "^0.0.53",
|
"@welshman/util": "^0.0.53",
|
||||||
"nostr-editor": "github:cesardeazevedo/nostr-editor#069fdde",
|
"nostr-editor": "github:cesardeazevedo/nostr-editor#a211491c",
|
||||||
"nostr-tools": "^2.8.1",
|
"nostr-tools": "^2.8.1",
|
||||||
"svelte": "^4.0.0",
|
"svelte": "^4.0.0",
|
||||||
"svelte-tiptap": "^1.0.0"
|
"svelte-tiptap": "^1.0.0"
|
||||||
@@ -6352,7 +6367,9 @@
|
|||||||
"version": "0.0.36",
|
"version": "0.0.36",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scure/base": "^1.1.6"
|
"@scure/base": "^1.1.6",
|
||||||
|
"@types/events": "^3.0.3",
|
||||||
|
"events": "^3.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/lib/node_modules/@scure/base": {
|
"packages/lib/node_modules/@scure/base": {
|
||||||
|
|||||||
+44
-30
@@ -2,14 +2,20 @@ import {openDB, deleteDB} from "idb"
|
|||||||
import type {IDBPDatabase} from "idb"
|
import type {IDBPDatabase} from "idb"
|
||||||
import {writable} from "svelte/store"
|
import {writable} from "svelte/store"
|
||||||
import type {Unsubscriber, Writable} from "svelte/store"
|
import type {Unsubscriber, Writable} from "svelte/store"
|
||||||
import {indexBy, throttle, fromPairs} from "@welshman/lib"
|
import {indexBy, equals, throttle, fromPairs} from "@welshman/lib"
|
||||||
import type {TrustedEvent, Repository} from "@welshman/util"
|
import type {TrustedEvent, Repository} from "@welshman/util"
|
||||||
import type {Tracker} from "@welshman/net"
|
import type {Tracker} from "@welshman/net"
|
||||||
import {withGetter, adapter, throttled, custom} from "@welshman/store"
|
import {withGetter, adapter, throttled, custom} from "@welshman/store"
|
||||||
|
|
||||||
export type IndexedDbAdapter = {
|
export type StorageAdapterOptions = {
|
||||||
|
throttle?: number
|
||||||
|
migrate?: (items: any[]) => any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type StorageAdapter = {
|
||||||
keyPath: string
|
keyPath: string
|
||||||
store: Writable<any[]>
|
store: Writable<any[]>
|
||||||
|
options: StorageAdapterOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
export let db: IDBPDatabase
|
export let db: IDBPDatabase
|
||||||
@@ -44,41 +50,45 @@ export const bulkDelete = async (name: string, ids: string[]) => {
|
|||||||
await tx.done
|
await tx.done
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initIndexedDbAdapter = async (name: string, adapter: IndexedDbAdapter) => {
|
export const initIndexedDbAdapter = async (name: string, adapter: StorageAdapter) => {
|
||||||
let prevRecords = await getAll(name)
|
let prevRecords = await getAll(name)
|
||||||
|
|
||||||
adapter.store.set(prevRecords)
|
adapter.store.set(prevRecords)
|
||||||
|
|
||||||
adapter.store.subscribe(async (currentRecords: any[]) => {
|
setTimeout(() => {
|
||||||
if (dead.get()) {
|
adapter.store.subscribe(async (currentRecords: any[]) => {
|
||||||
return
|
if (dead.get()) {
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const currentIds = new Set(currentRecords.map(item => item[adapter.keyPath]))
|
const currentIds = new Set(currentRecords.map(item => item[adapter.keyPath]))
|
||||||
const removedRecords = prevRecords.filter(r => !currentIds.has(r[adapter.keyPath]))
|
const removedRecords = prevRecords.filter(r => !currentIds.has(r[adapter.keyPath]))
|
||||||
|
|
||||||
const prevRecordsById = indexBy(item => item[adapter.keyPath], prevRecords)
|
const prevRecordsById = indexBy(item => item[adapter.keyPath], prevRecords)
|
||||||
const updatedRecords = currentRecords.filter(r => r !== prevRecordsById.get(r[adapter.keyPath]))
|
const updatedRecords = currentRecords.filter(
|
||||||
|
r => !equals(r, prevRecordsById.get(r[adapter.keyPath])),
|
||||||
prevRecords = currentRecords
|
|
||||||
|
|
||||||
if (updatedRecords.length > 0) {
|
|
||||||
await bulkPut(name, updatedRecords)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (removedRecords.length > 0) {
|
|
||||||
await bulkDelete(
|
|
||||||
name,
|
|
||||||
removedRecords.map(item => item[adapter.keyPath]),
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
})
|
prevRecords = currentRecords
|
||||||
|
|
||||||
|
if (updatedRecords.length > 0) {
|
||||||
|
await bulkPut(name, updatedRecords)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removedRecords.length > 0) {
|
||||||
|
await bulkDelete(
|
||||||
|
name,
|
||||||
|
removedRecords.map(item => item[adapter.keyPath]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, adapter.options.throttle || 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initStorage = async (
|
export const initStorage = async (
|
||||||
name: string,
|
name: string,
|
||||||
version: number,
|
version: number,
|
||||||
adapters: Record<string, IndexedDbAdapter>,
|
adapters: Record<string, StorageAdapter>,
|
||||||
) => {
|
) => {
|
||||||
if (!window.indexedDB) return
|
if (!window.indexedDB) return
|
||||||
|
|
||||||
@@ -124,15 +134,19 @@ export const clearStorage = async () => {
|
|||||||
await deleteDB(db.name)
|
await deleteDB(db.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StorageAdapterOptions = {
|
|
||||||
throttle?: number
|
|
||||||
migrate?: (items: any[]) => any[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const migrate = (data: any[], options: StorageAdapterOptions) =>
|
const migrate = (data: any[], options: StorageAdapterOptions) =>
|
||||||
options.migrate ? options.migrate(data) : data
|
options.migrate ? options.migrate(data) : data
|
||||||
|
|
||||||
export const storageAdapters = {
|
export const storageAdapters = {
|
||||||
|
fromCollectionStore: <T>(
|
||||||
|
keyPath: string,
|
||||||
|
store: Writable<T[]>,
|
||||||
|
options: StorageAdapterOptions = {},
|
||||||
|
) => ({
|
||||||
|
options,
|
||||||
|
keyPath,
|
||||||
|
store: throttled(options.throttle || 0, store),
|
||||||
|
}),
|
||||||
fromObjectStore: <T>(
|
fromObjectStore: <T>(
|
||||||
store: Writable<Record<string, T>>,
|
store: Writable<Record<string, T>>,
|
||||||
options: StorageAdapterOptions = {},
|
options: StorageAdapterOptions = {},
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import {
|
|||||||
import {repository} from "./core.js"
|
import {repository} from "./core.js"
|
||||||
import {relaysByUrl} from "./relays.js"
|
import {relaysByUrl} from "./relays.js"
|
||||||
|
|
||||||
|
const query = (filters: Filter[]) =>
|
||||||
|
repository.query(filters, {shouldSort: filters.every(f => f.limit === undefined)})
|
||||||
|
|
||||||
export const hasNegentropy = (url: string) => {
|
export const hasNegentropy = (url: string) => {
|
||||||
const p = relaysByUrl.get().get(url)?.profile
|
const p = relaysByUrl.get().get(url)?.profile
|
||||||
|
|
||||||
@@ -26,7 +29,7 @@ export type AppSyncOpts = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const pull = async ({relays, filters}: AppSyncOpts) => {
|
export const pull = async ({relays, filters}: AppSyncOpts) => {
|
||||||
const events = repository.query(filters)
|
const events = query(filters)
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
relays.map(async relay => {
|
relays.map(async relay => {
|
||||||
@@ -38,7 +41,7 @@ export const pull = async ({relays, filters}: AppSyncOpts) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const push = async ({relays, filters}: AppSyncOpts) => {
|
export const push = async ({relays, filters}: AppSyncOpts) => {
|
||||||
const events = repository.query(filters).filter(isSignedEvent)
|
const events = query(filters).filter(isSignedEvent)
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
relays.map(async relay => {
|
relays.map(async relay => {
|
||||||
@@ -50,7 +53,7 @@ export const push = async ({relays, filters}: AppSyncOpts) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const sync = async ({relays, filters}: AppSyncOpts) => {
|
export const sync = async ({relays, filters}: AppSyncOpts) => {
|
||||||
const events = repository.query(filters).filter(isSignedEvent)
|
const events = query(filters).filter(isSignedEvent)
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
relays.map(async relay => {
|
relays.map(async relay => {
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
"fix": "gts fix"
|
"fix": "gts fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scure/base": "^1.1.6"
|
"@scure/base": "^1.1.6",
|
||||||
|
"@types/events": "^3.0.3",
|
||||||
|
"events": "^3.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export class Connection extends Emitter {
|
|||||||
throw new Error(`Attempted to send message on ${this.status} connection`)
|
throw new Error(`Attempted to send message on ${this.status} connection`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.socket.open()
|
||||||
this.sender.push(message)
|
this.sender.push(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,9 +111,13 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query = (filters: Filter[], {includeDeleted = false} = {}) => {
|
query = (filters: Filter[], {includeDeleted = false, shouldSort = true} = {}) => {
|
||||||
const result: E[][] = []
|
const result: E[][] = []
|
||||||
for (let filter of filters) {
|
for (let filter of filters) {
|
||||||
|
if (filter.limit !== undefined && !shouldSort) {
|
||||||
|
throw new Error("Unable to skip sorting if limit is defined")
|
||||||
|
}
|
||||||
|
|
||||||
let events: E[] = Array.from(this.eventsById.values())
|
let events: E[] = Array.from(this.eventsById.values())
|
||||||
|
|
||||||
if (filter.ids) {
|
if (filter.ids) {
|
||||||
@@ -146,8 +150,10 @@ export class Repository<E extends HashedEvent = TrustedEvent> extends Emitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sorted = shouldSort ? sortBy((e: E) => -e.created_at, events) : events
|
||||||
|
|
||||||
const chunk: E[] = []
|
const chunk: E[] = []
|
||||||
for (const event of sortBy((e: E) => -e.created_at, events)) {
|
for (const event of sorted) {
|
||||||
if (filter.limit && chunk.length >= filter.limit) {
|
if (filter.limit && chunk.length >= filter.limit) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user