summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/util/query.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/util/query.ts')
-rw-r--r--packages/taler-wallet-core/src/util/query.ts98
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.
*