stronger type check to be sure that ErrorDetails is consistent
This commit is contained in:
parent
5be2d128ed
commit
eeea3e62a0
@ -32,6 +32,8 @@ import {
|
|||||||
TransactionType,
|
TransactionType,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
|
type empty = Record<string, never>;
|
||||||
|
|
||||||
export interface DetailsMap {
|
export interface DetailsMap {
|
||||||
[TalerErrorCode.WALLET_PENDING_OPERATION_FAILED]: {
|
[TalerErrorCode.WALLET_PENDING_OPERATION_FAILED]: {
|
||||||
innerError: TalerErrorDetail;
|
innerError: TalerErrorDetail;
|
||||||
@ -44,13 +46,13 @@ export interface DetailsMap {
|
|||||||
exchangeProtocolVersion: string;
|
exchangeProtocolVersion: string;
|
||||||
walletProtocolVersion: string;
|
walletProtocolVersion: string;
|
||||||
};
|
};
|
||||||
[TalerErrorCode.WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK]: {};
|
[TalerErrorCode.WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK]: empty;
|
||||||
[TalerErrorCode.WALLET_TIPPING_COIN_SIGNATURE_INVALID]: {};
|
[TalerErrorCode.WALLET_TIPPING_COIN_SIGNATURE_INVALID]: empty;
|
||||||
[TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED]: {
|
[TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED]: {
|
||||||
orderId: string;
|
orderId: string;
|
||||||
claimUrl: string;
|
claimUrl: string;
|
||||||
};
|
};
|
||||||
[TalerErrorCode.WALLET_CONTRACT_TERMS_MALFORMED]: {};
|
[TalerErrorCode.WALLET_CONTRACT_TERMS_MALFORMED]: empty;
|
||||||
[TalerErrorCode.WALLET_CONTRACT_TERMS_SIGNATURE_INVALID]: {
|
[TalerErrorCode.WALLET_CONTRACT_TERMS_SIGNATURE_INVALID]: {
|
||||||
merchantPub: string;
|
merchantPub: string;
|
||||||
orderId: string;
|
orderId: string;
|
||||||
@ -62,18 +64,46 @@ export interface DetailsMap {
|
|||||||
[TalerErrorCode.WALLET_INVALID_TALER_PAY_URI]: {
|
[TalerErrorCode.WALLET_INVALID_TALER_PAY_URI]: {
|
||||||
talerPayUri: string;
|
talerPayUri: string;
|
||||||
};
|
};
|
||||||
[TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR]: {};
|
[TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR]: {
|
||||||
[TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION]: {};
|
requestUrl: string;
|
||||||
[TalerErrorCode.WALLET_BANK_INTEGRATION_PROTOCOL_VERSION_INCOMPATIBLE]: {};
|
requestMethod: string;
|
||||||
[TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN]: {};
|
httpStatusCode: number;
|
||||||
[TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED]: {};
|
errorResponse?: any;
|
||||||
[TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT]: {};
|
};
|
||||||
[TalerErrorCode.WALLET_NETWORK_ERROR]: {};
|
[TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION]: {
|
||||||
[TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE]: {};
|
stack?: string;
|
||||||
[TalerErrorCode.WALLET_EXCHANGE_COIN_SIGNATURE_INVALID]: {};
|
};
|
||||||
[TalerErrorCode.WALLET_WITHDRAWAL_GROUP_INCOMPLETE]: {};
|
[TalerErrorCode.WALLET_BANK_INTEGRATION_PROTOCOL_VERSION_INCOMPATIBLE]: {
|
||||||
[TalerErrorCode.WALLET_CORE_NOT_AVAILABLE]: {};
|
exchangeProtocolVersion: string;
|
||||||
[TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR]: {};
|
walletProtocolVersion: string;
|
||||||
|
};
|
||||||
|
[TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN]: {
|
||||||
|
operation: string;
|
||||||
|
};
|
||||||
|
[TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED]: {
|
||||||
|
requestUrl: string;
|
||||||
|
requestMethod: string;
|
||||||
|
throttleStats: Record<string, unknown>;
|
||||||
|
};
|
||||||
|
[TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT]: empty;
|
||||||
|
[TalerErrorCode.WALLET_NETWORK_ERROR]: {
|
||||||
|
requestUrl: string;
|
||||||
|
requestMethod: string;
|
||||||
|
};
|
||||||
|
[TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE]: {
|
||||||
|
requestUrl: string;
|
||||||
|
requestMethod: string;
|
||||||
|
httpStatusCode: number;
|
||||||
|
validationError?: string;
|
||||||
|
};
|
||||||
|
[TalerErrorCode.WALLET_EXCHANGE_COIN_SIGNATURE_INVALID]: empty;
|
||||||
|
[TalerErrorCode.WALLET_WITHDRAWAL_GROUP_INCOMPLETE]: {
|
||||||
|
errorsPerCoin: Record<number, TalerErrorDetail>;
|
||||||
|
};
|
||||||
|
[TalerErrorCode.WALLET_CORE_NOT_AVAILABLE]: empty;
|
||||||
|
[TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR]: {
|
||||||
|
httpStatusCode: number;
|
||||||
|
};
|
||||||
[TalerErrorCode.WALLET_PAY_MERCHANT_SERVER_ERROR]: {
|
[TalerErrorCode.WALLET_PAY_MERCHANT_SERVER_ERROR]: {
|
||||||
requestError: TalerErrorDetail;
|
requestError: TalerErrorDetail;
|
||||||
};
|
};
|
||||||
@ -84,7 +114,7 @@ export interface DetailsMap {
|
|||||||
detail: string;
|
detail: string;
|
||||||
};
|
};
|
||||||
[TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED]: {
|
[TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED]: {
|
||||||
// FIXME!
|
kycUrl: string;
|
||||||
};
|
};
|
||||||
[TalerErrorCode.WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE]: {
|
[TalerErrorCode.WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE]: {
|
||||||
insufficientBalanceDetails: PayMerchantInsufficientBalanceDetails;
|
insufficientBalanceDetails: PayMerchantInsufficientBalanceDetails;
|
||||||
@ -94,7 +124,7 @@ export interface DetailsMap {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrBody<Y> = Y extends keyof DetailsMap ? DetailsMap[Y] : never;
|
type ErrBody<Y> = Y extends keyof DetailsMap ? DetailsMap[Y] : empty;
|
||||||
|
|
||||||
export function makeErrorDetail<C extends TalerErrorCode>(
|
export function makeErrorDetail<C extends TalerErrorCode>(
|
||||||
code: C,
|
code: C,
|
||||||
@ -133,7 +163,7 @@ function getDefaultHint(code: number): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TalerProtocolViolationError<T = any> extends Error {
|
export class TalerProtocolViolationError extends Error {
|
||||||
constructor(hint?: string) {
|
constructor(hint?: string) {
|
||||||
let msg: string;
|
let msg: string;
|
||||||
if (hint) {
|
if (hint) {
|
||||||
|
@ -734,7 +734,7 @@ async function runFirstBackupCycleForProvider(
|
|||||||
case OperationAttemptResultType.Error:
|
case OperationAttemptResultType.Error:
|
||||||
throw TalerError.fromDetail(
|
throw TalerError.fromDetail(
|
||||||
TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
|
TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
|
||||||
resp.errorDetail,
|
resp.errorDetail as any, //FIXME create an error for backup problems
|
||||||
);
|
);
|
||||||
case OperationAttemptResultType.Finished:
|
case OperationAttemptResultType.Finished:
|
||||||
return {
|
return {
|
||||||
|
@ -68,7 +68,7 @@ export interface HttpRequestOptions {
|
|||||||
*/
|
*/
|
||||||
cancellationToken?: CancellationToken;
|
cancellationToken?: CancellationToken;
|
||||||
|
|
||||||
body?: string | ArrayBuffer | Object;
|
body?: string | ArrayBuffer | Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -185,6 +185,7 @@ export async function readUnexpectedResponseDetails(
|
|||||||
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
|
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
|
||||||
{
|
{
|
||||||
requestUrl: httpResponse.requestUrl,
|
requestUrl: httpResponse.requestUrl,
|
||||||
|
requestMethod: httpResponse.requestMethod,
|
||||||
httpStatusCode: httpResponse.status,
|
httpStatusCode: httpResponse.status,
|
||||||
errorResponse: errJson,
|
errorResponse: errJson,
|
||||||
},
|
},
|
||||||
@ -211,6 +212,7 @@ export async function readSuccessResponseJsonOrErrorCode<T>(
|
|||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
{
|
{
|
||||||
requestUrl: httpResponse.requestUrl,
|
requestUrl: httpResponse.requestUrl,
|
||||||
|
requestMethod: httpResponse.requestMethod,
|
||||||
httpStatusCode: httpResponse.status,
|
httpStatusCode: httpResponse.status,
|
||||||
validationError: e.toString(),
|
validationError: e.toString(),
|
||||||
},
|
},
|
||||||
@ -223,11 +225,18 @@ export async function readSuccessResponseJsonOrErrorCode<T>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HttpErrorDetails = {
|
||||||
|
requestUrl: string;
|
||||||
|
requestMethod: string;
|
||||||
|
httpStatusCode: number;
|
||||||
|
};
|
||||||
|
|
||||||
export function getHttpResponseErrorDetails(
|
export function getHttpResponseErrorDetails(
|
||||||
httpResponse: HttpResponse,
|
httpResponse: HttpResponse,
|
||||||
): Record<string, unknown> {
|
): HttpErrorDetails {
|
||||||
return {
|
return {
|
||||||
requestUrl: httpResponse.requestUrl,
|
requestUrl: httpResponse.requestUrl,
|
||||||
|
requestMethod: httpResponse.requestMethod,
|
||||||
httpStatusCode: httpResponse.status,
|
httpStatusCode: httpResponse.status,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -240,6 +249,7 @@ export function throwUnexpectedRequestError(
|
|||||||
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
|
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
|
||||||
{
|
{
|
||||||
requestUrl: httpResponse.requestUrl,
|
requestUrl: httpResponse.requestUrl,
|
||||||
|
requestMethod: httpResponse.requestMethod,
|
||||||
httpStatusCode: httpResponse.status,
|
httpStatusCode: httpResponse.status,
|
||||||
errorResponse: talerErrorResponse,
|
errorResponse: talerErrorResponse,
|
||||||
},
|
},
|
||||||
|
@ -90,7 +90,8 @@ export class BrowserHttpLib implements HttpRequestLibrary {
|
|||||||
TalerError.fromDetail(
|
TalerError.fromDetail(
|
||||||
TalerErrorCode.WALLET_NETWORK_ERROR,
|
TalerErrorCode.WALLET_NETWORK_ERROR,
|
||||||
{
|
{
|
||||||
requestUrl: requestUrl,
|
requestUrl,
|
||||||
|
requestMethod,
|
||||||
},
|
},
|
||||||
"Could not make request",
|
"Could not make request",
|
||||||
),
|
),
|
||||||
@ -103,7 +104,8 @@ export class BrowserHttpLib implements HttpRequestLibrary {
|
|||||||
const exc = TalerError.fromDetail(
|
const exc = TalerError.fromDetail(
|
||||||
TalerErrorCode.WALLET_NETWORK_ERROR,
|
TalerErrorCode.WALLET_NETWORK_ERROR,
|
||||||
{
|
{
|
||||||
requestUrl: requestUrl,
|
requestUrl,
|
||||||
|
requestMethod,
|
||||||
},
|
},
|
||||||
"HTTP request failed (status 0, maybe URI scheme was wrong?)",
|
"HTTP request failed (status 0, maybe URI scheme was wrong?)",
|
||||||
);
|
);
|
||||||
@ -124,7 +126,8 @@ export class BrowserHttpLib implements HttpRequestLibrary {
|
|||||||
throw TalerError.fromDetail(
|
throw TalerError.fromDetail(
|
||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
{
|
{
|
||||||
requestUrl: requestUrl,
|
requestUrl,
|
||||||
|
requestMethod,
|
||||||
httpStatusCode: myRequest.status,
|
httpStatusCode: myRequest.status,
|
||||||
},
|
},
|
||||||
"Invalid JSON from HTTP response",
|
"Invalid JSON from HTTP response",
|
||||||
@ -134,7 +137,8 @@ export class BrowserHttpLib implements HttpRequestLibrary {
|
|||||||
throw TalerError.fromDetail(
|
throw TalerError.fromDetail(
|
||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
{
|
{
|
||||||
requestUrl: requestUrl,
|
requestUrl,
|
||||||
|
requestMethod,
|
||||||
httpStatusCode: myRequest.status,
|
httpStatusCode: myRequest.status,
|
||||||
},
|
},
|
||||||
"Invalid JSON from HTTP response",
|
"Invalid JSON from HTTP response",
|
||||||
|
@ -104,8 +104,8 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary {
|
|||||||
status: response.status,
|
status: response.status,
|
||||||
requestMethod,
|
requestMethod,
|
||||||
requestUrl,
|
requestUrl,
|
||||||
json: makeJsonHandler(response, requestUrl),
|
json: makeJsonHandler(response, requestUrl, requestMethod),
|
||||||
text: makeTextHandler(response, requestUrl),
|
text: makeTextHandler(response, requestUrl, requestMethod),
|
||||||
bytes: async () => (await response.blob()).arrayBuffer(),
|
bytes: async () => (await response.blob()).arrayBuffer(),
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -145,7 +145,11 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeTextHandler(response: Response, requestUrl: string) {
|
function makeTextHandler(
|
||||||
|
response: Response,
|
||||||
|
requestUrl: string,
|
||||||
|
requestMethod: string,
|
||||||
|
) {
|
||||||
return async function getJsonFromResponse(): Promise<any> {
|
return async function getJsonFromResponse(): Promise<any> {
|
||||||
let respText;
|
let respText;
|
||||||
try {
|
try {
|
||||||
@ -155,6 +159,7 @@ function makeTextHandler(response: Response, requestUrl: string) {
|
|||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
{
|
{
|
||||||
requestUrl,
|
requestUrl,
|
||||||
|
requestMethod,
|
||||||
httpStatusCode: response.status,
|
httpStatusCode: response.status,
|
||||||
},
|
},
|
||||||
"Invalid JSON from HTTP response",
|
"Invalid JSON from HTTP response",
|
||||||
@ -164,7 +169,11 @@ function makeTextHandler(response: Response, requestUrl: string) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeJsonHandler(response: Response, requestUrl: string) {
|
function makeJsonHandler(
|
||||||
|
response: Response,
|
||||||
|
requestUrl: string,
|
||||||
|
requestMethod: string,
|
||||||
|
) {
|
||||||
return async function getJsonFromResponse(): Promise<any> {
|
return async function getJsonFromResponse(): Promise<any> {
|
||||||
let responseJson;
|
let responseJson;
|
||||||
try {
|
try {
|
||||||
@ -174,6 +183,7 @@ function makeJsonHandler(response: Response, requestUrl: string) {
|
|||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
{
|
{
|
||||||
requestUrl,
|
requestUrl,
|
||||||
|
requestMethod,
|
||||||
httpStatusCode: response.status,
|
httpStatusCode: response.status,
|
||||||
},
|
},
|
||||||
"Invalid JSON from HTTP response",
|
"Invalid JSON from HTTP response",
|
||||||
@ -184,6 +194,7 @@ function makeJsonHandler(response: Response, requestUrl: string) {
|
|||||||
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
|
||||||
{
|
{
|
||||||
requestUrl,
|
requestUrl,
|
||||||
|
requestMethod,
|
||||||
httpStatusCode: response.status,
|
httpStatusCode: response.status,
|
||||||
},
|
},
|
||||||
"Invalid JSON from HTTP response",
|
"Invalid JSON from HTTP response",
|
||||||
|
Loading…
Reference in New Issue
Block a user