-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: try catch custom handler (#51)
* v1.22.22 * feat: add catchy libs * chore: update husky pre commit check unit test * feat: add verbose mode * docs: detailing the catchy module multi function test * refactor: rename e to errType * refactor: merge errsToCatch when exists
- Loading branch information
1 parent
ea1231b
commit 50197e1
Showing
4 changed files
with
123 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ | |
. "$(dirname "$0")/_/husky.sh" | ||
|
||
yarn lint-staged | ||
|
||
yarn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { describe, expect, jest, test } from '@jest/globals'; | ||
|
||
import { catchy } from './catchy'; | ||
|
||
async function getUser() { | ||
throw new Error('user not found'); | ||
} | ||
|
||
async function getMetadata() { | ||
return Promise.resolve('metadata found!'); | ||
} | ||
|
||
describe('Catchy Module - Single Function', () => { | ||
test('Given a promise that throws an error, when calling catchy, then it should return the error', async () => { | ||
const [err, user] = await catchy(getUser()); | ||
expect(err).toBeInstanceOf(Error); | ||
expect(user).toBeUndefined(); | ||
}); | ||
|
||
test('Given a promise that resolves, when calling catchy, then it should return the value', async () => { | ||
const [err, metadata] = await catchy(getMetadata()); | ||
expect(err).toBeUndefined(); | ||
expect(metadata).toBe('metadata found!'); | ||
}); | ||
|
||
test('Given a promise that throws an error, when calling catchy with an error to catch, then it should return the error', async () => { | ||
const [err, user] = await catchy(getUser(), [Error]); | ||
expect(err).toBeInstanceOf(Error); | ||
expect(user).toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe('Catchy Module - Multiple Functions', () => { | ||
test('Given a multiple function calls, when some of them throw an error at the end, then it should return the error', async () => { | ||
const [errMetadata, metadata] = await catchy(getMetadata()); | ||
expect(errMetadata).toBeUndefined(); | ||
expect(metadata).toBe('metadata found!'); | ||
|
||
const [errUser, user] = await catchy(getUser()); | ||
expect(errUser).toBeInstanceOf(Error); | ||
expect(user).toBeUndefined(); | ||
}); | ||
|
||
test('Given a multiple function calls, when some of them throw an error at the beginning, then it should return the error', async () => { | ||
const [errUser, user] = await catchy(getUser()); | ||
expect(errUser).toBeInstanceOf(Error); | ||
expect(user).toBeUndefined(); | ||
|
||
const [errMetadata, metadata] = await catchy(getMetadata()); | ||
expect(errMetadata).toBeUndefined(); | ||
expect(metadata).toBe('metadata found!'); | ||
}); | ||
}); | ||
|
||
describe('Catchy Module - Verbose Mode', () => { | ||
test('Given a promise that throws an error, when calling catchy with verbose mode, then it should return the error and log it', async () => { | ||
const consoleError = jest | ||
.spyOn(console, 'error') | ||
.mockImplementation(() => {}); | ||
const [err, user] = await catchy(getUser(), undefined, true); | ||
|
||
expect(err).toBeInstanceOf(Error); | ||
expect(user).toBeUndefined(); | ||
expect(consoleError).toHaveBeenCalled(); | ||
|
||
consoleError.mockRestore(); | ||
}); | ||
|
||
test('Given a promise that resolves, when calling catchy with verbose mode, then it should return the value', async () => { | ||
const consoleError = jest | ||
.spyOn(console, 'error') | ||
.mockImplementation(() => {}); | ||
|
||
const [err, metadata] = await catchy(getMetadata(), undefined, true); | ||
expect(err).toBeUndefined(); | ||
expect(metadata).toBe('metadata found!'); | ||
expect(consoleError).not.toHaveBeenCalled(); | ||
|
||
consoleError.mockRestore(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// this utility function wraps a promise and catches errors of a specific type. | ||
// it makes your code more catch-strict and less error - prone | ||
// since the `try-catch` must parse the errors to be caught | ||
async function catchy<T, E extends new (message?: string) => Error>( | ||
promise: Promise<T>, | ||
errsToCatch?: Array<E>, | ||
verbose?: boolean, | ||
): Promise<[undefined, T] | [InstanceType<E>]> { | ||
try { | ||
const v = await promise; | ||
return [undefined, v] as [undefined, T]; | ||
} catch (err) { | ||
/* eslint-disable curly */ | ||
/* eslint-disable no-console */ | ||
if (verbose) console.error(err); | ||
|
||
if (!errsToCatch || errsToCatch.some((errType) => err instanceof errType)) { | ||
return [err as InstanceType<E>]; | ||
} | ||
|
||
throw err; | ||
} | ||
} | ||
|
||
export { catchy }; |