diff options
Diffstat (limited to 'packages/taler-wallet-core/src/util/query.ts')
-rw-r--r-- | packages/taler-wallet-core/src/util/query.ts | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/packages/taler-wallet-core/src/util/query.ts b/packages/taler-wallet-core/src/util/query.ts index 309c17a43..5d563f620 100644 --- a/packages/taler-wallet-core/src/util/query.ts +++ b/packages/taler-wallet-core/src/util/query.ts @@ -454,8 +454,8 @@ type DerefKeyPath<T, P> = P extends `${infer PX extends keyof T & KeyPathComponents}` ? T[PX] : P extends `${infer P0 extends keyof T & KeyPathComponents}.${infer Rest}` - ? DerefKeyPath<T[P0], Rest> - : unknown; + ? DerefKeyPath<T[P0], Rest> + : unknown; /** * Return a path if it is a valid dot-separate path to an object. @@ -465,8 +465,8 @@ type ValidateKeyPath<T, P> = P extends `${infer PX extends keyof T & KeyPathComponents}` ? PX : P extends `${infer P0 extends keyof T & KeyPathComponents}.${infer Rest}` - ? `${P0}.${ValidateKeyPath<T[P0], Rest>}` - : never; + ? `${P0}.${ValidateKeyPath<T[P0], Rest>}` + : never; // function foo<T, P>( // x: T, @@ -545,11 +545,60 @@ type ReadWriteTransactionFunction<BoundStores, T> = ( rawTx: IDBTransaction, ) => Promise<T>; +export type DbReadWriteTransactionArr< + StoreMap, + StoresArr extends Array<StoreNames<StoreMap>>, +> = StoreMap extends { + [P in string]: StoreWithIndexes<infer _SN1, infer _SD1, infer _IM1>; +} + ? { + [X in StoresArr[number] & + keyof StoreMap]: StoreMap[X] extends StoreWithIndexes< + infer _StoreName, + infer RecordType, + infer IndexMap + > + ? StoreReadWriteAccessor<RecordType, IndexMap> + : unknown; + } + : never; + +export type DbReadOnlyTransactionArr< + StoreMap, + StoresArr extends Array<StoreNames<StoreMap>>, +> = StoreMap extends { + [P in string]: StoreWithIndexes<infer _SN1, infer _SD1, infer _IM1>; +} + ? { + [X in StoresArr[number] & + keyof StoreMap]: StoreMap[X] extends StoreWithIndexes< + infer _StoreName, + infer RecordType, + infer IndexMap + > + ? StoreReadOnlyAccessor<RecordType, IndexMap> + : unknown; + } + : never; + export interface TransactionContext<BoundStores> { runReadWrite<T>(f: ReadWriteTransactionFunction<BoundStores, T>): Promise<T>; runReadOnly<T>(f: ReadOnlyTransactionFunction<BoundStores, T>): Promise<T>; } +/** + * Convert the type of an array to a union of the contents. + * + * Example: + * Input ["foo", "bar"] + * Output "foo" | "bar" + */ +export type UnionFromArray<Arr> = Arr extends { + [X in keyof Arr]: Arr[X] & string; +} + ? Arr[keyof Arr & number] + : unknown; + function runTx<Arg, Res>( tx: IDBTransaction, arg: Arg, @@ -743,7 +792,10 @@ type StoreNamesOf<X> = X extends { [x: number]: infer F } * A store map is the metadata that describes the store. */ export class DbAccess<StoreMap> { - constructor(private db: IDBDatabase, private stores: StoreMap) {} + constructor( + private db: IDBDatabase, + private stores: StoreMap, + ) {} idbHandle(): IDBDatabase { return this.db; @@ -803,6 +855,42 @@ export class DbAccess<StoreMap> { }; } + runReadWriteTx<T, StoreNameArray extends Array<StoreNames<StoreMap>>>( + storeNames: StoreNameArray, + txf: ( + tx: DbReadWriteTransactionArr<StoreMap, StoreNameArray>, + ) => Promise<T>, + ): Promise<T> { + const accessibleStores: { [x: string]: StoreWithIndexes<any, any, any> } = + {}; + const strStoreNames: string[] = []; + for (const sn of storeNames) { + const swi = (this.stores as any)[sn] as StoreWithIndexes<any, any, any>; + strStoreNames.push(swi.storeName); + accessibleStores[swi.storeName] = swi; + } + const tx = this.db.transaction(strStoreNames, "readwrite"); + const writeContext = makeWriteContext(tx, accessibleStores); + return runTx(tx, writeContext, txf); + } + + runReadOnlyTx<T, StoreNameArray extends Array<StoreNames<StoreMap>>>( + storeNames: StoreNameArray, + txf: (tx: DbReadOnlyTransactionArr<StoreMap, StoreNameArray>) => Promise<T>, + ): Promise<T> { + const accessibleStores: { [x: string]: StoreWithIndexes<any, any, any> } = + {}; + const strStoreNames: string[] = []; + for (const sn of storeNames) { + const swi = (this.stores as any)[sn] as StoreWithIndexes<any, any, any>; + strStoreNames.push(swi.storeName); + accessibleStores[swi.storeName] = swi; + } + const tx = this.db.transaction(strStoreNames, "readwrite"); + const readContext = makeReadContext(tx, accessibleStores); + return runTx(tx, readContext, txf); + } + /** * Run a transaction with selected object stores. * |