aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-util/src/operation.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-util/src/operation.ts')
-rw-r--r--packages/taler-util/src/operation.ts68
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>);
- };
-};