diff options
Diffstat (limited to 'packages/taler-util/src/http-client/merchant.ts')
-rw-r--r-- | packages/taler-util/src/http-client/merchant.ts | 950 |
1 files changed, 682 insertions, 268 deletions
diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts index fec1e7143..892971fee 100644 --- a/packages/taler-util/src/http-client/merchant.ts +++ b/packages/taler-util/src/http-client/merchant.ts @@ -16,9 +16,11 @@ import { AccessToken, + FailCasesByMethod, HttpStatusCode, LibtoolVersion, PaginationParams, + ResultByMethod, TalerMerchantApi, codecForAbortResponse, codecForAccountAddResponse, @@ -30,6 +32,7 @@ import { codecForInventorySummaryResponse, codecForMerchantConfig, codecForMerchantOrderPrivateStatusResponse, + codecForMerchantPosProductDetail, codecForMerchantRefundResponse, codecForOrderHistory, codecForOtpDeviceDetails, @@ -60,6 +63,7 @@ import { HttpRequestLibrary, HttpResponse, createPlatformHttpLib, + readTalerErrorResponse, } from "@gnu-taler/taler-util/http"; import { opSuccessFromHttp, opUnknownFailure } from "../operation.js"; import { @@ -69,11 +73,45 @@ import { nullEvictor, } from "./utils.js"; +export type TalerMerchantInstanceResultByMethod< + prop extends keyof TalerMerchantInstanceHttpClient, +> = ResultByMethod<TalerMerchantInstanceHttpClient, prop>; +export type TalerMerchantInstanceErrorsByMethod< + prop extends keyof TalerMerchantInstanceHttpClient, +> = FailCasesByMethod<TalerMerchantInstanceHttpClient, prop>; + export enum TalerMerchantInstanceCacheEviction { CREATE_ORDER, + UPDATE_ORDER, + DELETE_ORDER, + UPDATE_CURRENT_INSTANCE, + DELETE_CURRENT_INSTANCE, + CREATE_BANK_ACCOUNT, + UPDATE_BANK_ACCOUNT, + DELETE_BANK_ACCOUNT, + CREATE_PRODUCT, + UPDATE_PRODUCT, + DELETE_PRODUCT, + CREATE_TRANSFER, + DELETE_TRANSFER, + CREATE_DEVICE, + UPDATE_DEVICE, + DELETE_DEVICE, + CREATE_TEMPLATE, + UPDATE_TEMPLATE, + DELETE_TEMPLATE, + CREATE_WEBHOOK, + UPDATE_WEBHOOK, + DELETE_WEBHOOK, + CREATE_TOKENFAMILY, + UPDATE_TOKENFAMILY, + DELETE_TOKENFAMILY, + LAST, } export enum TalerMerchantManagementCacheEviction { - CREATE_INSTANCE, + CREATE_INSTANCE = TalerMerchantInstanceCacheEviction.LAST + 1, + UPDATE_INSTANCE, + DELETE_INSTANCE, } /** * Protocol version spoken with the core bank. @@ -85,7 +123,7 @@ export enum TalerMerchantManagementCacheEviction { * Uses libtool's current:revision:age versioning. */ export class TalerMerchantInstanceHttpClient { - public readonly PROTOCOL_VERSION = "10:0:6"; + public readonly PROTOCOL_VERSION = "15:0:0"; readonly httpLib: HttpRequestLibrary; readonly cacheEvictor: CacheEvictor<TalerMerchantInstanceCacheEviction>; @@ -117,8 +155,10 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForMerchantConfig()); + case HttpStatusCode.NotFound: + return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -138,14 +178,18 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); return opSuccessFromHttp(resp, codecForClaimResponse()); + } case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -161,8 +205,12 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); return opSuccessFromHttp(resp, codecForPaymentResponse()); + } case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.PaymentRequired: @@ -184,7 +232,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.GatewayTimeout: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -246,7 +294,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.NotAcceptable: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -262,8 +310,12 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); return opSuccessFromHttp(resp, codecForPaidRefundStatusResponse()); + } case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Forbidden: @@ -271,7 +323,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -290,8 +342,12 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); return opSuccessFromHttp(resp, codecForAbortResponse()); + } case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Forbidden: @@ -299,7 +355,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -318,8 +374,12 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); return opSuccessFromHttp(resp, codecForWalletRefundResponse()); + } case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Forbidden: @@ -327,7 +387,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -344,9 +404,9 @@ export class TalerMerchantInstanceHttpClient { ) { const url = new URL(`private/auth`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -355,14 +415,16 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: // FIXME: missing in docs return opEmptySuccess(resp); - case HttpStatusCode.NoContent: // FIXME: missing in docs + case HttpStatusCode.NoContent: return opEmptySuccess(resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -375,9 +437,9 @@ export class TalerMerchantInstanceHttpClient { ) { const url = new URL(`private`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -385,12 +447,18 @@ export class TalerMerchantInstanceHttpClient { headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_CURRENT_INSTANCE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -398,12 +466,12 @@ export class TalerMerchantInstanceHttpClient { * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private * */ - async getCurrentInstance(token: AccessToken) { + async getCurrentInstanceDetails(token: AccessToken) { const url = new URL(`private`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -413,24 +481,31 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForQueryInstancesResponse()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private */ - async deleteCurrentInstance(token: AccessToken | undefined, params: { purge?: boolean } = {}) { + async deleteCurrentInstance( + token: AccessToken | undefined, + params: { purge?: boolean } = {}, + ) { const url = new URL(`private`, this.baseUrl); - if (params.purge) { - url.searchParams.set("purge", "YES"); + if (params.purge !== undefined) { + url.searchParams.set("purge", params.purge ? "YES" : "NO"); } - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", @@ -438,8 +513,12 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_CURRENT_INSTANCE, + ); return opEmptySuccess(resp); + } case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: @@ -447,7 +526,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -456,7 +535,7 @@ export class TalerMerchantInstanceHttpClient { */ async getCurrentIntanceKycStatus( token: AccessToken | undefined, - params: TalerMerchantApi.GetKycStatusRequestParams, + params: TalerMerchantApi.GetKycStatusRequestParams = {}, ) { const url = new URL(`private/kyc`, this.baseUrl); @@ -470,9 +549,9 @@ export class TalerMerchantInstanceHttpClient { url.searchParams.set("timeout_ms", String(params.timeout)); } - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -484,14 +563,22 @@ export class TalerMerchantInstanceHttpClient { return opSuccessFromHttp(resp, codecForAccountKycRedirects()); case HttpStatusCode.NoContent: return opEmptySuccess(resp); - case HttpStatusCode.BadGateway: + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: // FIXME: missing in docs return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.BadGateway: + return opKnownAlternativeFailure( + resp, + resp.status, + codecForAccountKycRedirects(), + ); case HttpStatusCode.ServiceUnavailable: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.Conflict: + case HttpStatusCode.GatewayTimeout: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -502,12 +589,15 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-accounts */ - async addAccount(token: AccessToken | undefined, body: TalerMerchantApi.AccountAddDetails) { + async addBankAccount( + token: AccessToken | undefined, + body: TalerMerchantApi.AccountAddDetails, + ) { const url = new URL(`private/accounts`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -516,30 +606,36 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_BANK_ACCOUNT, + ); return opSuccessFromHttp(resp, codecForAccountAddResponse()); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-accounts-$H_WIRE */ - async updateAccount( + async updateBankAccount( token: AccessToken | undefined, wireAccount: string, body: TalerMerchantApi.AccountPatchDetails, ) { const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -547,24 +643,32 @@ export class TalerMerchantInstanceHttpClient { headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_BANK_ACCOUNT, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts */ - async listAccounts(token: AccessToken) { + async listBankAccounts(token: AccessToken, params?: PaginationParams) { const url = new URL(`private/accounts`, this.baseUrl); - const headers: Record<string, string> = {} + // addMerchantPaginationParams(url, params); + + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -574,22 +678,27 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForAccountsSummaryResponse()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts-$H_WIRE */ - async getAccount(token: AccessToken | undefined, wireAccount: string) { + async getBankAccountDetails( + token: AccessToken | undefined, + wireAccount: string, + ) { const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -599,22 +708,24 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForBankAccountEntry()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-accounts-$H_WIRE */ - async deleteAccount(token: AccessToken | undefined, wireAccount: string) { + async deleteBankAccount(token: AccessToken | undefined, wireAccount: string) { const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", @@ -622,12 +733,18 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_BANK_ACCOUNT, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -638,12 +755,15 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-products */ - async addProduct(token: AccessToken | undefined, body: TalerMerchantApi.ProductAddDetail) { + async addProduct( + token: AccessToken | undefined, + body: TalerMerchantApi.ProductAddDetail, + ) { const url = new URL(`private/products`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -652,12 +772,20 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_PRODUCT, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -667,13 +795,13 @@ export class TalerMerchantInstanceHttpClient { async updateProduct( token: AccessToken | undefined, productId: string, - body: TalerMerchantApi.ProductAddDetail, + body: TalerMerchantApi.ProductPatchDetail, ) { const url = new URL(`private/products/${productId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -682,28 +810,37 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_PRODUCT, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products */ - async listProducts(token: AccessToken | undefined, params?: PaginationParams) { + async listProducts( + token: AccessToken | undefined, + params?: PaginationParams, + ) { const url = new URL(`private/products`, this.baseUrl); addMerchantPaginationParams(url, params); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -713,22 +850,50 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForInventorySummaryResponse()); + case HttpStatusCode.Unauthorized: // FIXME: not in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-pos + */ + async getPointOfSaleInventory(token: AccessToken | undefined) { + const url = new URL(`private/pos`, this.baseUrl); + + const headers: Record<string, string> = {}; + if (token) { + headers.Authorization = makeBearerTokenAuthHeader(token); + } + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + headers, + }); + + switch (resp.status) { + case HttpStatusCode.Ok: + return opSuccessFromHttp(resp, codecForMerchantPosProductDetail()); + case HttpStatusCode.NotFound: + return opKnownHttpFailure(resp.status, resp); + default: + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); + } + + } + + /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products-$PRODUCT_ID */ - async getProduct(token: AccessToken | undefined, productId: string) { + async getProductDetails(token: AccessToken | undefined, productId: string) { const url = new URL(`private/products/${productId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -738,22 +903,28 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForProductDetail()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#reserving-inventory */ - async lockProduct(token: AccessToken | undefined, productId: string, body: TalerMerchantApi.LockRequest) { + async lockProduct( + token: AccessToken | undefined, + productId: string, + body: TalerMerchantApi.LockRequest, + ) { const url = new URL(`private/products/${productId}/lock`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -762,26 +933,32 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_PRODUCT, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Gone: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#removing-products-from-inventory */ - async removeProduct(token: AccessToken | undefined, productId: string) { + async deleteProduct(token: AccessToken | undefined, productId: string) { const url = new URL(`private/products/${productId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", @@ -789,14 +966,20 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_PRODUCT, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -807,29 +990,36 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders */ - async createOrder(token: AccessToken | undefined, body: TalerMerchantApi.PostOrderRequest) { + async createOrder( + token: AccessToken | undefined, + body: TalerMerchantApi.PostOrderRequest, + ) { const url = new URL(`private/orders`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", body, headers, }); - return this.procesOrderCreationResponse(resp) + return this.procesOrderCreationResponse(resp); } private async procesOrderCreationResponse(resp: HttpResponse) { switch (resp.status) { case HttpStatusCode.Ok: { - this.cacheEvictor.notifySuccess(TalerMerchantInstanceCacheEviction.CREATE_ORDER) - return opSuccessFromHttp(resp, codecForPostOrderResponse()) + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_ORDER, + ); + return opSuccessFromHttp(resp, codecForPostOrderResponse()); } case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Gone: @@ -839,14 +1029,17 @@ export class TalerMerchantInstanceHttpClient { codecForOutOfStockResponse(), ); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#inspecting-orders */ - async listOrders(token: AccessToken | undefined, params: TalerMerchantApi.ListOrdersRequestParams = {}) { + async listOrders( + token: AccessToken | undefined, + params: TalerMerchantApi.ListOrdersRequestParams = {}, + ) { const url = new URL(`private/orders`, this.baseUrl); if (params.date) { @@ -855,11 +1048,11 @@ export class TalerMerchantInstanceHttpClient { if (params.fulfillmentUrl) { url.searchParams.set("fulfillment_url", params.fulfillmentUrl); } - if (params.paid) { - url.searchParams.set("paid", "YES"); + if (params.paid !== undefined) { + url.searchParams.set("paid", params.paid ? "YES" : "NO"); } - if (params.refunded) { - url.searchParams.set("refunded", "YES"); + if (params.refunded !== undefined) { + url.searchParams.set("refunded", params.refunded ? "YES" : "NO"); } if (params.sessionId) { url.searchParams.set("session_id", params.sessionId); @@ -867,14 +1060,14 @@ export class TalerMerchantInstanceHttpClient { if (params.timeout) { url.searchParams.set("timeout", String(params.timeout)); } - if (params.wired) { - url.searchParams.set("wired", "YES"); + if (params.wired !== undefined) { + url.searchParams.set("wired", params.wired ? "YES" : "NO"); } addMerchantPaginationParams(url, params); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -884,23 +1077,30 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForOrderHistory()); + case HttpStatusCode.NotFound: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-orders-$ORDER_ID */ - async getOrder( + async getOrderDetails( token: AccessToken | undefined, orderId: string, params: TalerMerchantApi.GetOrderRequestParams = {}, ) { const url = new URL(`private/orders/${orderId}`, this.baseUrl); - if (params.allowRefundedForRepurchase) { - url.searchParams.set("allow_refunded_for_repurchase", "YES"); + if (params.allowRefundedForRepurchase !== undefined) { + url.searchParams.set( + "allow_refunded_for_repurchase", + params.allowRefundedForRepurchase ? "YES" : "NO", + ); } if (params.sessionId) { url.searchParams.set("session_id", params.sessionId); @@ -909,9 +1109,9 @@ export class TalerMerchantInstanceHttpClient { url.searchParams.set("timeout_ms", String(params.timeout)); } - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -926,6 +1126,8 @@ export class TalerMerchantInstanceHttpClient { ); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.BadGateway: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.GatewayTimeout: @@ -935,19 +1137,23 @@ export class TalerMerchantInstanceHttpClient { codecForOutOfStockResponse(), ); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#private-order-data-cleanup */ - async forgetOrder(token: AccessToken | undefined, orderId: string, body: TalerMerchantApi.ForgetRequest) { + async forgetOrder( + token: AccessToken | undefined, + orderId: string, + body: TalerMerchantApi.ForgetRequest, + ) { const url = new URL(`private/orders/${orderId}/forget`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -956,10 +1162,16 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); return opEmptySuccess(resp); + } case HttpStatusCode.NoContent: return opEmptySuccess(resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: @@ -967,7 +1179,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -977,9 +1189,9 @@ export class TalerMerchantInstanceHttpClient { async deleteOrder(token: AccessToken | undefined, orderId: string) { const url = new URL(`private/orders/${orderId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", @@ -987,14 +1199,20 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_ORDER, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1005,12 +1223,16 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders-$ORDER_ID-refund */ - async addRefund(token: AccessToken | undefined, orderId: string, body: TalerMerchantApi.RefundRequest) { + async addRefund( + token: AccessToken | undefined, + orderId: string, + body: TalerMerchantApi.RefundRequest, + ) { const url = new URL(`private/orders/${orderId}/refund`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1019,10 +1241,16 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_ORDER, + ); return opSuccessFromHttp(resp, codecForMerchantRefundResponse()); + } case HttpStatusCode.Forbidden: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Gone: @@ -1030,7 +1258,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1041,12 +1269,15 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-transfers */ - async informWireTransfer(token: AccessToken | undefined, body: TalerMerchantApi.TransferInformation) { + async informWireTransfer( + token: AccessToken | undefined, + body: TalerMerchantApi.TransferInformation, + ) { const url = new URL(`private/transfers`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1055,14 +1286,20 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_TRANSFER, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1084,14 +1321,14 @@ export class TalerMerchantInstanceHttpClient { if (params.paytoURI) { url.searchParams.set("payto_uri", params.paytoURI); } - if (params.verified) { - url.searchParams.set("verified", "YES"); + if (params.verified !== undefined) { + url.searchParams.set("verified", params.verified ? "YES" : "NO"); } addMerchantPaginationParams(url, params); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1101,8 +1338,12 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForTansferList()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1112,9 +1353,9 @@ export class TalerMerchantInstanceHttpClient { async deleteWireTransfer(token: AccessToken | undefined, transferId: string) { const url = new URL(`private/transfers/${transferId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", @@ -1122,14 +1363,20 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_TRANSFER, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1140,12 +1387,15 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-otp-devices */ - async addOtpDevice(token: AccessToken | undefined, body: TalerMerchantApi.OtpDeviceAddDetails) { + async addOtpDevice( + token: AccessToken | undefined, + body: TalerMerchantApi.OtpDeviceAddDetails, + ) { const url = new URL(`private/otp-devices`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1154,12 +1404,18 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_DEVICE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1173,9 +1429,9 @@ export class TalerMerchantInstanceHttpClient { ) { const url = new URL(`private/otp-devices/${deviceId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -1183,26 +1439,37 @@ export class TalerMerchantInstanceHttpClient { headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_DEVICE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices */ - async listOtpDevices(token: AccessToken | undefined,) { + async listOtpDevices( + token: AccessToken | undefined, + params?: PaginationParams, + ) { const url = new URL(`private/otp-devices`, this.baseUrl); - const headers: Record<string, string> = {} + addMerchantPaginationParams(url, params); + + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1211,17 +1478,19 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForOtpDeviceSummaryResponse()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID */ - async getOtpDevice( + async getOtpDeviceDetails( token: AccessToken | undefined, deviceId: string, params: TalerMerchantApi.GetOtpDeviceRequestParams = {}, @@ -1234,9 +1503,9 @@ export class TalerMerchantInstanceHttpClient { if (params.price) { url.searchParams.set("price", params.price); } - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1246,10 +1515,12 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForOtpDeviceDetails()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1259,21 +1530,27 @@ export class TalerMerchantInstanceHttpClient { async deleteOtpDevice(token: AccessToken | undefined, deviceId: string) { const url = new URL(`private/otp-devices/${deviceId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_DEVICE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1284,12 +1561,15 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-templates */ - async addTemplate(token: AccessToken | undefined, body: TalerMerchantApi.TemplateAddDetails) { + async addTemplate( + token: AccessToken | undefined, + body: TalerMerchantApi.TemplateAddDetails, + ) { const url = new URL(`private/templates`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1297,12 +1577,18 @@ export class TalerMerchantInstanceHttpClient { headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_TEMPLATE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1316,9 +1602,9 @@ export class TalerMerchantInstanceHttpClient { ) { const url = new URL(`private/templates/${templateId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -1326,26 +1612,37 @@ export class TalerMerchantInstanceHttpClient { headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_TEMPLATE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#inspecting-template */ - async listTemplates(token: AccessToken | undefined,) { + async listTemplates( + token: AccessToken | undefined, + params?: PaginationParams, + ) { const url = new URL(`private/templates`, this.baseUrl); - const headers: Record<string, string> = {} + addMerchantPaginationParams(url, params); + + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1354,22 +1651,24 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForTemplateSummaryResponse()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID */ - async getTemplate(token: AccessToken | undefined, templateId: string) { + async getTemplateDetails(token: AccessToken | undefined, templateId: string) { const url = new URL(`private/templates/${templateId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1378,10 +1677,12 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForTemplateDetails()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1391,21 +1692,27 @@ export class TalerMerchantInstanceHttpClient { async deleteTemplate(token: AccessToken | undefined, templateId: string) { const url = new URL(`private/templates/${templateId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_TEMPLATE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1424,7 +1731,7 @@ export class TalerMerchantInstanceHttpClient { case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1442,7 +1749,7 @@ export class TalerMerchantInstanceHttpClient { body, }); - return this.procesOrderCreationResponse(resp) + return this.procesOrderCreationResponse(resp); } // @@ -1452,12 +1759,15 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-webhooks */ - async addWebhook(token: AccessToken | undefined, body: TalerMerchantApi.WebhookAddDetails) { + async addWebhook( + token: AccessToken | undefined, + body: TalerMerchantApi.WebhookAddDetails, + ) { const url = new URL(`private/webhooks`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1466,12 +1776,18 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_WEBHOOK, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1485,9 +1801,9 @@ export class TalerMerchantInstanceHttpClient { ) { const url = new URL(`private/webhooks/${webhookId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -1496,26 +1812,35 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_WEBHOOK, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks */ - async listWebhooks(token: AccessToken | undefined,) { + async listWebhooks( + token: AccessToken | undefined, + params?: PaginationParams, + ) { const url = new URL(`private/webhooks`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1523,24 +1848,26 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForWebhookSummaryResponse()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID */ - async getWebhook(token: AccessToken | undefined, webhookId: string) { + async getWebhookDetails(token: AccessToken | undefined, webhookId: string) { const url = new URL(`private/webhooks/${webhookId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1549,34 +1876,42 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: return opSuccessFromHttp(resp, codecForWebhookDetails()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID */ - async removeWebhook(token: AccessToken | undefined, webhookId: string) { + async deleteWebhook(token: AccessToken | undefined, webhookId: string) { const url = new URL(`private/webhooks/${webhookId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_WEBHOOK, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1587,12 +1922,15 @@ export class TalerMerchantInstanceHttpClient { /** * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-tokenfamilies */ - async createTokenFamily(token: AccessToken | undefined, body: TalerMerchantApi.TokenFamilyCreateRequest) { + async createTokenFamily( + token: AccessToken | undefined, + body: TalerMerchantApi.TokenFamilyCreateRequest, + ) { const url = new URL(`private/tokenfamilies`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1601,12 +1939,18 @@ export class TalerMerchantInstanceHttpClient { }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.CREATE_TOKENFAMILY, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1620,9 +1964,9 @@ export class TalerMerchantInstanceHttpClient { ) { const url = new URL(`private/tokenfamilies/${tokenSlug}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1630,24 +1974,33 @@ export class TalerMerchantInstanceHttpClient { headers, }); switch (resp.status) { - case HttpStatusCode.Ok: + case HttpStatusCode.Ok: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.UPDATE_TOKENFAMILY, + ); return opSuccessFromHttp(resp, codecForTokenFamilyDetails()); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies */ - async listTokenFamilies(token: AccessToken | undefined,) { + async listTokenFamilies( + token: AccessToken | undefined, + params?: PaginationParams, + ) { const url = new URL(`private/tokenfamilies`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1657,22 +2010,27 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForTokenFamiliesList()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG */ - async getTokenFamily(token: AccessToken | undefined, tokenSlug: string) { + async getTokenFamilyDetails( + token: AccessToken | undefined, + tokenSlug: string, + ) { const url = new URL(`private/tokenfamilies/${tokenSlug}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1682,10 +2040,12 @@ export class TalerMerchantInstanceHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForTokenFamilyDetails()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1695,21 +2055,27 @@ export class TalerMerchantInstanceHttpClient { async deleteTokenFamily(token: AccessToken | undefined, tokenSlug: string) { const url = new URL(`private/tokenfamilies/${tokenSlug}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheEvictor.notifySuccess( + TalerMerchantInstanceCacheEviction.DELETE_TOKENFAMILY, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1722,19 +2088,29 @@ export class TalerMerchantInstanceHttpClient { getAuthenticationAPI(): URL { return new URL(`private/`, this.baseUrl); } - } +export type TalerMerchantManagementResultByMethod< + prop extends keyof TalerMerchantManagementHttpClient, +> = ResultByMethod<TalerMerchantManagementHttpClient, prop>; +export type TalerMerchantManagementErrorsByMethod< + prop extends keyof TalerMerchantManagementHttpClient, +> = FailCasesByMethod<TalerMerchantManagementHttpClient, prop>; + export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttpClient { - readonly cacheManagementEvictor: CacheEvictor<TalerMerchantManagementCacheEviction>; + readonly cacheManagementEvictor: CacheEvictor< + TalerMerchantInstanceCacheEviction | TalerMerchantManagementCacheEviction + >; constructor( readonly baseUrl: string, httpClient?: HttpRequestLibrary, - cacheManagementEvictor?: CacheEvictor<TalerMerchantManagementCacheEviction>, - cacheEvictor?: CacheEvictor<TalerMerchantInstanceCacheEviction>, + // cacheManagementEvictor?: CacheEvictor<TalerMerchantManagementCacheEviction>, + cacheEvictor?: CacheEvictor< + TalerMerchantInstanceCacheEviction | TalerMerchantManagementCacheEviction + >, ) { super(baseUrl, httpClient, cacheEvictor); - this.cacheManagementEvictor = cacheManagementEvictor ?? nullEvictor; + this.cacheManagementEvictor = cacheEvictor ?? nullEvictor; } getSubInstanceAPI(instanceId: string) { @@ -1748,12 +2124,15 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp /** * https://docs.taler.net/core/api-merchant.html#post--management-instances */ - async createInstance(token: AccessToken | undefined, body: TalerMerchantApi.InstanceConfigurationMessage) { + async createInstance( + token: AccessToken | undefined, + body: TalerMerchantApi.InstanceConfigurationMessage, + ) { const url = new URL(`management/instances`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1761,16 +2140,19 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp headers, }); - switch (resp.status) { case HttpStatusCode.NoContent: { - this.cacheManagementEvictor.notifySuccess(TalerMerchantManagementCacheEviction.CREATE_INSTANCE) + this.cacheManagementEvictor.notifySuccess( + TalerMerchantManagementCacheEviction.CREATE_INSTANCE, + ); return opEmptySuccess(resp); } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1782,11 +2164,14 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp instanceId: string, body: TalerMerchantApi.InstanceAuthConfigurationMessage, ) { - const url = new URL(`management/instances/${instanceId}/auth`, this.baseUrl); + const url = new URL( + `management/instances/${instanceId}/auth`, + this.baseUrl, + ); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "POST", @@ -1797,10 +2182,12 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp switch (resp.status) { case HttpStatusCode.NoContent: return opEmptySuccess(resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1814,9 +2201,9 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp ) { const url = new URL(`management/instances/${instanceId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "PATCH", @@ -1824,24 +2211,33 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheManagementEvictor.notifySuccess( + TalerMerchantManagementCacheEviction.UPDATE_INSTANCE, + ); return opEmptySuccess(resp); + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#get--management-instances */ - async listInstances(token: AccessToken | undefined,) { + async listInstances( + token: AccessToken | undefined, + params?: PaginationParams, + ) { const url = new URL(`management/instances`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1851,8 +2247,10 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForInstancesResponse()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1860,12 +2258,12 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE * */ - async getInstance(token: AccessToken | undefined, instanceId: string) { + async getInstanceDetails(token: AccessToken | undefined, instanceId: string) { const url = new URL(`management/instances/${instanceId}`, this.baseUrl); - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1875,40 +2273,52 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForQueryInstancesResponse()); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-merchant.html#delete--management-instances-$INSTANCE */ - async deleteInstance(token: AccessToken | undefined, instanceId: string, params: { purge?: boolean } = {}) { + async deleteInstance( + token: AccessToken | undefined, + instanceId: string, + params: { purge?: boolean } = {}, + ) { const url = new URL(`management/instances/${instanceId}`, this.baseUrl); - if (params.purge) { - url.searchParams.set("purge", "YES"); + if (params.purge !== undefined) { + url.searchParams.set("purge", params.purge ? "YES" : "NO"); } - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "DELETE", headers, }); switch (resp.status) { - case HttpStatusCode.NoContent: + case HttpStatusCode.NoContent: { + this.cacheManagementEvictor.notifySuccess( + TalerMerchantManagementCacheEviction.DELETE_INSTANCE, + ); return opEmptySuccess(resp); - case HttpStatusCode.Unauthorized: + } + case HttpStatusCode.Unauthorized: // FIXME: missing in docs return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } @@ -1932,9 +2342,9 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp url.searchParams.set("timeout_ms", String(params.timeout)); } - const headers: Record<string, string> = {} + const headers: Record<string, string> = {}; if (token) { - headers.Authorization = makeBearerTokenAuthHeader(token) + headers.Authorization = makeBearerTokenAuthHeader(token); } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -1945,6 +2355,10 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp return opSuccessFromHttp(resp, codecForAccountKycRedirects()); case HttpStatusCode.NoContent: return opEmptySuccess(resp); + case HttpStatusCode.NotFound: + return opEmptySuccess(resp); + case HttpStatusCode.Unauthorized: // FIXME: missing in docs + return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.BadGateway: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.ServiceUnavailable: @@ -1952,7 +2366,7 @@ export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttp case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: - return opUnknownFailure(resp, await resp.text()); + return opUnknownFailure(resp, await readTalerErrorResponse(resp)); } } } |