@firtoz/drizzle-indexeddb 0.4.1 → 0.4.3
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/CHANGELOG.md +12 -0
- package/README.md +37 -3
- package/package.json +15 -10
- package/src/bin/generate-migrations.ts +28 -42
- package/src/context/DrizzleIndexedDBProvider.tsx +5 -14
- package/src/context/useDrizzleIndexedDB.ts +9 -4
- package/src/idb-operations.ts +8 -3
- package/src/native-idb-database.ts +119 -78
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @firtoz/drizzle-indexeddb
|
|
2
2
|
|
|
3
|
+
## 0.4.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`ed6dfce`](https://github.com/firtoz/fullstack-toolkit/commit/ed6dfce75be95d5349381ab43c6c22b25b164414) Thanks [@firtoz](https://github.com/firtoz)! - Enable drizzle and output dir configuration in drizzle-indexeddb-generate
|
|
8
|
+
|
|
9
|
+
## 0.4.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`58afa0a`](https://github.com/firtoz/fullstack-toolkit/commit/58afa0a5365f55f536e50194a73f847293102e7f) Thanks [@firtoz](https://github.com/firtoz)! - Hopefully this should work
|
|
14
|
+
|
|
3
15
|
## 0.4.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -385,8 +385,8 @@ bun drizzle-indexeddb-generate --help
|
|
|
385
385
|
|
|
386
386
|
| Option | Description | Default |
|
|
387
387
|
|--------|-------------|---------|
|
|
388
|
-
| `--drizzle-dir <path
|
|
389
|
-
| `--output-dir <path
|
|
388
|
+
| `--drizzle-dir <path>`, `-d` | Path to Drizzle directory | `./drizzle` |
|
|
389
|
+
| `--output-dir <path>`, `-o` | Path to output directory | `<drizzle-dir>/indexeddb-migrations` |
|
|
390
390
|
|
|
391
391
|
### npm scripts
|
|
392
392
|
|
|
@@ -395,11 +395,13 @@ Add to your `package.json`:
|
|
|
395
395
|
```json
|
|
396
396
|
{
|
|
397
397
|
"scripts": {
|
|
398
|
-
"db:generate": "bun drizzle-kit generate && bun drizzle-indexeddb-generate"
|
|
398
|
+
"db:generate": "bun --bun drizzle-kit generate && bun drizzle-indexeddb-generate"
|
|
399
399
|
}
|
|
400
400
|
}
|
|
401
401
|
```
|
|
402
402
|
|
|
403
|
+
> **Note:** The `--bun` flag forces bun's runtime instead of Node, which is needed because this package exports raw TypeScript. See [Troubleshooting](#err_unsupported_node_modules_type_stripping-error) if you encounter type stripping errors.
|
|
404
|
+
|
|
403
405
|
## Advanced Usage
|
|
404
406
|
|
|
405
407
|
### Custom Sync Configuration
|
|
@@ -666,6 +668,38 @@ Remove from schema and regenerate - the migrator will delete the object store.
|
|
|
666
668
|
|
|
667
669
|
## Troubleshooting
|
|
668
670
|
|
|
671
|
+
### "ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING" Error
|
|
672
|
+
|
|
673
|
+
If you see this error when running `drizzle-kit generate`:
|
|
674
|
+
|
|
675
|
+
```
|
|
676
|
+
Error [ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING]: Stripping types is currently unsupported for files under node_modules
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
This happens because this package exports raw TypeScript files, and Node's built-in type stripping doesn't work inside `node_modules`.
|
|
680
|
+
|
|
681
|
+
**Solution:** Use `bun --bun` to force bun's runtime instead of Node:
|
|
682
|
+
|
|
683
|
+
```bash
|
|
684
|
+
bun --bun drizzle-kit generate
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
Or in your `package.json`:
|
|
688
|
+
|
|
689
|
+
```json
|
|
690
|
+
{
|
|
691
|
+
"scripts": {
|
|
692
|
+
"db:generate": "bun --bun drizzle-kit generate && bun drizzle-indexeddb-generate"
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**Alternative:** If you're not using bun, use `tsx`:
|
|
698
|
+
|
|
699
|
+
```bash
|
|
700
|
+
npx tsx node_modules/drizzle-kit/bin.cjs generate --config ./drizzle.config.ts
|
|
701
|
+
```
|
|
702
|
+
|
|
669
703
|
### "Primary key structure changed" Error
|
|
670
704
|
|
|
671
705
|
This happens when you change the primary key of a table. IndexedDB doesn't support changing keyPath after creation.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firtoz/drizzle-indexeddb",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "IndexedDB migrations powered by Drizzle ORM",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"module": "./src/index.ts",
|
|
@@ -42,9 +42,7 @@
|
|
|
42
42
|
"typecheck": "tsc --noEmit -p ./tsconfig.json",
|
|
43
43
|
"lint": "biome check --write src",
|
|
44
44
|
"lint:ci": "biome ci src",
|
|
45
|
-
"format": "biome format src --write"
|
|
46
|
-
"test": "bun test --pass-with-no-tests",
|
|
47
|
-
"test:watch": "bun test --watch"
|
|
45
|
+
"format": "biome format src --write"
|
|
48
46
|
},
|
|
49
47
|
"keywords": [
|
|
50
48
|
"typescript",
|
|
@@ -69,17 +67,24 @@
|
|
|
69
67
|
"publishConfig": {
|
|
70
68
|
"access": "public"
|
|
71
69
|
},
|
|
72
|
-
"
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"@firtoz/drizzle-utils": ">=0.3.0",
|
|
72
|
+
"@tanstack/db": ">=0.5.0",
|
|
73
|
+
"drizzle-orm": ">=0.44.0",
|
|
74
|
+
"drizzle-valibot": ">=0.4.0",
|
|
75
|
+
"react": ">=18.0.0",
|
|
76
|
+
"valibot": ">=1.0.0"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
73
79
|
"@firtoz/drizzle-utils": "^0.3.0",
|
|
74
80
|
"@tanstack/db": "^0.5.11",
|
|
81
|
+
"@types/react": "^19.2.7",
|
|
75
82
|
"drizzle-orm": "^0.45.0",
|
|
76
83
|
"drizzle-valibot": "^0.4.2",
|
|
84
|
+
"react": "^19.2.1",
|
|
77
85
|
"valibot": "^1.2.0"
|
|
78
86
|
},
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
},
|
|
82
|
-
"devDependencies": {
|
|
83
|
-
"@types/react": "^19.2.7"
|
|
87
|
+
"dependencies": {
|
|
88
|
+
"citty": "^0.1.6"
|
|
84
89
|
}
|
|
85
90
|
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
11
11
|
import { join, resolve } from "node:path";
|
|
12
|
+
import { defineCommand, runMain } from "citty";
|
|
12
13
|
import type {
|
|
13
14
|
JournalEntry,
|
|
14
15
|
Journal,
|
|
@@ -240,49 +241,34 @@ export default migrations;
|
|
|
240
241
|
}
|
|
241
242
|
|
|
242
243
|
// CLI entry point
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
--drizzle-dir <path> Path to Drizzle directory (default: ./drizzle)
|
|
270
|
-
--output-dir <path> Path to output directory (default: ./drizzle/indexeddb-migrations)
|
|
271
|
-
-h, --help Show this help message
|
|
272
|
-
|
|
273
|
-
Examples:
|
|
274
|
-
bun drizzle-indexeddb-generate
|
|
275
|
-
bun drizzle-indexeddb-generate --drizzle-dir ./db/drizzle
|
|
276
|
-
bun drizzle-indexeddb-generate --output-dir ./src/migrations
|
|
277
|
-
`);
|
|
278
|
-
} else {
|
|
279
|
-
console.error(`Unknown command: ${command}`);
|
|
280
|
-
console.error(`Run 'bun drizzle-indexeddb-generate --help' for usage`);
|
|
281
|
-
process.exit(1);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
244
|
+
const main = defineCommand({
|
|
245
|
+
meta: {
|
|
246
|
+
name: "drizzle-indexeddb-generate",
|
|
247
|
+
description: "Generate IndexedDB migrations from Drizzle schema",
|
|
248
|
+
},
|
|
249
|
+
args: {
|
|
250
|
+
drizzleDir: {
|
|
251
|
+
type: "string",
|
|
252
|
+
alias: "d",
|
|
253
|
+
default: "./drizzle",
|
|
254
|
+
description: "Path to Drizzle directory",
|
|
255
|
+
},
|
|
256
|
+
outputDir: {
|
|
257
|
+
type: "string",
|
|
258
|
+
alias: "o",
|
|
259
|
+
description:
|
|
260
|
+
"Path to output directory (default: <drizzle-dir>/indexeddb-migrations)",
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
run({ args }) {
|
|
264
|
+
generateIndexedDBMigrations({
|
|
265
|
+
drizzleDir: args.drizzleDir,
|
|
266
|
+
outputDir: args.outputDir,
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
});
|
|
284
270
|
|
|
285
271
|
// Only run CLI when executed directly (not when imported)
|
|
286
272
|
if (import.meta.main) {
|
|
287
|
-
main
|
|
273
|
+
runMain(main);
|
|
288
274
|
}
|
|
@@ -134,10 +134,9 @@ export function DrizzleIndexedDBProvider<
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
useEffect(() => {
|
|
137
|
+
let db: IDBDatabaseLike | null = null;
|
|
137
138
|
const initDB = async () => {
|
|
138
139
|
try {
|
|
139
|
-
let db: IDBDatabaseLike;
|
|
140
|
-
|
|
141
140
|
if (migrations.length === 0) {
|
|
142
141
|
// Open database directly without migration logic
|
|
143
142
|
db = await openIndexedDb(dbName, dbCreator);
|
|
@@ -161,11 +160,11 @@ export function DrizzleIndexedDBProvider<
|
|
|
161
160
|
|
|
162
161
|
// Cleanup on unmount
|
|
163
162
|
return () => {
|
|
164
|
-
if (
|
|
165
|
-
|
|
163
|
+
if (db) {
|
|
164
|
+
db.close();
|
|
166
165
|
}
|
|
167
166
|
};
|
|
168
|
-
}, [dbName, migrations, migrateFunction, debug, readyPromise]);
|
|
167
|
+
}, [dbName, migrations, migrateFunction, debug, readyPromise, dbCreator]);
|
|
169
168
|
|
|
170
169
|
// Collection cache with ref counting
|
|
171
170
|
const collections = useMemo<Map<string, CollectionCacheEntry>>(
|
|
@@ -219,15 +218,7 @@ export function DrizzleIndexedDBProvider<
|
|
|
219
218
|
return collections.get(cacheKey)!
|
|
220
219
|
.collection as unknown as IndexedDbCollection<TSchema, TTableName>;
|
|
221
220
|
},
|
|
222
|
-
[
|
|
223
|
-
indexedDBRef,
|
|
224
|
-
collections,
|
|
225
|
-
schema,
|
|
226
|
-
readyPromise.promise,
|
|
227
|
-
debug,
|
|
228
|
-
dbName,
|
|
229
|
-
syncMode,
|
|
230
|
-
],
|
|
221
|
+
[collections, schema, readyPromise.promise, debug, dbName, syncMode],
|
|
231
222
|
);
|
|
232
223
|
|
|
233
224
|
const incrementRefCount: DrizzleIndexedDBContextValue<TSchema>["incrementRefCount"] =
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useContext } from "react";
|
|
1
|
+
import { useCallback, useContext } from "react";
|
|
2
2
|
import {
|
|
3
3
|
DrizzleIndexedDBContext,
|
|
4
4
|
useIndexedDBCollection,
|
|
@@ -28,10 +28,15 @@ export function useDrizzleIndexedDB<
|
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const useCollection = useCallback(
|
|
32
|
+
<TTableName extends keyof TSchema & string>(tableName: TTableName) =>
|
|
33
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: This is on purpose.
|
|
34
|
+
useIndexedDBCollection(context, tableName),
|
|
35
|
+
[context],
|
|
36
|
+
);
|
|
37
|
+
|
|
31
38
|
return {
|
|
32
|
-
useCollection
|
|
33
|
-
tableName: TTableName,
|
|
34
|
-
) => useIndexedDBCollection(context, tableName),
|
|
39
|
+
useCollection,
|
|
35
40
|
indexedDB: context.indexedDB,
|
|
36
41
|
};
|
|
37
42
|
}
|
package/src/idb-operations.ts
CHANGED
|
@@ -23,9 +23,14 @@ export async function openIndexedDb(
|
|
|
23
23
|
*/
|
|
24
24
|
const defaultIDBDeleter: IDBDeleter = (name: string): Promise<void> => {
|
|
25
25
|
return new Promise((resolve, reject) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
try {
|
|
27
|
+
const request = indexedDB.deleteDatabase(name);
|
|
28
|
+
request.onerror = () => reject(request.error);
|
|
29
|
+
request.onsuccess = () => resolve();
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error("Error deleting database", error);
|
|
32
|
+
reject(error);
|
|
33
|
+
}
|
|
29
34
|
});
|
|
30
35
|
};
|
|
31
36
|
|
|
@@ -104,12 +104,17 @@ class NativeIDBDatabase implements IDBDatabaseLike {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
return new Promise((resolve, reject) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
try {
|
|
108
|
+
const transaction = this.db.transaction(storeName, "readonly");
|
|
109
|
+
const store = transaction.objectStore(storeName);
|
|
110
|
+
const request = store.getAll();
|
|
111
|
+
|
|
112
|
+
request.onsuccess = () => resolve(request.result as T[]);
|
|
113
|
+
request.onerror = () => reject(request.error);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error("Error getting all items", error);
|
|
116
|
+
reject(error);
|
|
117
|
+
}
|
|
113
118
|
});
|
|
114
119
|
}
|
|
115
120
|
|
|
@@ -119,14 +124,19 @@ class NativeIDBDatabase implements IDBDatabaseLike {
|
|
|
119
124
|
keyRange?: KeyRangeSpec,
|
|
120
125
|
): Promise<T[]> {
|
|
121
126
|
return new Promise((resolve, reject) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
try {
|
|
128
|
+
const transaction = this.db.transaction(storeName, "readonly");
|
|
129
|
+
const store = transaction.objectStore(storeName);
|
|
130
|
+
const index = store.index(indexName);
|
|
131
|
+
const range = keyRange ? createKeyRange(keyRange) : undefined;
|
|
132
|
+
const request = index.getAll(range);
|
|
133
|
+
|
|
134
|
+
request.onsuccess = () => resolve(request.result as T[]);
|
|
135
|
+
request.onerror = () => reject(request.error);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error("Error getting all items by index", error);
|
|
138
|
+
reject(error);
|
|
139
|
+
}
|
|
130
140
|
});
|
|
131
141
|
}
|
|
132
142
|
|
|
@@ -135,72 +145,98 @@ class NativeIDBDatabase implements IDBDatabaseLike {
|
|
|
135
145
|
key: IDBValidKey,
|
|
136
146
|
): Promise<T | undefined> {
|
|
137
147
|
return new Promise((resolve, reject) => {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
try {
|
|
149
|
+
const transaction = this.db.transaction(storeName, "readonly");
|
|
150
|
+
const store = transaction.objectStore(storeName);
|
|
151
|
+
const request = store.get(key);
|
|
152
|
+
|
|
153
|
+
request.onsuccess = () => resolve(request.result as T | undefined);
|
|
154
|
+
request.onerror = () => reject(request.error);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error("Error getting item", error);
|
|
157
|
+
reject(error);
|
|
158
|
+
}
|
|
144
159
|
});
|
|
145
160
|
}
|
|
146
161
|
|
|
147
162
|
async add(storeName: string, items: unknown[]): Promise<void> {
|
|
148
163
|
return new Promise((resolve, reject) => {
|
|
149
|
-
|
|
150
|
-
|
|
164
|
+
try {
|
|
165
|
+
const transaction = this.db.transaction(storeName, "readwrite");
|
|
166
|
+
const store = transaction.objectStore(storeName);
|
|
151
167
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
168
|
+
for (const item of items) {
|
|
169
|
+
store.add(item);
|
|
170
|
+
}
|
|
155
171
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
172
|
+
transaction.oncomplete = () => resolve();
|
|
173
|
+
transaction.onerror = () => reject(transaction.error);
|
|
174
|
+
transaction.onabort = () => reject(new Error("Transaction aborted"));
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error("Error adding items", error);
|
|
177
|
+
reject(error);
|
|
178
|
+
}
|
|
159
179
|
});
|
|
160
180
|
}
|
|
161
181
|
|
|
162
182
|
async put(storeName: string, items: unknown[]): Promise<void> {
|
|
163
183
|
return new Promise((resolve, reject) => {
|
|
164
|
-
|
|
165
|
-
|
|
184
|
+
try {
|
|
185
|
+
const transaction = this.db.transaction(storeName, "readwrite");
|
|
186
|
+
const store = transaction.objectStore(storeName);
|
|
166
187
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
188
|
+
for (const item of items) {
|
|
189
|
+
store.put(item);
|
|
190
|
+
}
|
|
170
191
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
192
|
+
transaction.oncomplete = () => resolve();
|
|
193
|
+
transaction.onerror = () => reject(transaction.error);
|
|
194
|
+
transaction.onabort = () => reject(new Error("Transaction aborted"));
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error("Error putting items", error);
|
|
197
|
+
reject(error);
|
|
198
|
+
}
|
|
174
199
|
});
|
|
175
200
|
}
|
|
176
201
|
|
|
177
202
|
async delete(storeName: string, keys: IDBValidKey[]): Promise<void> {
|
|
178
203
|
return new Promise((resolve, reject) => {
|
|
179
|
-
|
|
180
|
-
|
|
204
|
+
try {
|
|
205
|
+
const transaction = this.db.transaction(storeName, "readwrite");
|
|
206
|
+
const store = transaction.objectStore(storeName);
|
|
181
207
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
208
|
+
for (const key of keys) {
|
|
209
|
+
store.delete(key);
|
|
210
|
+
}
|
|
185
211
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
212
|
+
transaction.oncomplete = () => resolve();
|
|
213
|
+
transaction.onerror = () => reject(transaction.error);
|
|
214
|
+
transaction.onabort = () => reject(new Error("Transaction aborted"));
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error("Error deleting items", error);
|
|
217
|
+
reject(error);
|
|
218
|
+
}
|
|
189
219
|
});
|
|
190
220
|
}
|
|
191
221
|
|
|
192
222
|
async clear(storeName: string): Promise<void> {
|
|
193
223
|
return new Promise((resolve, reject) => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
224
|
+
try {
|
|
225
|
+
const transaction = this.db.transaction(storeName, "readwrite");
|
|
226
|
+
const store = transaction.objectStore(storeName);
|
|
227
|
+
const request = store.clear();
|
|
228
|
+
|
|
229
|
+
request.onsuccess = () => resolve();
|
|
230
|
+
request.onerror = () => reject(request.error);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.error("Error clearing store", error);
|
|
233
|
+
reject(error);
|
|
234
|
+
}
|
|
200
235
|
});
|
|
201
236
|
}
|
|
202
237
|
|
|
203
238
|
close(): void {
|
|
239
|
+
console.log("Closing database");
|
|
204
240
|
this.db.close();
|
|
205
241
|
}
|
|
206
242
|
}
|
|
@@ -319,37 +355,42 @@ export const defaultIDBCreator: IDBCreator = (
|
|
|
319
355
|
options?: IDBOpenOptions,
|
|
320
356
|
): Promise<IDBDatabaseLike> => {
|
|
321
357
|
return new Promise((resolve, reject) => {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
request.onerror = () => reject(request.error);
|
|
358
|
+
try {
|
|
359
|
+
const request = options?.version
|
|
360
|
+
? indexedDB.open(name, options.version)
|
|
361
|
+
: indexedDB.open(name);
|
|
327
362
|
|
|
328
|
-
|
|
329
|
-
setTimeout(() => {
|
|
330
|
-
reject(new Error("Database upgrade blocked - close other tabs"));
|
|
331
|
-
}, 3000);
|
|
332
|
-
};
|
|
363
|
+
request.onerror = () => reject(request.error);
|
|
333
364
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
365
|
+
request.onblocked = () => {
|
|
366
|
+
setTimeout(() => {
|
|
367
|
+
reject(new Error("Database upgrade blocked - close other tabs"));
|
|
368
|
+
}, 3000);
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
request.onupgradeneeded = (event) => {
|
|
372
|
+
if (options?.onUpgrade) {
|
|
373
|
+
const db = request.result;
|
|
374
|
+
const transaction = (event.target as IDBOpenDBRequest).transaction;
|
|
375
|
+
if (!transaction) {
|
|
376
|
+
reject(new Error("No transaction during upgrade"));
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
// Create an upgrade-mode database wrapper
|
|
380
|
+
const upgradeDb = new UpgradeModeDatabase(db, transaction);
|
|
381
|
+
try {
|
|
382
|
+
options.onUpgrade(upgradeDb);
|
|
383
|
+
} catch (error) {
|
|
384
|
+
transaction.abort();
|
|
385
|
+
reject(error);
|
|
386
|
+
}
|
|
341
387
|
}
|
|
342
|
-
|
|
343
|
-
const upgradeDb = new UpgradeModeDatabase(db, transaction);
|
|
344
|
-
try {
|
|
345
|
-
options.onUpgrade(upgradeDb);
|
|
346
|
-
} catch (error) {
|
|
347
|
-
transaction.abort();
|
|
348
|
-
reject(error);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
};
|
|
388
|
+
};
|
|
352
389
|
|
|
353
|
-
|
|
390
|
+
request.onsuccess = () => resolve(new NativeIDBDatabase(request.result));
|
|
391
|
+
} catch (error) {
|
|
392
|
+
console.error("Error creating database", error);
|
|
393
|
+
reject(error);
|
|
394
|
+
}
|
|
354
395
|
});
|
|
355
396
|
};
|