@firtoz/drizzle-indexeddb 0.4.1 → 0.4.2

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @firtoz/drizzle-indexeddb
2
2
 
3
+ ## 0.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`58afa0a`](https://github.com/firtoz/fullstack-toolkit/commit/58afa0a5365f55f536e50194a73f847293102e7f) Thanks [@firtoz](https://github.com/firtoz)! - Hopefully this should work
8
+
3
9
  ## 0.4.1
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firtoz/drizzle-indexeddb",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
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,21 @@
69
67
  "publishConfig": {
70
68
  "access": "public"
71
69
  },
72
- "dependencies": {
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
- },
79
- "peerDependencies": {
80
- "react": "^19.2.1"
81
- },
82
- "devDependencies": {
83
- "@types/react": "^19.2.7"
84
86
  }
85
87
  }
@@ -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 (indexedDB) {
165
- indexedDB.close();
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: <TTableName extends keyof TSchema & string>(
33
- tableName: TTableName,
34
- ) => useIndexedDBCollection(context, tableName),
39
+ useCollection,
35
40
  indexedDB: context.indexedDB,
36
41
  };
37
42
  }
@@ -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
- const request = indexedDB.deleteDatabase(name);
27
- request.onerror = () => reject(request.error);
28
- request.onsuccess = () => resolve();
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
- const transaction = this.db.transaction(storeName, "readonly");
108
- const store = transaction.objectStore(storeName);
109
- const request = store.getAll();
110
-
111
- request.onsuccess = () => resolve(request.result as T[]);
112
- request.onerror = () => reject(request.error);
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
- const transaction = this.db.transaction(storeName, "readonly");
123
- const store = transaction.objectStore(storeName);
124
- const index = store.index(indexName);
125
- const range = keyRange ? createKeyRange(keyRange) : undefined;
126
- const request = index.getAll(range);
127
-
128
- request.onsuccess = () => resolve(request.result as T[]);
129
- request.onerror = () => reject(request.error);
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
- const transaction = this.db.transaction(storeName, "readonly");
139
- const store = transaction.objectStore(storeName);
140
- const request = store.get(key);
141
-
142
- request.onsuccess = () => resolve(request.result as T | undefined);
143
- request.onerror = () => reject(request.error);
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
- const transaction = this.db.transaction(storeName, "readwrite");
150
- const store = transaction.objectStore(storeName);
164
+ try {
165
+ const transaction = this.db.transaction(storeName, "readwrite");
166
+ const store = transaction.objectStore(storeName);
151
167
 
152
- for (const item of items) {
153
- store.add(item);
154
- }
168
+ for (const item of items) {
169
+ store.add(item);
170
+ }
155
171
 
156
- transaction.oncomplete = () => resolve();
157
- transaction.onerror = () => reject(transaction.error);
158
- transaction.onabort = () => reject(new Error("Transaction aborted"));
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
- const transaction = this.db.transaction(storeName, "readwrite");
165
- const store = transaction.objectStore(storeName);
184
+ try {
185
+ const transaction = this.db.transaction(storeName, "readwrite");
186
+ const store = transaction.objectStore(storeName);
166
187
 
167
- for (const item of items) {
168
- store.put(item);
169
- }
188
+ for (const item of items) {
189
+ store.put(item);
190
+ }
170
191
 
171
- transaction.oncomplete = () => resolve();
172
- transaction.onerror = () => reject(transaction.error);
173
- transaction.onabort = () => reject(new Error("Transaction aborted"));
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
- const transaction = this.db.transaction(storeName, "readwrite");
180
- const store = transaction.objectStore(storeName);
204
+ try {
205
+ const transaction = this.db.transaction(storeName, "readwrite");
206
+ const store = transaction.objectStore(storeName);
181
207
 
182
- for (const key of keys) {
183
- store.delete(key);
184
- }
208
+ for (const key of keys) {
209
+ store.delete(key);
210
+ }
185
211
 
186
- transaction.oncomplete = () => resolve();
187
- transaction.onerror = () => reject(transaction.error);
188
- transaction.onabort = () => reject(new Error("Transaction aborted"));
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
- const transaction = this.db.transaction(storeName, "readwrite");
195
- const store = transaction.objectStore(storeName);
196
- const request = store.clear();
197
-
198
- request.onsuccess = () => resolve();
199
- request.onerror = () => reject(request.error);
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
- const request = options?.version
323
- ? indexedDB.open(name, options.version)
324
- : indexedDB.open(name);
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
- request.onblocked = () => {
329
- setTimeout(() => {
330
- reject(new Error("Database upgrade blocked - close other tabs"));
331
- }, 3000);
332
- };
363
+ request.onerror = () => reject(request.error);
333
364
 
334
- request.onupgradeneeded = (event) => {
335
- if (options?.onUpgrade) {
336
- const db = request.result;
337
- const transaction = (event.target as IDBOpenDBRequest).transaction;
338
- if (!transaction) {
339
- reject(new Error("No transaction during upgrade"));
340
- return;
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
- // Create an upgrade-mode database wrapper
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
- request.onsuccess = () => resolve(new NativeIDBDatabase(request.result));
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
  };