Skip to content

Commit 0e5d0e8

Browse files
committed
feat: allow to use a reporter with a custom formatter, and also pass it to the schema options
1 parent 02e2564 commit 0e5d0e8

File tree

3 files changed

+77
-7
lines changed

3 files changed

+77
-7
lines changed

src/MorphismTree.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
SCHEMA_OPTIONS_SYMBOL,
1414
isEmptyObject
1515
} from './helpers';
16-
import { ValidationError, ERRORS, targetHasErrors, ValidationErrors, reporter } from './validation/reporter';
16+
import { ValidationError, ERRORS, targetHasErrors, ValidationErrors, reporter, Reporter } from './validation/reporter';
1717
import { ValidatorError } from './validation/validators/ValidatorError';
1818

1919
export enum NodeKind {
@@ -94,6 +94,12 @@ export interface SchemaOptions<Target = any> {
9494
* @type {boolean}
9595
*/
9696
throw: boolean;
97+
/**
98+
* Custom reporter to use when throw option is set to true
99+
* @default false
100+
* @type {boolean}
101+
*/
102+
reporter?: Reporter;
97103
};
98104
}
99105

@@ -258,7 +264,11 @@ export class MorphismSchemaTree<Target, Source> {
258264
if (targetHasErrors(objectToCompute)) {
259265
objectToCompute[ERRORS].addError(validationError);
260266
} else {
261-
objectToCompute[ERRORS] = new ValidationErrors(reporter, objectToCompute);
267+
if (this.schemaOptions.validation && this.schemaOptions.validation.reporter) {
268+
objectToCompute[ERRORS] = new ValidationErrors(this.schemaOptions.validation.reporter, objectToCompute);
269+
} else {
270+
objectToCompute[ERRORS] = new ValidationErrors(reporter, objectToCompute);
271+
}
262272
objectToCompute[ERRORS].addError(validationError);
263273
}
264274
} else {

src/morphism.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Schema, StrictSchema, Constructable, SourceFromSchema, Mapper, Destinat
66
import { MorphismSchemaTree, createSchema, SchemaOptions } from './MorphismTree';
77
import { MorphismRegistry, IMorphismRegistry } from './MorphismRegistry';
88
import { decorator } from './MorphismDecorator';
9-
import { Reporter, reporter, Formatter, targetHasErrors } from './validation/reporter';
9+
import { Reporter, reporter as defaultReporter, Formatter, targetHasErrors, ValidationErrors } from './validation/reporter';
1010

1111
/**
1212
* Low Level transformer function.
@@ -68,7 +68,13 @@ function transformValuesFromObject<Source, Target>(
6868
function checkIfValidationShouldThrow<Target>(options: SchemaOptions<Target>, finalObject: Target) {
6969
if (options && options.validation && options.validation.throw) {
7070
if (targetHasErrors(finalObject)) {
71-
const errors = reporter.extractErrors(finalObject);
71+
let errors: ValidationErrors | null;
72+
if (options.validation.reporter) {
73+
const reporter = options.validation.reporter;
74+
errors = reporter.extractErrors(finalObject);
75+
} else {
76+
errors = defaultReporter.extractErrors(finalObject);
77+
}
7278
if (errors) {
7379
throw errors;
7480
}
@@ -230,5 +236,16 @@ morphismMixin.mappers = morphismRegistry.mappers;
230236

231237
const Morphism: typeof morphism & IMorphismRegistry = morphismMixin;
232238

233-
export { morphism, createSchema, Schema, StrictSchema, SchemaOptions, Mapper, SCHEMA_OPTIONS_SYMBOL, Reporter, reporter, Formatter };
239+
export {
240+
morphism,
241+
createSchema,
242+
Schema,
243+
StrictSchema,
244+
SchemaOptions,
245+
Mapper,
246+
SCHEMA_OPTIONS_SYMBOL,
247+
Reporter,
248+
defaultReporter as reporter,
249+
Formatter
250+
};
234251
export default Morphism;

src/validation/reporter.spec.ts

+45-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { morphism, createSchema } from '../morphism';
2-
import { defaultFormatter, reporter, ValidationError } from './reporter';
1+
import { morphism, createSchema, Reporter } from '../morphism';
2+
import { defaultFormatter, reporter, ValidationError, Formatter } from './reporter';
33
import { Validation } from './Validation';
44

55
describe('Reporter', () => {
@@ -50,6 +50,49 @@ describe('Reporter', () => {
5050
}).toThrow('Rule max has already been used');
5151
});
5252

53+
it('should allow to use a reporter with a custom formatter', () => {
54+
interface Target {
55+
t1: string;
56+
}
57+
const formatter: Formatter = error => {
58+
const { expect, targetProperty, value } = error;
59+
return `Expected ${expect} but received ${value} for property ${targetProperty}`;
60+
};
61+
const reporter = new Reporter(formatter);
62+
63+
const schema = createSchema<Target>({ t1: { path: 's1', validation: Validation.string() } });
64+
const result = morphism(schema, { s1: 1234 });
65+
const error = new ValidationError({ targetProperty: 't1', value: 1234, expect: 'value to be typeof string' });
66+
const message = formatter(error);
67+
const errors = reporter.report(result);
68+
expect(errors).not.toBeNull();
69+
if (errors) {
70+
expect(errors[0]).toBe(message);
71+
}
72+
});
73+
74+
it('should allow to use a reporter with a custom formatter via schema options', () => {
75+
interface Target {
76+
t1: string;
77+
}
78+
const formatter: Formatter = error => {
79+
const { expect, targetProperty, value } = error;
80+
return `Expected ${expect} but received ${value} for property ${targetProperty}`;
81+
};
82+
const reporter = new Reporter(formatter);
83+
84+
const schema = createSchema<Target>(
85+
{ t1: { path: 's1', validation: Validation.string() } },
86+
{ validation: { throw: true, reporter } }
87+
);
88+
89+
const error = new ValidationError({ targetProperty: 't1', value: 1234, expect: 'value to be typeof string' });
90+
const message = formatter(error);
91+
expect(() => {
92+
morphism(schema, { s1: 1234 });
93+
}).toThrow(message);
94+
});
95+
5396
describe('string', () => {
5497
it('should report error on string undefined', () => {
5598
interface S {

0 commit comments

Comments
 (0)