summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-28 02:04:29 +0100
committerFlorian Dold <florian@dold.me>2024-02-28 02:04:40 +0100
commit8e716c3bff673a35e9f40cb54fca666aee0bd67b (patch)
tree8390a86e54d0fcb04bf1509e56fa72696081bc70
parent8b88540037d6f5a6d2d8fa583c6a7d46e7fd6e04 (diff)
downloadwallet-core-8e716c3bff673a35e9f40cb54fca666aee0bd67b.tar.gz
wallet-core-8e716c3bff673a35e9f40cb54fca666aee0bd67b.tar.bz2
wallet-core-8e716c3bff673a35e9f40cb54fca666aee0bd67b.zip
wallet-core: fix exchange entry deletion, test it
-rw-r--r--packages/taler-harness/src/integrationtests/test-exchange-management-fault.ts286
-rw-r--r--packages/taler-harness/src/integrationtests/test-exchange-management.ts250
-rw-r--r--packages/taler-harness/src/integrationtests/testrunner.ts4
-rw-r--r--packages/taler-wallet-cli/src/index.ts17
-rw-r--r--packages/taler-wallet-core/src/exchanges.ts27
-rw-r--r--packages/taler-wallet-core/src/query.ts22
6 files changed, 362 insertions, 244 deletions
diff --git a/packages/taler-harness/src/integrationtests/test-exchange-management-fault.ts b/packages/taler-harness/src/integrationtests/test-exchange-management-fault.ts
new file mode 100644
index 000000000..d3bd022ae
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-exchange-management-fault.ts
@@ -0,0 +1,286 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Imports.
+ */
+import {
+ ExchangesListResponse,
+ TalerCorebankApiClient,
+ TalerErrorCode,
+ URL,
+ j2s,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { defaultCoinConfig } from "../harness/denomStructures.js";
+import {
+ FaultInjectedExchangeService,
+ FaultInjectionResponseContext,
+} from "../harness/faultInjection.js";
+import {
+ BankService,
+ ExchangeService,
+ GlobalTestState,
+ MerchantService,
+ WalletCli,
+ generateRandomPayto,
+ setupDb,
+} from "../harness/harness.js";
+
+/**
+ * Test if the wallet handles outdated exchange versions correctly.
+ */
+export async function runExchangeManagementFaultTest(
+ t: GlobalTestState,
+): Promise<void> {
+ // Set up test environment
+
+ const db = await setupDb(t);
+
+ const bank = await BankService.create(t, {
+ allowRegistrations: true,
+ currency: "TESTKUDOS",
+ database: db.connStr,
+ httpPort: 8082,
+ });
+
+ const exchange = ExchangeService.create(t, {
+ name: "testexchange-1",
+ currency: "TESTKUDOS",
+ httpPort: 8081,
+ database: db.connStr,
+ });
+
+ const merchant = await MerchantService.create(t, {
+ name: "testmerchant-1",
+ currency: "TESTKUDOS",
+ httpPort: 8083,
+ database: db.connStr,
+ });
+
+ const exchangeBankAccount = await bank.createExchangeAccount(
+ "myexchange",
+ "x",
+ );
+ exchange.addBankAccount("1", exchangeBankAccount);
+
+ const faultyExchange = new FaultInjectedExchangeService(t, exchange, 8091);
+ // Base URL must contain port that the proxy is listening on.
+ await exchange.modifyConfig(async (config) => {
+ config.setString("exchange", "base_url", "http://localhost:8091/");
+ });
+
+ bank.setSuggestedExchange(
+ faultyExchange,
+ exchangeBankAccount.accountPaytoUri,
+ );
+
+ await bank.start();
+
+ await bank.pingUntilAvailable();
+
+ exchange.addOfferedCoins(defaultCoinConfig);
+
+ await exchange.start();
+ await exchange.pingUntilAvailable();
+
+ merchant.addExchange(exchange);
+
+ await merchant.start();
+ await merchant.pingUntilAvailable();
+
+ await merchant.addInstanceWithWireAccount({
+ id: "default",
+ name: "Default Instance",
+ paytoUris: [generateRandomPayto("merchant-default")],
+ });
+
+ await merchant.addInstanceWithWireAccount({
+ id: "minst1",
+ name: "minst1",
+ paytoUris: [generateRandomPayto("minst1")],
+ });
+
+ console.log("setup done!");
+
+ /*
+ * =========================================================================
+ * Check that the exchange can be added to the wallet
+ * (without any faults active).
+ * =========================================================================
+ */
+
+ const wallet = new WalletCli(t);
+
+ let exchangesList: ExchangesListResponse;
+
+ exchangesList = await wallet.client.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+ console.log("exchanges list:", j2s(exchangesList));
+ t.assertTrue(exchangesList.exchanges.length === 0);
+
+ // Try before fault is injected
+ await wallet.client.call(WalletApiOperation.AddExchange, {
+ exchangeBaseUrl: faultyExchange.baseUrl,
+ });
+
+ exchangesList = await wallet.client.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+ t.assertTrue(exchangesList.exchanges.length === 1);
+
+ await wallet.client.call(WalletApiOperation.ListExchanges, {});
+
+ console.log("listing exchanges");
+
+ exchangesList = await wallet.client.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+ t.assertTrue(exchangesList.exchanges.length === 1);
+
+ console.log("got list", exchangesList);
+
+ /*
+ * =========================================================================
+ * Check what happens if the exchange returns something totally
+ * bogus for /keys.
+ * =========================================================================
+ */
+
+ wallet.deleteDatabase();
+
+ exchangesList = await wallet.client.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+ t.assertTrue(exchangesList.exchanges.length === 0);
+
+ faultyExchange.faultProxy.addFault({
+ async modifyResponse(ctx: FaultInjectionResponseContext) {
+ const url = new URL(ctx.request.requestUrl);
+ if (url.pathname === "/keys") {
+ const body = {
+ version: "whaaat",
+ };
+ ctx.responseBody = Buffer.from(JSON.stringify(body), "utf-8");
+ }
+ },
+ });
+
+ const err1 = await t.assertThrowsTalerErrorAsync(async () => {
+ await wallet.client.call(WalletApiOperation.AddExchange, {
+ exchangeBaseUrl: faultyExchange.baseUrl,
+ });
+ });
+
+ console.log("got error", err1);
+
+ // Response is malformed, since it didn't even contain a version code
+ // in a format the wallet can understand.
+ t.assertTrue(
+ err1.errorDetail.code === TalerErrorCode.WALLET_EXCHANGE_UNAVAILABLE,
+ );
+
+ exchangesList = await wallet.client.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+ console.log("exchanges list", j2s(exchangesList));
+ t.assertTrue(exchangesList.exchanges.length === 1);
+ t.assertTrue(
+ exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
+ TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+ );
+
+ /*
+ * =========================================================================
+ * Check what happens if the exchange returns an old, unsupported
+ * version for /keys
+ * =========================================================================
+ */
+
+ wallet.deleteDatabase();
+ faultyExchange.faultProxy.clearAllFaults();
+
+ faultyExchange.faultProxy.addFault({
+ async modifyResponse(ctx: FaultInjectionResponseContext) {
+ const url = new URL(ctx.request.requestUrl);
+ if (url.pathname === "/keys") {
+ const keys = ctx.responseBody?.toString("utf-8");
+ t.assertTrue(keys != null);
+ const keysJson = JSON.parse(keys);
+ keysJson["version"] = "2:0:0";
+ ctx.responseBody = Buffer.from(JSON.stringify(keysJson), "utf-8");
+ }
+ },
+ });
+
+ const err2 = await t.assertThrowsTalerErrorAsync(async () => {
+ await wallet.client.call(WalletApiOperation.AddExchange, {
+ exchangeBaseUrl: faultyExchange.baseUrl,
+ });
+ });
+
+ t.assertTrue(err2.hasErrorCode(TalerErrorCode.WALLET_EXCHANGE_UNAVAILABLE));
+
+ exchangesList = await wallet.client.call(
+ WalletApiOperation.ListExchanges,
+ {},
+ );
+ t.assertTrue(exchangesList.exchanges.length === 1);
+ t.assertTrue(
+ exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
+ TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE,
+ );
+
+ /*
+ * =========================================================================
+ * Check that the exchange version is also checked when
+ * the exchange is implicitly added via the suggested
+ * exchange of a bank-integrated withdrawal.
+ * =========================================================================
+ */
+
+ // Fault from above is still active!
+
+ // Create withdrawal operation
+
+ const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl);
+
+ const user = await bankClient.createRandomBankUser();
+ const wop = await bankClient.createWithdrawalOperation(
+ user.username,
+ "TESTKUDOS:10",
+ );
+
+ // Hand it to the wallet
+
+ const wd = await wallet.client.call(
+ WalletApiOperation.GetWithdrawalDetailsForUri,
+ {
+ talerWithdrawUri: wop.taler_withdraw_uri,
+ },
+ );
+
+ // Make sure the faulty exchange isn't used for the suggestion.
+ t.assertTrue(wd.possibleExchanges.length === 0);
+}
+
+runExchangeManagementFaultTest.suites = ["wallet", "exchange"];
diff --git a/packages/taler-harness/src/integrationtests/test-exchange-management.ts b/packages/taler-harness/src/integrationtests/test-exchange-management.ts
index 37b490d6b..8e2a8f589 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-management.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-management.ts
@@ -17,28 +17,9 @@
/**
* Imports.
*/
-import {
- ExchangesListResponse,
- TalerCorebankApiClient,
- TalerErrorCode,
- URL,
- j2s,
-} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- FaultInjectedExchangeService,
- FaultInjectionResponseContext,
-} from "../harness/faultInjection.js";
-import {
- BankService,
- ExchangeService,
- GlobalTestState,
- MerchantService,
- WalletCli,
- generateRandomPayto,
- setupDb,
-} from "../harness/harness.js";
+import { GlobalTestState } from "../harness/harness.js";
+import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
/**
* Test if the wallet handles outdated exchange versions correctly.
@@ -48,239 +29,52 @@ export async function runExchangeManagementTest(
): Promise<void> {
// Set up test environment
- const db = await setupDb(t);
+ const { walletClient, bank, exchange } =
+ await createSimpleTestkudosEnvironmentV2(t);
- const bank = await BankService.create(t, {
- allowRegistrations: true,
- currency: "TESTKUDOS",
- database: db.connStr,
- httpPort: 8082,
- });
-
- const exchange = ExchangeService.create(t, {
- name: "testexchange-1",
- currency: "TESTKUDOS",
- httpPort: 8081,
- database: db.connStr,
- });
-
- const merchant = await MerchantService.create(t, {
- name: "testmerchant-1",
- currency: "TESTKUDOS",
- httpPort: 8083,
- database: db.connStr,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- const faultyExchange = new FaultInjectedExchangeService(t, exchange, 8091);
- // Base URL must contain port that the proxy is listening on.
- await exchange.modifyConfig(async (config) => {
- config.setString("exchange", "base_url", "http://localhost:8091/");
- });
-
- bank.setSuggestedExchange(
- faultyExchange,
- exchangeBankAccount.accountPaytoUri,
- );
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addOfferedCoins(defaultCoinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstanceWithWireAccount({
- id: "default",
- name: "Default Instance",
- paytoUris: [generateRandomPayto("merchant-default")],
- });
-
- await merchant.addInstanceWithWireAccount({
- id: "minst1",
- name: "minst1",
- paytoUris: [generateRandomPayto("minst1")],
- });
-
- console.log("setup done!");
-
- /*
- * =========================================================================
- * Check that the exchange can be added to the wallet
- * (without any faults active).
- * =========================================================================
- */
-
- const wallet = new WalletCli(t);
-
- let exchangesList: ExchangesListResponse;
-
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- console.log("exchanges list:", j2s(exchangesList));
- t.assertTrue(exchangesList.exchanges.length === 0);
-
- // Try before fault is injected
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: faultyExchange.baseUrl,
- });
-
- exchangesList = await wallet.client.call(
+ const exchangesListResult = await walletClient.call(
WalletApiOperation.ListExchanges,
{},
);
- t.assertTrue(exchangesList.exchanges.length === 1);
-
- await wallet.client.call(WalletApiOperation.ListExchanges, {});
- console.log("listing exchanges");
-
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- t.assertTrue(exchangesList.exchanges.length === 1);
+ t.assertDeepEqual(exchangesListResult.exchanges.length, 1);
- console.log("got list", exchangesList);
-
- /*
- * =========================================================================
- * Check what happens if the exchange returns something totally
- * bogus for /keys.
- * =========================================================================
- */
-
- wallet.deleteDatabase();
+ await walletClient.call(WalletApiOperation.UpdateExchangeEntry, {
+ exchangeBaseUrl: exchange.baseUrl,
+ force: true,
+ });
- exchangesList = await wallet.client.call(
+ const exchangesListResult2 = await walletClient.call(
WalletApiOperation.ListExchanges,
{},
);
- t.assertTrue(exchangesList.exchanges.length === 0);
- faultyExchange.faultProxy.addFault({
- async modifyResponse(ctx: FaultInjectionResponseContext) {
- const url = new URL(ctx.request.requestUrl);
- if (url.pathname === "/keys") {
- const body = {
- version: "whaaat",
- };
- ctx.responseBody = Buffer.from(JSON.stringify(body), "utf-8");
- }
- },
- });
+ t.assertDeepEqual(exchangesListResult2.exchanges.length, 2);
- const err1 = await t.assertThrowsTalerErrorAsync(async () => {
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: faultyExchange.baseUrl,
- });
+ await walletClient.call(WalletApiOperation.DeleteExchange, {
+ exchangeBaseUrl: exchange.baseUrl,
});
- console.log("got error", err1);
-
- // Response is malformed, since it didn't even contain a version code
- // in a format the wallet can understand.
- t.assertTrue(
- err1.errorDetail.code === TalerErrorCode.WALLET_EXCHANGE_UNAVAILABLE,
- );
-
- exchangesList = await wallet.client.call(
+ const exchangesListResult3 = await walletClient.call(
WalletApiOperation.ListExchanges,
{},
);
- console.log("exchanges list", j2s(exchangesList));
- t.assertTrue(exchangesList.exchanges.length === 1);
- t.assertTrue(
- exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
- TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
- );
-
- /*
- * =========================================================================
- * Check what happens if the exchange returns an old, unsupported
- * version for /keys
- * =========================================================================
- */
- wallet.deleteDatabase();
- faultyExchange.faultProxy.clearAllFaults();
+ t.assertDeepEqual(exchangesListResult3.exchanges.length, 1);
- faultyExchange.faultProxy.addFault({
- async modifyResponse(ctx: FaultInjectionResponseContext) {
- const url = new URL(ctx.request.requestUrl);
- if (url.pathname === "/keys") {
- const keys = ctx.responseBody?.toString("utf-8");
- t.assertTrue(keys != null);
- const keysJson = JSON.parse(keys);
- keysJson["version"] = "2:0:0";
- ctx.responseBody = Buffer.from(JSON.stringify(keysJson), "utf-8");
- }
- },
- });
+ // Check for regression: Can we re-add a deleted exchange?
- const err2 = await t.assertThrowsTalerErrorAsync(async () => {
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: faultyExchange.baseUrl,
- });
+ await walletClient.call(WalletApiOperation.UpdateExchangeEntry, {
+ exchangeBaseUrl: exchange.baseUrl,
+ force: true,
});
- t.assertTrue(err2.hasErrorCode(TalerErrorCode.WALLET_EXCHANGE_UNAVAILABLE));
-
- exchangesList = await wallet.client.call(
+ const exchangesListResult4 = await walletClient.call(
WalletApiOperation.ListExchanges,
{},
);
- t.assertTrue(exchangesList.exchanges.length === 1);
- t.assertTrue(
- exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
- TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE,
- );
-
- /*
- * =========================================================================
- * Check that the exchange version is also checked when
- * the exchange is implicitly added via the suggested
- * exchange of a bank-integrated withdrawal.
- * =========================================================================
- */
-
- // Fault from above is still active!
-
- // Create withdrawal operation
-
- const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl);
-
- const user = await bankClient.createRandomBankUser();
- const wop = await bankClient.createWithdrawalOperation(
- user.username,
- "TESTKUDOS:10",
- );
-
- // Hand it to the wallet
-
- const wd = await wallet.client.call(
- WalletApiOperation.GetWithdrawalDetailsForUri,
- {
- talerWithdrawUri: wop.taler_withdraw_uri,
- },
- );
- // Make sure the faulty exchange isn't used for the suggestion.
- t.assertTrue(wd.possibleExchanges.length === 0);
+ t.assertDeepEqual(exchangesListResult4.exchanges.length, 2);
}
runExchangeManagementTest.suites = ["wallet", "exchange"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts
index 1fb987802..b57d82939 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -39,6 +39,7 @@ import { runCurrencyScopeTest } from "./test-currency-scope.js";
import { runDenomUnofferedTest } from "./test-denom-unoffered.js";
import { runDepositTest } from "./test-deposit.js";
import { runExchangeDepositTest } from "./test-exchange-deposit.js";
+import { runExchangeManagementFaultTest } from "./test-exchange-management-fault.js";
import { runExchangeManagementTest } from "./test-exchange-management.js";
import { runExchangePurseTest } from "./test-exchange-purse.js";
import { runExchangeTimetravelTest } from "./test-exchange-timetravel.js";
@@ -129,7 +130,7 @@ const allTests: TestMainFunction[] = [
runDenomUnofferedTest,
runDepositTest,
runSimplePaymentTest,
- runExchangeManagementTest,
+ runExchangeManagementFaultTest,
runExchangeTimetravelTest,
runFeeRegressionTest,
runForcedSelectionTest,
@@ -194,6 +195,7 @@ const allTests: TestMainFunction[] = [
runWalletCliTerminationTest,
runOtpTest,
runWalletBalanceNotificationsTest,
+ runExchangeManagementTest,
];
export interface TestRunSpec {
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts
index b1d813e0d..ffe033b24 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -840,6 +840,23 @@ exchangesCli
});
exchangesCli
+ .subcommand("exchangesAddCmd", "delete", {
+ help: "Delete an exchange by base URL.",
+ })
+ .requiredArgument("url", clk.STRING, {
+ help: "Base URL of the exchange.",
+ })
+ .flag("purge", ["--purge"])
+ .action(async (args) => {
+ await withWallet(args, async (wallet) => {
+ await wallet.client.call(WalletApiOperation.DeleteExchange, {
+ exchangeBaseUrl: args.exchangesAddCmd.url,
+ purge: args.exchangesAddCmd.purge,
+ });
+ });
+ });
+
+exchangesCli
.subcommand("exchangesAcceptTosCmd", "accept-tos", {
help: "Accept terms of service.",
})
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
index 5b0d3e823..dd4296d8a 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -2016,23 +2016,20 @@ export async function deleteExchange(
return;
}
const res = await internalGetExchangeResources(wex, tx, exchangeBaseUrl);
- if (res.hasResources) {
- if (req.purge) {
- const detRecs =
- await tx.exchangeDetails.indexes.byExchangeBaseUrl.getAll();
- for (const r of detRecs) {
- if (r.rowId == null) {
- // Should never happen, as rowId is the primary key.
- continue;
- }
- await tx.exchangeDetails.delete(r.rowId);
- }
- // FIXME: Also remove records related to transactions?
- } else {
- inUse = true;
- return;
+ if (res.hasResources && !req.purge) {
+ inUse = true;
+ return;
+ }
+ const detRecs =
+ await tx.exchangeDetails.indexes.byExchangeBaseUrl.getAll();
+ for (const r of detRecs) {
+ if (r.rowId == null) {
+ // Should never happen, as rowId is the primary key.
+ continue;
}
+ await tx.exchangeDetails.delete(r.rowId);
}
+ // FIXME: Also remove records related to transactions?
await tx.exchanges.delete(exchangeBaseUrl);
},
);
diff --git a/packages/taler-wallet-core/src/query.ts b/packages/taler-wallet-core/src/query.ts
index 994a6a96d..d128805d2 100644
--- a/packages/taler-wallet-core/src/query.ts
+++ b/packages/taler-wallet-core/src/query.ts
@@ -349,6 +349,10 @@ interface IndexReadOnlyAccessor<RecordType> {
query?: IDBKeyRange | IDBValidKey,
count?: number,
): Promise<RecordType[]>;
+ getAllKeys(
+ query?: IDBKeyRange | IDBValidKey,
+ count?: number,
+ ): Promise<IDBValidKey[]>;
count(query?: IDBValidKey): Promise<number>;
}
@@ -363,6 +367,10 @@ interface IndexReadWriteAccessor<RecordType> {
query?: IDBKeyRange | IDBValidKey,
count?: number,
): Promise<RecordType[]>;
+ getAllKeys(
+ query?: IDBKeyRange | IDBValidKey,
+ count?: number,
+ ): Promise<IDBValidKey[]>;
count(query?: IDBValidKey): Promise<number>;
}
@@ -642,6 +650,13 @@ function makeReadContext(
.getAll(query, count);
return requestToPromise(req);
},
+ getAllKeys(query, count) {
+ const req = tx
+ .objectStore(storeName)
+ .index(indexName)
+ .getAllKeys(query, count);
+ return requestToPromise(req);
+ },
count(query) {
const req = tx.objectStore(storeName).index(indexName).count(query);
return requestToPromise(req);
@@ -699,6 +714,13 @@ function makeWriteContext(
.getAll(query, count);
return requestToPromise(req);
},
+ getAllKeys(query, count) {
+ const req = tx
+ .objectStore(storeName)
+ .index(indexName)
+ .getAllKeys(query, count);
+ return requestToPromise(req);
+ },
count(query) {
const req = tx.objectStore(storeName).index(indexName).count(query);
return requestToPromise(req);