Skip to content

Commit 77a762d

Browse files
committed
updates
1 parent 7ecc10f commit 77a762d

File tree

3 files changed

+76
-21
lines changed

3 files changed

+76
-21
lines changed

packages/effect-form-adapter/src/tests/FieldApi.spec.ts

+35-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import { describe, expect, it } from 'vitest'
22

33
import { FieldApi, FormApi } from '@tanstack/form-core'
4-
import { effectValidator } from '../validator'
5-
import { asyncSchema, schema, sleep } from './utils'
4+
import { createValidator, effectValidator } from '../validator'
5+
import {
6+
asyncSchema,
7+
ctxLayer,
8+
schema,
9+
schemaWithContext,
10+
sleep,
11+
} from './utils'
612

713
describe('field api', () => {
814
it('should run an onChange with Schema.minLength validation', () => {
@@ -79,14 +85,38 @@ describe('field api', () => {
7985
expect(field.getMeta().errors).toEqual([])
8086
field.setValue('a', { touch: true })
8187
await sleep(30)
82-
expect(field.getMeta().errors).toEqual([
83-
'You must have a length of at least 3',
84-
])
88+
expect(field.getMeta().errors).toEqual(['async schema error'])
8589
field.setValue('asdf', { touch: true })
8690
await sleep(30)
8791
expect(field.getMeta().errors).toEqual([])
8892
})
8993

94+
it('Effect error message w/ context', async () => {
95+
const customValidator = createValidator(ctxLayer)
96+
97+
const form = new FormApi({
98+
defaultValues: {
99+
name: '',
100+
},
101+
})
102+
103+
const field = new FieldApi({
104+
form,
105+
validatorAdapter: customValidator,
106+
name: 'name',
107+
validators: {
108+
onChange: schemaWithContext,
109+
},
110+
})
111+
112+
field.mount()
113+
114+
expect(field.getMeta().errors).toEqual([])
115+
field.setValue('a', { touch: true })
116+
await sleep(30)
117+
expect(field.getMeta().errors).toEqual(['ctx-123'])
118+
})
119+
90120
it('should run an onChangeAsyc fn with validation option enabled', async () => {
91121
const form = new FormApi({
92122
defaultValues: {

packages/effect-form-adapter/src/tests/utils.ts

+32-8
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,47 @@
1-
import { Context, Effect, Layer } from 'effect'
1+
import { Context, Effect, Layer, Option } from 'effect'
22
import { Schema } from '@effect/schema'
3+
import * as ParseResult from '@effect/schema/ParseResult'
34

45
export class Ctx extends Context.Tag('Ctx')<Ctx, string>() {}
5-
export const ctx = Layer.succeed(Ctx, Ctx.of('ctx-123'))
6+
export const ctxLayer = Layer.succeed(Ctx, Ctx.of('ctx-123'))
67

78
export const schema = Schema.String.pipe(
89
Schema.minLength(3, {
910
message: () => 'You must have a length of at least 3',
1011
}),
1112
)
1213

13-
export const schemaWithContext = Schema.transformOrFail(schema, schema, {
14-
decode: () => Effect.flatMap(Ctx, (c) => Effect.succeed(c)),
15-
encode: (value) => Effect.succeed(value),
14+
const delay = Effect.delay('10 millis')
15+
export const asyncSchema = Schema.transformOrFail(
16+
Schema.String,
17+
Schema.String,
18+
{
19+
decode: (value, _, ast) =>
20+
delay(
21+
value.length >= 3
22+
? Effect.succeed(value)
23+
: Effect.fail(new ParseResult.Type(ast, value, 'inner msg')),
24+
),
25+
encode: (value) => Effect.succeed(value).pipe(delay),
26+
},
27+
).annotations({
28+
message: () => delay(Effect.succeed('async schema error')),
1629
})
1730

18-
export const asyncSchema = Schema.transformOrFail(schema, schema, {
19-
decode: (value) => Effect.succeed(value).pipe(Effect.delay('10 millis')),
20-
encode: (value) => Effect.succeed(value).pipe(Effect.delay('10 millis')),
31+
export const schemaWithContext = Schema.transformOrFail(
32+
Schema.String,
33+
Schema.String,
34+
{
35+
decode: (_, value, ast) =>
36+
Effect.fail(new ParseResult.Type(ast, value, '')),
37+
encode: (value) => Effect.succeed(value),
38+
},
39+
).annotations({
40+
message: () =>
41+
Effect.map(
42+
Effect.serviceOption(Ctx),
43+
Option.getOrElse(() => 'no context'),
44+
),
2145
})
2246

2347
export function sleep(timeout: number): Promise<void> {

packages/effect-form-adapter/src/validator.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@ export const createValidator = <R>(layer: Layer.Layer<R>) => {
1313
const validator: Validator<unknown, Schema.Schema<any, any, R>> = () => ({
1414
validate(
1515
{ value }: { value: unknown },
16-
schema: Schema.Schema<any, any>,
16+
schema: Schema.Schema<any, any, R>,
1717
): ValidationError {
18-
const result = Schema.decodeUnknownEither(schema)(value)
19-
if (Either.isLeft(result)) {
20-
return ArrayFormatter.formatErrorSync(result.left)
21-
.map((e) => e.message)
22-
.join(', ') // must be joined into 1 string
23-
}
24-
return
18+
const exit = runtime.runSyncExit(
19+
Schema.decodeUnknown(schema)(value).pipe(
20+
Effect.flip,
21+
Effect.flatMap(ArrayFormatter.formatError),
22+
Effect.map((es) => es.map((e) => e.message).join(', ')),
23+
),
24+
)
25+
return Exit.getOrElse(exit, () => undefined)
2526
},
2627
async validateAsync(
2728
{ value }: { value: unknown },

0 commit comments

Comments
 (0)