diff options
Diffstat (limited to 'packages/taler-util/src/operation.ts')
-rw-r--r-- | packages/taler-util/src/operation.ts | 68 |
1 files changed, 27 insertions, 41 deletions
diff --git a/packages/taler-util/src/operation.ts b/packages/taler-util/src/operation.ts index 8b264d905..fd31fce39 100644 --- a/packages/taler-util/src/operation.ts +++ b/packages/taler-util/src/operation.ts @@ -3,23 +3,40 @@ import { Codec, HttpStatusCode, TalerError, TalerErrorCode, TalerErrorDetail } f export type OperationResult<Body, ErrorEnum> = | OperationOk<Body> + | OperationAlternative<ErrorEnum, Body> | OperationFail<ErrorEnum>; -export interface OperationOk<T> { - type: "ok", - body: T; -} 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) @@ -31,6 +48,11 @@ export function opFixedSuccess<T>(body: T): OperationOk<T> { 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 } @@ -43,6 +65,7 @@ export async function opKnownFailure<T extends string>(s: T, resp: HttpResponse) 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, @@ -55,23 +78,6 @@ export function opUnknownFailure(resp: HttpResponse, text: string): never { `Unexpected HTTP status ${resp.status} in response`, ); } -export async function succeedOrThrow<R, E>(cb: () => Promise<OperationResult<R, E>>): Promise<R> { - const resp = await cb() - if (resp.type === "ok") return resp.body - throw TalerError.fromUncheckedDetail({ ...resp.detail, case: resp.case }) -} -export async function failOrThrow<E>(s: E, cb: () => Promise<OperationResult<unknown, E>>): Promise<TalerErrorDetail> { - const resp = await cb() - if (resp.type === "ok") { - throw TalerError.fromException(new Error(`request succeed but failure "${s}" was expected`)) - } - if (resp.case === s) { - return resp.detail - } - throw TalerError.fromException(new Error(`request failed with "${resp.case}" but case "${s}" was expected`)) -} - - export type ResultByMethod<TT extends object, p extends keyof TT> = TT[p] extends (...args: any[]) => infer Ret ? Ret extends Promise<infer Result> ? @@ -81,23 +87,3 @@ export type ResultByMethod<TT extends object, p extends keyof TT> = TT[p] extend export type FailCasesByMethod<TT extends object, p extends keyof TT> = Exclude<ResultByMethod<TT, p>, OperationOk<any>> -type MethodsOfOperations<T extends object> = keyof { - [P in keyof T as - //when the property is a function - T[P] extends (...args: any[]) => infer Ret ? - // that returns a promise - Ret extends Promise<infer Result> ? - // of an operation - Result extends OperationResult<any, any> ? - P : never - : never - : never]: any -} - -type AllKnownCases<t extends object, d extends keyof t> = "success" | FailCasesByMethod<t, d>["case"] - -export type TestForApi<ApiType extends object> = { - [OpType in MethodsOfOperations<ApiType> as `test_${OpType & string}`]: { - [c in AllKnownCases<ApiType, OpType>]: undefined | (() => Promise<void>); - }; -}; |