diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index ac3c79e20..ecc5509dc 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -39,11 +39,11 @@ export function openTalerDatabase( if (oldVersion === 0) { for (const n in Stores) { if ((Stores as any)[n] instanceof Store) { - const si: Store = (Stores as any)[n]; + const si: Store = (Stores as any)[n]; const s = db.createObjectStore(si.name, si.storeParams); for (const indexName in si as any) { if ((si as any)[indexName] instanceof Index) { - const ii: Index = (si as any)[indexName]; + const ii: Index = (si as any)[indexName]; s.createIndex(ii.indexName, ii.keyPath, ii.options); } } @@ -57,7 +57,7 @@ export function openTalerDatabase( logger.info(`upgrading database from ${oldVersion} to ${newVersion}`); for (const n in Stores) { if ((Stores as any)[n] instanceof Store) { - const si: Store = (Stores as any)[n]; + const si: Store = (Stores as any)[n]; let s: IDBObjectStore; if ((si.storeParams?.versionAdded ?? 1) > oldVersion) { s = db.createObjectStore(si.name, si.storeParams); @@ -66,7 +66,7 @@ export function openTalerDatabase( } for (const indexName in si as any) { if ((si as any)[indexName] instanceof Index) { - const ii: Index = (si as any)[indexName]; + const ii: Index = (si as any)[indexName]; if ((ii.options?.versionAdded ?? 0) > oldVersion) { s.createIndex(ii.indexName, ii.keyPath, ii.options); } diff --git a/packages/taler-wallet-core/src/operations/balance.ts b/packages/taler-wallet-core/src/operations/balance.ts index 91c5e639e..b82e4c9d1 100644 --- a/packages/taler-wallet-core/src/operations/balance.ts +++ b/packages/taler-wallet-core/src/operations/balance.ts @@ -38,7 +38,13 @@ interface WalletBalance { */ export async function getBalancesInsideTransaction( ws: InternalWalletState, - tx: TransactionHandle, + tx: TransactionHandle< + | typeof Stores.reserves + | typeof Stores.coins + | typeof Stores.reserves + | typeof Stores.refreshGroups + | typeof Stores.withdrawalGroups + >, ): Promise { const balanceStore: Record = {}; diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts index 4f6477d50..a42d89c9a 100644 --- a/packages/taler-wallet-core/src/operations/pending.ts +++ b/packages/taler-wallet-core/src/operations/pending.ts @@ -37,7 +37,7 @@ import { getDurationRemaining, durationMin, } from "../util/time"; -import { TransactionHandle } from "../util/query"; +import { Store, TransactionHandle } from "../util/query"; import { InternalWalletState } from "./state"; import { getBalancesInsideTransaction } from "./balance"; @@ -52,7 +52,7 @@ function updateRetryDelay( } async function gatherExchangePending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, @@ -171,7 +171,7 @@ async function gatherExchangePending( } async function gatherReservePending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, @@ -226,7 +226,7 @@ async function gatherReservePending( } async function gatherRefreshPending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, @@ -255,7 +255,7 @@ async function gatherRefreshPending( } async function gatherWithdrawalPending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, @@ -295,7 +295,7 @@ async function gatherWithdrawalPending( } async function gatherProposalPending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, @@ -346,7 +346,7 @@ async function gatherProposalPending( } async function gatherTipPending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, @@ -376,7 +376,7 @@ async function gatherTipPending( } async function gatherPurchasePending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, @@ -419,7 +419,7 @@ async function gatherPurchasePending( } async function gatherRecoupPending( - tx: TransactionHandle, + tx: TransactionHandle, now: Timestamp, resp: PendingOperationsResponse, onlyDue = false, diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts index 634869ece..585c91a09 100644 --- a/packages/taler-wallet-core/src/operations/recoup.ts +++ b/packages/taler-wallet-core/src/operations/recoup.ts @@ -46,7 +46,7 @@ import { import { Amounts } from "../util/amounts"; import { createRefreshGroup, processRefreshGroup } from "./refresh"; import { RefreshReason, TalerErrorDetails } from "../types/walletTypes"; -import { TransactionHandle } from "../util/query"; +import { Store, StoreParams, TransactionHandle } from "../util/query"; import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto"; import { getTimestampNow } from "../util/time"; import { guardOperationException } from "./errors"; @@ -82,7 +82,7 @@ async function incrementRecoupRetry( async function putGroupAsFinished( ws: InternalWalletState, - tx: TransactionHandle, + tx: TransactionHandle, recoupGroup: RecoupGroupRecord, coinIdx: number, ): Promise { @@ -366,7 +366,7 @@ async function processRecoupGroupImpl( export async function createRecoupGroup( ws: InternalWalletState, - tx: TransactionHandle, + tx: TransactionHandle, coinPubs: string[], ): Promise { const recoupGroupId = encodeCrock(getRandomBytes(32)); diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index c92ce9209..21c884d48 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -52,9 +52,7 @@ import { durationMax, durationMul, } from "../util/time"; -import { - readSuccessResponseJsonOrThrow, -} from "../util/http"; +import { readSuccessResponseJsonOrThrow } from "../util/http"; import { codecForExchangeMeltResponse, codecForExchangeRevealResponse, @@ -567,7 +565,11 @@ async function processRefreshSession( */ export async function createRefreshGroup( ws: InternalWalletState, - tx: TransactionHandle, + tx: TransactionHandle< + | typeof Stores.denominations + | typeof Stores.coins + | typeof Stores.refreshGroups + >, oldCoinPubs: CoinPublicKey[], reason: RefreshReason, ): Promise { diff --git a/packages/taler-wallet-core/src/operations/refund.ts b/packages/taler-wallet-core/src/operations/refund.ts index 49d03ea15..e0d060376 100644 --- a/packages/taler-wallet-core/src/operations/refund.ts +++ b/packages/taler-wallet-core/src/operations/refund.ts @@ -103,7 +103,7 @@ function getRefundKey(d: MerchantCoinRefundStatus): string { } async function applySuccessfulRefund( - tx: TransactionHandle, + tx: TransactionHandle, p: PurchaseRecord, refreshCoinsMap: Record, r: MerchantCoinRefundSuccessStatus, @@ -162,7 +162,7 @@ async function applySuccessfulRefund( } async function storePendingRefund( - tx: TransactionHandle, + tx: TransactionHandle, p: PurchaseRecord, r: MerchantCoinRefundFailureStatus, ): Promise { @@ -212,7 +212,7 @@ async function storePendingRefund( } async function storeFailedRefund( - tx: TransactionHandle, + tx: TransactionHandle, p: PurchaseRecord, refreshCoinsMap: Record, r: MerchantCoinRefundFailureStatus, diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts index b20570e09..a2a1b3018 100644 --- a/packages/taler-wallet-core/src/operations/reserves.ts +++ b/packages/taler-wallet-core/src/operations/reserves.ts @@ -81,7 +81,11 @@ import { } from "../util/http"; import { codecForAny } from "../util/codec"; import { URL } from "../util/url"; -import { initRetryInfo, getRetryDuration, updateRetryInfoTimeout } from "../util/retries"; +import { + initRetryInfo, + getRetryDuration, + updateRetryInfoTimeout, +} from "../util/retries"; const logger = new Logger("reserves.ts"); @@ -523,7 +527,8 @@ async function updateReserve( if (result.isError) { if ( resp.status === 404 && - result.talerErrorResponse.code === TalerErrorCode.EXCHANGE_RESERVES_GET_STATUS_UNKNOWN + result.talerErrorResponse.code === + TalerErrorCode.EXCHANGE_RESERVES_GET_STATUS_UNKNOWN ) { ws.notify({ type: NotificationType.ReserveNotYetFound, @@ -863,7 +868,7 @@ export async function createTalerWithdrawReserve( * Get payto URIs needed to fund a reserve. */ export async function getFundingPaytoUris( - tx: TransactionHandle, + tx: TransactionHandle, reservePub: string, ): Promise { const r = await tx.get(Stores.reserves, reservePub); diff --git a/packages/taler-wallet-core/src/util/query.ts b/packages/taler-wallet-core/src/util/query.ts index fa0d8beb7..08572fbd2 100644 --- a/packages/taler-wallet-core/src/util/query.ts +++ b/packages/taler-wallet-core/src/util/query.ts @@ -270,13 +270,21 @@ class ResultStream { } } -type StrKey = string & keyof T; - type StoreName = S extends Store ? N : never; type StoreContent = S extends Store ? R : never; type IndexRecord = Ind extends Index ? R : never; -export class TransactionHandle> { +type InferStore = S extends Store ? Store : never; +type InferIndex = Ind extends Index< + infer StN, + infer IndN, + infer KT, + infer RT +> + ? Index + : never; + +export class TransactionHandle> { constructor(private tx: IDBTransaction) {} put( @@ -306,14 +314,9 @@ export class TransactionHandle> { } getIndexed< - StoreName extends StrKey, - IndexName extends string, - S extends IDBValidKey, - T - >( - index: Index, - key: any, - ): Promise { + St extends StoreTypes, + Ind extends Index, string, any, any> + >(index: InferIndex, key: any): Promise | undefined> { const req = this.tx .objectStore(index.storeName) .index(index.indexName) @@ -321,39 +324,37 @@ export class TransactionHandle> { return requestToPromise(req); } - iter, T extends StoreTypes[N]>( - store: Store, + iter>( + store: St, key?: any, - ): ResultStream { + ): ResultStream> { const req = this.tx.objectStore(store.name).openCursor(key); - return new ResultStream(req); + return new ResultStream>(req); } iterIndexed< - StoreName extends StrKey, - IndexName extends string, - S extends IDBValidKey, - T - >(index: Index, key?: any): ResultStream { + St extends InferStore, + Ind extends InferIndex, string, any, any>> + >(index: Ind, key?: any): ResultStream> { const req = this.tx .objectStore(index.storeName) .index(index.indexName) .openCursor(key); - return new ResultStream(req); + return new ResultStream>(req); } - delete, T extends StoreTypes[N]>( - store: Store, + delete( + store: InferStore, key: any, ): Promise { const req = this.tx.objectStore(store.name).delete(key); return requestToPromise(req); } - mutate, T extends StoreTypes[N]>( - store: Store, + mutate( + store: InferStore, key: any, - f: (x: T) => T | undefined, + f: (x: StoreContent) => StoreContent | undefined, ): Promise { const req = this.tx.objectStore(store.name).openCursor(key); return applyMutation(req, f); @@ -583,9 +584,7 @@ export class Database { } async getIndexed>( - index: Ind extends Index - ? Index - : never, + index: InferIndex, key: any, ): Promise | undefined> { const tx = this.db.transaction([index.storeName], "readonly"); @@ -624,16 +623,16 @@ export class Database { return new ResultStream(req); } - iterIndex( - index: Index, + iterIndex>( + index: InferIndex, query?: any, - ): ResultStream { + ): ResultStream> { const tx = this.db.transaction([index.storeName], "readonly"); const req = tx .objectStore(index.storeName) .index(index.indexName) .openCursor(query); - return new ResultStream(req); + return new ResultStream>(req); } async runWithReadTransaction>(