@firtoz/drizzle-indexeddb 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/CHANGELOG.md ADDED
@@ -0,0 +1,139 @@
1
+ # @firtoz/drizzle-indexeddb
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#22](https://github.com/firtoz/fullstack-toolkit/pull/22) [`05e88e7`](https://github.com/firtoz/fullstack-toolkit/commit/05e88e775f262488d1da2b579eadd560cee2eba9) Thanks [@firtoz](https://github.com/firtoz)! - Initial release of `@firtoz/drizzle-indexeddb` - TanStack DB collections backed by IndexedDB with automatic migrations powered by Drizzle ORM snapshots.
8
+
9
+ > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
10
+
11
+ **Note:** This package currently builds on top of Drizzle's SQLite integration (using `drizzle-orm/sqlite-core` types and snapshots) until Drizzle adds native IndexedDB support. The migration system reads Drizzle's SQLite snapshots and translates them into IndexedDB object stores and indexes.
12
+
13
+ ## Features
14
+
15
+ ### TanStack DB Collections (Primary Feature)
16
+
17
+ **`indexedDBCollectionOptions(config)`** - The main feature: Create reactive TanStack DB collections backed by IndexedDB:
18
+
19
+ - Full CRUD operations with type safety
20
+ - Reactive subscriptions to data changes
21
+ - Soft delete support (respects `deletedAt` column)
22
+ - Automatic pagination and sorting
23
+ - Query optimization with IndexedDB indexes
24
+ - Sync configuration for real-time updates
25
+ - Works seamlessly with React hooks
26
+
27
+ ### Snapshot-Based Migration
28
+
29
+ **`migrateIndexedDB(dbName, config, debug?)`** - Automatically migrates IndexedDB databases using Drizzle snapshot files:
30
+
31
+ - Reads Drizzle journal and snapshot files
32
+ - Tracks applied migrations in `__drizzle_migrations` store
33
+ - Creates/updates object stores and indexes based on schema changes
34
+ - Handles table deletion, index changes, and schema evolution
35
+ - Incremental migrations - only applies pending changes
36
+ - Validates primary key structure changes (requires manual migration if keys change)
37
+ - Performance logging when debug mode is enabled
38
+
39
+ ### Function-Based Migration
40
+
41
+ **`migrateIndexedDBWithFunctions(dbName, migrations, debug?)`** - Run migrations using custom migration functions:
42
+
43
+ - Execute custom migration logic for complex schema changes
44
+ - Full control over IndexedDB transaction and database during migration
45
+ - Tracks applied migrations automatically
46
+ - Ideal for data transformations and complex schema changes
47
+
48
+ ### React Context & Hooks
49
+
50
+ **`DrizzleIndexedDBProvider`** - React context provider for IndexedDB:
51
+
52
+ - Manages IndexedDB connection lifecycle
53
+ - Provides collection access with automatic caching
54
+ - Reference counting for memory management
55
+
56
+ **`useDrizzleIndexedDB()`** - React hook for accessing IndexedDB context:
57
+
58
+ - Get collection instances with type safety
59
+ - Automatic ref counting for cleanup
60
+
61
+ **`useIndexedDBCollection(tableName)`** - React hook for using specific collections:
62
+
63
+ - Automatic ref counting and cleanup
64
+ - Type-safe collection access
65
+
66
+ ### Utilities
67
+
68
+ **`deleteIndexedDB(dbName)`** - Utility to completely delete an IndexedDB database
69
+
70
+ ## Example
71
+
72
+ ```typescript
73
+ import { migrateIndexedDB } from "@firtoz/drizzle-indexeddb";
74
+ import journal from "./drizzle/journal.json";
75
+ import * as snapshots from "./drizzle/snapshots";
76
+
77
+ // Migrate database using Drizzle snapshots
78
+ const db = await migrateIndexedDB(
79
+ "my-app-db",
80
+ {
81
+ journal,
82
+ snapshots,
83
+ },
84
+ true
85
+ ); // debug mode
86
+
87
+ // Use with TanStack DB
88
+ import { createCollection } from "@tanstack/db";
89
+ import { indexedDBCollectionOptions } from "@firtoz/drizzle-indexeddb";
90
+
91
+ const todosCollection = createCollection(
92
+ indexedDBCollectionOptions({
93
+ db,
94
+ tableName: "todos",
95
+ })
96
+ );
97
+
98
+ // React integration
99
+ import {
100
+ DrizzleIndexedDBProvider,
101
+ useDrizzleIndexedDB,
102
+ } from "@firtoz/drizzle-indexeddb";
103
+
104
+ function App() {
105
+ return (
106
+ <DrizzleIndexedDBProvider db={db} schema={schema}>
107
+ <TodoList />
108
+ </DrizzleIndexedDBProvider>
109
+ );
110
+ }
111
+
112
+ function TodoList() {
113
+ const { getCollection } = useDrizzleIndexedDB();
114
+ const todos = getCollection("todos");
115
+
116
+ // Use collection with TanStack DB hooks...
117
+ }
118
+ ```
119
+
120
+ ## Migration Workflow
121
+
122
+ 1. Generate Drizzle snapshots: `drizzle-kit generate`
123
+ 2. Import journal and snapshots
124
+ 3. Call `migrateIndexedDB()` on app startup
125
+ 4. Database automatically updates to latest schema
126
+
127
+ ## Dependencies
128
+
129
+ - `@firtoz/drizzle-utils` (workspace)
130
+ - `drizzle-orm`
131
+ - `drizzle-valibot`
132
+ - `@tanstack/db`
133
+ - `valibot`
134
+ - `react` (peer dependency)
135
+
136
+ ### Patch Changes
137
+
138
+ - Updated dependencies [[`05e88e7`](https://github.com/firtoz/fullstack-toolkit/commit/05e88e775f262488d1da2b579eadd560cee2eba9)]:
139
+ - @firtoz/drizzle-utils@0.1.0
package/README.md ADDED
@@ -0,0 +1,477 @@
1
+ # @firtoz/drizzle-indexeddb
2
+
3
+ TanStack DB collections backed by IndexedDB with automatic migrations powered by Drizzle ORM snapshots. Build reactive, type-safe IndexedDB applications with the power of Drizzle's schema management.
4
+
5
+ > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
6
+
7
+ > **Note:** This package currently builds on top of Drizzle's SQLite integration (using `drizzle-orm/sqlite-core` types and snapshots) until Drizzle adds native IndexedDB support. The migration system reads Drizzle's SQLite snapshots and translates them into IndexedDB object stores and indexes.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @firtoz/drizzle-indexeddb @firtoz/drizzle-utils drizzle-orm @tanstack/db
13
+ ```
14
+
15
+ ## Features
16
+
17
+ - ⚡ **TanStack DB collections** - Reactive collections with type safety (primary feature)
18
+ - 🎯 **Type-safe** - Full TypeScript support with automatic type inference
19
+ - 🔍 **Query optimization** - Leverage IndexedDB indexes for fast queries
20
+ - 📦 **Soft deletes** - Built-in support for `deletedAt` column
21
+ - ⚛️ **React hooks** - Provider and hooks for easy React integration
22
+ - 🔄 **Snapshot-based migrations** - Use Drizzle's generated snapshots to migrate IndexedDB
23
+ - 📝 **Function-based migrations** - Write custom migration functions for complex changes
24
+
25
+ ## Quick Start
26
+
27
+ ### 1. Setup Drizzle Schema
28
+
29
+ ```typescript
30
+ // schema.ts
31
+ import { syncableTable } from "@firtoz/drizzle-utils";
32
+ import { text, integer } from "drizzle-orm/sqlite-core";
33
+
34
+ export const todoTable = syncableTable("todos", {
35
+ title: text("title").notNull(),
36
+ completed: integer("completed", { mode: "boolean" }).notNull().default(false),
37
+ });
38
+ ```
39
+
40
+ ### 2. Generate Migrations
41
+
42
+ ```bash
43
+ # Generate Drizzle snapshots
44
+ drizzle-kit generate
45
+ ```
46
+
47
+ ### 3. Migrate IndexedDB
48
+
49
+ ```typescript
50
+ // db.ts
51
+ import { migrateIndexedDB } from "@firtoz/drizzle-indexeddb";
52
+ import journal from "./drizzle/meta/_journal.json";
53
+ import * as snapshots from "./drizzle/snapshots";
54
+
55
+ export const db = await migrateIndexedDB("my-app", {
56
+ journal,
57
+ snapshots,
58
+ }, true); // Enable debug logging
59
+ ```
60
+
61
+ ### 4. Use with React
62
+
63
+ ```typescript
64
+ // App.tsx
65
+ import { DrizzleIndexedDBProvider, useIndexedDBCollection } from "@firtoz/drizzle-indexeddb";
66
+ import { createCollection } from "@tanstack/db";
67
+
68
+ function App() {
69
+ return (
70
+ <DrizzleIndexedDBProvider db={db} schema={schema}>
71
+ <TodoList />
72
+ </DrizzleIndexedDBProvider>
73
+ );
74
+ }
75
+
76
+ function TodoList() {
77
+ const collection = useIndexedDBCollection("todos");
78
+ const [todos] = collection.useStore();
79
+
80
+ return (
81
+ <ul>
82
+ {todos.map(todo => (
83
+ <li key={todo.id}>{todo.title}</li>
84
+ ))}
85
+ </ul>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ## TanStack DB Collections
91
+
92
+ The primary feature of this package: Create reactive, type-safe collections backed by IndexedDB.
93
+
94
+ ### Basic Usage
95
+
96
+ Create reactive collections backed by IndexedDB:
97
+
98
+ ```typescript
99
+ import { createCollection } from "@tanstack/db";
100
+ import { indexedDBCollectionOptions } from "@firtoz/drizzle-indexeddb";
101
+
102
+ const todosCollection = createCollection(
103
+ indexedDBCollectionOptions({
104
+ db,
105
+ tableName: "todos",
106
+ syncMode: "on-demand", // or "realtime"
107
+ })
108
+ );
109
+
110
+ // Subscribe to changes
111
+ const unsubscribe = todosCollection.subscribe((todos) => {
112
+ console.log("Todos updated:", todos);
113
+ });
114
+
115
+ // CRUD operations
116
+ await todosCollection.insert({
117
+ title: "Buy milk",
118
+ completed: false,
119
+ });
120
+
121
+ await todosCollection.update(todoId, {
122
+ completed: true,
123
+ });
124
+
125
+ await todosCollection.delete(todoId); // Soft delete (sets deletedAt)
126
+
127
+ // Query with filters
128
+ const completedTodos = await todosCollection.find({
129
+ where: { completed: true },
130
+ orderBy: { createdAt: "desc" },
131
+ limit: 10,
132
+ });
133
+ ```
134
+
135
+ ### Collection Options
136
+
137
+ ```typescript
138
+ interface IndexedDBCollectionConfig {
139
+ db: IDBDatabase;
140
+ tableName: string;
141
+ syncMode?: "on-demand" | "realtime";
142
+ debug?: boolean;
143
+ }
144
+ ```
145
+
146
+ ### Supported Operations
147
+
148
+ - **Insert** - Add new records
149
+ - **Update** - Modify existing records
150
+ - **Delete** - Soft delete (sets `deletedAt`) or hard delete
151
+ - **Find** - Query with filters, sorting, pagination
152
+ - **Subscribe** - React to data changes
153
+
154
+ ### Query Features
155
+
156
+ ```typescript
157
+ // Filtering
158
+ collection.find({
159
+ where: {
160
+ completed: false,
161
+ title: { contains: "urgent" },
162
+ priority: { in: ["high", "critical"] },
163
+ createdAt: { gt: yesterday },
164
+ }
165
+ });
166
+
167
+ // Sorting
168
+ collection.find({
169
+ orderBy: { createdAt: "desc" }
170
+ });
171
+
172
+ // Pagination
173
+ collection.find({
174
+ limit: 10,
175
+ offset: 20,
176
+ });
177
+
178
+ // Soft delete filtering (automatic)
179
+ // By default, records with deletedAt !== null are excluded
180
+ ```
181
+
182
+ ## Migration Methods
183
+
184
+ ### Snapshot-Based Migration
185
+
186
+ Use Drizzle's snapshot files to automatically migrate your IndexedDB schema:
187
+
188
+ ```typescript
189
+ import { migrateIndexedDB } from "@firtoz/drizzle-indexeddb";
190
+ import journal from "./drizzle/meta/_journal.json";
191
+ import * as snapshots from "./drizzle/snapshots";
192
+
193
+ const db = await migrateIndexedDB("my-app-db", {
194
+ journal,
195
+ snapshots,
196
+ }, true); // debug flag
197
+
198
+ console.log("Database migrated successfully!");
199
+ ```
200
+
201
+ **Features:**
202
+ - Automatically creates/updates object stores
203
+ - Manages indexes based on Drizzle schema
204
+ - Handles table deletion
205
+ - Tracks applied migrations
206
+ - Validates primary key changes
207
+ - Incremental migrations (only applies pending changes)
208
+
209
+ **Migration Tracking:**
210
+
211
+ Migrations are tracked in the `__drizzle_migrations` object store:
212
+
213
+ ```typescript
214
+ interface MigrationRecord {
215
+ id: number; // Migration index
216
+ tag: string; // Migration name
217
+ when: number; // Migration timestamp
218
+ appliedAt: number; // When it was applied
219
+ }
220
+ ```
221
+
222
+ ### Function-Based Migration
223
+
224
+ For complex migrations that require custom logic:
225
+
226
+ ```typescript
227
+ import { migrateIndexedDBWithFunctions } from "@firtoz/drizzle-indexeddb";
228
+
229
+ const migrations = [
230
+ // Migration 0: Initial schema
231
+ async (db: IDBDatabase, transaction: IDBTransaction) => {
232
+ const store = db.createObjectStore("todos", { keyPath: "id" });
233
+ store.createIndex("title", "title", { unique: false });
234
+ },
235
+
236
+ // Migration 1: Add completed index
237
+ async (db: IDBDatabase, transaction: IDBTransaction) => {
238
+ const store = transaction.objectStore("todos");
239
+ store.createIndex("completed", "completed", { unique: false });
240
+ },
241
+
242
+ // Migration 2: Transform data
243
+ async (db: IDBDatabase, transaction: IDBTransaction) => {
244
+ const store = transaction.objectStore("todos");
245
+ const todos = await new Promise<any[]>((resolve, reject) => {
246
+ const req = store.getAll();
247
+ req.onsuccess = () => resolve(req.result);
248
+ req.onerror = () => reject(req.error);
249
+ });
250
+
251
+ // Transform data
252
+ for (const todo of todos) {
253
+ todo.priority = todo.priority || "medium";
254
+ store.put(todo);
255
+ }
256
+ },
257
+ ];
258
+
259
+ const db = await migrateIndexedDBWithFunctions("my-app-db", migrations, true);
260
+ ```
261
+
262
+ ## React Integration
263
+
264
+ ### DrizzleIndexedDBProvider
265
+
266
+ Wrap your app with the provider:
267
+
268
+ ```typescript
269
+ import { DrizzleIndexedDBProvider } from "@firtoz/drizzle-indexeddb";
270
+
271
+ function App() {
272
+ return (
273
+ <DrizzleIndexedDBProvider db={db} schema={schema}>
274
+ <YourApp />
275
+ </DrizzleIndexedDBProvider>
276
+ );
277
+ }
278
+ ```
279
+
280
+ ### useDrizzleIndexedDB
281
+
282
+ Access the context:
283
+
284
+ ```typescript
285
+ import { useDrizzleIndexedDB } from "@firtoz/drizzle-indexeddb";
286
+
287
+ function MyComponent() {
288
+ const { getCollection } = useDrizzleIndexedDB();
289
+
290
+ const todosCollection = getCollection("todos");
291
+ const usersCollection = getCollection("users");
292
+
293
+ // Use collections...
294
+ }
295
+ ```
296
+
297
+ **Features:**
298
+ - Collection caching (same collection instance for same table)
299
+ - Reference counting for memory management
300
+ - Type-safe collection access
301
+
302
+ ### useIndexedDBCollection
303
+
304
+ Hook for a specific collection:
305
+
306
+ ```typescript
307
+ import { useIndexedDBCollection } from "@firtoz/drizzle-indexeddb";
308
+
309
+ function TodoList() {
310
+ const collection = useIndexedDBCollection("todos");
311
+
312
+ // Automatic ref counting and cleanup
313
+ useEffect(() => {
314
+ return () => {
315
+ // Collection automatically cleaned up when component unmounts
316
+ };
317
+ }, []);
318
+
319
+ // Use collection...
320
+ }
321
+ ```
322
+
323
+ ## Utilities
324
+
325
+ ### deleteIndexedDB
326
+
327
+ Completely delete an IndexedDB database:
328
+
329
+ ```typescript
330
+ import { deleteIndexedDB } from "@firtoz/drizzle-indexeddb";
331
+
332
+ await deleteIndexedDB("my-app-db");
333
+ console.log("Database deleted!");
334
+ ```
335
+
336
+ Useful for:
337
+ - Resetting the database during development
338
+ - Clearing user data on logout
339
+ - Testing scenarios
340
+
341
+ ## Advanced Usage
342
+
343
+ ### Custom Sync Configuration
344
+
345
+ ```typescript
346
+ import { indexedDBCollectionOptions } from "@firtoz/drizzle-indexeddb";
347
+
348
+ const collection = createCollection(
349
+ indexedDBCollectionOptions({
350
+ db,
351
+ tableName: "todos",
352
+ syncMode: "realtime", // Subscribe to changes automatically
353
+ debug: true, // Enable debug logging
354
+ })
355
+ );
356
+ ```
357
+
358
+ ### Handling Migration Errors
359
+
360
+ ```typescript
361
+ try {
362
+ const db = await migrateIndexedDB("my-app", config, true);
363
+ } catch (error) {
364
+ console.error("Migration failed:", error);
365
+
366
+ // Option 1: Delete and start fresh
367
+ await deleteIndexedDB("my-app");
368
+ const db = await migrateIndexedDB("my-app", config, true);
369
+
370
+ // Option 2: Handle specific errors
371
+ if (error.message.includes("Primary key structure changed")) {
372
+ // Guide user to export data, delete DB, and reimport
373
+ }
374
+ }
375
+ ```
376
+
377
+ ### Performance Optimization
378
+
379
+ ```typescript
380
+ // Enable debug mode to see performance metrics
381
+ const db = await migrateIndexedDB("my-app", config, true);
382
+
383
+ // Output shows:
384
+ // [PERF] IndexedDB snapshot migrator start for my-app
385
+ // [PERF] Latest applied migration index: 5 (checked 5 migrations)
386
+ // [PERF] Found 2 pending migrations to apply: ["add_priority", "add_category"]
387
+ // [PERF] Upgrade started: v5 → v7
388
+ // [PERF] Creating object store: categories
389
+ // [PERF] Creating index: name on categories
390
+ // [PERF] Migration 5 complete
391
+ // [PERF] Migration 6 complete
392
+ // [PERF] All 2 migrations applied successfully
393
+ // [PERF] Migrator complete - database ready
394
+ ```
395
+
396
+ ## Schema Changes
397
+
398
+ ### Adding a Column
399
+
400
+ Just update your schema and regenerate:
401
+
402
+ ```typescript
403
+ // Before
404
+ const todoTable = syncableTable("todos", {
405
+ title: text("title").notNull(),
406
+ });
407
+
408
+ // After
409
+ const todoTable = syncableTable("todos", {
410
+ title: text("title").notNull(),
411
+ priority: text("priority").notNull().default("medium"),
412
+ });
413
+ ```
414
+
415
+ ```bash
416
+ drizzle-kit generate
417
+ ```
418
+
419
+ The migrator handles it automatically!
420
+
421
+ ### Adding an Index
422
+
423
+ ```typescript
424
+ const todoTable = syncableTable("todos", {
425
+ title: text("title").notNull(),
426
+ completed: integer("completed", { mode: "boolean" }),
427
+ }, (table) => [
428
+ index("title_idx").on(table.title),
429
+ index("completed_idx").on(table.completed),
430
+ ]);
431
+ ```
432
+
433
+ ### Renaming a Column
434
+
435
+ Drizzle snapshots don't track renames directly, but you can:
436
+
437
+ 1. Use function-based migrations to handle data transformation
438
+ 2. Or: Add new column, copy data, delete old column (3 separate migrations)
439
+
440
+ ### Deleting a Table
441
+
442
+ Remove from schema and regenerate - the migrator will delete the object store.
443
+
444
+ ## Troubleshooting
445
+
446
+ ### "Primary key structure changed" Error
447
+
448
+ This happens when you change the primary key of a table. IndexedDB doesn't support changing keyPath after creation.
449
+
450
+ **Solution:**
451
+ 1. Export your data
452
+ 2. Delete the database: `await deleteIndexedDB("my-app")`
453
+ 3. Re-run migrations
454
+ 4. Import your data
455
+
456
+ ### Migrations Not Applying
457
+
458
+ - Check that journal and snapshots are correctly imported
459
+ - Verify the snapshot files exist in `drizzle/snapshots/`
460
+ - Enable debug mode to see what's happening
461
+ - Check browser DevTools → Application → IndexedDB
462
+
463
+ ### Performance Issues
464
+
465
+ - Add indexes to frequently queried columns
466
+ - Use `syncMode: "on-demand"` for collections that don't need real-time updates
467
+ - Consider pagination for large datasets
468
+ - Use `deletedAt` soft deletes instead of hard deletes for better performance
469
+
470
+ ## License
471
+
472
+ MIT
473
+
474
+ ## Author
475
+
476
+ Firtina Ozbalikchi <firtoz@github.com>
477
+
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@firtoz/drizzle-indexeddb",
3
+ "version": "0.1.0",
4
+ "description": "IndexedDB migrations powered by Drizzle ORM snapshots",
5
+ "main": "./src/index.ts",
6
+ "module": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./src/index.ts",
12
+ "import": "./src/index.ts",
13
+ "require": "./src/index.ts"
14
+ },
15
+ "./*": {
16
+ "types": "./src/*.ts",
17
+ "import": "./src/*.ts",
18
+ "require": "./src/*.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "src/**/*.ts",
23
+ "!src/**/*.test.ts",
24
+ "README.md",
25
+ "CHANGELOG.md"
26
+ ],
27
+ "scripts": {
28
+ "typecheck": "tsc --noEmit -p ./tsconfig.json",
29
+ "lint": "biome check --write src",
30
+ "lint:ci": "biome ci src",
31
+ "format": "biome format src --write",
32
+ "test": "bun test --pass-with-no-tests",
33
+ "test:watch": "bun test --watch"
34
+ },
35
+ "keywords": [
36
+ "typescript",
37
+ "indexeddb",
38
+ "drizzle",
39
+ "migrations"
40
+ ],
41
+ "author": "Firtina Ozbalikchi <firtoz@github.com>",
42
+ "license": "MIT",
43
+ "homepage": "https://github.com/firtoz/fullstack-toolkit#readme",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/firtoz/fullstack-toolkit.git",
47
+ "directory": "packages/drizzle-indexeddb"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/firtoz/fullstack-toolkit/issues"
51
+ },
52
+ "engines": {
53
+ "node": ">=18.0.0"
54
+ },
55
+ "publishConfig": {
56
+ "access": "public"
57
+ },
58
+ "dependencies": {
59
+ "@firtoz/drizzle-utils": "^0.1.0",
60
+ "@tanstack/db": "^0.5.0",
61
+ "drizzle-orm": "^0.44.7",
62
+ "drizzle-valibot": "^0.4.2",
63
+ "valibot": "^1.0.0"
64
+ },
65
+ "peerDependencies": {
66
+ "react": "^19.2.0"
67
+ },
68
+ "devDependencies": {
69
+ "@types/react": "^19.2.5"
70
+ }
71
+ }