@firtoz/drizzle-indexeddb 4.0.1 → 5.0.1
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 +26 -0
- package/README.md +9 -1
- package/dist/bin/generate-migrations.d.ts +15 -0
- package/dist/bin/generate-migrations.js +184 -0
- package/dist/bin/generate-migrations.js.map +1 -0
- package/dist/chunk-5KCMKETG.js +212 -0
- package/dist/chunk-5KCMKETG.js.map +1 -0
- package/dist/chunk-7X4EIKN4.js +128 -0
- package/dist/chunk-7X4EIKN4.js.map +1 -0
- package/dist/chunk-CPLA7X66.js +129 -0
- package/dist/chunk-CPLA7X66.js.map +1 -0
- package/dist/chunk-HJFI7QKW.js +28 -0
- package/dist/chunk-HJFI7QKW.js.map +1 -0
- package/dist/chunk-JVUF63L6.js +27 -0
- package/dist/chunk-JVUF63L6.js.map +1 -0
- package/dist/chunk-OSOLYU2M.js +126 -0
- package/dist/chunk-OSOLYU2M.js.map +1 -0
- package/dist/chunk-WMCUJFEC.js +311 -0
- package/dist/chunk-WMCUJFEC.js.map +1 -0
- package/dist/chunk-Y6XE3FVT.js +147 -0
- package/dist/chunk-Y6XE3FVT.js.map +1 -0
- package/dist/collections/drizzle-indexeddb-collection.d.ts +62 -0
- package/dist/collections/drizzle-indexeddb-collection.js +3 -0
- package/dist/collections/drizzle-indexeddb-collection.js.map +1 -0
- package/dist/context/DrizzleIndexedDBProvider.d.ts +35 -0
- package/dist/context/DrizzleIndexedDBProvider.js +7 -0
- package/dist/context/DrizzleIndexedDBProvider.js.map +1 -0
- package/dist/context/useDrizzleIndexedDB.d.ts +17 -0
- package/dist/context/useDrizzleIndexedDB.js +8 -0
- package/dist/context/useDrizzleIndexedDB.js.map +1 -0
- package/dist/function-migrator.d.ts +56 -0
- package/dist/function-migrator.js +5 -0
- package/dist/function-migrator.js.map +1 -0
- package/dist/idb-interceptor.d.ts +68 -0
- package/dist/idb-interceptor.js +3 -0
- package/dist/idb-interceptor.js.map +1 -0
- package/dist/idb-operations.d.ts +13 -0
- package/dist/idb-operations.js +4 -0
- package/dist/idb-operations.js.map +1 -0
- package/dist/idb-types.d.ts +82 -0
- package/dist/idb-types.js +3 -0
- package/dist/idb-types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumented-idb-database.d.ts +17 -0
- package/dist/instrumented-idb-database.js +4 -0
- package/dist/instrumented-idb-database.js.map +1 -0
- package/dist/native-idb-database.d.ts +9 -0
- package/dist/native-idb-database.js +3 -0
- package/dist/native-idb-database.js.map +1 -0
- package/dist/standalone-collection.d.ts +154 -0
- package/dist/standalone-collection.js +7 -0
- package/dist/standalone-collection.js.map +1 -0
- package/package.json +34 -29
- package/src/collections/drizzle-indexeddb-collection.ts +4 -4
- package/src/context/DrizzleIndexedDBProvider.tsx +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/function-migrator.ts"],"names":[],"mappings":"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","file":"chunk-7X4EIKN4.js","sourcesContent":["// IndexedDB migrator with declarative migration format\n\nimport { exhaustiveGuard } from \"@firtoz/maybe-error\";\nimport type { IDBCreator, IDBDatabaseLike } from \"./idb-types\";\nimport { openIndexedDb } from \"./idb-operations\";\n\n// ============================================================================\n// Declarative Migration Types\n// ============================================================================\n\nexport interface CreateTableOperation {\n\ttype: \"createTable\";\n\tname: string;\n\tkeyPath?: string;\n\tautoIncrement?: boolean;\n\tindexes?: Array<{\n\t\tname: string;\n\t\tkeyPath: string | string[];\n\t\tunique?: boolean;\n\t}>;\n}\n\nexport interface DeleteTableOperation {\n\ttype: \"deleteTable\";\n\tname: string;\n}\n\nexport interface CreateIndexOperation {\n\ttype: \"createIndex\";\n\ttableName: string;\n\tindexName: string;\n\tkeyPath: string | string[];\n\tunique?: boolean;\n}\n\nexport interface DeleteIndexOperation {\n\ttype: \"deleteIndex\";\n\ttableName: string;\n\tindexName: string;\n}\n\nexport type MigrationOperation =\n\t| CreateTableOperation\n\t| DeleteTableOperation\n\t| CreateIndexOperation\n\t| DeleteIndexOperation;\n\n/** A migration is an array of operations to perform */\nexport type Migration = MigrationOperation[];\n\n// ============================================================================\n// Migration Record\n// ============================================================================\n\ninterface MigrationRecord {\n\tid: number;\n\tappliedAt: number;\n}\n\nconst MIGRATIONS_STORE = \"__drizzle_migrations\";\n\n// ============================================================================\n// Migration Executor\n// ============================================================================\n\n/**\n * Executes a single migration operation on the database.\n */\nfunction executeMigrationOperation(\n\tdb: IDBDatabaseLike,\n\top: MigrationOperation,\n): void {\n\tswitch (op.type) {\n\t\tcase \"createTable\": {\n\t\t\tif (!db.hasStore(op.name)) {\n\t\t\t\tdb.createStore(op.name, {\n\t\t\t\t\tkeyPath: op.keyPath,\n\t\t\t\t\tautoIncrement: op.autoIncrement,\n\t\t\t\t});\n\t\t\t\t// Create indexes if specified\n\t\t\t\tif (op.indexes) {\n\t\t\t\t\tfor (const idx of op.indexes) {\n\t\t\t\t\t\tdb.createIndex(op.name, idx.name, idx.keyPath, {\n\t\t\t\t\t\t\tunique: idx.unique,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase \"deleteTable\": {\n\t\t\tif (db.hasStore(op.name)) {\n\t\t\t\tdb.deleteStore(op.name);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase \"createIndex\": {\n\t\t\tif (db.hasStore(op.tableName)) {\n\t\t\t\tdb.createIndex(op.tableName, op.indexName, op.keyPath, {\n\t\t\t\t\tunique: op.unique,\n\t\t\t\t});\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase \"deleteIndex\": {\n\t\t\tif (db.hasStore(op.tableName)) {\n\t\t\t\tdb.deleteIndex(op.tableName, op.indexName);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\texhaustiveGuard(op);\n\t}\n}\n\n/**\n * Executes a full migration (array of operations).\n */\nfunction executeMigration(db: IDBDatabaseLike, migration: Migration): void {\n\tfor (const op of migration) {\n\t\texecuteMigrationOperation(db, op);\n\t}\n}\n\n// ============================================================================\n// Main Migrator\n// ============================================================================\n\n/**\n * Runs IndexedDB migrations using declarative migration arrays.\n * Version = total migrations + 1.\n *\n * Example usage:\n * ```typescript\n * const migrations: Migration[] = [\n * [\n * { type: \"createTable\", name: \"todo\", keyPath: \"id\", indexes: [\n * { name: \"todo_user_id\", keyPath: \"user_id\" }\n * ]}\n * ],\n * [\n * { type: \"createTable\", name: \"user\", keyPath: \"id\" }\n * ]\n * ];\n *\n * const db = await migrateIndexedDBWithFunctions('my-db', migrations);\n * ```\n */\nexport async function migrateIndexedDBWithFunctions(\n\tdbName: string,\n\tmigrations: Migration[],\n\tdebug: boolean = false,\n\tdbCreator?: IDBCreator,\n): Promise<IDBDatabaseLike> {\n\tif (debug) {\n\t\tconsole.log(`[IndexedDB] Starting migration for ${dbName}`);\n\t}\n\n\tconst targetVersion = migrations.length + 1;\n\n\t// Open database to check current state\n\tlet db = await openIndexedDb(dbName, dbCreator);\n\tconst currentVersion = db.version;\n\n\tif (debug) {\n\t\tconsole.log(\n\t\t\t`[IndexedDB] Current version: ${currentVersion}, Target: ${targetVersion}`,\n\t\t);\n\t}\n\n\t// If already at target version, check if all migrations are recorded\n\tif (currentVersion >= targetVersion) {\n\t\tconst applied = await getAppliedMigrations(db);\n\t\tif (applied.length === migrations.length) {\n\t\t\tif (debug) {\n\t\t\t\tconsole.log(\"[IndexedDB] Already up to date\");\n\t\t\t}\n\t\t\treturn db;\n\t\t}\n\t}\n\n\t// Get applied migrations before closing\n\tconst appliedMigrations = await getAppliedMigrations(db);\n\tconst appliedSet = new Set(appliedMigrations.map((m) => m.id));\n\n\t// Find pending migrations\n\tconst pendingMigrations = migrations\n\t\t.map((migration, idx) => ({ migration, idx }))\n\t\t.filter(({ idx }) => !appliedSet.has(idx));\n\n\tif (pendingMigrations.length === 0) {\n\t\tif (debug) {\n\t\t\tconsole.log(\"[IndexedDB] No pending migrations\");\n\t\t}\n\t\treturn db;\n\t}\n\n\tif (debug) {\n\t\tconsole.log(\n\t\t\t`[IndexedDB] ${pendingMigrations.length} pending migrations to apply`,\n\t\t);\n\t}\n\n\t// Close to allow version upgrade\n\tdb.close();\n\n\t// Open with target version, running migrations during upgrade\n\tawait openIndexedDb(dbName, dbCreator, {\n\t\tversion: targetVersion,\n\t\tonUpgrade: (upgradeDb) => {\n\t\t\t// Ensure migrations store exists\n\t\t\tif (!upgradeDb.hasStore(MIGRATIONS_STORE)) {\n\t\t\t\tupgradeDb.createStore(MIGRATIONS_STORE, {\n\t\t\t\t\tkeyPath: \"id\",\n\t\t\t\t\tautoIncrement: false,\n\t\t\t\t});\n\t\t\t\tif (debug) {\n\t\t\t\t\tconsole.log(\"[IndexedDB] Created migrations store\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run pending migrations\n\t\t\tfor (const { migration, idx } of pendingMigrations) {\n\t\t\t\tif (debug) {\n\t\t\t\t\tconsole.log(`[IndexedDB] Running migration ${idx}`);\n\t\t\t\t}\n\t\t\t\texecuteMigration(upgradeDb, migration);\n\t\t\t}\n\t\t},\n\t});\n\n\t// Reopen normally and record applied migrations\n\tdb = await openIndexedDb(dbName, dbCreator);\n\n\tfor (const { idx } of pendingMigrations) {\n\t\tawait db.add(MIGRATIONS_STORE, [{ id: idx, appliedAt: Date.now() }]);\n\t}\n\n\tif (debug) {\n\t\tconsole.log(\n\t\t\t`[IndexedDB] Applied ${pendingMigrations.length} migrations, now at version ${targetVersion}`,\n\t\t);\n\t}\n\n\treturn db;\n}\n\n/**\n * Gets applied migrations from the database.\n */\nasync function getAppliedMigrations(\n\tdb: IDBDatabaseLike,\n): Promise<MigrationRecord[]> {\n\tif (!db.hasStore(MIGRATIONS_STORE)) {\n\t\treturn [];\n\t}\n\treturn db.getAll<MigrationRecord>(MIGRATIONS_STORE);\n}\n"]}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { drizzleIndexedDBCollectionOptions } from './chunk-5KCMKETG.js';
|
|
2
|
+
import { migrateIndexedDBWithFunctions } from './chunk-7X4EIKN4.js';
|
|
3
|
+
import { openIndexedDb } from './chunk-JVUF63L6.js';
|
|
4
|
+
import { createCollection } from '@tanstack/db';
|
|
5
|
+
|
|
6
|
+
function createStandaloneCollection(config) {
|
|
7
|
+
const {
|
|
8
|
+
dbName,
|
|
9
|
+
table,
|
|
10
|
+
storeName = table._.name,
|
|
11
|
+
migrations = [],
|
|
12
|
+
dbCreator,
|
|
13
|
+
debug = false,
|
|
14
|
+
syncMode = "eager"
|
|
15
|
+
} = config;
|
|
16
|
+
let resolveReady;
|
|
17
|
+
const readyPromise = new Promise((resolve) => {
|
|
18
|
+
resolveReady = resolve;
|
|
19
|
+
});
|
|
20
|
+
const indexedDBRef = { current: null };
|
|
21
|
+
const initDB = async () => {
|
|
22
|
+
try {
|
|
23
|
+
if (migrations.length === 0) {
|
|
24
|
+
if (debug) {
|
|
25
|
+
console.log(
|
|
26
|
+
`[StandaloneCollection] Opening database "${dbName}" directly`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
indexedDBRef.current = await openIndexedDb(dbName, dbCreator);
|
|
30
|
+
} else {
|
|
31
|
+
if (debug) {
|
|
32
|
+
console.log(`[StandaloneCollection] Migrating database "${dbName}"`);
|
|
33
|
+
}
|
|
34
|
+
indexedDBRef.current = await migrateIndexedDBWithFunctions(
|
|
35
|
+
dbName,
|
|
36
|
+
migrations,
|
|
37
|
+
debug,
|
|
38
|
+
dbCreator
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
if (debug) {
|
|
42
|
+
console.log(`[StandaloneCollection] Database "${dbName}" initialized`);
|
|
43
|
+
}
|
|
44
|
+
resolveReady();
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error(
|
|
47
|
+
`[StandaloneCollection] Failed to initialize database "${dbName}":`,
|
|
48
|
+
error
|
|
49
|
+
);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
initDB();
|
|
54
|
+
const collectionConfig = drizzleIndexedDBCollectionOptions({
|
|
55
|
+
indexedDBRef,
|
|
56
|
+
table,
|
|
57
|
+
storeName,
|
|
58
|
+
readyPromise,
|
|
59
|
+
debug,
|
|
60
|
+
syncMode
|
|
61
|
+
});
|
|
62
|
+
const collection = createCollection(
|
|
63
|
+
collectionConfig
|
|
64
|
+
);
|
|
65
|
+
const collectionReady = new Promise((resolve) => {
|
|
66
|
+
if (collection.isReady()) {
|
|
67
|
+
resolve();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
collection.preload();
|
|
71
|
+
collection.onFirstReady(() => resolve());
|
|
72
|
+
});
|
|
73
|
+
const ready = Promise.all([readyPromise, collectionReady]).then(() => {
|
|
74
|
+
});
|
|
75
|
+
const waitForPersist = async (transaction, callback) => {
|
|
76
|
+
if (callback) {
|
|
77
|
+
callback(transaction);
|
|
78
|
+
}
|
|
79
|
+
await transaction.isPersisted.promise;
|
|
80
|
+
return transaction;
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
ready,
|
|
84
|
+
isReady() {
|
|
85
|
+
return collection.isReady();
|
|
86
|
+
},
|
|
87
|
+
getAll() {
|
|
88
|
+
return collection.toArray;
|
|
89
|
+
},
|
|
90
|
+
get(key) {
|
|
91
|
+
return collection.state.get(key);
|
|
92
|
+
},
|
|
93
|
+
insert(data, callback) {
|
|
94
|
+
const items = Array.isArray(data) ? data : [data];
|
|
95
|
+
const transaction = collection.insert(
|
|
96
|
+
items
|
|
97
|
+
);
|
|
98
|
+
return waitForPersist(transaction, callback);
|
|
99
|
+
},
|
|
100
|
+
update(key, updater, callback) {
|
|
101
|
+
const transaction = collection.update(
|
|
102
|
+
key,
|
|
103
|
+
updater
|
|
104
|
+
);
|
|
105
|
+
return waitForPersist(transaction, callback);
|
|
106
|
+
},
|
|
107
|
+
delete(key, callback) {
|
|
108
|
+
const keys = Array.isArray(key) ? key : [key];
|
|
109
|
+
const transaction = collection.delete(keys);
|
|
110
|
+
return waitForPersist(transaction, callback);
|
|
111
|
+
},
|
|
112
|
+
truncate() {
|
|
113
|
+
return collection.utils.truncate();
|
|
114
|
+
},
|
|
115
|
+
utils: collection.utils,
|
|
116
|
+
collection,
|
|
117
|
+
get db() {
|
|
118
|
+
return indexedDBRef.current;
|
|
119
|
+
},
|
|
120
|
+
close() {
|
|
121
|
+
indexedDBRef.current?.close();
|
|
122
|
+
indexedDBRef.current = null;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export { createStandaloneCollection };
|
|
128
|
+
//# sourceMappingURL=chunk-CPLA7X66.js.map
|
|
129
|
+
//# sourceMappingURL=chunk-CPLA7X66.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/standalone-collection.ts"],"names":[],"mappings":"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","file":"chunk-CPLA7X66.js","sourcesContent":["import {\n\tcreateCollection,\n\ttype Collection,\n\ttype InferSchemaInput,\n\ttype InferSchemaOutput,\n\ttype SyncMode,\n\ttype Transaction,\n\ttype WritableDeep,\n} from \"@tanstack/db\";\nimport type { Table } from \"drizzle-orm\";\nimport type { CollectionUtils } from \"@firtoz/db-helpers\";\nimport type {\n\tIdOf,\n\tInsertSchema,\n\tInsertToSelectSchema,\n\tSelectSchema,\n} from \"@firtoz/drizzle-utils\";\nimport {\n\tdrizzleIndexedDBCollectionOptions,\n\ttype DrizzleIndexedDBCollectionConfig,\n} from \"./collections/drizzle-indexeddb-collection\";\nimport {\n\tmigrateIndexedDBWithFunctions,\n\ttype Migration,\n} from \"./function-migrator\";\nimport { openIndexedDb } from \"./idb-operations\";\nimport type { IDBCreator, IDBDatabaseLike } from \"./idb-types\";\n\n/**\n * Configuration for creating a standalone IndexedDB collection\n */\nexport interface StandaloneCollectionConfig<TTable extends Table> {\n\t/**\n\t * Name of the IndexedDB database\n\t */\n\tdbName: string;\n\t/**\n\t * The Drizzle table definition\n\t */\n\ttable: TTable;\n\t/**\n\t * The name of the IndexedDB object store (defaults to table name)\n\t */\n\tstoreName?: string;\n\t/**\n\t * Migrations to apply (optional)\n\t */\n\tmigrations?: Migration[];\n\t/**\n\t * Custom database creator (for testing/mocking)\n\t */\n\tdbCreator?: IDBCreator;\n\t/**\n\t * Enable debug logging\n\t */\n\tdebug?: boolean;\n\t/**\n\t * Sync mode: 'eager' (immediate) or 'lazy' (on-demand)\n\t */\n\tsyncMode?: SyncMode;\n}\n\n/**\n * Type for the underlying collection\n */\ntype InternalCollection<TTable extends Table> = Collection<\n\tInferSchemaOutput<SelectSchema<TTable>>,\n\tIdOf<TTable>,\n\tCollectionUtils<InferSchemaOutput<SelectSchema<TTable>>>,\n\tInsertToSelectSchema<TTable>,\n\tInferSchemaInput<InsertSchema<TTable>>\n>;\n\n/**\n * Transaction type for mutations\n */\ntype MutationTransaction<TTable extends Table> = Transaction<\n\tInferSchemaOutput<SelectSchema<TTable>>\n>;\n\n/**\n * Insert input type (what you pass to insert)\n */\ntype InsertInput<TTable extends Table> = InferSchemaInput<InsertSchema<TTable>>;\n\n/**\n * Item type (what you get back from getAll, etc.)\n */\ntype ItemType<TTable extends Table> = InferSchemaOutput<SelectSchema<TTable>>;\n\n/**\n * Writable draft type for update callbacks\n */\ntype DraftType<TTable extends Table> = WritableDeep<InsertInput<TTable>>;\n\n/**\n * Standalone IndexedDB collection API\n */\nexport interface StandaloneCollection<TTable extends Table> {\n\t/**\n\t * Promise that resolves when the collection is ready\n\t */\n\tready: Promise<void>;\n\n\t/**\n\t * Check if the collection is ready (sync)\n\t */\n\tisReady(): boolean;\n\n\t/**\n\t * Get all items (sync - returns current state)\n\t */\n\tgetAll(): ItemType<TTable>[];\n\n\t/**\n\t * Get an item by key (sync)\n\t */\n\tget(key: IdOf<TTable>): ItemType<TTable> | undefined;\n\n\t/**\n\t * Insert item(s)\n\t * @returns Promise that resolves when persisted\n\t */\n\tinsert(\n\t\tdata: InsertInput<TTable> | InsertInput<TTable>[],\n\t\tcallback?: (transaction: MutationTransaction<TTable>) => void,\n\t): Promise<MutationTransaction<TTable>>;\n\n\t/**\n\t * Update an item by key using a callback that receives a draft\n\t * @returns Promise that resolves when persisted\n\t */\n\tupdate(\n\t\tkey: IdOf<TTable>,\n\t\tupdater: (draft: DraftType<TTable>) => void,\n\t\tcallback?: (transaction: MutationTransaction<TTable>) => void,\n\t): Promise<MutationTransaction<TTable>>;\n\n\t/**\n\t * Delete item(s) by key\n\t * @returns Promise that resolves when persisted\n\t */\n\tdelete(\n\t\tkey: IdOf<TTable> | IdOf<TTable>[],\n\t\tcallback?: (transaction: MutationTransaction<TTable>) => void,\n\t): Promise<MutationTransaction<TTable>>;\n\n\t/**\n\t * Clear all items from the store\n\t * @returns Promise that resolves when truncate is complete\n\t */\n\ttruncate(): Promise<void>;\n\n\t/**\n\t * Access to collection utils (truncate, receiveSync)\n\t */\n\tutils: CollectionUtils<ItemType<TTable>>;\n\n\t/**\n\t * The underlying TanStack DB collection (for advanced usage)\n\t */\n\tcollection: InternalCollection<TTable>;\n\n\t/**\n\t * The IndexedDB database instance (available after ready)\n\t */\n\tdb: IDBDatabaseLike | null;\n\n\t/**\n\t * Close the database connection\n\t */\n\tclose(): void;\n}\n\n/**\n * Create a standalone IndexedDB collection for use outside of React.\n *\n * @example\n * ```ts\n * const db = await createStandaloneCollection({\n * dbName: \"myapp.db\",\n * table: schema.todos,\n * migrations,\n * });\n *\n * // Wait for ready\n * await db.ready;\n *\n * // Get all items\n * const items = db.getAll();\n *\n * // Insert\n * await db.insert({ title: \"New todo\" });\n *\n * // Update\n * await db.update(itemId, { title: \"Updated\" });\n *\n * // Delete\n * await db.delete(itemId);\n *\n * // Truncate\n * await db.truncate();\n *\n * // Clean up\n * db.close();\n * ```\n */\nexport function createStandaloneCollection<TTable extends Table>(\n\tconfig: StandaloneCollectionConfig<TTable>,\n): StandaloneCollection<TTable> {\n\tconst {\n\t\tdbName,\n\t\ttable,\n\t\tstoreName = (table as unknown as { _: { name: string } })._.name,\n\t\tmigrations = [],\n\t\tdbCreator,\n\t\tdebug = false,\n\t\tsyncMode = \"eager\",\n\t} = config;\n\n\t// Create ready promise\n\tlet resolveReady: () => void;\n\tconst readyPromise = new Promise<void>((resolve) => {\n\t\tresolveReady = resolve;\n\t});\n\n\t// Database ref\n\tconst indexedDBRef: { current: IDBDatabaseLike | null } = { current: null };\n\n\t// Initialize database\n\tconst initDB = async () => {\n\t\ttry {\n\t\t\tif (migrations.length === 0) {\n\t\t\t\tif (debug) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`[StandaloneCollection] Opening database \"${dbName}\" directly`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tindexedDBRef.current = await openIndexedDb(dbName, dbCreator);\n\t\t\t} else {\n\t\t\t\tif (debug) {\n\t\t\t\t\tconsole.log(`[StandaloneCollection] Migrating database \"${dbName}\"`);\n\t\t\t\t}\n\t\t\t\tindexedDBRef.current = await migrateIndexedDBWithFunctions(\n\t\t\t\t\tdbName,\n\t\t\t\t\tmigrations,\n\t\t\t\t\tdebug,\n\t\t\t\t\tdbCreator,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (debug) {\n\t\t\t\tconsole.log(`[StandaloneCollection] Database \"${dbName}\" initialized`);\n\t\t\t}\n\n\t\t\tresolveReady();\n\t\t} catch (error) {\n\t\t\tconsole.error(\n\t\t\t\t`[StandaloneCollection] Failed to initialize database \"${dbName}\":`,\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\t// Start initialization\n\tinitDB();\n\n\t// Create collection config\n\tconst collectionConfig = drizzleIndexedDBCollectionOptions({\n\t\tindexedDBRef,\n\t\ttable,\n\t\tstoreName,\n\t\treadyPromise,\n\t\tdebug,\n\t\tsyncMode,\n\t} as DrizzleIndexedDBCollectionConfig<TTable>);\n\n\t// biome-ignore lint/suspicious/noExplicitAny: createCollection overloads can't resolve InsertToSelectSchema for generic TTable; collection is re-typed below\n\tconst collection = createCollection(\n\t\tcollectionConfig as any,\n\t) as unknown as InternalCollection<TTable>;\n\n\t// Wait for collection to be ready\n\tconst collectionReady = new Promise<void>((resolve) => {\n\t\tif (collection.isReady()) {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tcollection.preload();\n\t\tcollection.onFirstReady(() => resolve());\n\t});\n\n\t// Combined ready promise\n\tconst ready = Promise.all([readyPromise, collectionReady]).then(() => {});\n\n\t// Helper to wait for transaction to persist\n\tconst waitForPersist = async (\n\t\ttransaction: MutationTransaction<TTable>,\n\t\tcallback?: (transaction: MutationTransaction<TTable>) => void,\n\t): Promise<MutationTransaction<TTable>> => {\n\t\tif (callback) {\n\t\t\tcallback(transaction);\n\t\t}\n\t\tawait transaction.isPersisted.promise;\n\t\treturn transaction;\n\t};\n\n\treturn {\n\t\tready,\n\n\t\tisReady(): boolean {\n\t\t\treturn collection.isReady();\n\t\t},\n\n\t\tgetAll(): ItemType<TTable>[] {\n\t\t\treturn collection.toArray;\n\t\t},\n\n\t\tget(key: IdOf<TTable>): ItemType<TTable> | undefined {\n\t\t\treturn collection.state.get(key);\n\t\t},\n\n\t\tinsert(\n\t\t\tdata: InsertInput<TTable> | InsertInput<TTable>[],\n\t\t\tcallback?: (transaction: MutationTransaction<TTable>) => void,\n\t\t): Promise<MutationTransaction<TTable>> {\n\t\t\tconst items = (Array.isArray(data) ? data : [data]) as InferSchemaOutput<\n\t\t\t\tSelectSchema<TTable>\n\t\t\t>;\n\t\t\tconst transaction = collection.insert(\n\t\t\t\titems,\n\t\t\t) as MutationTransaction<TTable>;\n\t\t\treturn waitForPersist(transaction, callback);\n\t\t},\n\n\t\tupdate(\n\t\t\tkey: IdOf<TTable>,\n\t\t\tupdater: (draft: DraftType<TTable>) => void,\n\t\t\tcallback?: (transaction: MutationTransaction<TTable>) => void,\n\t\t): Promise<MutationTransaction<TTable>> {\n\t\t\tconst transaction = collection.update(\n\t\t\t\tkey,\n\t\t\t\tupdater,\n\t\t\t) as MutationTransaction<TTable>;\n\t\t\treturn waitForPersist(transaction, callback);\n\t\t},\n\n\t\tdelete(\n\t\t\tkey: IdOf<TTable> | IdOf<TTable>[],\n\t\t\tcallback?: (transaction: MutationTransaction<TTable>) => void,\n\t\t): Promise<MutationTransaction<TTable>> {\n\t\t\tconst keys = Array.isArray(key) ? key : [key];\n\t\t\tconst transaction = collection.delete(keys);\n\t\t\treturn waitForPersist(transaction, callback);\n\t\t},\n\n\t\ttruncate(): Promise<void> {\n\t\t\treturn collection.utils.truncate();\n\t\t},\n\n\t\tutils: collection.utils,\n\n\t\tcollection,\n\n\t\tget db(): IDBDatabaseLike | null {\n\t\t\treturn indexedDBRef.current;\n\t\t},\n\n\t\tclose(): void {\n\t\t\tindexedDBRef.current?.close();\n\t\t\tindexedDBRef.current = null;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DrizzleIndexedDBContext, useIndexedDBCollection } from './chunk-Y6XE3FVT.js';
|
|
2
|
+
import { useContext, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
function useDrizzleIndexedDB() {
|
|
5
|
+
const context = useContext(
|
|
6
|
+
DrizzleIndexedDBContext
|
|
7
|
+
);
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
"useDrizzleIndexedDBContext must be used within a DrizzleIndexedDBProvider"
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
const useCollection = useCallback(
|
|
14
|
+
(tableName) => (
|
|
15
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: This is on purpose.
|
|
16
|
+
useIndexedDBCollection(context, tableName)
|
|
17
|
+
),
|
|
18
|
+
[context]
|
|
19
|
+
);
|
|
20
|
+
return {
|
|
21
|
+
useCollection,
|
|
22
|
+
indexedDB: context.indexedDB
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { useDrizzleIndexedDB };
|
|
27
|
+
//# sourceMappingURL=chunk-HJFI7QKW.js.map
|
|
28
|
+
//# sourceMappingURL=chunk-HJFI7QKW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context/useDrizzleIndexedDB.ts"],"names":[],"mappings":";;;AAiBO,SAAS,mBAAA,GAE+B;AAC9C,EAAA,MAAM,OAAA,GAAU,UAAA;AAAA,IACf;AAAA,GACD;AAEA,EAAA,IAAI,CAAC,OAAA,EAAS;AACb,IAAA,MAAM,IAAI,KAAA;AAAA,MACT;AAAA,KACD;AAAA,EACD;AAEA,EAAA,MAAM,aAAA,GAAgB,WAAA;AAAA,IACrB,CAA4C,SAAA;AAAA;AAAA,MAE3C,sBAAA,CAAuB,SAAS,SAAS;AAAA,KAAA;AAAA,IAC1C,CAAC,OAAO;AAAA,GACT;AAEA,EAAA,OAAO;AAAA,IACN,aAAA;AAAA,IACA,WAAW,OAAA,CAAQ;AAAA,GACpB;AACD","file":"chunk-HJFI7QKW.js","sourcesContent":["import { useCallback, useContext } from \"react\";\nimport {\n\tDrizzleIndexedDBContext,\n\tuseIndexedDBCollection,\n\ttype DrizzleIndexedDBContextValue,\n} from \"./DrizzleIndexedDBProvider\";\nimport type { IDBDatabaseLike } from \"../idb-types\";\n\nexport type UseDrizzleIndexedDBContextReturn<\n\tTSchema extends Record<string, unknown>,\n> = {\n\tuseCollection: <TTableName extends keyof TSchema & string>(\n\t\ttableName: TTableName,\n\t) => ReturnType<typeof useIndexedDBCollection<TSchema, TTableName>>;\n\tindexedDB: IDBDatabaseLike | null;\n};\n\nexport function useDrizzleIndexedDB<\n\tTSchema extends Record<string, unknown>,\n>(): UseDrizzleIndexedDBContextReturn<TSchema> {\n\tconst context = useContext(\n\t\tDrizzleIndexedDBContext,\n\t) as DrizzleIndexedDBContextValue<TSchema> | null;\n\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useDrizzleIndexedDBContext must be used within a DrizzleIndexedDBProvider\",\n\t\t);\n\t}\n\n\tconst useCollection = useCallback(\n\t\t<TTableName extends keyof TSchema & string>(tableName: TTableName) =>\n\t\t\t// biome-ignore lint/correctness/useHookAtTopLevel: This is on purpose.\n\t\t\tuseIndexedDBCollection(context, tableName),\n\t\t[context],\n\t);\n\n\treturn {\n\t\tuseCollection,\n\t\tindexedDB: context.indexedDB,\n\t};\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defaultIDBCreator } from './chunk-WMCUJFEC.js';
|
|
2
|
+
|
|
3
|
+
// src/idb-operations.ts
|
|
4
|
+
async function openIndexedDb(name, dbCreator, options) {
|
|
5
|
+
const dbCreatorToUse = dbCreator ?? defaultIDBCreator;
|
|
6
|
+
return dbCreatorToUse(name, options);
|
|
7
|
+
}
|
|
8
|
+
var defaultIDBDeleter = (name) => {
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
try {
|
|
11
|
+
const request = indexedDB.deleteDatabase(name);
|
|
12
|
+
request.onerror = () => reject(request.error);
|
|
13
|
+
request.onsuccess = () => resolve();
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error("Error deleting database", error);
|
|
16
|
+
reject(error);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
async function deleteIndexedDB(dbName, dbDeleter) {
|
|
21
|
+
const dbDeleterToUse = dbDeleter ?? defaultIDBDeleter;
|
|
22
|
+
return dbDeleterToUse(dbName);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { deleteIndexedDB, openIndexedDb };
|
|
26
|
+
//# sourceMappingURL=chunk-JVUF63L6.js.map
|
|
27
|
+
//# sourceMappingURL=chunk-JVUF63L6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/idb-operations.ts"],"names":[],"mappings":";;;AAWA,eAAsB,aAAA,CACrB,IAAA,EACA,SAAA,EACA,OAAA,EAC2B;AAC3B,EAAA,MAAM,iBAAiB,SAAA,IAAa,iBAAA;AACpC,EAAA,OAAO,cAAA,CAAe,MAAM,OAAO,CAAA;AACpC;AAKA,IAAM,iBAAA,GAAgC,CAAC,IAAA,KAAgC;AACtE,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACvC,IAAA,IAAI;AACH,MAAA,MAAM,OAAA,GAAU,SAAA,CAAU,cAAA,CAAe,IAAI,CAAA;AAC7C,MAAA,OAAA,CAAQ,OAAA,GAAU,MAAM,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AAC5C,MAAA,OAAA,CAAQ,SAAA,GAAY,MAAM,OAAA,EAAQ;AAAA,IACnC,SAAS,KAAA,EAAO;AACf,MAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA;AAC9C,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,IACb;AAAA,EACD,CAAC,CAAA;AACF,CAAA;AAKA,eAAsB,eAAA,CACrB,QACA,SAAA,EACgB;AAChB,EAAA,MAAM,iBAAiB,SAAA,IAAa,iBAAA;AACpC,EAAA,OAAO,eAAe,MAAM,CAAA;AAC7B","file":"chunk-JVUF63L6.js","sourcesContent":["import type {\n\tIDBDatabaseLike,\n\tIDBCreator,\n\tIDBOpenOptions,\n\tIDBDeleter,\n} from \"./idb-types\";\nimport { defaultIDBCreator } from \"./native-idb-database\";\n\n/**\n * Opens an IndexedDB database using the provided creator or the default native implementation.\n */\nexport async function openIndexedDb(\n\tname: string,\n\tdbCreator?: IDBCreator,\n\toptions?: IDBOpenOptions,\n): Promise<IDBDatabaseLike> {\n\tconst dbCreatorToUse = dbCreator ?? defaultIDBCreator;\n\treturn dbCreatorToUse(name, options);\n}\n\n/**\n * Default IDB deleter that uses the native IndexedDB API.\n */\nconst defaultIDBDeleter: IDBDeleter = (name: string): Promise<void> => {\n\treturn new Promise((resolve, reject) => {\n\t\ttry {\n\t\t\tconst request = indexedDB.deleteDatabase(name);\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => resolve();\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Error deleting database\", error);\n\t\t\treject(error);\n\t\t}\n\t});\n};\n\n/**\n * Deletes an IndexedDB database (useful for testing)\n */\nexport async function deleteIndexedDB(\n\tdbName: string,\n\tdbDeleter?: IDBDeleter,\n): Promise<void> {\n\tconst dbDeleterToUse = dbDeleter ?? defaultIDBDeleter;\n\treturn dbDeleterToUse(dbName);\n}\n"]}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { defaultIDBCreator } from './chunk-WMCUJFEC.js';
|
|
2
|
+
|
|
3
|
+
// src/instrumented-idb-database.ts
|
|
4
|
+
var InstrumentedIDBDatabase = class {
|
|
5
|
+
constructor(db, interceptor) {
|
|
6
|
+
this.db = db;
|
|
7
|
+
this.interceptor = interceptor;
|
|
8
|
+
}
|
|
9
|
+
get version() {
|
|
10
|
+
return this.db.version;
|
|
11
|
+
}
|
|
12
|
+
// Schema operations (pass through without interception)
|
|
13
|
+
hasStore(storeName) {
|
|
14
|
+
return this.db.hasStore(storeName);
|
|
15
|
+
}
|
|
16
|
+
getStoreNames() {
|
|
17
|
+
return this.db.getStoreNames();
|
|
18
|
+
}
|
|
19
|
+
createStore(storeName, options) {
|
|
20
|
+
this.db.createStore(storeName, options);
|
|
21
|
+
}
|
|
22
|
+
deleteStore(storeName) {
|
|
23
|
+
this.db.deleteStore(storeName);
|
|
24
|
+
}
|
|
25
|
+
createIndex(storeName, indexName, keyPath, options) {
|
|
26
|
+
this.db.createIndex(storeName, indexName, keyPath, options);
|
|
27
|
+
}
|
|
28
|
+
deleteIndex(storeName, indexName) {
|
|
29
|
+
this.db.deleteIndex(storeName, indexName);
|
|
30
|
+
}
|
|
31
|
+
getStoreIndexes(storeName) {
|
|
32
|
+
return this.db.getStoreIndexes(storeName);
|
|
33
|
+
}
|
|
34
|
+
// Data operations (intercepted)
|
|
35
|
+
async getAll(storeName) {
|
|
36
|
+
const items = await this.db.getAll(storeName);
|
|
37
|
+
this.interceptor.onOperation?.({
|
|
38
|
+
type: "getAll",
|
|
39
|
+
storeName,
|
|
40
|
+
itemsReturned: items,
|
|
41
|
+
itemCount: items.length,
|
|
42
|
+
timestamp: Date.now()
|
|
43
|
+
});
|
|
44
|
+
return items;
|
|
45
|
+
}
|
|
46
|
+
async getAllByIndex(storeName, indexName, keyRange) {
|
|
47
|
+
const items = await this.db.getAllByIndex(
|
|
48
|
+
storeName,
|
|
49
|
+
indexName,
|
|
50
|
+
keyRange
|
|
51
|
+
);
|
|
52
|
+
this.interceptor.onOperation?.({
|
|
53
|
+
type: "index-getAll",
|
|
54
|
+
storeName,
|
|
55
|
+
indexName,
|
|
56
|
+
keyRange,
|
|
57
|
+
itemsReturned: items,
|
|
58
|
+
itemCount: items.length,
|
|
59
|
+
timestamp: Date.now()
|
|
60
|
+
});
|
|
61
|
+
return items;
|
|
62
|
+
}
|
|
63
|
+
async get(storeName, key) {
|
|
64
|
+
const item = await this.db.get(storeName, key);
|
|
65
|
+
this.interceptor.onOperation?.({
|
|
66
|
+
type: "get",
|
|
67
|
+
storeName,
|
|
68
|
+
key,
|
|
69
|
+
itemReturned: item,
|
|
70
|
+
timestamp: Date.now()
|
|
71
|
+
});
|
|
72
|
+
return item;
|
|
73
|
+
}
|
|
74
|
+
async add(storeName, items) {
|
|
75
|
+
await this.db.add(storeName, items);
|
|
76
|
+
this.interceptor.onOperation?.({
|
|
77
|
+
type: "add",
|
|
78
|
+
storeName,
|
|
79
|
+
items,
|
|
80
|
+
itemCount: items.length,
|
|
81
|
+
timestamp: Date.now()
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async put(storeName, items) {
|
|
85
|
+
await this.db.put(storeName, items);
|
|
86
|
+
this.interceptor.onOperation?.({
|
|
87
|
+
type: "put",
|
|
88
|
+
storeName,
|
|
89
|
+
items,
|
|
90
|
+
itemCount: items.length,
|
|
91
|
+
timestamp: Date.now()
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
async delete(storeName, keys) {
|
|
95
|
+
await this.db.delete(storeName, keys);
|
|
96
|
+
this.interceptor.onOperation?.({
|
|
97
|
+
type: "delete",
|
|
98
|
+
storeName,
|
|
99
|
+
keys,
|
|
100
|
+
keyCount: keys.length,
|
|
101
|
+
timestamp: Date.now()
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async clear(storeName) {
|
|
105
|
+
await this.db.clear(storeName);
|
|
106
|
+
this.interceptor.onOperation?.({
|
|
107
|
+
type: "clear",
|
|
108
|
+
storeName,
|
|
109
|
+
timestamp: Date.now()
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
close() {
|
|
113
|
+
this.db.close();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
function createInstrumentedDbCreator(interceptor, baseCreator) {
|
|
117
|
+
const creator = baseCreator ?? defaultIDBCreator;
|
|
118
|
+
return async (name, options) => {
|
|
119
|
+
const db = await creator(name, options);
|
|
120
|
+
return new InstrumentedIDBDatabase(db, interceptor);
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export { createInstrumentedDbCreator };
|
|
125
|
+
//# sourceMappingURL=chunk-OSOLYU2M.js.map
|
|
126
|
+
//# sourceMappingURL=chunk-OSOLYU2M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/instrumented-idb-database.ts"],"names":[],"mappings":"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","file":"chunk-OSOLYU2M.js","sourcesContent":["import type { KeyRangeSpec } from \"@firtoz/idb-collections\";\nimport type {\n\tIDBDatabaseLike,\n\tIDBCreator,\n\tIDBOpenOptions,\n\tIndexInfo,\n\tCreateStoreOptions,\n\tCreateIndexOptions,\n} from \"./idb-types\";\nimport type { IDBInterceptor } from \"./idb-interceptor\";\nimport { defaultIDBCreator } from \"./native-idb-database\";\n\n/**\n * A database wrapper that intercepts operations and reports them to an interceptor.\n * Useful for testing to verify what IndexedDB operations are actually performed.\n */\nclass InstrumentedIDBDatabase implements IDBDatabaseLike {\n\tconstructor(\n\t\tprivate db: IDBDatabaseLike,\n\t\tprivate interceptor: IDBInterceptor,\n\t) {}\n\n\tget version(): number {\n\t\treturn this.db.version;\n\t}\n\n\t// Schema operations (pass through without interception)\n\thasStore(storeName: string): boolean {\n\t\treturn this.db.hasStore(storeName);\n\t}\n\n\tgetStoreNames(): string[] {\n\t\treturn this.db.getStoreNames();\n\t}\n\n\tcreateStore(storeName: string, options?: CreateStoreOptions): void {\n\t\tthis.db.createStore(storeName, options);\n\t}\n\n\tdeleteStore(storeName: string): void {\n\t\tthis.db.deleteStore(storeName);\n\t}\n\n\tcreateIndex(\n\t\tstoreName: string,\n\t\tindexName: string,\n\t\tkeyPath: string | string[],\n\t\toptions?: CreateIndexOptions,\n\t): void {\n\t\tthis.db.createIndex(storeName, indexName, keyPath, options);\n\t}\n\n\tdeleteIndex(storeName: string, indexName: string): void {\n\t\tthis.db.deleteIndex(storeName, indexName);\n\t}\n\n\tgetStoreIndexes(storeName: string): IndexInfo[] {\n\t\treturn this.db.getStoreIndexes(storeName);\n\t}\n\n\t// Data operations (intercepted)\n\tasync getAll<T = unknown>(storeName: string): Promise<T[]> {\n\t\tconst items = await this.db.getAll<T>(storeName);\n\n\t\tthis.interceptor.onOperation?.({\n\t\t\ttype: \"getAll\",\n\t\t\tstoreName,\n\t\t\titemsReturned: items,\n\t\t\titemCount: items.length,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\n\t\treturn items;\n\t}\n\n\tasync getAllByIndex<T = unknown>(\n\t\tstoreName: string,\n\t\tindexName: string,\n\t\tkeyRange?: KeyRangeSpec,\n\t): Promise<T[]> {\n\t\tconst items = await this.db.getAllByIndex<T>(\n\t\t\tstoreName,\n\t\t\tindexName,\n\t\t\tkeyRange,\n\t\t);\n\n\t\tthis.interceptor.onOperation?.({\n\t\t\ttype: \"index-getAll\",\n\t\t\tstoreName,\n\t\t\tindexName,\n\t\t\tkeyRange: keyRange as unknown as IDBKeyRange | undefined,\n\t\t\titemsReturned: items,\n\t\t\titemCount: items.length,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\n\t\treturn items;\n\t}\n\n\tasync get<T = unknown>(\n\t\tstoreName: string,\n\t\tkey: IDBValidKey,\n\t): Promise<T | undefined> {\n\t\tconst item = await this.db.get<T>(storeName, key);\n\n\t\tthis.interceptor.onOperation?.({\n\t\t\ttype: \"get\",\n\t\t\tstoreName,\n\t\t\tkey,\n\t\t\titemReturned: item,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\n\t\treturn item;\n\t}\n\n\tasync add(storeName: string, items: unknown[]): Promise<void> {\n\t\tawait this.db.add(storeName, items);\n\n\t\tthis.interceptor.onOperation?.({\n\t\t\ttype: \"add\",\n\t\t\tstoreName,\n\t\t\titems,\n\t\t\titemCount: items.length,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\t}\n\n\tasync put(storeName: string, items: unknown[]): Promise<void> {\n\t\tawait this.db.put(storeName, items);\n\n\t\tthis.interceptor.onOperation?.({\n\t\t\ttype: \"put\",\n\t\t\tstoreName,\n\t\t\titems,\n\t\t\titemCount: items.length,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\t}\n\n\tasync delete(storeName: string, keys: IDBValidKey[]): Promise<void> {\n\t\tawait this.db.delete(storeName, keys);\n\n\t\tthis.interceptor.onOperation?.({\n\t\t\ttype: \"delete\",\n\t\t\tstoreName,\n\t\t\tkeys,\n\t\t\tkeyCount: keys.length,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\t}\n\n\tasync clear(storeName: string): Promise<void> {\n\t\tawait this.db.clear(storeName);\n\n\t\tthis.interceptor.onOperation?.({\n\t\t\ttype: \"clear\",\n\t\t\tstoreName,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\t}\n\n\tclose(): void {\n\t\tthis.db.close();\n\t}\n}\n\n/**\n * Creates an instrumented database creator that wraps operations with interception.\n * Use this for testing to verify what IndexedDB operations are performed.\n *\n * @example\n * const interceptor = { onOperation: (op) => console.log(op) };\n * const dbCreator = createInstrumentedDbCreator(interceptor);\n *\n * <DrizzleIndexedDBProvider dbCreator={dbCreator} ... />\n */\nexport function createInstrumentedDbCreator(\n\tinterceptor: IDBInterceptor,\n\tbaseCreator?: IDBCreator,\n): IDBCreator {\n\tconst creator = baseCreator ?? defaultIDBCreator;\n\n\treturn async (name: string, options?: IDBOpenOptions) => {\n\t\tconst db = await creator(name, options);\n\t\treturn new InstrumentedIDBDatabase(db, interceptor);\n\t};\n}\n"]}
|