1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
import { HttpResponse, readSuccessResponseJsonOrThrow, readTalerErrorResponse } from "./http-common.js";
import { Codec, HttpStatusCode, TalerError, TalerErrorCode, TalerErrorDetail } from "./index.js";
export type OperationResult<Body, ErrorEnum> =
| OperationOk<Body>
| OperationAlternative<ErrorEnum, Body>
| OperationFail<ErrorEnum>;
export function isOperationOk<T, E>(c: OperationResult<T, E>): c is OperationOk<T> {
return c.type === "ok"
}
export function isOperationFail<T, E>(c: OperationResult<T, E>): c is OperationFail<E> {
return c.type === "fail"
}
/**
* succesful operation
*/
export interface OperationOk<T> {
type: "ok",
body: T;
}
/**
* unsuccesful operation, see details
*/
export interface OperationFail<T> {
type: "fail",
case: T,
detail: TalerErrorDetail,
}
/**
* unsuccesful operation, see body
*/
export interface OperationAlternative<T, B> {
type: "fail",
case: T,
body: B,
}
export async function opSuccess<T>(resp: HttpResponse, codec: Codec<T>): Promise<OperationOk<T>> {
const body = await readSuccessResponseJsonOrThrow(resp, codec)
return { type: "ok" as const, body }
}
export function opFixedSuccess<T>(body: T): OperationOk<T> {
return { type: "ok" as const, body }
}
export function opEmptySuccess(): OperationOk<void> {
return { type: "ok" as const, body: void 0 }
}
export async function opKnownAlternativeFailure<T extends HttpStatusCode, B>(resp: HttpResponse, s: T, codec: Codec<B>): Promise<OperationAlternative<T, B>> {
const body = await readSuccessResponseJsonOrThrow(resp, codec)
return { type: "fail", case: s, body }
}
export async function opKnownHttpFailure<T extends HttpStatusCode>(s: T, resp: HttpResponse): Promise<OperationFail<T>> {
const detail = await readTalerErrorResponse(resp)
return { type: "fail", case: s, detail }
}
export async function opKnownTalerFailure<T extends TalerErrorCode>(s: T, resp: HttpResponse): Promise<OperationFail<T>> {
const detail = await readTalerErrorResponse(resp)
return { type: "fail", case: s, detail }
}
export async function opKnownFailure<T extends string>(s: T, resp: HttpResponse): Promise<OperationFail<T>> {
const detail = await readTalerErrorResponse(resp)
return { type: "fail", case: s, detail }
}
export function opUnknownFailure(resp: HttpResponse, text: string): never {
throw TalerError.fromDetail(
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
{
requestUrl: resp.requestUrl,
requestMethod: resp.requestMethod,
httpStatusCode: resp.status,
errorResponse: text,
},
`Unexpected HTTP status ${resp.status} in response`,
);
}
export type ResultByMethod<TT extends object, p extends keyof TT> = TT[p] extends (...args: any[]) => infer Ret ?
Ret extends Promise<infer Result> ?
Result extends OperationResult<any, any> ? Result : never :
never : //api always use Promises
never; //error cases just for functions
export type FailCasesByMethod<TT extends object, p extends keyof TT> = Exclude<ResultByMethod<TT, p>, OperationOk<any>>
|