diff --git a/src/constructor.ts b/src/constructor.ts index 670da040..aa4d01a3 100644 --- a/src/constructor.ts +++ b/src/constructor.ts @@ -13,7 +13,38 @@ import type { } from './types.ts' import * as Future from 'npm:composable-functions@beta' -function composableToDF( +function toComposable( + df: DomainFunction, +): Future.Composable<(input?: unknown, environment?: unknown) => R> { + return (async (input?: unknown, environment?: unknown) => { + const result = await df(input, environment) + + if (result.success) { + return { + success: true, + data: result.data, + errors: [], + inputErrors: [], + environmentErrors: [], + } + } else { + return { + success: false, + errors: [ + ...result.errors.map((e) => e.exception ?? new Error(e.message)), + ...result.inputErrors.map( + (e) => new Future.InputError(e.message, e.path), + ), + ...result.environmentErrors.map( + (e) => new Future.EnvironmentError(e.message, e.path), + ), + ], + } + } + }) as Future.Composable<(input?: unknown, environment?: unknown) => R> +} + +function fromComposable( cf: Future.Composable<(inout?: unknown, environment?: unknown) => R>, ) { return (async (input?: unknown, environment?: unknown) => { @@ -92,7 +123,7 @@ function composableToDF( * } */ async function safeResult(fn: () => T): Promise> { - return await composableToDF(Future.composable(fn))() + return await fromComposable(Future.composable(fn))() } /** @@ -129,7 +160,7 @@ function makeDomainFunction( safeParse: () => inputResult, } - return composableToDF( + return fromComposable( Future.withSchema( futureInputSchema as any, futureEnvSchema as any, @@ -164,4 +195,10 @@ const undefinedSchema: ParserSchema = { }, } -export { makeDomainFunction, makeDomainFunction as mdf, safeResult } +export { + makeDomainFunction, + makeDomainFunction as mdf, + safeResult, + fromComposable, + toComposable +} diff --git a/src/domain-functions.ts b/src/domain-functions.ts index b95e3d65..be1caaad 100644 --- a/src/domain-functions.ts +++ b/src/domain-functions.ts @@ -13,7 +13,8 @@ import type { } from './types.ts' import type { Last } from './types.ts' import type { SuccessResult } from './types.ts' -import { safeResult } from './constructor.ts' +import { safeResult, fromComposable, toComposable } from './constructor.ts' +import * as Future from 'npm:composable-functions@beta' /** * Creates a single domain function out of multiple domain functions. It will pass the same input and environment to each provided function. The functions will run in parallel. If all constituent functions are successful, The data field will be a tuple containing each function's output. @@ -29,25 +30,9 @@ const df = all(a, b, c) function all( ...fns: Fns ): DomainFunction> { - return ((input, environment) => { - return safeResult(async () => { - const results = await Promise.all( - fns.map((fn) => (fn as DomainFunction)(input, environment)), - ) - - if (!isListOfSuccess(results)) { - throw new ResultError({ - errors: results.map(({ errors }) => errors).flat(), - inputErrors: results.map(({ inputErrors }) => inputErrors).flat(), - environmentErrors: results - .map(({ environmentErrors }) => environmentErrors) - .flat(), - }) - } - - return results.map(({ data }) => data) - }) - }) as DomainFunction> + return fromComposable(Future.all(...fns.map(toComposable))) as DomainFunction< + UnpackAll + > } /**