Skip to content

Commit

Permalink
feat(utils): tryit
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed May 25, 2023
1 parent 1fb621e commit 90cb6cf
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
40 changes: 40 additions & 0 deletions src/utils/__tests__/tryit.spec.ts
Original file line number Diff line number Diff line change
@@ -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<Fn<[string?], typeof INTEGER>>

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])
})
})
})
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
29 changes: 29 additions & 0 deletions src/utils/tryit.ts
Original file line number Diff line number Diff line change
@@ -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<T, E>} Error first callback
*/
function tryit<T extends Fn, E extends Error = Error>(fn: T): Tryit<T, E> {
return async (
...args: Parameters<T>
): Promise<[E, null] | [null, Awaited<ReturnType<T>>]> => {
try {
return [null, (await fn(...args)) as Awaited<ReturnType<T>>]
} catch (e: unknown) {
return [e as E, null]
}
}
}

export default tryit

0 comments on commit 90cb6cf

Please sign in to comment.