Skip to content

Commit

Permalink
feat: Allow async error mappers (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
runeh authored Jun 21, 2021
1 parent 780a166 commit 1596744
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ that is likely more specific.
The `TypicalHttpError` includes the `Response` object so consumers can extract
more information from it as needed. The default error handing will not have
called the `.text()` and `.json()`methods on the response, so these can bue used
when parsing the error.
when parsing the error. Error mappers are allowed to be asynchronous.

```typescript
const fetcher = buildCall() //
Expand Down
48 changes: 48 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,54 @@ describe('call builder', () => {
expect(scope.isDone()).toEqual(true);
});

it('async error mapper', async () => {
const scope = nock(baseUrl) //
.get('/boop')
.reply(500);

const fetcher = buildCall()
.path('/boop')
.method('get')
.mapError(async (_err) => {
await new Promise((res) => setTimeout(res, 1));
return 'async arrar!';
})
.build();

const res = await fetcher({ baseUrl });

expect(res.success).toEqual(false);
expect(res?.error).toEqual('async arrar!');
expect(res?.error).toMatchInlineSnapshot(`"async arrar!"`);
expect(scope.isDone()).toEqual(true);
});

it('mixed sync and async error mapper', async () => {
const scope = nock(baseUrl) //
.get('/boop')
.reply(500);

const fetcher = buildCall()
.path('/boop')
.method('get')
.mapError((_) => 'error!')
.mapError(async (err) => {
console.log(err);
await new Promise((res) => setTimeout(res, 1));
return err.toUpperCase();
})

.mapError((err) => `${err}!!11`)
.build();

const res = await fetcher({ baseUrl });

expect(res.success).toEqual(false);
expect(res?.error).toEqual('ERROR!!!11');
expect(res?.error).toMatchInlineSnapshot(`"ERROR!!!11"`);
expect(scope.isDone()).toEqual(true);
});

it.todo('runtype failure');
});
});
Expand Down
4 changes: 2 additions & 2 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ export function getFetchParams(
return { url, headers, body };
}

export function applyErrorMappers(
export async function applyErrorMappers(
error: any,
mappers: CallRecord['errorMappers'],
args: any,
) {
let newError = error;
for (const mapper of mappers) {
newError = mapper(newError, args);
newError = await mapper(newError, args);
}
return newError;
}
Expand Down
10 changes: 6 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export { unwrapError } from './common';
export class CallBuilder<
Ret = void,
Arg extends Record<string, any> = { baseUrl: string | URL },
Err = TypicalWrappedError | TypicalHttpError,
Err = TypicalWrappedError | TypicalHttpError
> {
private record: CallRecord;

Expand Down Expand Up @@ -145,7 +145,9 @@ export class CallBuilder<
* called multiple times. Each map function will receive the result of the
* previous mapper.
*/
mapError<T>(mapper: (error: Err, args: Arg) => T): CallBuilder<Ret, Arg, T> {
mapError<T>(
mapper: (error: Err, args: Arg) => T | Promise<T>,
): CallBuilder<Ret, Arg, T> {
return new CallBuilder<Ret, Arg, T>({
...this.record,
errorMappers: [...this.record.errorMappers, mapper],
Expand Down Expand Up @@ -273,7 +275,7 @@ export class CallBuilder<
return {
success: false,
body: undefined,
error: applyErrorMappers(
error: await applyErrorMappers(
new TypicalHttpError(res),
errorMappers,
args,
Expand Down Expand Up @@ -307,7 +309,7 @@ export class CallBuilder<
return {
success: false,
body: undefined,
error: applyErrorMappers(
error: await applyErrorMappers(
new TypicalWrappedError(error, res, text),
errorMappers,
args,
Expand Down

0 comments on commit 1596744

Please sign in to comment.