Skip to content

Commit c7d7f97

Browse files
author
jquense
committed
fix: lazy validation errors thrown in builders should resolve async like other validations
1 parent f27fa44 commit c7d7f97

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

src/Lazy.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {
44
ISchema,
55
ValidateOptions,
66
NestedTestConfig,
7+
InferType,
78
} from './types';
89
import type { ResolveOptions } from './Condition';
910

@@ -14,7 +15,8 @@ import type {
1415
SchemaLazyDescription,
1516
} from './schema';
1617
import { Flags, Maybe } from './util/types';
17-
import { InferType, Schema } from '.';
18+
import ValidationError from './ValidationError';
19+
import Schema from './schema';
1820

1921
export type LazyBuilder<
2022
TSchema extends ISchema<TContext>,
@@ -28,6 +30,15 @@ export function create<
2830
return new Lazy<InferType<TSchema>, TContext>(builder);
2931
}
3032

33+
function catchValidationError(fn: () => any) {
34+
try {
35+
return fn();
36+
} catch (err) {
37+
if (ValidationError.isError(err)) return Promise.reject(err);
38+
throw err;
39+
}
40+
}
41+
3142
export interface LazySpec {
3243
meta: Record<string, unknown> | undefined;
3344
optional: boolean;
@@ -113,15 +124,19 @@ class Lazy<T, TContext = AnyObject, TFlags extends Flags = any>
113124
}
114125

115126
validate(value: any, options?: ValidateOptions<TContext>): Promise<T> {
116-
return this._resolve(value, options).validate(value, options);
127+
return catchValidationError(() =>
128+
this._resolve(value, options).validate(value, options),
129+
);
117130
}
118131

119132
validateSync(value: any, options?: ValidateOptions<TContext>): T {
120133
return this._resolve(value, options).validateSync(value, options);
121134
}
122135

123136
validateAt(path: string, value: any, options?: ValidateOptions<TContext>) {
124-
return this._resolve(value, options).validateAt(path, value, options);
137+
return catchValidationError(() =>
138+
this._resolve(value, options).validateAt(path, value, options),
139+
);
125140
}
126141

127142
validateSyncAt(
@@ -133,7 +148,14 @@ class Lazy<T, TContext = AnyObject, TFlags extends Flags = any>
133148
}
134149

135150
isValid(value: any, options?: ValidateOptions<TContext>) {
136-
return this._resolve(value, options).isValid(value, options);
151+
try {
152+
return this._resolve(value, options).isValid(value, options);
153+
} catch (err) {
154+
if (ValidationError.isError(err)) {
155+
return Promise.resolve(false);
156+
}
157+
throw err;
158+
}
137159
}
138160

139161
isValidSync(value: any, options?: ValidateOptions<TContext>) {

test/lazy.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
import { lazy, object, mixed, AnyObject, MixedSchema } from '../src';
1+
import {
2+
lazy,
3+
object,
4+
mixed,
5+
AnyObject,
6+
MixedSchema,
7+
ValidationError,
8+
} from '../src';
29

310
describe('lazy', function () {
411
it('should throw on a non-schema value', () => {
512
// @ts-expect-error testing incorrect usage
6-
expect(() => lazy(() => undefined).validate(undefined)).toThrowError();
13+
expect(() => lazy(() => undefined).validateSync(undefined)).toThrowError();
714
});
815

916
describe('mapper', () => {
@@ -54,5 +61,23 @@ describe('lazy', function () {
5461
added: true,
5562
});
5663
});
64+
65+
it('should allow throwing validation error in builder', async () => {
66+
const schema = lazy(() => {
67+
throw new ValidationError('oops');
68+
});
69+
70+
await expect(schema.validate(value)).rejects.toThrowError('oops');
71+
await expect(schema.isValid(value)).resolves.toEqual(false);
72+
73+
expect(() => schema.validateSync(value)).toThrowError('oops');
74+
75+
const schema2 = lazy(() => {
76+
throw new Error('error');
77+
});
78+
// none validation errors are thrown sync to maintain back compat
79+
expect(() => schema2.validate(value)).toThrowError('error');
80+
expect(() => schema2.isValid(value)).toThrowError('error');
81+
});
5782
});
5883
});

0 commit comments

Comments
 (0)