39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import { formatIssue } from '@effect/schema/ArrayFormatter';
|
|
import { decodeUnknown } from '@effect/schema/ParseResult';
|
|
import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';
|
|
import * as Effect from 'effect/Effect';
|
|
import type { FieldErrors } from 'react-hook-form';
|
|
import type { Resolver } from './types';
|
|
|
|
export const effectTsResolver: Resolver =
|
|
(schema, config = { errors: 'all', onExcessProperty: 'ignore' }) =>
|
|
(values, _, options) => {
|
|
return decodeUnknown(
|
|
schema,
|
|
config,
|
|
)(values).pipe(
|
|
Effect.catchAll((parseIssue) => Effect.flip(formatIssue(parseIssue))),
|
|
Effect.mapError((issues) => {
|
|
const errors = issues.reduce((acc, current) => {
|
|
const key = current.path.join('.');
|
|
acc[key] = { message: current.message, type: current._tag };
|
|
return acc;
|
|
}, {} as FieldErrors);
|
|
|
|
return toNestErrors(errors, options);
|
|
}),
|
|
Effect.tap(() =>
|
|
Effect.sync(
|
|
() =>
|
|
options.shouldUseNativeValidation &&
|
|
validateFieldsNatively({}, options),
|
|
),
|
|
),
|
|
Effect.match({
|
|
onFailure: (errors) => ({ errors, values: {} }),
|
|
onSuccess: (result) => ({ errors: {}, values: result }),
|
|
}),
|
|
Effect.runPromise,
|
|
);
|
|
};
|