@xyo-network/diviner-payload-indexeddb 2.87.2 → 2.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/Diviner.d.cts +8 -2
- package/dist/browser/Diviner.d.cts.map +1 -1
- package/dist/browser/Diviner.d.mts +8 -2
- package/dist/browser/Diviner.d.mts.map +1 -1
- package/dist/browser/Diviner.d.ts +8 -2
- package/dist/browser/Diviner.d.ts.map +1 -1
- package/dist/browser/index.cjs +66 -50
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.js +66 -50
- package/dist/browser/index.js.map +1 -1
- package/dist/node/Diviner.d.cts +8 -2
- package/dist/node/Diviner.d.cts.map +1 -1
- package/dist/node/Diviner.d.mts +8 -2
- package/dist/node/Diviner.d.mts.map +1 -1
- package/dist/node/Diviner.d.ts +8 -2
- package/dist/node/Diviner.d.ts.map +1 -1
- package/dist/node/index.cjs +66 -50
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +66 -50
- package/dist/node/index.js.map +1 -1
- package/package.json +14 -13
- package/src/Diviner.ts +87 -63
package/src/Diviner.ts
CHANGED
|
@@ -71,58 +71,59 @@ export class IndexedDbPayloadDiviner<
|
|
|
71
71
|
protected override async divineHandler(payloads?: TIn[]): Promise<TOut[]> {
|
|
72
72
|
const query = payloads?.filter(isPayloadDivinerQueryPayload)?.pop()
|
|
73
73
|
if (!query) return []
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
74
|
+
const result = await this.tryUseDb(async (db) => {
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
76
|
+
const { schemas, limit, offset, hash, order, schema: _schema, sources, ...props } = query as unknown as TIn & { sources?: string[] }
|
|
77
|
+
const tx = db.transaction(this.storeName, 'readonly')
|
|
78
|
+
const store = tx.objectStore(this.storeName)
|
|
79
|
+
const results: TOut[] = []
|
|
80
|
+
let parsedOffset = offset ?? 0
|
|
81
|
+
const parsedLimit = limit ?? 10
|
|
82
|
+
assertEx((schemas?.length ?? 1) === 1, 'IndexedDbPayloadDiviner: Only one filter schema supported')
|
|
83
|
+
const filterSchema = schemas?.[0]
|
|
84
|
+
const filter = filterSchema ? { schema: filterSchema, ...props } : { ...props }
|
|
85
|
+
const direction: IDBCursorDirection = order === 'desc' ? 'prev' : 'next'
|
|
86
|
+
const suggestedIndex = this.selectBestIndex(filter, store)
|
|
87
|
+
const keyRangeValue = this.getKeyRangeValue(suggestedIndex, filter)
|
|
88
|
+
const valueFilters: ValueFilter[] = props
|
|
89
|
+
? Object.entries(props)
|
|
90
|
+
.map(([key, value]) => payloadValueFilter(key, value))
|
|
91
|
+
.filter(exists)
|
|
92
|
+
: []
|
|
93
|
+
let cursor = suggestedIndex
|
|
94
|
+
? // Conditionally filter on schemas
|
|
95
|
+
await store.index(suggestedIndex).openCursor(IDBKeyRange.only(keyRangeValue), direction)
|
|
96
|
+
: // Just iterate all records
|
|
97
|
+
await store.openCursor(suggestedIndex, direction)
|
|
98
|
+
|
|
99
|
+
// Skip records until the offset is reached
|
|
100
|
+
while (cursor && parsedOffset > 0) {
|
|
101
|
+
cursor = await cursor.advance(parsedOffset)
|
|
102
|
+
parsedOffset = 0 // Reset offset after skipping
|
|
103
|
+
}
|
|
104
|
+
// Collect results up to the limit
|
|
105
|
+
while (cursor && results.length < parsedLimit) {
|
|
106
|
+
const value = cursor.value
|
|
107
|
+
if (value) {
|
|
108
|
+
// If we're filtering on more than just the schema
|
|
109
|
+
if (valueFilters.length > 0) {
|
|
110
|
+
// Ensure all filters pass
|
|
111
|
+
if (valueFilters.every((filter) => filter(value))) {
|
|
112
|
+
// Then save the value
|
|
113
|
+
results.push(value)
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
// Otherwise just save the value
|
|
114
117
|
results.push(value)
|
|
115
118
|
}
|
|
116
|
-
} else {
|
|
117
|
-
// Otherwise just save the value
|
|
118
|
-
results.push(value)
|
|
119
119
|
}
|
|
120
|
+
cursor = await cursor.continue()
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return
|
|
122
|
+
await tx.done
|
|
123
|
+
// Remove any metadata before returning to the client
|
|
124
|
+
return results.map((payload) => PayloadHasher.jsonPayload(payload))
|
|
125
|
+
})
|
|
126
|
+
return result ?? []
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
protected override async startHandler() {
|
|
@@ -177,27 +178,50 @@ export class IndexedDbPayloadDiviner<
|
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
/**
|
|
180
|
-
* Checks that the desired DB/
|
|
181
|
-
* @returns The initialized DB or undefined if it does not exist
|
|
181
|
+
* Checks that the desired DB/objectStore exists and is initialized to the correct version
|
|
182
|
+
* @returns The initialized DB or undefined if it does not exist in the desired state
|
|
182
183
|
*/
|
|
183
184
|
private async tryGetInitializedDb(): Promise<IDBPDatabase<PayloadStore> | undefined> {
|
|
184
|
-
// If we've already checked and found a successfully initialized
|
|
185
|
-
// db and objectStore, return the cached value
|
|
186
|
-
if (this._db) return this._db
|
|
187
185
|
// Enumerate the DBs
|
|
188
186
|
const dbs = await indexedDB.databases()
|
|
187
|
+
// Check that the DB exists at the desired version
|
|
189
188
|
const dbExists = dbs.some((db) => {
|
|
190
|
-
// Check for the desired name/version
|
|
191
189
|
return db.name === this.dbName && db.version === this.dbVersion
|
|
192
190
|
})
|
|
193
|
-
// If the DB
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
191
|
+
// If the DB exists at the desired version
|
|
192
|
+
if (dbExists) {
|
|
193
|
+
// If the db does exist, open it
|
|
194
|
+
const db = await openDB<PayloadStore>(this.dbName, this.dbVersion)
|
|
195
|
+
// Check that the desired objectStore exists
|
|
196
|
+
const storeExists = db.objectStoreNames.contains(this.storeName)
|
|
197
|
+
// If the correct db/version/objectStore exists
|
|
198
|
+
if (storeExists) {
|
|
199
|
+
return db
|
|
200
|
+
} else {
|
|
201
|
+
// Otherwise close the db so the process that is going to update the
|
|
202
|
+
// db can open it
|
|
203
|
+
db.close()
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Executes a callback with the initialized DB and then closes the db
|
|
210
|
+
* @param callback The method to execute with the initialized DB
|
|
211
|
+
* @returns
|
|
212
|
+
*/
|
|
213
|
+
private async tryUseDb<T>(callback: (db: IDBPDatabase<PayloadStore>) => Promise<T> | T): Promise<T | undefined> {
|
|
214
|
+
// Get the initialized DB
|
|
215
|
+
const db = await this.tryGetInitializedDb()
|
|
216
|
+
if (db) {
|
|
217
|
+
try {
|
|
218
|
+
// Perform the callback
|
|
219
|
+
return await callback(db)
|
|
220
|
+
} finally {
|
|
221
|
+
// Close the DB
|
|
222
|
+
db.close()
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return undefined
|
|
202
226
|
}
|
|
203
227
|
}
|