diff --git a/src/utils/__tests__/tryit.spec.ts b/src/utils/__tests__/tryit.spec.ts new file mode 100644 index 00000000..c2ed658b --- /dev/null +++ b/src/utils/__tests__/tryit.spec.ts @@ -0,0 +1,40 @@ +/** + * @file Unit Tests - tryit + * @module tutils/utils/tests/unit/tryit + */ + +import INTEGER from '#fixtures/integer' +import type { Fn } from '#src/types' +import type { Mock } from '#tests/interfaces' +import testSubject from '../tryit' + +describe('unit:utils/tryit', () => { + let fn: Mock> + + beforeAll(() => { + fn = vi.fn() + }) + + it('should return error-first async callback', () => { + expect(testSubject(fn)).to.be.a('function') + }) + + describe('error-first callback', () => { + it('should return [error, null] if fn throws', async () => { + // Arrange + const error: Error = new Error('not implemented') + fn.mockRejectedValueOnce(error) + + // Act + Expect + expect(await testSubject(fn)()).to.deep.equal([error, null]) + }) + + it('should return [null, result]', async () => { + // Arrange + fn.mockResolvedValueOnce(INTEGER) + + // Act + Expect + expect(await testSubject(fn)()).to.deep.equal([null, INTEGER]) + }) + }) +}) diff --git a/src/utils/index.ts b/src/utils/index.ts index 8280770e..b0877ad3 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -57,5 +57,6 @@ export { default as timeunix } from './timeunix' export { default as trim } from './trim' export { default as trimEnd } from './trim-end' export { default as trimStart } from './trim-start' +export { default as tryit } from './tryit' export { default as unique } from './unique' export { default as uppercase } from './uppercase' diff --git a/src/utils/tryit.ts b/src/utils/tryit.ts new file mode 100644 index 00000000..860734a4 --- /dev/null +++ b/src/utils/tryit.ts @@ -0,0 +1,29 @@ +/** + * @file Utilities - tryit + * @module tutils/utils/tryit + */ + +import type { Fn, Tryit } from '#src/types' + +/** + * Converts `fn` to an error-first callback. + * + * @template T - Function to convert + * @template E - Error type + * + * @param {T} fn - Function to convert + * @return {Tryit} Error first callback + */ +function tryit(fn: T): Tryit { + return async ( + ...args: Parameters + ): Promise<[E, null] | [null, Awaited>]> => { + try { + return [null, (await fn(...args)) as Awaited>] + } catch (e: unknown) { + return [e as E, null] + } + } +} + +export default tryit