forked from rjsf-team/react-jsonschema-form
/
ErrorSchemaBuilder.ts
118 lines (108 loc) · 5.13 KB
/
ErrorSchemaBuilder.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import cloneDeep from "lodash/cloneDeep";
import get from "lodash/get";
import set from "lodash/set";
import { ErrorSchema } from "./types";
import { ERRORS_KEY } from "./constants";
/** The `ErrorSchemaBuilder<T>` is used to build an `ErrorSchema<T>` since the definition of the `ErrorSchema` type is
* designed for reading information rather than writing it. Use this class to add, replace or clear errors in an error
* schema by using either dotted path or an array of path names. Once you are done building the `ErrorSchema`, you can
* get the result and/or reset all the errors back to an initial set and start again.
*/
export default class ErrorSchemaBuilder<T = any> {
/** The error schema being built
*
* @private
*/
private errorSchema: ErrorSchema<T> = {};
/** Construct an `ErrorSchemaBuilder` with an optional initial set of errors in an `ErrorSchema`.
*
* @param [initialSchema] - The optional set of initial errors, that will be cloned into the class
*/
constructor(initialSchema?: ErrorSchema<T>) {
this.resetAllErrors(initialSchema);
}
/** Returns the `ErrorSchema` that has been updated by the methods of the `ErrorSchemaBuilder`
*/
get ErrorSchema() {
return this.errorSchema;
}
/** Will get an existing `ErrorSchema` at the specified `pathOfError` or create and return one.
*
* @param [pathOfError] - The optional path into the `ErrorSchema` at which to add the error(s)
* @returns - The error block for the given `pathOfError` or the root if not provided
* @private
*/
private getOrCreateErrorBlock(pathOfError?: string | string[]) {
const hasPath =
(Array.isArray(pathOfError) && pathOfError.length > 0) ||
typeof pathOfError === "string";
let errorBlock: ErrorSchema = hasPath
? get(this.errorSchema, pathOfError)
: this.errorSchema;
if (!errorBlock && pathOfError) {
errorBlock = {};
set(this.errorSchema, pathOfError, errorBlock);
}
return errorBlock;
}
/** Resets all errors in the `ErrorSchemaBuilder` back to the `initialSchema` if provided, otherwise an empty set.
*
* @param [initialSchema] - The optional set of initial errors, that will be cloned into the class
* @returns - The `ErrorSchemaBuilder` object for chaining purposes
*/
resetAllErrors(initialSchema?: ErrorSchema<T>) {
this.errorSchema = initialSchema ? cloneDeep(initialSchema) : {};
return this;
}
/** Adds the `errorOrList` to the list of errors in the `ErrorSchema` at either the root level or the location within
* the schema described by the `pathOfError`. For more information about how to specify the path see the
* [eslint lodash plugin docs](https://github.com/wix/eslint-plugin-lodash/blob/master/docs/rules/path-style.md).
*
* @param errorOrList - The error or list of errors to add into the `ErrorSchema`
* @param [pathOfError] - The optional path into the `ErrorSchema` at which to add the error(s)
* @returns - The `ErrorSchemaBuilder` object for chaining purposes
*/
addErrors(errorOrList: string | string[], pathOfError?: string | string[]) {
const errorBlock: ErrorSchema = this.getOrCreateErrorBlock(pathOfError);
let errorsList = get(errorBlock, ERRORS_KEY);
if (!Array.isArray(errorsList)) {
errorsList = [];
errorBlock[ERRORS_KEY] = errorsList;
}
if (Array.isArray(errorOrList)) {
errorsList.push(...errorOrList);
} else {
errorsList.push(errorOrList);
}
return this;
}
/** Sets/replaces the `errorOrList` as the error(s) in the `ErrorSchema` at either the root level or the location
* within the schema described by the `pathOfError`. For more information about how to specify the path see the
* [eslint lodash plugin docs](https://github.com/wix/eslint-plugin-lodash/blob/master/docs/rules/path-style.md).
*
* @param errorOrList - The error or list of errors to set into the `ErrorSchema`
* @param [pathOfError] - The optional path into the `ErrorSchema` at which to set the error(s)
* @returns - The `ErrorSchemaBuilder` object for chaining purposes
*/
setErrors(errorOrList: string | string[], pathOfError?: string | string[]) {
const errorBlock: ErrorSchema = this.getOrCreateErrorBlock(pathOfError);
// Effectively clone the array being given to prevent accidental outside manipulation of the given list
const listToAdd = Array.isArray(errorOrList)
? [...errorOrList]
: [errorOrList];
set(errorBlock, ERRORS_KEY, listToAdd);
return this;
}
/** Clears the error(s) in the `ErrorSchema` at either the root level or the location within the schema described by
* the `pathOfError`. For more information about how to specify the path see the
* [eslint lodash plugin docs](https://github.com/wix/eslint-plugin-lodash/blob/master/docs/rules/path-style.md).
*
* @param [pathOfError] - The optional path into the `ErrorSchema` at which to clear the error(s)
* @returns - The `ErrorSchemaBuilder` object for chaining purposes
*/
clearErrors(pathOfError?: string | string[]) {
const errorBlock: ErrorSchema = this.getOrCreateErrorBlock(pathOfError);
set(errorBlock, ERRORS_KEY, []);
return this;
}
}