mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Introduce "call-result" to formalize non-failing yet non-fatal behaviour
Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> Co-authored-by: Gabriel <gaccettola@mirantis.com>
This commit is contained in:
parent
39a5c71aef
commit
b847bb71f4
@ -0,0 +1,55 @@
|
||||
import {
|
||||
CallResult,
|
||||
callWasFailure,
|
||||
callWasSuccessful,
|
||||
getFailure,
|
||||
getSuccess,
|
||||
} from "./call-result";
|
||||
|
||||
describe("call-result", () => {
|
||||
it("given successful call, narrows type of response", () => {
|
||||
const someSuccess: CallResult<string> = getSuccess("some-success");
|
||||
|
||||
if (callWasSuccessful(someSuccess)) {
|
||||
expect(someSuccess.response).toBe("some-success");
|
||||
}
|
||||
|
||||
expect.assertions(1);
|
||||
});
|
||||
|
||||
it("given successful call, call is not failure", () => {
|
||||
const actual = callWasFailure(getSuccess("some-success"));
|
||||
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
|
||||
it("given unsuccessful call, narrows type of error", () => {
|
||||
const someFailure: CallResult<string> = getFailure(
|
||||
"some-cause",
|
||||
);
|
||||
|
||||
// Todo: find out why this this type narrowing isn't working anymore.
|
||||
if (callWasFailure(someFailure)) {
|
||||
expect(someFailure.error).toEqual({
|
||||
cause: "some-cause",
|
||||
message: "some-cause",
|
||||
});
|
||||
}
|
||||
|
||||
expect.assertions(1);
|
||||
});
|
||||
|
||||
it("given unsuccessful call, call is not successful", () => {
|
||||
const actual = callWasSuccessful(
|
||||
getFailure("some-cause")
|
||||
);
|
||||
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
|
||||
it('when a call fails by throwing a thing with no known message, fails with no message', () => {
|
||||
const failure = getFailure({ noKnownMessage: 'irrelevant' });
|
||||
|
||||
expect(failure.error.message).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,52 @@
|
||||
import { isString } from "lodash/fp";
|
||||
|
||||
export type CallFailure = {
|
||||
callWasSuccessful: false;
|
||||
error: { message: string | undefined; cause: unknown };
|
||||
};
|
||||
|
||||
export type CallSuccess<Response> = Response extends void
|
||||
? { callWasSuccessful: true; response?: undefined }
|
||||
: { callWasSuccessful: true; response: Response };
|
||||
|
||||
export type CallResult<Response> = CallSuccess<Response> | CallFailure;
|
||||
|
||||
export type AsyncCallResult<Response> = Promise<CallResult<Response>>;
|
||||
|
||||
export type AsyncCallSuccess<Response> = Promise<CallSuccess<Response>>;
|
||||
|
||||
export const getSuccess = <T>(response: T) => ({
|
||||
callWasSuccessful: true as const,
|
||||
response,
|
||||
});
|
||||
|
||||
const getErrorMessage = (cause: unknown) => {
|
||||
if (isString(cause)) {
|
||||
return cause;
|
||||
}
|
||||
|
||||
const causeObject = cause as any;
|
||||
|
||||
if (causeObject.message) {
|
||||
return causeObject.message;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getFailure = (errorCause: unknown) => ({
|
||||
callWasSuccessful: false as const,
|
||||
|
||||
error: {
|
||||
cause: errorCause,
|
||||
message: getErrorMessage(errorCause),
|
||||
},
|
||||
});
|
||||
|
||||
export const callWasSuccessful = <Result>(
|
||||
callResult: CallResult<Result>
|
||||
): callResult is CallSuccess<Result> => callResult.callWasSuccessful;
|
||||
|
||||
export const callWasFailure = <Result>(
|
||||
callResult: CallResult<Result>
|
||||
): callResult is CallFailure => !callResult.callWasSuccessful;
|
||||
Loading…
Reference in New Issue
Block a user