gs-idb-pro 0.1.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/README.md +342 -0
- package/lib/index.cjs +1 -0
- package/lib/index.d.ts +1118 -0
- package/lib/index.js +1 -0
- package/lib/index.web.js +1 -0
- package/package.json +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# gs-idb-pro
|
|
2
|
+
<details>
|
|
3
|
+
<summary>中文</summary>
|
|
4
|
+
|
|
5
|
+
> 一款对于浏览器indexedDB的全功能封装
|
|
6
|
+
> 包含: 查询、游标、分页、事务、关联、数据库版本处理、配置管理……等功能
|
|
7
|
+
|
|
8
|
+
## 安装
|
|
9
|
+
```shell
|
|
10
|
+
npx yarn gs-idb-pro
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 使用
|
|
14
|
+
### 1. 基础使用
|
|
15
|
+
#### 1. 基本CRUD
|
|
16
|
+
```ts
|
|
17
|
+
import {dbStore} from 'gs-idb-pro'
|
|
18
|
+
|
|
19
|
+
//在默认数据库中创建名为`user`的`IDBObjectStore`,默认`keyPath`为`id`,`autoIncrement`为`true`
|
|
20
|
+
const userStore = dbStore('user')
|
|
21
|
+
// 在 `userStore` 中创建名为`name`的索引
|
|
22
|
+
const nameIndex = userStore.index('name');
|
|
23
|
+
// 在 `userStore` 中创建名为`age`的索引
|
|
24
|
+
const ageIndex = userStore.index('age');
|
|
25
|
+
|
|
26
|
+
// 通过 `add` 方法向 `userStore` 中添加数据,默认会记录添加时间与修改时间(可配置)
|
|
27
|
+
await userStore.add({name: '张三', age: 18, id: 1})
|
|
28
|
+
await userStore.add({name: '李四', age: 19, id: 2})
|
|
29
|
+
await userStore.add({name: '王五', age: 20, id: 3})
|
|
30
|
+
await userStore.add({name: '赵六', age: 20, id: 4})
|
|
31
|
+
|
|
32
|
+
// 通过 `all` 方法获取 `userStore` 中的所有数据
|
|
33
|
+
console.log(await userStore.all())
|
|
34
|
+
|
|
35
|
+
// 通过 `get` 方法获取 `userStore` 中 `id` 为 1 的数据
|
|
36
|
+
console.log(await userStore.get(1))
|
|
37
|
+
|
|
38
|
+
// 通过 `get` 方法获取 `userStore` 中 `name`索引值为 '张三' 的数据
|
|
39
|
+
console.log(await nameIndex.get('张三'))
|
|
40
|
+
|
|
41
|
+
// 通过 `get` 方法获取 `age`索引值为 20 的数据
|
|
42
|
+
console.log(await ageIndex.get(20))
|
|
43
|
+
|
|
44
|
+
// 通过 `delete` 方法删除 `userStore` 中 `id` 为 1 的数据
|
|
45
|
+
await userStore.delete(1)
|
|
46
|
+
|
|
47
|
+
// 获取分页数据第一页(添加时间降序,前2条)
|
|
48
|
+
const page1 = await userStore.page({size:2},1)
|
|
49
|
+
console.log(page1)
|
|
50
|
+
|
|
51
|
+
// 获取下一页分页数据(最后1条数据)
|
|
52
|
+
console.log(await userStore.nextPage(page1.info))
|
|
53
|
+
```
|
|
54
|
+
#### 2. 保存配置信息
|
|
55
|
+
> 将某一个`IDBObjectStore`当作一个键值对数据库使用
|
|
56
|
+
> 可用于保存常见配置信息
|
|
57
|
+
> 特别是文件句柄(`FileSystemHandle`)在目前的浏览器环境中的只能使用`indexedDB`保存
|
|
58
|
+
```ts
|
|
59
|
+
import {dbMap} from 'gs-idb-pro'
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 创建一个无`keyPath`的`IDBObjectStore`
|
|
63
|
+
*/
|
|
64
|
+
const settings = dbMap('settings');
|
|
65
|
+
|
|
66
|
+
await new Promise(( (resolve, reject)=> {
|
|
67
|
+
const btn = document.createElement('button');
|
|
68
|
+
btn.innerText = 'Click me to test.'
|
|
69
|
+
document.body.append(btn)
|
|
70
|
+
btn.onclick = async ()=>{
|
|
71
|
+
try{
|
|
72
|
+
// 设置 工作目录
|
|
73
|
+
await settings.set('workDir', await showDirectoryPicker());
|
|
74
|
+
resolve();
|
|
75
|
+
} catch (e) {
|
|
76
|
+
reject(e)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}))
|
|
80
|
+
|
|
81
|
+
// 读取 工作目录 的设置
|
|
82
|
+
console.log(await settings.get('workDir'))
|
|
83
|
+
```
|
|
84
|
+
#### 3. 事务与批处理
|
|
85
|
+
```ts
|
|
86
|
+
// 批量读取,过程中不会重复关闭打开数据库
|
|
87
|
+
const result = await userStore.batchRead(async (openedStore) => {
|
|
88
|
+
return [
|
|
89
|
+
await openedStore.get(1),
|
|
90
|
+
await openedStore.filter({lte: 10, gt: 3})
|
|
91
|
+
]
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
// 多次读写操作, 如果中途出错,将回滚所有写入
|
|
95
|
+
await userStore.batchWrite(async (openedStore)=>{
|
|
96
|
+
// 代码
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
#### 4. 关联
|
|
100
|
+
```ts
|
|
101
|
+
import {asyncMap } from 'gs-base'
|
|
102
|
+
import {dbMap} from 'gs-idb-pro'
|
|
103
|
+
|
|
104
|
+
//创建 `user` 与 `role` 的关联存储
|
|
105
|
+
const stores = dbStores(['user','role'])
|
|
106
|
+
|
|
107
|
+
// 执行关联读取
|
|
108
|
+
const result = await stores.read((userStore, roleStore) => {
|
|
109
|
+
return asyncMap(userStore.filter(), async (user) => ({...user, role: await roleStore.get(user.roleId)}))
|
|
110
|
+
})
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 2. 更多
|
|
114
|
+
#### 1. Schema定义
|
|
115
|
+
```ts
|
|
116
|
+
import {IDbPro} from 'gs-idb-pro'
|
|
117
|
+
|
|
118
|
+
//配置默认数据库名称
|
|
119
|
+
IDbPro.defaultDb.schema.name = 'db-name'
|
|
120
|
+
|
|
121
|
+
//配置默认数据库版本
|
|
122
|
+
IDbPro.defaultDb.schema.version = 2
|
|
123
|
+
|
|
124
|
+
//配置将来创建`IDBObjectStore`时的默认值
|
|
125
|
+
IDbPro.defaultDb.schema.storeTemplate = {
|
|
126
|
+
keyPath: 'id',
|
|
127
|
+
autoIncrement: true,
|
|
128
|
+
addedTimeField: false,
|
|
129
|
+
updatedTimeField: 'updated_at',
|
|
130
|
+
softDeletedField: true
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 创建带默认值、无`keyPath`的`IDBObjectStore`
|
|
134
|
+
dbMap('map', [
|
|
135
|
+
['v1', 'k1'],
|
|
136
|
+
['v2', 'k2'],
|
|
137
|
+
// ……
|
|
138
|
+
])
|
|
139
|
+
|
|
140
|
+
// 详细创建多索引和默认值的`IDBObjectStore`
|
|
141
|
+
dbStore({
|
|
142
|
+
name: 'user',
|
|
143
|
+
indexSchemas: [
|
|
144
|
+
{name: 'name_age', keyPath: ['name', 'age']},
|
|
145
|
+
{name: 'tags', keyPath: 'tags', multiEntry: true},
|
|
146
|
+
],
|
|
147
|
+
defaultData: [
|
|
148
|
+
{name: '张三', age: 18, tags: ['年轻', '贪玩']},
|
|
149
|
+
]
|
|
150
|
+
}, {name: 'name', unique: true})
|
|
151
|
+
|
|
152
|
+
// 初始化 Schema (赋予默认值和转换详细信息,仅用于调试配置信息,非调试时不需要手工调用 )
|
|
153
|
+
IDbPro.defaultDb.initSchema();
|
|
154
|
+
|
|
155
|
+
//向控制台输出当前配置结果
|
|
156
|
+
IDbPro.defaultDb.traceSchema()
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
#### 2. 多数据库
|
|
161
|
+
> 由于浏览器限制,不能同时打开多个数据库
|
|
162
|
+
> 所以没有特殊情况不建议创建多个数据库
|
|
163
|
+
```ts
|
|
164
|
+
const db1 = new IDbPro('db1')
|
|
165
|
+
const db2 = new IDbPro({name:'db2',version:2})
|
|
166
|
+
db1.store('db1-store-1')
|
|
167
|
+
db1.store('db1-store-2')
|
|
168
|
+
db2.store('db2-store-1')
|
|
169
|
+
db2.store('db2-store-2')
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
</details>
|
|
173
|
+
|
|
174
|
+
<details>
|
|
175
|
+
<summary>English</summary>
|
|
176
|
+
|
|
177
|
+
> A full-featured wrapper for browser IndexedDB
|
|
178
|
+
> Includes: query, cursor, pagination, transactions, relations, DB version handling, config management, etc.
|
|
179
|
+
|
|
180
|
+
## Installation
|
|
181
|
+
```shell
|
|
182
|
+
npx yarn gs-idb-pro
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Usage
|
|
186
|
+
### 1. Basic Usage
|
|
187
|
+
#### 1. Basic CRUD
|
|
188
|
+
```ts
|
|
189
|
+
import {dbStore} from 'gs-idb-pro'
|
|
190
|
+
|
|
191
|
+
// Create an `IDBObjectStore` named `user` in the default DB, with `keyPath`=`id` and `autoIncrement`=true
|
|
192
|
+
const userStore = dbStore('user')
|
|
193
|
+
// Create an index named `name` in `userStore`
|
|
194
|
+
const nameIndex = userStore.index('name');
|
|
195
|
+
// Create an index named `age` in `userStore`
|
|
196
|
+
const ageIndex = userStore.index('age');
|
|
197
|
+
|
|
198
|
+
// Add data using `add` (creation & update timestamps are added by default, configurable)
|
|
199
|
+
await userStore.add({name: 'John Smith', age: 18, id: 1})
|
|
200
|
+
await userStore.add({name: 'Alice Brown', age: 19, id: 2})
|
|
201
|
+
await userStore.add({name: 'Michael Lee', age: 20, id: 3})
|
|
202
|
+
await userStore.add({name: 'Sarah Johnson', age: 20, id: 4})
|
|
203
|
+
|
|
204
|
+
// Get all data from `userStore`
|
|
205
|
+
console.log(await userStore.all())
|
|
206
|
+
|
|
207
|
+
// Get data with `id` = 1
|
|
208
|
+
console.log(await userStore.get(1))
|
|
209
|
+
|
|
210
|
+
// Get data by index `name` = 'John Smith'
|
|
211
|
+
console.log(await nameIndex.get('John Smith'))
|
|
212
|
+
|
|
213
|
+
// Get data by index `age` = 20
|
|
214
|
+
console.log(await ageIndex.get(20))
|
|
215
|
+
|
|
216
|
+
// Delete data with `id` = 1
|
|
217
|
+
await userStore.delete(1)
|
|
218
|
+
|
|
219
|
+
// Get first page (size 2, sorted by added time desc)
|
|
220
|
+
const page1 = await userStore.page({size:2},1)
|
|
221
|
+
console.log(page1)
|
|
222
|
+
|
|
223
|
+
// Get next page (remaining data)
|
|
224
|
+
console.log(await userStore.nextPage(page1.info))
|
|
225
|
+
```
|
|
226
|
+
#### 2. Storing Config Data
|
|
227
|
+
> Use an IDBObjectStore as a simple key-value DB
|
|
228
|
+
> Suitable for storing common configuration
|
|
229
|
+
> Especially FileSystemHandle must be stored in indexedDB in browsers
|
|
230
|
+
```ts
|
|
231
|
+
import {dbMap} from 'gs-idb-pro'
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Create an `IDBObjectStore` without `keyPath`
|
|
235
|
+
*/
|
|
236
|
+
const settings = dbMap('settings');
|
|
237
|
+
|
|
238
|
+
await new Promise((resolve, reject)=> {
|
|
239
|
+
const btn = document.createElement('button');
|
|
240
|
+
btn.innerText = 'Click me to test.'
|
|
241
|
+
document.body.append(btn)
|
|
242
|
+
btn.onclick = async ()=>{
|
|
243
|
+
try{
|
|
244
|
+
// Set working directory
|
|
245
|
+
await settings.set('workDir', await showDirectoryPicker());
|
|
246
|
+
resolve();
|
|
247
|
+
} catch (e) {
|
|
248
|
+
reject(e)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
// Read working directory setting
|
|
254
|
+
console.log(await settings.get('workDir'))
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
#### 3. Transactions & Batch
|
|
258
|
+
```ts
|
|
259
|
+
// Batch read, DB won't reopen repeatedly
|
|
260
|
+
const result = await userStore.batchRead(async (openedStore) => {
|
|
261
|
+
return [
|
|
262
|
+
await openedStore.get(1),
|
|
263
|
+
await openedStore.filter({lte: 10, gt: 3})
|
|
264
|
+
]
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
// Multiple read/write in a single transaction; all writes will rollback if error occurs
|
|
268
|
+
await userStore.batchWrite(async (openedStore)=>{
|
|
269
|
+
// code
|
|
270
|
+
})
|
|
271
|
+
```
|
|
272
|
+
#### 4. Relations
|
|
273
|
+
```ts
|
|
274
|
+
import {asyncMap } from 'gs-base'
|
|
275
|
+
import {dbMap, dbStores} from 'gs-idb-pro'
|
|
276
|
+
|
|
277
|
+
// Create related stores `user` and `role`
|
|
278
|
+
const stores = dbStores(['user','role'])
|
|
279
|
+
|
|
280
|
+
// Perform relational read
|
|
281
|
+
const result = await stores.read((userStore, roleStore) => {
|
|
282
|
+
return asyncMap(userStore.filter(), async (user) => ({...user, role: await roleStore.get(user.roleId)}))
|
|
283
|
+
})
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 2. Advanced
|
|
287
|
+
#### 1. Schema Definition
|
|
288
|
+
```ts
|
|
289
|
+
import {IDbPro} from 'gs-idb-pro'
|
|
290
|
+
|
|
291
|
+
// Set default DB name
|
|
292
|
+
IDbPro.defaultDb.schema.name = 'db-name'
|
|
293
|
+
|
|
294
|
+
// Set default DB version
|
|
295
|
+
IDbPro.defaultDb.schema.version = 2
|
|
296
|
+
|
|
297
|
+
// Default schema template for future stores
|
|
298
|
+
IDbPro.defaultDb.schema.storeTemplate = {
|
|
299
|
+
keyPath: 'id',
|
|
300
|
+
autoIncrement: true,
|
|
301
|
+
addedTimeField: false,
|
|
302
|
+
updatedTimeField: 'updated_at',
|
|
303
|
+
softDeletedField: true
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Create a key-value style store with defaults
|
|
307
|
+
dbMap('map', [
|
|
308
|
+
['v1', 'k1'],
|
|
309
|
+
['v2', 'k2'],
|
|
310
|
+
// ...
|
|
311
|
+
])
|
|
312
|
+
|
|
313
|
+
// Create store with multiple indexes and default data
|
|
314
|
+
dbStore({
|
|
315
|
+
name: 'user',
|
|
316
|
+
indexSchemas: [
|
|
317
|
+
{name: 'name_age', keyPath: ['name', 'age']},
|
|
318
|
+
{name: 'tags', keyPath: 'tags', multiEntry: true},
|
|
319
|
+
],
|
|
320
|
+
defaultData: [
|
|
321
|
+
{name: 'John Smith', age: 18, tags: ['young', 'playful']},
|
|
322
|
+
]
|
|
323
|
+
}, {name: 'name', unique: true})
|
|
324
|
+
|
|
325
|
+
// Initialize schema (for debugging, not required normally)
|
|
326
|
+
IDbPro.defaultDb.initSchema();
|
|
327
|
+
|
|
328
|
+
// Trace schema in console
|
|
329
|
+
IDbPro.defaultDb.traceSchema()
|
|
330
|
+
```
|
|
331
|
+
#### 2. Multiple Databases
|
|
332
|
+
> Due to browser limits, you can't open multiple DBs at once.
|
|
333
|
+
> Avoid multiple DBs unless necessary.
|
|
334
|
+
```ts
|
|
335
|
+
const db1 = new IDbPro('db1')
|
|
336
|
+
const db2 = new IDbPro({name:'db2',version:2})
|
|
337
|
+
db1.store('db1-store-1')
|
|
338
|
+
db1.store('db1-store-2')
|
|
339
|
+
db2.store('db2-store-1')
|
|
340
|
+
db2.store('db2-store-2')
|
|
341
|
+
```
|
|
342
|
+
</details>
|
package/lib/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("gs-base"),t=require("gs-idb-basic");const r=Symbol("save"),a=Symbol("delete"),n=Object.freeze({key:({primaryKey:e})=>({value:e}),value:({value:e})=>({value:e}),keyValue:({primaryKey:e,value:t})=>({value:[e,t]})});function s(e){if(Array.isArray(e))return{key:e[1],value:e[0]};if("value"in e){const{key:t,value:r}=e;return{key:t,value:r}}throw new Error(`not include value in invalid DBRecord:${JSON.stringify(e)}`)}const i=Symbol("break"),o=Symbol("finished"),c=Symbol("continue"),u=Symbol("continue key"),d=Symbol("next key"),h=Symbol("continue primary key"),l=Symbol("next primary key");function m(e){return e instanceof IDBObjectStore||e instanceof IDBIndex}const f=Object.freeze({keyPath:"id",autoIncrement:!0,addedTimeField:!0,updatedTimeField:!0}),y=Object.freeze({addedTimeField:"added_at",softDeletedField:"deleted",updatedCountField:"updated_count",updatedTimeField:"updated_at"}),p=e=>e instanceof Date?e.getTime():e;function g(e){if(t.isDbQueryOrNull(e))return e;const r=e;if("lt"in r&&"gt"in r){if(p(r.gt)>p(r.lt))throw new Error(`Invalid IDBRange: gt (${r.gt}) cannot be greater than lt (${r.lt})`);return IDBKeyRange.bound(r.gt,r.lt,!0,!0)}if("lt"in r&&"gte"in r){if(p(r.gte)>p(r.lt))throw new Error(`Invalid IDBRange: gte (${r.gte}) cannot be greater than lt (${r.lt})`);return IDBKeyRange.bound(r.gte,r.lt,!1,!0)}if("lte"in r&&"gt"in r){if(p(r.gt)>p(r.lte))throw new Error(`Invalid IDBRange: gt (${r.gt}) cannot be greater than lte (${r.lte})`);return IDBKeyRange.bound(r.gt,r.lte,!0,!1)}if("lte"in r&&"gte"in r){if(p(r.gte)>p(r.lte))throw new Error(`Invalid IDBRange: gte (${r.gte}) cannot be greater than lte (${r.lte})`);return IDBKeyRange.bound(r.gte,r.lte,!1,!1)}return"lt"in r?IDBKeyRange.upperBound(r.lt,!0):"lte"in r?IDBKeyRange.upperBound(r.lte,!1):"gt"in r?IDBKeyRange.lowerBound(r.gt,!0):"gte"in r?IDBKeyRange.lowerBound(r.gte,!1):void 0}function b(e){return null!=g(e)}async function S(e,r,a){const{query:n,direction:s="prev",preSkip:i,startKey:o,startPrimaryKey:c}=r,u=e.openCursor(g(n),s);return i&&(await t.requestDbResult(u)).advance(i),o&&(c?(await t.requestDbResult(u)).continuePrimaryKey(o,c):(await t.requestDbResult(u)).continue(o)),u}function w(t,r,a){return Array.isArray(t)?r=>e.copyFields({},r,t):e.isFunction(t)?t:r?e=>e:a?(e,t)=>[e,t]:(e,t)=>({key:e,value:t})}class x{idbPro;target;#e;constructor(e,t){this.idbPro=t,this.#e=e.storeSchema,this.target=e.target,m(e.target)&&(this.tx=this.#t)}get storeName(){return this.nativeStore?.name||this.target.store}get storeSchema(){if(this.#e)return this.#e;const e=this.idbPro.getStoreSchema(this.storeName);return Object.isFrozen(e)&&(this.#e=e),e}get factory(){return this.idbPro.factory}get nativeStore(){const{target:e}=this;return e instanceof IDBObjectStore?e:e instanceof IDBIndex?e.objectStore:void 0}get keyPath(){const{target:e}=this;if(m(e))return e.keyPath;const{storeSchema:t}=this,{index:r}=e;return r?t.indexSchemas.find(e=>e.name===r)?.keyPath:t.keyPath}async forEach(t,r){return t=e.isFunction(t)?{fn:t}:t,r?this.cursorResult(t,!1):this.cursorVoid(t,!1)}async tx(e,t,r){let{target:a}=this;const{store:n,index:s}=a,i=await this.idbPro.openNativeDb();let o,c;try{o=i.transaction(n,!0===e?"readwrite":"readonly"),a=c=o.objectStore(n),s&&(a=a.index(s))}catch(e){throw i.close(),e}if(!t)return Object.freeze({db:i,tx:o,nativeStore:c,target:a});try{if(!0===e){const e=await t(a,c);return o.commit(),e}return t(a)}catch(e){throw!1!==r&&o.abort(),e}finally{i.close()}}openCursor(e,t){return this.tx(t,t=>new Promise(async(r,a)=>{const{fn:n}=e,s=await S(t,e);s.onsuccess=async()=>{s.result?!1===await n(s.result)&&r():r()},s.onerror=()=>a(s.error)}))}cursorVoid({query:t,direction:n,preSkip:s,startKey:o,startPrimaryKey:c,fn:d},l){let m=0;return this.openCursor({query:t,direction:n,preSkip:s,startKey:o,startPrimaryKey:c,fn:async t=>{const{value:n,primaryKey:s}=t,o=await d(n,s,m++),{control:c,key:f,primaryKey:y,modify:p,value:g}=e.isObject(o)?o:{control:o};switch(l&&(p===r?t.update(g||n):p===a&&t.delete()),c){case i:return!1;case u:t.continue(f);break;case h:t.continuePrimaryKey(f,y);break;default:t.continue()}}},!0)}async cursorResult({query:e,direction:t,preSkip:n,startKey:s,startPrimaryKey:c,fn:m,mapper:f},y){const{keyPath:p,defaultGetMapper:g}=this.storeSchema,b=w(f||g,p),S=[];let x=0;return await this.openCursor({query:e,direction:t,preSkip:n,startKey:s,startPrimaryKey:c,fn:async e=>{const{value:t,primaryKey:n}=e,{control:s,value:c,key:f,primaryKey:p,modify:g}=await(m?.(t,n,x,S))||{};switch(y&&(g===r?e.update(c||t):g===a&&e.delete()),(!s||s===o||s===d||s===l)&&S.push(b(c||t,p||n,x)),s){case i:case o:return!1;case d:case u:e.continue(f);break;case l:case h:e.continuePrimaryKey(f,p);break;default:e.continue()}x++}},y),S}#t(e,t){const{target:r}=this,a=r instanceof IDBObjectStore?r:r.objectStore;return t?t(r,a):Object.freeze({nativeStore:a,target:r})}}class D{idbPro;schemas;#r;constructor(e,t){this.idbPro=e,this.schemas=t}get storeNames(){return this.#r||(this.#r=Array.from(new Set(this.schemas.map(e=>e.target.store))))}read(e){return this.tx("newReader",e)}write(e,t=!0){return this.tx("newWriter",e,!0,t)}export(){return this.tx("newReader",async(...e)=>{const t={};for(const r of e)t[r.storeName]=await r.export();return t})}import(e,t,r){return r||(r="addOrChangeMany"),this.tx("newWriter",async(...a)=>{const n={};a=Array.from(new Map(a.map(e=>[e.storeName,e.asStore(!0)])).values());for(const s of a){const{storeName:a}=s,i=e[a];i&&(n[a]=await s[r](i,t))}if(t)return n},!0)}async tx(e,t,r,a){const{idbPro:n,schemas:s}=this,{factory:i}=n.schema,o=await n.openNativeDb();try{const c=o.transaction(this.storeNames,r?"readwrite":"readonly");try{const a=s.map(({storeSchema:t,target:r})=>{let a=c.objectStore(r.store);return r.index&&(a=a.index(r.index)),i[e]({storeSchema:t,target:a},n)});if(r){const e=await t(...a);return c.commit(),e}return await t(...a)}catch(e){throw!1!==a&&c.abort(),e}}finally{o.close()}}}class v extends x{direction;query;writable;parser;endsWithNull;preSkip;startKey;startPrimaryKey;constructor(t,r,a){if(super(t,r),!a)return;const{parser:s}=a;this.direction=a.direction,this.query=a.query,this.writable=!!a.writable,this.endsWithNull=!!a.endsWithNull,this.preSkip=a.preSkip,this.startKey=a.startKey,this.startPrimaryKey=a.startPrimaryKey,s&&(this.parser=e.isFunction(s)?s:n[s])}async*[Symbol.asyncIterator](){const{parser:e,writable:r,endsWithNull:a}=this,{db:n,tx:s,target:o}=await this.tx(r);try{const n=await S(o,this);let c;if(e)for(;c=await t.requestDbResult(n);){const{control:t,value:r}=await e(c);if(t||(yield r),t===i)break;c.continue()}else{let e=!1;const r=()=>{e=!0};for(;!e&&(c=await t.requestDbResult(n));)yield{cursor:c,end:r}}r&&s?.commit(),a&&!c&&(yield null)}finally{n?.close()}}}function k(t,r,a,n){const s=e.isObject(t)?t:{};return e.isFunction(t)?s.fn=t:b(t)&&(s.query=t),e.isFunction(r)?s.fn=r:r&&(s.direction=r),a&&(s.direction=a),n?s.limit=n:s.limit||(s.limit=1e3),s.maxEmptyChecks||(s.maxEmptyChecks=2e4),s}async function P(t,r,a){r.size||(r.size=100),r.nextSkip||(r.nextSkip=0);const{query:n,direction:s,total:i,maxEmptyChecks:o,fn:c}=r;return await t.batchRead(async t=>(i||(r.total=await t.count({query:n,direction:s,maxEmptyChecks:o,fn:c}),r.pages=Math.ceil(r.total/r.size)),r.total<1?{info:e.deepFreeze(r),rows:[]}:c?await async function(e,t,r){t.maxEmptyChecks||(t.maxEmptyChecks=2e4);const{page:a,query:n,direction:s,nextSkip:i}=t,{keyPath:o}=e.storeSchema;return 1===a?await q(e,await S(e.target,{query:n,direction:s}),t,o):r&&i&&a-r.page===1?await q(e,await S(e.target,{query:n,direction:s,preSkip:i}),t,o):await q(e,await S(e.target,{query:n,direction:s}),t,o,!0)}(t,r,a):await async function(t,r){const{keyPath:a}=t.storeSchema,{page:n,query:s,direction:i,size:o,mapper:c}=r,u=(n-1)*o,d=await t.filter({query:s,preSkip:u,direction:i,limit:o,mapper:w(c,a,!0)});return r.nextSkip=u+d.length,{info:e.deepFreeze(r),rows:d}}(t,r)))}async function q({storeSchema:{defaultGetMapper:t}},r,a,n,s){const{page:i,size:o,total:c,maxEmptyChecks:u,fn:d}=a,h=w(a.mapper||t,n,!0),l=[],m=(i-1)*a.size;if(m>=c)return{info:e.deepFreeze(a),rows:[]};let f=0;return await new Promise(async(e,t)=>{let a=0,n=0;const i=async()=>{const{result:t}=r;if(!t)return e();let{value:n,primaryKey:s}=t;if(await d(n,s,f)?(a=0,l.push(h(n,s,f))):a++,l.length>=o||a>=u)return e();f++,t.continue()};r.onerror=()=>t(r.error),r.onsuccess=s?async()=>{const{result:t}=r;if(!t)return e();let{value:s,primaryKey:o}=t;if(await d(s,o,f)?(a=0,n++):a++,n>=m||a>=u)return f=a=0,r.onsuccess=i,void t.continue();t.continue(),f++}:i}),f&&(a.nextSkip+=f+1),{info:e.deepFreeze(a),rows:l}}class O extends x{all(r,a){const n={};return e.isNumber(a)&&(n.limit=a),b(r)?n.query=r:e.isObject(r)&&Object.assign(n,r),this.tx(!1,e=>t.requestDbResult(e.getAll(g(n.query),n.limit||1e3)))}async count(e,r,a){const n=k(e,r,a),{query:s,direction:i,fn:o}=n;if(!o)return await this.tx(!1,e=>t.requestDbResult(e.count(g(s))));const{maxEmptyChecks:c}=n,u=o;let d=0,h=0,l=0;return await this.openCursor({query:s,direction:i,fn:e=>{if(u(e.value,e.primaryKey,l++))d++,h=0;else if(++h>=c)return!1;e.continue()}}),d}get(e){return this.tx(!1,r=>t.requestDbResult(r.get(g(e))))}getMany(t,r){return this.batchRead(async a=>{const n=await e.asyncMap(t,e=>a.get(e));return r?n.filter(e=>e):n})}getRange(e,t){return this.forEach({query:e,direction:t},!0)}async getRangeMany(t,r,a){return(await this.batchRead(a=>e.asyncMap(t,e=>a.getRange(e,r)))).flat()}index(e,t){let{target:r}=this;return r instanceof IDBIndex&&(r=r.objectStore),r instanceof IDBObjectStore?(r=r.index(e),this.createOperator(r,t)):this.idbPro.store(r.store,e)}asStore(e){let{target:t}=this;if(t instanceof IDBObjectStore)return this;if(t instanceof IDBIndex)t=t.objectStore;else{if(!("index"in t))return this;t={store:t.store}}return this.createOperator(t,e)}batchRead(e){return m(this.target)?e(this):this.tx(!1,t=>e(this.idbPro.schema.factory.newReader({storeSchema:this.storeSchema,target:t},this.idbPro)))}iterator(t,r){const a={};return e.isString(r)&&(a.direction=r),b(t)?a.query=t:e.isObject(t)&&Object.assign(a,t),new v({storeSchema:this.storeSchema,target:this.target},this.idbPro,{...a,parser:"value"})}async filter(e,t,r,a){const n=k(e,t,r,a),{maxEmptyChecks:s,limit:u,fn:d}=n,{keyPath:h,defaultGetMapper:l}=this.storeSchema,m=w(n.mapper||l,h,!0);if(!d)return await this.forEach({...n,mapper:m,fn:(e,t,r)=>{if(r>=u-1)return{control:o}}},!0);let f=0;return this.forEach({...n,mapper:m,fn:(e,t,r,a)=>(e=m(e,t,r),d(e,t,r)?(f=0,a.length>=u-1?{control:o}:void 0):++f>=s?{control:i}:{control:c})},!0)}async find(e,t,r){const[a]=await this.filter(e,t,r,1);return a}async page(e,t){const r={...e};return r.page=t||e?.page||1,P(this,r,e)}nextPage(e){return this.page(e,e.page+1)}export(e,t){const r=k(e,t),{keyPath:a,exportMapper:n,name:s,defaultGetMapper:i}=this.storeSchema;if(!a&&Array.isArray(n))throw new Error(`When store [ ${s} ] keyPath does not exist, exportMapper does not support string[].`);return r.direction="next",r.mapper=w(n||i,a,!0),r.limit=r.maxEmptyChecks=Number.MAX_SAFE_INTEGER,this.filter(r)}asMap(){let{target:e}=this;return e instanceof IDBIndex?e=e.objectStore:e instanceof IDBObjectStore||(e={store:e.store}),this.factory.newDbMap({target:e},this.idbPro)}createOperator(e,t){const{idbPro:r}=this,a=this.storeSchema,n={storeSchema:Object.isFrozen(a)?a:void 0,target:e};return t?this.factory.newWriter(n,r):this.factory.newReader(n,r)}}function I(e,t){if(!Array.isArray(e))return{[e]:t};const r={},a=e;for(let e=0;e<a.length;e++)r[a[e]]=t[e];return r}function R(e,t){if(!Array.isArray(e))return t[e];const r=[];for(const a of e){if(!t[a])return;r.push(t[a])}return r}function F(t,r){if(!r||!(r instanceof Object)||Array.isArray(r))return r;const{addedTimeField:a,updatedTimeField:n,updatedCountField:s,softDeletedField:i}=t;return r={...r},a?.name&&!e.isNumber(r[a.name])&&(r[a.name]=Date.now()),n?.name&&!e.isNumber(r[n.name])&&(r[n.name]=Date.now()),i?.name&&!e.isNumber(r[i.name])&&(r[i.name]=0),s?.name&&(r[s.name]=0),r}function M(e,t,r){if(!t||!(t instanceof Object)||Array.isArray(t))return t;const{updatedTimeField:a,updatedCountField:n}=e;return t={...r,...t},a.name&&(t[a.name]=Date.now()),n.name&&(t[n.name]=(t[n.name]||0)+1),t}class E extends O{add(e){return this.changeByPk({record:e,fn:async(e,r,a,n,s)=>{const{storeSchema:i}=this;return a=F(i,a),s?[{...a,...I(s,await t.requestDbResult(e.add(a)))},r]:[a,await t.requestDbResult(e.add(a,r))]}})}addMany(t,r){return this.batchWrite(a=>r?e.asyncMap(t,e=>a.add(e)):e.asyncForEach(t,e=>a.add(e)),!0)}addOrSkip(e){return this.batchWrite(async r=>{const{keyPath:a,defaultGetMapper:n}=r.storeSchema,{key:i,value:o}=a?{key:R(a,e),value:e}:s(e);if(i){const e=await t.requestDbResult(r.nativeStore.get(i));if(e)return w(n,a)?.(e,i)}if(r.target instanceof IDBIndex){const{keyPath:t}=r,a=R(t,o);if(!a)return r.add(e);let n=await r.find(a);if(n)return n}return r.add(e)})}addOrSkipMany(t,r){return this.batchWrite(a=>r?e.asyncMap(t,e=>a.addOrSkip(e)):e.asyncForEach(t,e=>a.addOrSkip(e)),!0)}replace(e){return this.changeByPk({record:e,getOld:!0,fn:async(e,r,a,n,s)=>{const{storeSchema:i}=this,{updatedTimeField:o,updatedCountField:c,addedTimeField:u}=i;return a=n?M(i,a,{[o.name]:n[o.name],[c.name]:n[c.name],[u.name]:n[u.name]}):F(i,a),s?[{...a,...I(s,await t.requestDbResult(e.put(a)))},r]:[a,await t.requestDbResult(e.put(a,r))]}})}replaceMany(t,r){return this.batchWrite(a=>r?e.asyncMap(t,e=>a.replace(e)):e.asyncForEach(t,e=>a.replace(e)),!0)}change(e,r){return this.changeByPk({record:e,getOld:!0,requiredOld:r,requiredPk:r,fn:async(e,r,a,n,s)=>{const{storeSchema:i}=this;if(n)return a=M(i,a,n),s?[{...a,...I(s,await t.requestDbResult(e.put(a)))},r]:[a,await t.requestDbResult(e.put(a,r))]}})}changeMany(t,r){const{returns:a,throwIfMissing:n}=e.isBoolean(r)?{returns:r}:r||{};return this.batchWrite(r=>a?e.asyncMap(t,e=>r.change(e,n)):e.asyncForEach(t,e=>r.change(e,n)),!0)}addOrChange(e){return this.changeByPk({record:e,getOld:!0,fn:async(e,r,a,n,s)=>{const{storeSchema:i}=this;return n?(a=M(i,a,n),s?[{...a,...I(s,await t.requestDbResult(e.put(a)))},r]:[a,await t.requestDbResult(e.put(a,r))]):(a=F(i,a),s?[{...a,...I(s,await t.requestDbResult(e.add(a)))},r]:[a,await t.requestDbResult(e.add(a,r))])}})}addOrChangeMany(t,r){return this.batchWrite(a=>r?e.asyncMap(t,e=>a.addOrChange(e)):e.asyncForEach(t,e=>a.addOrChange(e)),!0)}delete(e,t){return this.changeByPk({pk:e,getOld:t,fn:(e,r,a,n)=>{if(e.delete(r),t)return[n,r]}})}deleteMany(t,r){return this.batchWrite(a=>r?e.asyncMap(t,e=>a.delete(e,!0)):e.asyncForEach(t,e=>a.delete(e)),!0)}deleteRange(t,n){const{returns:s,physical:i,direction:o}=e.isBoolean(n)?{returns:n}:n||{},{name:c}=this.storeSchema.softDeletedField||{};return this.cursor({query:t,direction:o,fn:e=>i||!c?{modify:a}:(e[c]=1,{modify:r})},s)}deleteRangeMany(t,r){const a=e.isBoolean(r)?{returns:r}:r;return this.batchWrite(r=>a?.returns?e.asyncMap(t,e=>r.deleteRange(e,a)):e.asyncForEach(t,e=>r.deleteRange(e,a)),!0)}changeRange(e,t){let{direction:a="next",query:n,newValue:s}="newValue"in e?e:{newValue:e};if(n||(n=R(this.keyPath,s)),!n)throw new Error(`query is required:${JSON.stringify(e)}`);return this.cursor({query:n,direction:a,fn:e=>e instanceof Object?{modify:r,value:{...e,...s}}:{modify:r,value:s}},t)}changeRangeMany(t,r){return this.batchWrite(a=>r?e.asyncMap(t,e=>a.changeRange(e,r)):e.asyncForEach(t,e=>a.changeRange(e,r)),!0)}cursor(t,r){return(t=e.isFunction(t)?{fn:t}:t||{}).fn?r?this.cursorResult(t,!0):this.cursorVoid(t,!0):new v(this,this.idbPro)}batchWrite(e,t){const{target:r}=this;if(m(r))try{return e(this)}catch(e){throw!1!==t&&(r instanceof IDBIndex?r.objectStore:r).transaction.abort(),e}return this.tx(!0,t=>e(this.idbPro.schema.factory.newWriter({storeSchema:this.storeSchema,target:t},this.idbPro)),t)}changeByPk({pk:e,record:r,fn:a,requiredPk:n,getOld:i,requiredOld:o,saveMapper:c,getMapper:u}){const{storeSchema:d}=this,{keyPath:h,defaultSaveMapper:l,defaultGetMapper:m}=d;return r&&(c||l)&&(r=w(c||l,h)?.(r)),this.batchWrite(async c=>{let d,l=r;if(e)d=g(e);else if(h)d=R(h,r);else{const{key:e,value:t}=s(r);d=e,l=t}if(n&&!d)throw new Error(`key is required: ${JSON.stringify(r)}`);const f=d&&(i||o)?await t.requestDbResult(c.nativeStore.get(d)):void 0;if(o&&!f)throw new Error(`record not found: ${JSON.stringify(r)}`);const y=await a(c.nativeStore,d,l,f,h);if(y)return w(u||m,h)?.(y[0],y[1])})}}class j extends x{get size(){return this.tx(!1,e=>t.requestDbResult(e.count()))}delete(e){return this.tx(!0,async(t,r)=>{r.delete(e)})}batch(e){const{idbPro:t,storeSchema:r,factory:a}=this;return this.tx(!0,async(n,s)=>await e(a.newDbMap({storeSchema:r,target:s},t)))}asStore(e){const{factory:t}=this.idbPro.schema;return e?t.newWriter(this,this.idbPro):t.newReader({target:this.target},this.idbPro)}entries(){return new v({target:this.target},this.idbPro,{parser:"keyValue"})}async get(e,r){return await this.tx(!1,r=>t.requestDbResult(r.get(e)))||r}getMany(e){return this.tx(!1,async r=>{const a=[];for(const n of e)a.push(await t.requestDbResult(r.get(n)));return a})}async has(e){return!!await this.get(e)}keys(){return new v({storeSchema:this.storeSchema,target:this.target},this.idbPro,{parser:"key"})}set(e,r){return this.tx(!0,async(a,n)=>{await t.requestDbResult(n.put(r,e))})}setMany(e){return this.tx(!0,async(t,r)=>{for(const[t,a]of e)r.put(a,t)})}values(){return new v({storeSchema:this.storeSchema,target:this.target},this.idbPro,{parser:"value"})}}function N(e,t){if(e==t)return!0;if(typeof e!=typeof t)return!1;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}return!1}const B=({stores:e,schema:t})=>{const r=t.storeSchemas;let a="";for(const t of e){const e=r.find(e=>e.name===t.name);if(e){if(!N(t.keyPath,e.keyPath)){a=`store [ ${t.name} ] keyPath not equal,schema.keyPath:${e.keyPath},store.keyPath:${t.keyPath}[]`;break}if(!t.autoIncrement!=!e.autoIncrement){a=`store [ ${t.name} ] autoIncrement not equal`;break}}}return!a||`The existing database is inconsistent with the definition and cannot be corrected: ${a}`},C=async t=>{let r=B(t);return e.isString(r)||(r=K(t)),r},K=({stores:e,schema:t})=>{const r=t.storeSchemas,a=e.map(e=>e.name);let n="";const s=r.map(e=>e.name).filter(e=>!a.includes(e));if(s.length)n=`store [ ${s.join(",")} ] not exist`;else for(const t of e){const e=r.find(e=>e.name===t.name);if(e&&(n=$(t,Array.from(t.indexNames),e.indexSchemas),n))break}return!n||`The existing database Store index is inconsistent with the definition and requires a database version upgrade to be fixed: ${n}`};function $(e,t,r){if(t.length!==r.length)return`store [ ${e.name} ] index count not equal`;for(const a of t){const t=r.find(e=>e.name===a);if(!t)return`store [ ${e.name} ] index [ ${a} ] not exist`;const n=e.index(a);if(!t.unique!=!n.unique)return`store [ ${e.name} ] index [ ${a} ] unique not equal`;if(!t.multiEntry!=!n.multiEntry)return`store [ ${e.name} ] index [ ${a} ] multiEntry not equal`;if(!N(t.keyPath,n.keyPath))return`store [ ${e.name} ] index [ ${a} ] keyPath not equal`}return""}class A{upgradeContext;storeSchema;nativeStore;#a;constructor(e,t,r){this.upgradeContext=e,this.storeSchema=t,this.nativeStore=r}get writer(){return this.#a||(this.#a=this.upgradeContext.dbSchema.factory?.newWriter({target:this.nativeStore,storeSchema:this.storeSchema}))}add(e,t,r){return this.upgradeContext.versionIn(e)?this.writer.addMany(t,r):Promise.resolve()}addOrChange(e,t,r){return this.upgradeContext.versionIn(e)?this.writer.addOrChangeMany(t,r):Promise.resolve()}async call(e,t){if(this.upgradeContext.versionIn(e))return await t(this.writer,this.upgradeContext)}replace(e,t,r){return this.upgradeContext.versionIn(e)?this.writer.replaceMany(t,r):Promise.resolve()}}const T=Object.freeze({newDataOperators:(e,t)=>new D(t,e),newDbMap:(e,t)=>new j(e,t),newReader:(e,t)=>new O(e,t),newStoreUpgradeable:(e,t,r)=>new A(r,t,e),newWriter:(e,t)=>new E(e,t)});function V(t,r,a,n){const s=function(t,r,a){if(!1===t)return!1;if(e.isString(t))return{name:t};if(e.isObject(t)){const a=t;return e.isBoolean(a.name)&&(a.name=r),t}if(!0===t||a)return{name:r};return!1}(r,a,n);if(!s)return s;const i=s;if(!1!==i.isIndexed){i.isIndexed||(i.isIndexed=!0);const{name:e}=i,r=t.indexSchemas;r.some(t=>t===e||t.name===e)||r.push(e)}return i}function W(t,r){let a=e.isString(t)?{name:t}:t;return r&&(a={...r,...a}),a.indexSchemas||(a.indexSchemas=[]),function(e){Object.isFrozen(e)||(e.addedTimeField=V(e,e.addedTimeField,"added_at",!0),e.updatedTimeField=V(e,e.updatedTimeField,"updated_at",!0),e.updatedCountField=V(e,e.updatedCountField,"updated_count",!1),e.softDeletedField=V(e,e.softDeletedField,"deleted",!1))}(a),Object.isFrozen(a)||(a.indexSchemas=a.indexSchemas.map(z)),function(e){if(!e.keyPath&&e.defaultData?.length)for(const t of e.defaultData)if(!Array.isArray(t)&&!("value"in t))throw new Error(`When \`defaultData\` must contain \`value\` fields or be an array:${JSON.stringify(t)}`)}(a),a}function z(t){const r=e.isString(t)?{name:t}:t;return r.keyPath||(r.keyPath=r.name),r}const _=e=>{const{versionDiffValidate:t,versionSameValidate:r,factory:a}=e;return e.storeSchemas||(e.storeSchemas=[]),e.storeTemplate||(e.storeTemplate={...f}),!t&&!1!==t&&(e.versionDiffValidate=B),!r&&!1!==r&&(e.versionSameValidate=C),a?a!==T&&(e.factory={...T,...a}):e.factory=T,e.storeSchemas=e.storeSchemas.map(t=>W(t,e.storeTemplate)),e};function U(e,t){(function(e,t){return e.unique===t.unique&&e.multiEntry===t.multiEntry&&N(t.keyPath,e.keyPath)})(e.index(t.name),t)||(e.deleteIndex(t.name),J(e,t))}function J(e,t){try{e.createIndex(t.name,t.keyPath,{unique:t.unique,multiEntry:t.multiEntry})}catch{throw new Error(`store [ ${e.name} ] index [ ${t.name} ] create error: ${JSON.stringify(t)}`)}}function G(e,t){return e.database.objectStoreNames.contains(t.name)?function(e,t){const{indexSchemas:r}=e,a=t.indexNames,n=r.map(e=>e.name);for(const e of Array.from(a))n.includes(e)||t.deleteIndex(e);for(const e of r)a.contains(e.name)?U(t,e):J(t,e);return t}(t,e.transaction?.objectStore(t.name)):function(e,t){const r=t.createObjectStore(e.name,{keyPath:e.keyPath,autoIncrement:e.autoIncrement});for(const t of e.indexSchemas)J(r,t);return r}(t,e.database)}class Q{database;newVersion;oldVersion;dbSchema;transaction;#n={};constructor(e){this.database=e.database,this.newVersion=e.newVersion,this.oldVersion=e.oldVersion,this.dbSchema=e.dbSchema,this.transaction=e.transaction}deleteStoreIfExists(e){const t=this.database;t.objectStoreNames.contains(e)&&t.deleteObjectStore(e)}destroy(){try{e.destroyRecords(this.#n)}finally{for(const e of Object.keys(this.#n))delete this.#n[e]}}store(e){if(e in this.#n)return this.#n[e];const{factory:t}=this.dbSchema,{storeSchemas:r}=this.dbSchema,a=r.find(t=>t.name===e),n=G(this,a);return this.#n[e]=t.newStoreUpgradeable(n,a,this)}versionIn({oldMin:e,oldMax:t,newMax:r,newMin:a}){if(void 0===t&&void 0===r&&void 0===e&&void 0===a)throw new Error(`versionIn bounds must not be empty ${JSON.stringify({oldMax:t,newMax:r,oldMin:e,newMin:a})}`);if(t<e)throw new Error(`oldMax (${t}) cannot be less than oldMin (${e})`);if(r<a)throw new Error(`newMax (${r}) cannot be less than newMin (${a})`);const{oldVersion:n,newVersion:s}=this;return!(void 0!==e&&n<e||void 0!==t&&n>t||void 0!==a&&s<a)&&!(void 0!==r&&s>r)}}function L(t,r){let{store:a,index:n}=t;const{storeTemplate:s}=r,{storeSchemas:i=[]}=r,o=e.isString(a)?a:a.name,c=i.findIndex(e=>e===o||e.name===o),u=c>-1&&i[c];let d;d=e.isString(a)?u||o:!u||e.isString(u)||a===u?a:{...u,...a},(n||u?.indexSchemas?.length||a?.indexSchemas?.length)&&(e.isString(d)&&(d={name:d}),d.indexSchemas=function(t,r,a){a&&r.push(a);for(const a of r){const r=e.isString(a)?a:a.name,n=t.findIndex(e=>e===r||e.name===r);if(n>-1){const r=t[n];e.isString(r)?t[n]=a:e.isString(a)||(t[n]=Object.assign(r,a))}else t.push(a)}return t}(u.indexSchemas||[],a.indexSchemas||[],n));const h=W(d,s);c>-1?i[c]=h:i.push(h),r.storeSchemas=i;const l={store:o};return n&&(l.index=e.isString(n)?n:n.name),{target:l}}const X=Object.assign({name:"",addedTimeField:!1,autoIncrement:!1,indexSchemas:[],keyPath:void 0,softDeletedField:!1,updatedCountField:!1,updatedTimeField:!1});class H{static#s;#i;#o;#c={};constructor(t,r){this.#i=t=e.isString(t)?{name:t}:t,Array.isArray(t.storeSchemas)||(t.storeSchemas=[]),e.isObject(t.storeTemplate)||(t.storeTemplate=f),r&&(this.#o=!0)}static get defaultDb(){return this.#s||(this.#s=new H(t.DefaultDbName))}get initialized(){return Object.isFrozen(this.#i)}get schema(){return this.#i}get storeNames(){return Array.from(new Set(this.#i.storeSchemas.map(t=>e.isString(t)?t:t.name)))}get factory(){return this.#i.factory||(this.#i.factory=T)}static releaseDefaultDB(){this.#s=void 0}static async openExistDb(e){const{generateDbSchema:t}=await Promise.resolve().then(function(){return te});return new H(await t(e))}static store(e,t){return H.defaultDb.store(e,t)}static stores(e){return H.defaultDb.stores(e)}static map(e,t){return H.defaultDb.map(e,t)}async openNativeDb(){const r=this.#i=e.deepFreeze(this.initSchema());await this.#u();const{name:a,version:n}=r;return await t.openDb({name:a,version:n,onupgradeneeded:(t,a,n)=>async function(t,r,a,n){const{storeSchemas:s,beforeUpgrade:i,afterUpgrade:o,version:c}=t,{newVersion:u=c,oldVersion:d}=a,{transaction:h}=n,l=new Q({database:r,newVersion:u,oldVersion:d,dbSchema:t,transaction:h});try{const t=[];if(e.isFunction(i))try{await i(l)}catch(e){t.push(e)}for(const e of s.map(e=>e.name))try{l.store(e)}catch(e){t.push(e)}for(const{name:e,defaultData:r}of s)if(r)try{await l.store(e).add({oldMax:0},r)}catch(e){t.push(e)}for(const{name:e,versionData:r}of s)if(r)for(const{version:a,data:n,use:s="addOrChange"}of r)try{await l.store(e)[s](a,n)}catch(e){t.push(e)}for(const{name:e,storeDefined:r}of s)try{await(r?.(l.store(e)))}catch(e){t.push(e)}if(e.isFunction(o))try{await o(l)}catch(e){t.push(e)}if(!t.length)return;throw 1===t.length?t[0]:new AggregateError(t,"Database upgrade error")}finally{e.destroy(l)}}(r,t,a,n)})}store(e,t){const r=e.store?e:{store:e};return r.store||(r.store=e),r.index||(r.index=t),this.factory.newWriter(L(r,this.schema),this)}stores(t){const{schema:r}=this,a=t.map(t=>L(e.isString(t)?{store:t}:t,r));return this.factory.newDataOperators(a,this)}initSchema(){if(this.initialized)return this.#i;const{validateSchemaWithDefaults:e=_}=this.#i;return this.#i=e(this.#i)}async traceSchema(t){await e.logJson(this.schema,t)}map(r,a){const n=e.isString(r)?r:e.isString(a)?a:t.DefaultStorageStoreName;Array.isArray(r)&&(a=r);const{storeSchemas:s}=this.schema;return s.find(e=>e.name===n||e===n)||s.push({...X,name:n,defaultData:a}),this.factory.newDbMap({target:{store:n}},this)}export(){return this.stores(this.storeNames).export()}import(e,t,r){return this.stores(this.storeNames).import(e,t,r)}getStoreSchema(t){if(t in this.#c)return this.#c[t];const r=this.schema.storeSchemas.findIndex(e=>e===t||e.name===t);let a=this.schema.storeSchemas[r];return this.initialized?this.#c[t]=a:e.isString(a)&&(this.schema.storeSchemas[r]=a={name:a}),a}async#u(){let r=this.#o;if(void 0===r&&(r=this.#o=await async function(r){const{name:a,version:n}=r,s=await t.findExistDb(a);if(!s)return!0;const{versionDiffValidate:i,versionSameValidate:o}=r,c=await t.openDb(a);try{if(r.version<c.version)return"The existing database version is greater than the current version";const u=void 0===r.version||c.version===r.version?o:i;if(!u)return!0;const d=Array.from(c.objectStoreNames);if(d.length<1)return`The existing database [ ${a} ] is empty`;const h=await t.readTx(c,d),l=await u({schema:r,db:c,stores:h});if(e.isString(l)||n!==s.version)return l}finally{c?.close()}return!0}(this.#i)),!0===r)return!0;if(e.isString(r))throw new Error(r)}}function Y(e,t){const r=Array.from(e.indexNames).map(t=>e.index(t)),a=[],n=[];for(const{name:e,keyPath:t,unique:s,multiEntry:i}of r)Array.isArray(t)?n.push(...t):n.push(t),a.push({name:e,keyPath:t,unique:s,multiEntry:i});const s=new Set(n);return{indexSchemas:a,addedTimeField:Z(t.addedTimeField,s),updatedTimeField:Z(t.updatedTimeField,s),updatedCountField:Z(t.updatedCountField,s),softDeletedField:Z(t.softDeletedField,s)}}function Z(e,t){return!!t.has(e)&&{name:e,isIndexed:!1}}async function ee(r,a){if(!await t.findExistDb(r))throw new Error(`db [ ${r} ] not exist`);let{asString:n,specialFields:s=y,dataExportTarget:i}=a||{};!0===n&&(n=160),isNaN(n)||n<1&&(n=1);let o=await function(e,r){return t.openDb(e,async function(e){const t=Array.from(e.objectStoreNames),a=e.transaction(t,"readonly");try{return{name:e.name,version:e.version,storeSchemas:t.map(e=>function(e,t){const{name:r,keyPath:a,autoIncrement:n}=e;return{name:r,keyPath:a,autoIncrement:n,...Y(e,t)}}(a.objectStore(e),r))}}finally{a.abort()}})}(r,s);return i&&await async function(t,r){const a=await new H(e.copyObject(t),!0).export();for(const e of t.storeSchemas){const n=a[e.name];n?.length&&("defaultData"===r?e.defaultData=n:"versionData"===r&&(e.versionData||(e.versionData=[]),e.versionData.push({version:{oldMax:t.version},data:n})))}return t}(o,i),n?await e.toJson({rootData$:o,spaceEffectiveLength:n}):o}var te=Object.freeze({__proto__:null,generateDbSchema:ee});exports.Break=i,exports.Continue=c,exports.ContinueKey=u,exports.ContinuePrimaryKey=h,exports.DataOperationBase=x,exports.DataOperators=D,exports.DataReader=O,exports.DataWriter=E,exports.DbIterator=v,exports.DbIteratorParsers=n,exports.DbMap=j,exports.Delete=a,exports.Finished=o,exports.IDbPro=H,exports.NextKey=d,exports.NextPrimaryKey=l,exports.Save=r,exports.StoreUpgradeable=A,exports.UpgradeContext=Q,exports.dbMap=function(e,t){return H.defaultDb.map(e,t)},exports.dbStore=function(e,t){return H.defaultDb.store(e,t)},exports.dbStores=function(e){return H.defaultDb.stores(e)},exports.defaultSpecialFields=y,exports.defaultStoreSchemaTemplate=f,exports.generateDbSchema=ee,exports.isIDbQuery=b,exports.isNativeTarget=m,exports.parseDbNoneKeyPathRecord=s,exports.parseIDbQuery=g,exports.releaseDefaultDB=function(){H.releaseDefaultDB()},exports.validateSchemaWithDefaults=_,exports.versionDiffValidate=B,exports.versionSameValidate=C;
|