Skip to content

Commit

Permalink
Allow async maps, since they are useful, should behave in a similar w…
Browse files Browse the repository at this point in the history
…ay and no big runtime change is needed.
  • Loading branch information
diogob committed May 22, 2024
1 parent 881a6e6 commit f3952ee
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 9 deletions.
16 changes: 9 additions & 7 deletions src/domain-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,11 @@ function sequence<Fns extends DomainFunction[]>(
*/
function map<O, R>(
dfn: DomainFunction<O>,
mapper: (element: O) => R,
mapper: (element: O) => R | Promise<R>,
): DomainFunction<R> {
return fromComposable(Future.map(toComposable(dfn), mapper))
return fromComposable(
Future.map(toComposable(dfn), mapper),
) as DomainFunction<R>
}

/**
Expand Down Expand Up @@ -276,16 +278,16 @@ function fromSuccess<T extends DomainFunction>(
*/
function mapError<O>(
dfn: DomainFunction<O>,
mapper: (element: ErrorData) => ErrorData,
mapper: (element: ErrorData) => ErrorData | Promise<ErrorData>,
): DomainFunction<O> {
return async (input, environment) => {
return (async (input, environment) => {
const result = await dfn(input, environment)
if (result.success) return result

return safeResult(() => {
throw new ResultError({ ...mapper(result) })
return safeResult(async () => {
throw new ResultError({ ...(await mapper(result)) })
})
}
}) as DomainFunction<O>
}

type TraceData<T> = {
Expand Down
29 changes: 27 additions & 2 deletions src/map-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('mapError', () => {
({
errors: [{ message: 'New Error Message' }],
inputErrors: [{ message: 'New Input Error Message' }],
} as ErrorData)
}) as ErrorData

const c = mapError(a, b)
type _R = Expect<Equal<typeof c, DomainFunction<number>>>
Expand All @@ -39,7 +39,32 @@ describe('mapError', () => {
path: [],
},
],
} as ErrorData)
}) as ErrorData

const c = mapError(a, b)
type _R = Expect<Equal<typeof c, DomainFunction<number>>>

assertEquals(await c({ invalidInput: '1' }), {
success: false,
errors: [{ message: 'Number of errors: 0' }],
environmentErrors: [],
inputErrors: [{ message: 'Number of input errors: 1', path: [] }],
})
})

it('returns a domain function function that will apply an async function over the error of the first one', async () => {
const a = mdf(z.object({ id: z.number() }))(({ id }) => id + 1)
const b = (result: ErrorData) =>
Promise.resolve({
errors: [{ message: 'Number of errors: ' + result.errors.length }],
environmentErrors: [],
inputErrors: [
{
message: 'Number of input errors: ' + result.inputErrors.length,
path: [],
},
],
}) as Promise<ErrorData>

const c = mapError(a, b)
type _R = Expect<Equal<typeof c, DomainFunction<number>>>
Expand Down
16 changes: 16 additions & 0 deletions src/map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ describe('map', () => {
})
})

it('returns a domain function function that will apply an async function over the results of the first one', async () => {
const a = mdf(z.object({ id: z.number() }))(({ id }) => id + 1)
const b = (id: number) => Promise.resolve(id + 1)

const c = map(a, b)
type _R = Expect<Equal<typeof c, DomainFunction<number>>>

assertEquals(await c({ id: 1 }), {
success: true,
data: 3,
errors: [],
inputErrors: [],
environmentErrors: [],
})
})

it('returns the error when the domain function fails', async () => {
const firstInputParser = z.object({ id: z.number() })
const a = mdf(firstInputParser)(({ id }) => id + 1)
Expand Down

0 comments on commit f3952ee

Please sign in to comment.