@xylabs/indexed-db 4.4.31 → 4.4.33

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.
@@ -1,19 +1,17 @@
1
- import type { EmptyObject } from '@xylabs/object';
2
1
  import type { KeyValueStore } from '@xylabs/storage';
3
- import type { IDBPDatabase, StoreNames, StoreValue } from 'idb';
4
- import type { ObjectStore } from './ObjectStore.ts';
2
+ import type { DBSchema, IDBPDatabase, StoreKey, StoreNames, StoreValue } from 'idb';
5
3
  /**
6
4
  * An IndexedDB key/value store.
7
5
  */
8
- export declare class IndexedDbKeyValueStore<T extends EmptyObject> implements KeyValueStore<T, string> {
6
+ export declare class IndexedDbKeyValueStore<T extends DBSchema, S extends StoreNames<T>> implements KeyValueStore<StoreValue<T, S>, StoreKey<T, S>> {
9
7
  readonly dbName: string;
10
- readonly storeName: StoreNames<ObjectStore<T>>;
11
- constructor(dbName: string, storeName: StoreNames<ObjectStore<T>>);
8
+ readonly storeName: S;
9
+ constructor(dbName: string, storeName: S);
12
10
  clear?(): Promise<void>;
13
11
  delete(key: string): Promise<void>;
14
- get(key: string): Promise<T | undefined>;
15
- keys?(): Promise<string[]>;
16
- set(key: string, value: StoreValue<ObjectStore<T>, StoreNames<ObjectStore<T>>>): Promise<void>;
17
- withDb<R = T>(callback: (db: IDBPDatabase<ObjectStore<T>>) => Promise<R> | R): Promise<R>;
12
+ get(key: string): Promise<StoreValue<T, S> | undefined>;
13
+ keys?(): Promise<StoreKey<T, S>[]>;
14
+ set(key: string, value: StoreValue<T, S>): Promise<void>;
15
+ withDb<R = StoreValue<T, S>>(callback: (db: IDBPDatabase<T>) => Promise<R> | R): Promise<R>;
18
16
  }
19
17
  //# sourceMappingURL=IndexedDbKeyValueStore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IndexedDbKeyValueStore.d.ts","sourceRoot":"","sources":["../../src/IndexedDbKeyValueStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,KAAK,EACV,YAAY,EAAE,UAAU,EAAE,UAAU,EACrC,MAAM,KAAK,CAAA;AAEZ,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnD;;GAEG;AACH,qBAAa,sBAAsB,CAAC,CAAC,SAAS,WAAW,CAAE,YAAW,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAE,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;gBAA9D,MAAM,EAAE,MAAM,EAAW,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAE7E,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAMvB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAMxC,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAM1B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9F,MAAM,CAAC,CAAC,GAAG,CAAC,EAChB,QAAQ,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KACzC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;CAMnB"}
1
+ {"version":3,"file":"IndexedDbKeyValueStore.d.ts","sourceRoot":"","sources":["../../src/IndexedDbKeyValueStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAC/C,MAAM,KAAK,CAAA;AAIZ;;GAEG;AACH,qBAAa,sBAAsB,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7H,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAE,QAAQ,CAAC,SAAS,EAAE,CAAC;gBAArC,MAAM,EAAE,MAAM,EAAW,SAAS,EAAE,CAAC;IAEpD,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAMvB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC,GAAG,CAAC,GAAG,EAAE,MAAM;IAMf,IAAI,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAMlC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,KAC5B,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;CAMnB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/IndexDescription.ts","../../src/createStore.ts","../../src/withReadOnlyStore.ts","../../src/getExistingIndexes.ts","../../src/withDb.ts","../../src/IndexedDbKeyValueStore.ts","../../src/withReadWriteStore.ts"],"sourcesContent":["/**\n * The index direction (1 for ascending, -1 for descending)\n */\nexport type IndexDirection = -1 | 1\n\n/**\n * Description of index(es) to be created on a store\n */\nexport type IndexDescription = {\n /**\n * The key(s) to index\n */\n key: Record<string, IndexDirection>\n /**\n * Is the indexed value an array\n */\n multiEntry?: boolean\n /**\n * The name of the index\n */\n name?: string\n /**\n * If true, the index must enforce uniqueness on the key\n */\n unique?: boolean\n}\n\nexport const IndexSeparator = '-'\n\n/**\n * Given an index description, this will build the index\n * name in standard form\n * @param index The index description\n * @returns The index name in standard form\n */\nexport const buildStandardIndexName = (index: IndexDescription) => {\n const { key, unique } = index\n const prefix = unique ? 'UX' : 'IX'\n const indexKeys = Object.keys(key)\n return `${prefix}_${indexKeys.join(IndexSeparator)}`\n}\n","import type { Logger } from '@xylabs/logger'\nimport type { EmptyObject } from '@xylabs/object'\nimport type {\n IDBPDatabase, IndexNames, StoreNames,\n} from 'idb'\n\nimport {\n buildStandardIndexName,\n type IndexDescription,\n} from './IndexDescription.ts'\nimport type { ObjectStore } from './ObjectStore.ts'\n\nexport function createStore<T extends EmptyObject = EmptyObject>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n indexes: IndexDescription[],\n logger?: Logger,\n) {\n logger?.log(`Creating store ${storeName}`)\n // Create the store\n const store = db.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n for (const {\n key, multiEntry, unique,\n } of indexes) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = buildStandardIndexName({ key, unique }) as IndexNames<ObjectStore<T>, StoreNames<ObjectStore<T>>>\n console.log('createIndex', indexName, keys, { multiEntry, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type {\n IDBPDatabase, IDBPObjectStore, StoreNames,\n} from 'idb'\n\nimport type { ObjectStore } from './ObjectStore.ts'\n\nexport async function withReadOnlyStore<T extends EmptyObject = EmptyObject, R = T>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n callback: (store: IDBPObjectStore<ObjectStore<T>, [StoreNames<ObjectStore<T>>], StoreNames<ObjectStore<T>>, string>) => Promise<R> | R,\n): Promise<R> {\n const transaction = db.transaction(storeName, 'readonly')\n const store = transaction.objectStore(storeName)\n try {\n return await callback(store)\n } finally {\n await transaction.done\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type { IDBPDatabase, StoreNames } from 'idb'\n\nimport {\n type IndexDescription,\n type IndexDirection,\n} from './IndexDescription.ts'\nimport type { ObjectStore } from './ObjectStore.ts'\nimport { withReadOnlyStore } from './withReadOnlyStore.ts'\n\nexport async function getExistingIndexes<T extends EmptyObject = EmptyObject>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n): Promise<IndexDescription[]> {\n return await withReadOnlyStore(db, storeName, (store) => {\n return [...store.indexNames].map((indexName) => {\n const index = store.index(indexName)\n const key: Record<string, IndexDirection> = {}\n if (Array.isArray(index.keyPath)) {\n for (const keyPath of index.keyPath) {\n key[keyPath] = 1\n }\n } else {\n key[index.keyPath] = 1\n }\n const desc: IndexDescription = {\n name: indexName as string,\n key,\n unique: index.unique,\n multiEntry: index.multiEntry,\n }\n return desc\n })\n })\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type { IDBPDatabase } from 'idb'\nimport { openDB } from 'idb'\n\nimport type { ObjectStore } from './ObjectStore.ts'\n\nexport async function withDb<T extends EmptyObject = EmptyObject, R = T>(\n dbName: string,\n callback: (db: IDBPDatabase<ObjectStore<T>>) => Promise<R> | R,\n): Promise<R> {\n const db = await openDB<ObjectStore<T>>(dbName)\n try {\n return await callback(db)\n } finally {\n db.close()\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type { KeyValueStore } from '@xylabs/storage'\nimport type {\n IDBPDatabase, StoreNames, StoreValue,\n} from 'idb'\n\nimport type { ObjectStore } from './ObjectStore.ts'\nimport { withDb } from './withDb.ts'\n\n/**\n * An IndexedDB key/value store.\n */\nexport class IndexedDbKeyValueStore<T extends EmptyObject> implements KeyValueStore<T, string> {\n constructor(readonly dbName: string, readonly storeName: StoreNames<ObjectStore<T>>) {}\n\n async clear?(): Promise<void> {\n return await this.withDb((db) => {\n return db.clear(this.storeName)\n })\n }\n\n async delete(key: string): Promise<void> {\n return await this.withDb((db) => {\n return db.delete(this.storeName, key)\n })\n }\n\n async get(key: string): Promise<T | undefined> {\n return await this.withDb((db) => {\n return db.get(this.storeName, key) ?? undefined\n })\n }\n\n async keys?(): Promise<string[]> {\n return await this.withDb((db) => {\n return db.getAllKeys(this.storeName)\n })\n }\n\n async set(key: string, value: StoreValue<ObjectStore<T>, StoreNames<ObjectStore<T>>>): Promise<void> {\n return await this.withDb((db) => {\n return db.put(this.storeName, value, key)\n })\n }\n\n async withDb<R = T>(\n callback: (db: IDBPDatabase<ObjectStore<T>>) =>\n Promise<R> | R,\n ) {\n return await withDb<T, R>(this.dbName, (db) => {\n return callback(db)\n })\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type {\n IDBPDatabase, IDBPObjectStore, StoreNames,\n} from 'idb'\n\nimport type { ObjectStore } from './ObjectStore.ts'\n\nexport async function withReadWriteStore<T extends EmptyObject = EmptyObject, R = T>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n callback: (store: IDBPObjectStore<ObjectStore<T>, [StoreNames<ObjectStore<T>>], StoreNames<ObjectStore<T>>, string>) => Promise<R> | R,\n): Promise<R> {\n const transaction = db.transaction(storeName, 'readwrite')\n const store = transaction.objectStore(storeName)\n try {\n return await callback(store)\n } finally {\n await transaction.done\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/IndexDescription.ts","../../src/createStore.ts","../../src/withReadOnlyStore.ts","../../src/getExistingIndexes.ts","../../src/withDb.ts","../../src/IndexedDbKeyValueStore.ts","../../src/withReadWriteStore.ts"],"sourcesContent":["/**\n * The index direction (1 for ascending, -1 for descending)\n */\nexport type IndexDirection = -1 | 1\n\n/**\n * Description of index(es) to be created on a store\n */\nexport type IndexDescription = {\n /**\n * The key(s) to index\n */\n key: Record<string, IndexDirection>\n /**\n * Is the indexed value an array\n */\n multiEntry?: boolean\n /**\n * The name of the index\n */\n name?: string\n /**\n * If true, the index must enforce uniqueness on the key\n */\n unique?: boolean\n}\n\nexport const IndexSeparator = '-'\n\n/**\n * Given an index description, this will build the index\n * name in standard form\n * @param index The index description\n * @returns The index name in standard form\n */\nexport const buildStandardIndexName = (index: IndexDescription) => {\n const { key, unique } = index\n const prefix = unique ? 'UX' : 'IX'\n const indexKeys = Object.keys(key)\n return `${prefix}_${indexKeys.join(IndexSeparator)}`\n}\n","import type { Logger } from '@xylabs/logger'\nimport type { EmptyObject } from '@xylabs/object'\nimport type {\n IDBPDatabase, IndexNames, StoreNames,\n} from 'idb'\n\nimport {\n buildStandardIndexName,\n type IndexDescription,\n} from './IndexDescription.ts'\nimport type { ObjectStore } from './ObjectStore.ts'\n\nexport function createStore<T extends EmptyObject = EmptyObject>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n indexes: IndexDescription[],\n logger?: Logger,\n) {\n logger?.log(`Creating store ${storeName}`)\n // Create the store\n const store = db.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n for (const {\n key, multiEntry, unique,\n } of indexes) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = buildStandardIndexName({ key, unique }) as IndexNames<ObjectStore<T>, StoreNames<ObjectStore<T>>>\n console.log('createIndex', indexName, keys, { multiEntry, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type {\n IDBPDatabase, IDBPObjectStore, StoreNames,\n} from 'idb'\n\nimport type { ObjectStore } from './ObjectStore.ts'\n\nexport async function withReadOnlyStore<T extends EmptyObject = EmptyObject, R = T>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n callback: (store: IDBPObjectStore<ObjectStore<T>, [StoreNames<ObjectStore<T>>], StoreNames<ObjectStore<T>>, string>) => Promise<R> | R,\n): Promise<R> {\n const transaction = db.transaction(storeName, 'readonly')\n const store = transaction.objectStore(storeName)\n try {\n return await callback(store)\n } finally {\n await transaction.done\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type { IDBPDatabase, StoreNames } from 'idb'\n\nimport {\n type IndexDescription,\n type IndexDirection,\n} from './IndexDescription.ts'\nimport type { ObjectStore } from './ObjectStore.ts'\nimport { withReadOnlyStore } from './withReadOnlyStore.ts'\n\nexport async function getExistingIndexes<T extends EmptyObject = EmptyObject>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n): Promise<IndexDescription[]> {\n return await withReadOnlyStore(db, storeName, (store) => {\n return [...store.indexNames].map((indexName) => {\n const index = store.index(indexName)\n const key: Record<string, IndexDirection> = {}\n if (Array.isArray(index.keyPath)) {\n for (const keyPath of index.keyPath) {\n key[keyPath] = 1\n }\n } else {\n key[index.keyPath] = 1\n }\n const desc: IndexDescription = {\n name: indexName as string,\n key,\n unique: index.unique,\n multiEntry: index.multiEntry,\n }\n return desc\n })\n })\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type { DBSchema, IDBPDatabase } from 'idb'\nimport { openDB } from 'idb'\n\nexport async function withDb<DBTypes extends DBSchema | unknown = unknown, R = EmptyObject>(\n dbName: string,\n callback: (db: IDBPDatabase<DBTypes>) => Promise<R> | R,\n): Promise<R> {\n const db = await openDB<DBTypes>(dbName)\n try {\n return await callback(db)\n } finally {\n db.close()\n }\n}\n","import type { KeyValueStore } from '@xylabs/storage'\nimport type {\n DBSchema,\n IDBPDatabase, StoreKey, StoreNames, StoreValue,\n} from 'idb'\n\nimport { withDb } from './withDb.ts'\n\n/**\n * An IndexedDB key/value store.\n */\nexport class IndexedDbKeyValueStore<T extends DBSchema, S extends StoreNames<T>> implements KeyValueStore<StoreValue<T, S>, StoreKey<T, S>> {\n constructor(readonly dbName: string, readonly storeName: S) {}\n\n async clear?(): Promise<void> {\n return await this.withDb((db) => {\n return db.clear(this.storeName)\n })\n }\n\n async delete(key: string): Promise<void> {\n return await this.withDb((db) => {\n return db.delete(this.storeName, key)\n })\n }\n\n async get(key: string) {\n return await this.withDb((db) => {\n return db.get(this.storeName, key) ?? undefined\n })\n }\n\n async keys?(): Promise<StoreKey<T, S>[]> {\n return await this.withDb((db) => {\n return db.getAllKeys(this.storeName)\n })\n }\n\n async set(key: string, value: StoreValue<T, S>): Promise<void> {\n return await this.withDb((db) => {\n return db.put(this.storeName, value, key)\n })\n }\n\n async withDb<R = StoreValue<T, S>>(\n callback: (db: IDBPDatabase<T>) =>\n Promise<R> | R,\n ) {\n return await withDb<T, R>(this.dbName, (db) => {\n return callback(db)\n })\n }\n}\n","import type { EmptyObject } from '@xylabs/object'\nimport type {\n IDBPDatabase, IDBPObjectStore, StoreNames,\n} from 'idb'\n\nimport type { ObjectStore } from './ObjectStore.ts'\n\nexport async function withReadWriteStore<T extends EmptyObject = EmptyObject, R = T>(\n db: IDBPDatabase<ObjectStore<T>>,\n storeName: StoreNames<ObjectStore<T>>,\n callback: (store: IDBPObjectStore<ObjectStore<T>, [StoreNames<ObjectStore<T>>], StoreNames<ObjectStore<T>>, string>) => Promise<R> | R,\n): Promise<R> {\n const transaction = db.transaction(storeName, 'readwrite')\n const store = transaction.objectStore(storeName)\n try {\n return await callback(store)\n } finally {\n await transaction.done\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,4 @@
1
1
  import type { EmptyObject } from '@xylabs/object';
2
- import type { IDBPDatabase } from 'idb';
3
- import type { ObjectStore } from './ObjectStore.ts';
4
- export declare function withDb<T extends EmptyObject = EmptyObject, R = T>(dbName: string, callback: (db: IDBPDatabase<ObjectStore<T>>) => Promise<R> | R): Promise<R>;
2
+ import type { DBSchema, IDBPDatabase } from 'idb';
3
+ export declare function withDb<DBTypes extends DBSchema | unknown = unknown, R = EmptyObject>(dbName: string, callback: (db: IDBPDatabase<DBTypes>) => Promise<R> | R): Promise<R>;
5
4
  //# sourceMappingURL=withDb.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"withDb.d.ts","sourceRoot":"","sources":["../../src/withDb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAA;AAGvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEnD,wBAAsB,MAAM,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,CAAC,GAAG,CAAC,EACrE,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAC7D,OAAO,CAAC,CAAC,CAAC,CAOZ"}
1
+ {"version":3,"file":"withDb.d.ts","sourceRoot":"","sources":["../../src/withDb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,KAAK,CAAA;AAGjD,wBAAsB,MAAM,CAAC,OAAO,SAAS,QAAQ,GAAG,OAAO,GAAG,OAAO,EAAE,CAAC,GAAG,WAAW,EACxF,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GACtD,OAAO,CAAC,CAAC,CAAC,CAOZ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xylabs/indexed-db",
3
- "version": "4.4.31",
3
+ "version": "4.4.33",
4
4
  "description": "Base functionality used throughout XY Labs TypeScript/JavaScript libraries",
5
5
  "keywords": [
6
6
  "hex",
@@ -39,15 +39,15 @@
39
39
  "packages/**/*"
40
40
  ],
41
41
  "dependencies": {
42
- "@xylabs/logger": "^4.4.31",
43
- "@xylabs/object": "^4.4.31",
44
- "@xylabs/storage": "^4.4.31",
42
+ "@xylabs/logger": "^4.4.33",
43
+ "@xylabs/object": "^4.4.33",
44
+ "@xylabs/storage": "^4.4.33",
45
45
  "idb": "^8.0.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@xylabs/ts-scripts-yarn3": "^4.2.6",
49
49
  "@xylabs/tsconfig": "^4.2.6",
50
- "@xylabs/vitest-extended": "^4.4.31",
50
+ "@xylabs/vitest-extended": "^4.4.33",
51
51
  "typescript": "^5.7.2",
52
52
  "vitest": "^2.1.8"
53
53
  },
@@ -1,17 +1,16 @@
1
- import type { EmptyObject } from '@xylabs/object'
2
1
  import type { KeyValueStore } from '@xylabs/storage'
3
2
  import type {
4
- IDBPDatabase, StoreNames, StoreValue,
3
+ DBSchema,
4
+ IDBPDatabase, StoreKey, StoreNames, StoreValue,
5
5
  } from 'idb'
6
6
 
7
- import type { ObjectStore } from './ObjectStore.ts'
8
7
  import { withDb } from './withDb.ts'
9
8
 
10
9
  /**
11
10
  * An IndexedDB key/value store.
12
11
  */
13
- export class IndexedDbKeyValueStore<T extends EmptyObject> implements KeyValueStore<T, string> {
14
- constructor(readonly dbName: string, readonly storeName: StoreNames<ObjectStore<T>>) {}
12
+ export class IndexedDbKeyValueStore<T extends DBSchema, S extends StoreNames<T>> implements KeyValueStore<StoreValue<T, S>, StoreKey<T, S>> {
13
+ constructor(readonly dbName: string, readonly storeName: S) {}
15
14
 
16
15
  async clear?(): Promise<void> {
17
16
  return await this.withDb((db) => {
@@ -25,26 +24,26 @@ export class IndexedDbKeyValueStore<T extends EmptyObject> implements KeyValueSt
25
24
  })
26
25
  }
27
26
 
28
- async get(key: string): Promise<T | undefined> {
27
+ async get(key: string) {
29
28
  return await this.withDb((db) => {
30
29
  return db.get(this.storeName, key) ?? undefined
31
30
  })
32
31
  }
33
32
 
34
- async keys?(): Promise<string[]> {
33
+ async keys?(): Promise<StoreKey<T, S>[]> {
35
34
  return await this.withDb((db) => {
36
35
  return db.getAllKeys(this.storeName)
37
36
  })
38
37
  }
39
38
 
40
- async set(key: string, value: StoreValue<ObjectStore<T>, StoreNames<ObjectStore<T>>>): Promise<void> {
39
+ async set(key: string, value: StoreValue<T, S>): Promise<void> {
41
40
  return await this.withDb((db) => {
42
41
  return db.put(this.storeName, value, key)
43
42
  })
44
43
  }
45
44
 
46
- async withDb<R = T>(
47
- callback: (db: IDBPDatabase<ObjectStore<T>>) =>
45
+ async withDb<R = StoreValue<T, S>>(
46
+ callback: (db: IDBPDatabase<T>) =>
48
47
  Promise<R> | R,
49
48
  ) {
50
49
  return await withDb<T, R>(this.dbName, (db) => {
package/src/withDb.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  import type { EmptyObject } from '@xylabs/object'
2
- import type { IDBPDatabase } from 'idb'
2
+ import type { DBSchema, IDBPDatabase } from 'idb'
3
3
  import { openDB } from 'idb'
4
4
 
5
- import type { ObjectStore } from './ObjectStore.ts'
6
-
7
- export async function withDb<T extends EmptyObject = EmptyObject, R = T>(
5
+ export async function withDb<DBTypes extends DBSchema | unknown = unknown, R = EmptyObject>(
8
6
  dbName: string,
9
- callback: (db: IDBPDatabase<ObjectStore<T>>) => Promise<R> | R,
7
+ callback: (db: IDBPDatabase<DBTypes>) => Promise<R> | R,
10
8
  ): Promise<R> {
11
- const db = await openDB<ObjectStore<T>>(dbName)
9
+ const db = await openDB<DBTypes>(dbName)
12
10
  try {
13
11
  return await callback(db)
14
12
  } finally {