@firtoz/drizzle-indexeddb 0.6.2 → 2.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @firtoz/drizzle-indexeddb
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3) Thanks [@firtoz](https://github.com/firtoz)! - BREAKING: Renamed Drizzle-specific exports with `Drizzle` prefix for clarity. `indexedDBCollectionOptions` → `drizzleIndexedDBCollectionOptions`, `IndexedDBCollectionConfig` → `DrizzleIndexedDBCollectionConfig`, `IndexedDBSyncItem` → `DrizzleIndexedDBSyncItem`. Removed `KeyRangeSpec` re-export (import from `@firtoz/idb-collections` instead). `tryExtractIndexedQuery` moved to `@firtoz/idb-collections`.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3), [`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3), [`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3), [`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3)]:
12
+ - @firtoz/idb-collections@0.2.0
13
+ - @firtoz/db-helpers@2.0.0
14
+ - @firtoz/drizzle-utils@1.0.1
15
+
16
+ ## 1.0.0
17
+
18
+ ### Major Changes
19
+
20
+ - [`3c7ce1d`](https://github.com/firtoz/fullstack-toolkit/commit/3c7ce1dbca5c5396386db9927ae7f5e19a562cf6) Thanks [@firtoz](https://github.com/firtoz)! - **IndexedDB proxy removed**
21
+
22
+ The IDB proxy layer (proxy client/server, transport, sync adapter) has been removed. Provider no longer exposes proxy sync; use native IndexedDB only.
23
+
24
+ **Upgrade:** If you were using the IDB proxy (e.g. `idb-proxy-client`, `idb-proxy-server`, `handleProxySync`, `onSyncReady`): remove that code. There is no replacement API; you implement the transport and call `receiveSync` with `SyncMessage[]` from `@firtoz/drizzle-utils` on each side.
25
+
26
+ **Remote / multi-context setup:** Use a **memory collection** (`@firtoz/db-helpers`) in the context that cannot access IndexedDB and keep the **IDB collection** where IndexedDB is available (source of truth). Implement your own channel (e.g. BroadcastChannel, `postMessage`, or WebSocket): when a context receives sync messages, call `utils.receiveSync(messages)` on its collection. Use `SyncMessage` from `@firtoz/db-helpers` (or `@firtoz/drizzle-utils`). The side that holds IDB can push initial state and updates as `SyncMessage[]` so the other side’s memory collection stays in sync.
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [[`3c7ce1d`](https://github.com/firtoz/fullstack-toolkit/commit/3c7ce1dbca5c5396386db9927ae7f5e19a562cf6), [`3c7ce1d`](https://github.com/firtoz/fullstack-toolkit/commit/3c7ce1dbca5c5396386db9927ae7f5e19a562cf6)]:
31
+ - @firtoz/db-helpers@1.0.0
32
+ - @firtoz/drizzle-utils@1.0.0
33
+
3
34
  ## 0.6.2
4
35
 
5
36
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firtoz/drizzle-indexeddb",
3
- "version": "0.6.2",
3
+ "version": "2.0.0",
4
4
  "description": "IndexedDB migrations powered by Drizzle ORM",
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
@@ -68,23 +68,26 @@
68
68
  "access": "public"
69
69
  },
70
70
  "peerDependencies": {
71
- "@firtoz/drizzle-utils": ">=0.3.3",
72
- "@tanstack/db": ">=0.5.25",
71
+ "@firtoz/drizzle-utils": ">=1.0.1",
72
+ "@tanstack/db": ">=0.5.33",
73
73
  "drizzle-orm": ">=0.45.1",
74
74
  "drizzle-valibot": ">=0.4.0",
75
75
  "react": ">=19.2.4",
76
76
  "valibot": ">=1.0.0"
77
77
  },
78
78
  "devDependencies": {
79
- "@firtoz/drizzle-utils": "^0.3.3",
80
- "@tanstack/db": "^0.5.25",
81
- "@types/react": "^19.2.13",
79
+ "@firtoz/drizzle-utils": "^1.0.1",
80
+ "@tanstack/db": "^0.5.33",
81
+ "@types/react": "^19.2.14",
82
82
  "drizzle-orm": "^0.45.1",
83
83
  "drizzle-valibot": "^0.4.2",
84
84
  "react": "^19.2.4",
85
85
  "valibot": "^1.2.0"
86
86
  },
87
87
  "dependencies": {
88
- "citty": "^0.2.0"
88
+ "@firtoz/db-helpers": "^2.0.0",
89
+ "@firtoz/idb-collections": "^0.2.0",
90
+ "@firtoz/maybe-error": "^1.5.2",
91
+ "citty": "^0.2.1"
89
92
  }
90
93
  }
@@ -0,0 +1,310 @@
1
+ import type { InferSchemaOutput, SyncMode } from "@tanstack/db";
2
+ import type { IR } from "@tanstack/db";
3
+ import { parseOrderByExpression } from "@tanstack/db";
4
+ import type { Table } from "drizzle-orm";
5
+
6
+ import {
7
+ type IdOf,
8
+ type SelectSchema,
9
+ type BaseSyncConfig,
10
+ type SyncBackend,
11
+ createSyncFunction,
12
+ createInsertSchemaWithDefaults,
13
+ createGetKeyFunction,
14
+ createCollectionConfig,
15
+ } from "@firtoz/drizzle-utils";
16
+ import { evaluateExpression } from "@firtoz/db-helpers";
17
+ import { tryExtractIndexedQuery } from "@firtoz/idb-collections";
18
+
19
+ import type { IDBDatabaseLike } from "../idb-types";
20
+
21
+ // biome-ignore lint/suspicious/noExplicitAny: intentional
22
+ type AnyId = IdOf<any>;
23
+
24
+ /**
25
+ * Type for items stored in IndexedDB (must have required sync fields)
26
+ */
27
+ export type DrizzleIndexedDBSyncItem = {
28
+ id: AnyId;
29
+ createdAt: Date;
30
+ updatedAt: Date;
31
+ deletedAt: Date | null;
32
+ [key: string]: unknown;
33
+ };
34
+
35
+ export interface DrizzleIndexedDBCollectionConfig<TTable extends Table> {
36
+ /**
37
+ * Ref to the IndexedDB database instance
38
+ */
39
+ indexedDBRef: React.RefObject<IDBDatabaseLike | null>;
40
+ /**
41
+ * The Drizzle table definition (used for schema and type inference only)
42
+ */
43
+ table: TTable;
44
+ /**
45
+ * The name of the IndexedDB object store (should match the table name)
46
+ */
47
+ storeName: string;
48
+ /**
49
+ * Promise that resolves when the database is ready
50
+ */
51
+ readyPromise: Promise<void>;
52
+ /**
53
+ * Sync mode: 'eager' (immediate) or 'on-demand'
54
+ */
55
+ syncMode?: SyncMode;
56
+ /**
57
+ * Enable debug logging for index discovery and query optimization
58
+ */
59
+ debug?: boolean;
60
+ }
61
+
62
+ /**
63
+ * Auto-discovers indexes from the IndexedDB store.
64
+ * Returns a map of field names to index names for single-column indexes.
65
+ */
66
+ function discoverIndexes(
67
+ db: IDBDatabaseLike,
68
+ storeName: string,
69
+ ): Record<string, string> {
70
+ const indexes = db.getStoreIndexes(storeName);
71
+ const indexMap: Record<string, string> = {};
72
+
73
+ for (const index of indexes) {
74
+ if (typeof index.keyPath === "string") {
75
+ indexMap[index.keyPath] = index.name;
76
+ }
77
+ }
78
+
79
+ return indexMap;
80
+ }
81
+
82
+ /**
83
+ * Creates a TanStack DB collection config for IndexedDB backed by Drizzle ORM.
84
+ */
85
+ export function drizzleIndexedDBCollectionOptions<const TTable extends Table>(
86
+ config: DrizzleIndexedDBCollectionConfig<TTable>,
87
+ ) {
88
+ let discoveredIndexes: Record<string, string> = {};
89
+ let indexesDiscovered = false;
90
+
91
+ const table = config.table;
92
+
93
+ const discoverIndexesOnce = async () => {
94
+ await config.readyPromise;
95
+
96
+ const db = config.indexedDBRef.current;
97
+ if (!db) {
98
+ throw new Error("Database not ready");
99
+ }
100
+
101
+ if (!indexesDiscovered) {
102
+ discoveredIndexes = discoverIndexes(db, config.storeName);
103
+
104
+ indexesDiscovered = true;
105
+ }
106
+ };
107
+
108
+ const backend: SyncBackend<TTable> = {
109
+ initialLoad: async () => {
110
+ const db = config.indexedDBRef.current;
111
+ if (!db) {
112
+ throw new Error("Database not ready");
113
+ }
114
+
115
+ await discoverIndexesOnce();
116
+
117
+ const items = await db.getAll<DrizzleIndexedDBSyncItem>(config.storeName);
118
+
119
+ return items as unknown as InferSchemaOutput<SelectSchema<TTable>>[];
120
+ },
121
+ loadSubset: async (options) => {
122
+ const db = config.indexedDBRef.current;
123
+ if (!db) {
124
+ throw new Error("Database not ready");
125
+ }
126
+
127
+ if (!indexesDiscovered) {
128
+ discoveredIndexes = discoverIndexes(db, config.storeName);
129
+ indexesDiscovered = true;
130
+ }
131
+
132
+ let items: DrizzleIndexedDBSyncItem[];
133
+
134
+ let combinedWhere = options.where;
135
+ if (options.cursor?.whereFrom) {
136
+ if (combinedWhere) {
137
+ combinedWhere = {
138
+ type: "func",
139
+ name: "and",
140
+ args: [combinedWhere, options.cursor.whereFrom],
141
+ } as IR.Func;
142
+ } else {
143
+ combinedWhere = options.cursor.whereFrom;
144
+ }
145
+ }
146
+
147
+ const indexedQuery = combinedWhere
148
+ ? tryExtractIndexedQuery(combinedWhere, discoveredIndexes, config.debug)
149
+ : null;
150
+
151
+ if (indexedQuery) {
152
+ items = await db.getAllByIndex<DrizzleIndexedDBSyncItem>(
153
+ config.storeName,
154
+ indexedQuery.indexName,
155
+ indexedQuery.keyRange,
156
+ );
157
+ } else {
158
+ items = await db.getAll<DrizzleIndexedDBSyncItem>(config.storeName);
159
+
160
+ if (combinedWhere) {
161
+ const whereExpression = combinedWhere;
162
+ items = items.filter((item) =>
163
+ evaluateExpression(
164
+ whereExpression,
165
+ item as Record<string, unknown>,
166
+ ),
167
+ );
168
+ }
169
+ }
170
+
171
+ if (options.orderBy) {
172
+ const sorts = parseOrderByExpression(options.orderBy);
173
+ items.sort((a, b) => {
174
+ for (const sort of sorts) {
175
+ // biome-ignore lint/suspicious/noExplicitAny: Need any for dynamic field access
176
+ let aValue: any = a;
177
+ // biome-ignore lint/suspicious/noExplicitAny: Need any for dynamic field access
178
+ let bValue: any = b;
179
+ for (const fieldName of sort.field) {
180
+ aValue = aValue?.[fieldName];
181
+ bValue = bValue?.[fieldName];
182
+ }
183
+
184
+ if (aValue < bValue) {
185
+ return sort.direction === "asc" ? -1 : 1;
186
+ }
187
+ if (aValue > bValue) {
188
+ return sort.direction === "asc" ? 1 : -1;
189
+ }
190
+ }
191
+ return 0;
192
+ });
193
+ }
194
+
195
+ if (options.offset !== undefined && options.offset > 0) {
196
+ items = items.slice(options.offset);
197
+ }
198
+
199
+ if (options.limit !== undefined) {
200
+ items = items.slice(0, options.limit);
201
+ }
202
+
203
+ return items as unknown as InferSchemaOutput<SelectSchema<TTable>>[];
204
+ },
205
+
206
+ handleInsert: async (itemsToInsert) => {
207
+ const db = config.indexedDBRef.current;
208
+ if (!db) {
209
+ throw new Error("Database not ready");
210
+ }
211
+
212
+ await db.add(config.storeName, itemsToInsert);
213
+
214
+ return itemsToInsert;
215
+ },
216
+
217
+ handleUpdate: async (mutations) => {
218
+ const db = config.indexedDBRef.current;
219
+
220
+ if (!db) {
221
+ throw new Error("Database not ready");
222
+ }
223
+
224
+ const results: Array<InferSchemaOutput<SelectSchema<TTable>>> = [];
225
+ const itemsToUpdate: DrizzleIndexedDBSyncItem[] = [];
226
+
227
+ for (const mutation of mutations) {
228
+ const existing = await db.get<DrizzleIndexedDBSyncItem>(
229
+ config.storeName,
230
+ mutation.key,
231
+ );
232
+
233
+ if (existing) {
234
+ const updateTime = new Date();
235
+ const updatedItem = {
236
+ ...existing,
237
+ ...mutation.changes,
238
+ updatedAt: updateTime,
239
+ } as DrizzleIndexedDBSyncItem;
240
+
241
+ itemsToUpdate.push(updatedItem);
242
+ results.push(
243
+ updatedItem as unknown as InferSchemaOutput<SelectSchema<TTable>>,
244
+ );
245
+ } else {
246
+ results.push(mutation.original);
247
+ }
248
+ }
249
+
250
+ if (itemsToUpdate.length > 0) {
251
+ await db.put(config.storeName, itemsToUpdate);
252
+ }
253
+
254
+ return results;
255
+ },
256
+
257
+ handleDelete: async (mutations) => {
258
+ const db = config.indexedDBRef.current;
259
+
260
+ if (!db) {
261
+ throw new Error("Database not ready");
262
+ }
263
+
264
+ const keysToDelete: IDBValidKey[] = mutations.map((m) => m.key);
265
+
266
+ await db.delete(config.storeName, keysToDelete);
267
+ },
268
+
269
+ handleTruncate: async () => {
270
+ const db = config.indexedDBRef.current;
271
+
272
+ if (!db) {
273
+ throw new Error("Database not ready");
274
+ }
275
+
276
+ await db.clear(config.storeName);
277
+ },
278
+ };
279
+
280
+ const wrappedBackend: SyncBackend<TTable> = {
281
+ ...backend,
282
+ initialLoad: async () => {
283
+ if (config.syncMode === "eager" || !config.syncMode) {
284
+ return await backend.initialLoad();
285
+ }
286
+
287
+ await discoverIndexesOnce();
288
+
289
+ return [];
290
+ },
291
+ };
292
+
293
+ const baseSyncConfig: BaseSyncConfig<TTable> = {
294
+ table,
295
+ readyPromise: config.readyPromise,
296
+ syncMode: config.syncMode,
297
+ debug: config.debug,
298
+ };
299
+
300
+ const syncResult = createSyncFunction(baseSyncConfig, wrappedBackend);
301
+
302
+ const schema = createInsertSchemaWithDefaults(table);
303
+
304
+ return createCollectionConfig({
305
+ schema,
306
+ getKey: createGetKeyFunction<TTable>(),
307
+ syncResult,
308
+ syncMode: config.syncMode,
309
+ });
310
+ }
@@ -16,16 +16,16 @@ import {
16
16
  } from "@tanstack/db";
17
17
  import { getTableName, type Table } from "drizzle-orm";
18
18
  import {
19
- indexedDBCollectionOptions,
20
- type IndexedDBCollectionConfig,
19
+ drizzleIndexedDBCollectionOptions,
20
+ type DrizzleIndexedDBCollectionConfig,
21
21
  } from "@firtoz/drizzle-indexeddb";
22
+ import type { CollectionUtils } from "@firtoz/db-helpers";
22
23
  import type {
23
24
  IdOf,
24
25
  InsertSchema,
25
26
  SelectSchema,
26
27
  GetTableFromSchema,
27
28
  InferCollectionFromTable,
28
- CollectionUtils,
29
29
  } from "@firtoz/drizzle-utils";
30
30
  import {
31
31
  type Migration,
@@ -33,7 +33,6 @@ import {
33
33
  } from "../function-migrator";
34
34
  import type { IDBCreator, IDBDatabaseLike } from "../idb-types";
35
35
  import { openIndexedDb } from "../idb-operations";
36
- import type { IDBProxySyncMessage } from "../proxy/idb-proxy-types";
37
36
 
38
37
  interface CollectionCacheEntry {
39
38
  // biome-ignore lint/suspicious/noExplicitAny: Cache needs to store collections of various types
@@ -65,11 +64,6 @@ export type DrizzleIndexedDBContextValue<
65
64
  ) => IndexedDbCollection<TSchema, TTableName>;
66
65
  incrementRefCount: (tableName: string) => void;
67
66
  decrementRefCount: (tableName: string) => void;
68
- /**
69
- * Handle a sync message from a proxy server.
70
- * Routes the message to the appropriate collection's external sync handler.
71
- */
72
- handleProxySync: (message: IDBProxySyncMessage) => void;
73
67
  };
74
68
 
75
69
  export const DrizzleIndexedDBContext =
@@ -94,18 +88,6 @@ type DrizzleIndexedDBProviderProps<TSchema extends Record<string, unknown>> =
94
88
  * Use createInstrumentedDbCreator() to track IndexedDB operations.
95
89
  */
96
90
  dbCreator?: IDBCreator;
97
- /**
98
- * Called when the sync handler is ready.
99
- * Use this to connect proxy sync messages to the provider.
100
- *
101
- * @example
102
- * const proxyClient = ...;
103
- * <DrizzleIndexedDBProvider
104
- * onSyncReady={(handleSync) => proxyClient.onSync(handleSync)}
105
- * ...
106
- * />
107
- */
108
- onSyncReady?: (handleSync: (message: IDBProxySyncMessage) => void) => void;
109
91
  }>;
110
92
 
111
93
  export function DrizzleIndexedDBProvider<
@@ -119,7 +101,6 @@ export function DrizzleIndexedDBProvider<
119
101
  debug = false,
120
102
  syncMode = "eager",
121
103
  dbCreator,
122
- onSyncReady,
123
104
  }: DrizzleIndexedDBProviderProps<TSchema>) {
124
105
  const [indexedDB, setIndexedDB] = useState<IDBDatabaseLike | null>(null);
125
106
  const indexedDBRef = useRef<IDBDatabaseLike | null>(null);
@@ -192,14 +173,14 @@ export function DrizzleIndexedDBProvider<
192
173
  const actualTableName = getTableName(table);
193
174
 
194
175
  // Create collection options
195
- const collectionConfig = indexedDBCollectionOptions({
176
+ const collectionConfig = drizzleIndexedDBCollectionOptions({
196
177
  indexedDBRef,
197
178
  table,
198
179
  storeName: actualTableName,
199
180
  readyPromise: readyPromise.promise,
200
181
  debug,
201
182
  syncMode,
202
- } as IndexedDBCollectionConfig<Table>);
183
+ } as DrizzleIndexedDBCollectionConfig<Table>);
203
184
 
204
185
  // Create new collection and cache it with ref count 0
205
186
  // The collection will wait for readyPromise before accessing the database
@@ -248,80 +229,14 @@ export function DrizzleIndexedDBProvider<
248
229
  [collections],
249
230
  );
250
231
 
251
- // Handle proxy sync messages by routing to the appropriate collection
252
- const handleProxySync: DrizzleIndexedDBContextValue<TSchema>["handleProxySync"] =
253
- useCallback(
254
- (message: IDBProxySyncMessage) => {
255
- // Find the collection for this store by checking the schema
256
- for (const [tableName, table] of Object.entries(schema)) {
257
- const actualStoreName = getTableName(table as Table);
258
- if (actualStoreName === message.storeName) {
259
- const entry = collections.get(tableName);
260
- if (entry) {
261
- const { pushExternalSync } = entry.collection.utils;
262
- // Route sync message to collection
263
- switch (message.type) {
264
- case "sync:add":
265
- pushExternalSync({
266
- type: "insert",
267
- items: message.items,
268
- });
269
- break;
270
- case "sync:put":
271
- pushExternalSync({
272
- type: "update",
273
- items: message.items,
274
- });
275
- break;
276
- case "sync:delete":
277
- // For delete, construct items with id
278
- pushExternalSync({
279
- type: "delete",
280
- items: message.keys.map((key) => ({ id: key })),
281
- });
282
- break;
283
- case "sync:truncate":
284
- pushExternalSync({
285
- type: "truncate",
286
- });
287
- break;
288
- }
289
- }
290
- return;
291
- }
292
- }
293
-
294
- if (debug) {
295
- console.warn(
296
- `[DrizzleIndexedDBProvider] No collection found for store: ${message.storeName}`,
297
- );
298
- }
299
- },
300
- [collections, schema, debug],
301
- );
302
-
303
- // Call onSyncReady when handleProxySync is available
304
- useEffect(() => {
305
- if (onSyncReady) {
306
- onSyncReady(handleProxySync);
307
- }
308
- }, [onSyncReady, handleProxySync]);
309
-
310
232
  const contextValue: DrizzleIndexedDBContextValue<TSchema> = useMemo(
311
233
  () => ({
312
234
  indexedDB,
313
235
  getCollection,
314
236
  incrementRefCount,
315
237
  decrementRefCount,
316
- handleProxySync,
317
238
  }),
318
- [
319
- indexedDB,
320
- getCollection,
321
- incrementRefCount,
322
- decrementRefCount,
323
- handleProxySync,
324
- ],
239
+ [indexedDB, getCollection, incrementRefCount, decrementRefCount],
325
240
  );
326
241
 
327
242
  return (
@@ -1,5 +1,6 @@
1
1
  // IndexedDB migrator with declarative migration format
2
2
 
3
+ import { exhaustiveGuard } from "@firtoz/maybe-error";
3
4
  import type { IDBCreator, IDBDatabaseLike } from "./idb-types";
4
5
  import { openIndexedDb } from "./idb-operations";
5
6
 
@@ -107,6 +108,8 @@ function executeMigrationOperation(
107
108
  }
108
109
  break;
109
110
  }
111
+ default:
112
+ exhaustiveGuard(op);
110
113
  }
111
114
  }
112
115
 
package/src/idb-types.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { KeyRangeSpec } from "@firtoz/idb-collections";
2
+
1
3
  /**
2
4
  * Index information returned by getStoreIndexes
3
5
  */
@@ -21,18 +23,6 @@ export interface CreateIndexOptions {
21
23
  unique?: boolean;
22
24
  }
23
25
 
24
- /**
25
- * Key range specification for index queries
26
- */
27
- export interface KeyRangeSpec {
28
- type: "only" | "lowerBound" | "upperBound" | "bound";
29
- value?: unknown;
30
- lower?: unknown;
31
- upper?: unknown;
32
- lowerOpen?: boolean;
33
- upperOpen?: boolean;
34
- }
35
-
36
26
  /**
37
27
  * Minimal database interface with high-level async operations.
38
28
  * This is the interface that custom implementations (mocks, Chrome extension proxies, etc.) need to implement.
package/src/index.ts CHANGED
@@ -17,7 +17,6 @@ export type {
17
17
  IndexInfo,
18
18
  CreateStoreOptions,
19
19
  CreateIndexOptions,
20
- KeyRangeSpec,
21
20
  } from "./idb-types";
22
21
 
23
22
  // IDB Interceptor (for testing/debugging)
@@ -34,10 +33,10 @@ export { createInstrumentedDbCreator } from "./instrumented-idb-database";
34
33
 
35
34
  // Collection
36
35
  export {
37
- indexedDBCollectionOptions,
38
- type IndexedDBCollectionConfig,
39
- type IndexedDBSyncItem,
40
- } from "./collections/indexeddb-collection";
36
+ drizzleIndexedDBCollectionOptions,
37
+ type DrizzleIndexedDBCollectionConfig,
38
+ type DrizzleIndexedDBSyncItem,
39
+ } from "./collections/drizzle-indexeddb-collection";
41
40
 
42
41
  // Standalone Collection (for use outside React)
43
42
  export {
@@ -59,30 +58,3 @@ export {
59
58
  useDrizzleIndexedDB,
60
59
  type UseDrizzleIndexedDBContextReturn,
61
60
  } from "./context/useDrizzleIndexedDB";
62
-
63
- // IDB Proxy (for Chrome extension, messaging-based IDB access)
64
- export {
65
- // Types
66
- type IDBProxyRequest,
67
- type IDBProxyRequestBody,
68
- type IDBProxyResponse,
69
- type IDBProxySyncMessage,
70
- generateRequestId,
71
- generateClientId,
72
- // Transport
73
- type IDBProxyClientTransport,
74
- type IDBProxyServerTransport,
75
- createInMemoryTransport,
76
- createMultiClientTransport,
77
- // Client
78
- IDBProxyClient,
79
- createProxyIDbCreator,
80
- type SyncHandler,
81
- // Server
82
- IDBProxyServer,
83
- createProxyServer,
84
- type IDBProxyServerOptions,
85
- // Sync adapter (connects proxy sync to collection)
86
- createCollectionSyncHandler,
87
- combineSyncHandlers,
88
- } from "./proxy";
@@ -1,3 +1,4 @@
1
+ import type { KeyRangeSpec } from "@firtoz/idb-collections";
1
2
  import type {
2
3
  IDBDatabaseLike,
3
4
  IDBCreator,
@@ -5,7 +6,6 @@ import type {
5
6
  IndexInfo,
6
7
  CreateStoreOptions,
7
8
  CreateIndexOptions,
8
- KeyRangeSpec,
9
9
  } from "./idb-types";
10
10
  import type { IDBInterceptor } from "./idb-interceptor";
11
11
  import { defaultIDBCreator } from "./native-idb-database";
@@ -1,3 +1,5 @@
1
+ import { exhaustiveGuard } from "@firtoz/maybe-error";
2
+ import type { KeyRangeSpec } from "@firtoz/idb-collections";
1
3
  import type {
2
4
  IDBDatabaseLike,
3
5
  IDBCreator,
@@ -5,7 +7,6 @@ import type {
5
7
  IndexInfo,
6
8
  CreateStoreOptions,
7
9
  CreateIndexOptions,
8
- KeyRangeSpec,
9
10
  } from "./idb-types";
10
11
 
11
12
  /**
@@ -26,6 +27,8 @@ function createKeyRange(spec: KeyRangeSpec): IDBKeyRange {
26
27
  spec.lowerOpen,
27
28
  spec.upperOpen,
28
29
  );
30
+ default:
31
+ exhaustiveGuard(spec.type);
29
32
  }
30
33
  }
31
34