Skip to content

Commit 304bae1

Browse files
committed
feat: add errors mutator to unstable
1 parent 0dd9996 commit 304bae1

File tree

17 files changed

+243
-45
lines changed

17 files changed

+243
-45
lines changed

src/lib/unstable/core/SchemaRenderer/SchemaRenderer.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,32 @@ const SchemaRendererComponent: React.FC<SchemaRendererProps> = ({
1818
config,
1919
errorMessages,
2020
mode,
21-
name,
21+
name: headName,
2222
schema,
2323
}) => {
24-
const serviceFieldName = `DYNAMIC_FORMS_SERVICE_FIELD/${name}`;
24+
const serviceFieldName = `DYNAMIC_FORMS_SERVICE_FIELD.${headName}`;
2525

2626
const context: SchemaRendererContextType = React.useMemo(
2727
() => ({
2828
config,
2929
mode,
30-
name,
30+
headName,
3131
schema,
3232
serviceFieldName,
3333
}),
34-
[config, mode, name, schema, serviceFieldName],
34+
[config, mode, headName, schema, serviceFieldName],
3535
);
3636

3737
return (
3838
<SchemaRendererContext.Provider value={context}>
3939
<SchemaRendererServiceField
4040
config={config}
4141
errorMessages={errorMessages}
42-
name={name}
42+
headName={headName}
4343
mainSchema={schema}
4444
serviceFieldName={serviceFieldName}
4545
/>
46-
<Entity name={name} schema={schema} />
46+
<Entity name={headName} schema={schema} />
4747
</SchemaRendererContext.Provider>
4848
);
4949
};

src/lib/unstable/core/SchemaRendererContext/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {JsonSchema, SchemaRendererConfig} from '../types';
44
export interface SchemaRendererContextType {
55
config: SchemaRendererConfig;
66
mode: SchemaRendererMode;
7-
name: string;
7+
headName: string;
88
schema: JsonSchema;
99
serviceFieldName: string;
1010
}

src/lib/unstable/core/SchemaRendererServiceField/SchemaRendererServiceField.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ import {getValidate} from './utils';
99
export interface SchemaRendererProps {
1010
config: SchemaRendererConfig;
1111
errorMessages?: ErrorMessages;
12-
name: string;
12+
headName: string;
1313
mainSchema: JsonSchema;
1414
serviceFieldName: string;
1515
}
1616

1717
const SchemaRendererServiceFieldComponent: React.FC<SchemaRendererProps> = ({
1818
config,
1919
errorMessages,
20-
name,
20+
headName,
2121
mainSchema,
2222
serviceFieldName,
2323
}) => {
@@ -28,7 +28,7 @@ const SchemaRendererServiceFieldComponent: React.FC<SchemaRendererProps> = ({
2828
getValidate({
2929
config,
3030
errorMessages,
31-
name,
31+
headName,
3232
mainSchema,
3333
serviceFieldName,
3434
setValidationCache,
@@ -37,7 +37,7 @@ const SchemaRendererServiceFieldComponent: React.FC<SchemaRendererProps> = ({
3737
[
3838
config,
3939
errorMessages,
40-
name,
40+
headName,
4141
mainSchema,
4242
serviceFieldName,
4343
setValidationCache,

src/lib/unstable/core/SchemaRendererServiceField/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export interface GetAjvErrorMessageParams {
4141
export type GetValidateParams<Schema extends JsonSchema> = {
4242
config: SchemaRendererConfig;
4343
errorMessages?: ErrorMessages;
44-
name: string;
44+
headName: string;
4545
mainSchema: Schema;
4646
serviceFieldName: string;
4747
setValidationCache: SetValidationCacheMutator;

src/lib/unstable/core/SchemaRendererServiceField/utils.ts

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import Ajv from 'ajv';
33
import get from 'lodash/get';
44
import isEqual from 'lodash/isEqual';
55
import isString from 'lodash/isString';
6+
import mapValues from 'lodash/mapValues';
67
import omit from 'lodash/omit';
78
import set from 'lodash/set';
89

9-
import {ARRAY_AND_OBJECT_ERRORS, EMPTY_OBJECT, JsonSchemaType} from '../constants';
10-
import type {ValidationState, ValidationWaiter} from '../mutators';
10+
import {ARRAY_AND_OBJECT_ERRORS, EMPTY_OBJECT, JsonSchemaType, OBJECT_ERROR} from '../constants';
11+
import type {ErrorsState, ValidationState, ValidationWaiter} from '../mutators';
1112
import type {FieldValue, JsonSchema, ObjectValue, SyncValidateError, Validator} from '../types';
12-
import {parseFinalFormPath} from '../utils';
13+
import {getSchemaByFinalFormPath, parseFinalFormPath} from '../utils';
1314

1415
import type {
1516
EntityParametersError,
@@ -73,6 +74,10 @@ const parseSchemaPath = (schemaPath: string): string[] => {
7374
};
7475

7576
const parseInstancePath = (instancePath: string): string[] => {
77+
if (!instancePath.length) {
78+
return [];
79+
}
80+
7681
return instancePath
7782
.slice('/'.length)
7883
.split('/')
@@ -85,7 +90,11 @@ const getSchemaBySchemaPath = (
8590
): JsonSchema | undefined => {
8691
const pathArr = parseSchemaPath(schemaPath);
8792

88-
return pathArr.length ? get(mainSchema, pathArr) : mainSchema;
93+
if (!pathArr.length) {
94+
return mainSchema;
95+
}
96+
97+
return get(mainSchema, pathArr);
8998
};
9099

91100
const getSchemaByInstancePath = (
@@ -148,7 +157,7 @@ const getAjvErrorMessage = ({
148157
export const getValidate = <Schema extends JsonSchema>({
149158
config,
150159
errorMessages,
151-
name,
160+
headName,
152161
mainSchema,
153162
serviceFieldName,
154163
setValidationCache,
@@ -157,15 +166,17 @@ export const getValidate = <Schema extends JsonSchema>({
157166
const ajvValidate = getAjvValidate({config, mainSchema});
158167

159168
return (_value, allValues, meta) => {
160-
ajvValidate(get(allValues, name));
169+
ajvValidate(get(allValues, headName));
161170

162171
if (!ajvValidate.errors?.length) {
163172
return false;
164173
}
165174

175+
const result = {[ARRAY_AND_OBJECT_ERRORS]: {}};
176+
166177
const waiters: Record<string, ValidationWaiter> = {};
167-
const ajvErrors: {instancePath: string; error: SyncValidateError}[] = [];
168-
const entityParametersErrors: {instancePath: string; error: SyncValidateError}[] = [];
178+
const ajvErrors: {path: string[]; error: SyncValidateError}[] = [];
179+
const entityParametersErrors: {path: string[]; error: SyncValidateError}[] = [];
169180

170181
ajvValidate.errors.forEach((ajvOrEntityParametersError) => {
171182
if (ajvOrEntityParametersError.keyword === 'entityParameters') {
@@ -180,7 +191,10 @@ export const getValidate = <Schema extends JsonSchema>({
180191

181192
if (cacheItem?.result) {
182193
entityParametersErrors.push({
183-
instancePath: entityParametersError.instancePath,
194+
path: [
195+
...parseFinalFormPath(headName),
196+
...parseInstancePath(entityParametersError.instancePath),
197+
],
184198
error: cacheItem.result,
185199
});
186200
} else if (!waiter || !isEqual(entityParametersError.params, waiter)) {
@@ -205,7 +219,10 @@ export const getValidate = <Schema extends JsonSchema>({
205219
});
206220
} else {
207221
entityParametersErrors.push({
208-
instancePath: entityParametersError.instancePath,
222+
path: [
223+
...parseFinalFormPath(headName),
224+
...parseInstancePath(entityParametersError.instancePath),
225+
],
209226
error: errorOrPromise,
210227
});
211228
}
@@ -225,7 +242,10 @@ export const getValidate = <Schema extends JsonSchema>({
225242
}
226243

227244
ajvErrors.push({
228-
instancePath,
245+
path: [
246+
...parseFinalFormPath(headName),
247+
...parseInstancePath(ajvError.instancePath),
248+
],
229249
error: getAjvErrorMessage({
230250
ajvErrorMessage: ajvError.message,
231251
errorMessages,
@@ -242,25 +262,36 @@ export const getValidate = <Schema extends JsonSchema>({
242262
setValidationWaiters({name: serviceFieldName, waiters});
243263
}
244264

245-
const result = {[ARRAY_AND_OBJECT_ERRORS]: {}};
265+
const errorsState: ErrorsState | undefined = meta?.data;
266+
const externalRegularErrors: {path: string[]; error: SyncValidateError}[] = Object.values(
267+
mapValues(errorsState?.regularErrors, (value, key) => ({
268+
path: parseFinalFormPath(key),
269+
error: value,
270+
})),
271+
);
272+
const externalPriorityErrors: {path: string[]; error: SyncValidateError}[] = Object.values(
273+
mapValues(errorsState?.priorityErrors, (value, key) => ({
274+
path: parseFinalFormPath(key),
275+
error: value,
276+
})),
277+
);
246278

247-
[...ajvErrors, ...entityParametersErrors].forEach((item) => {
279+
[
280+
...externalRegularErrors,
281+
...ajvErrors,
282+
...entityParametersErrors,
283+
...externalPriorityErrors,
284+
].forEach((item) => {
248285
if (item.error) {
249-
const itemSchema = getSchemaByInstancePath(item.instancePath, mainSchema);
286+
const itemSchema = getSchemaByFinalFormPath(item.path, headName, mainSchema);
250287

251288
if (itemSchema) {
252-
const arrayOrObjectSchema =
253-
itemSchema.type === JsonSchemaType.Array ||
254-
itemSchema.type === JsonSchemaType.Object;
255-
256-
const path = [
257-
...parseFinalFormPath(name),
258-
...parseInstancePath(item.instancePath),
259-
];
289+
const arraySchema = itemSchema.type === JsonSchemaType.Array;
290+
const objectSchema = itemSchema.type === JsonSchemaType.Object;
260291

261292
set(
262-
arrayOrObjectSchema ? result[ARRAY_AND_OBJECT_ERRORS] : result,
263-
path,
293+
arraySchema || objectSchema ? result[ARRAY_AND_OBJECT_ERRORS] : result,
294+
objectSchema ? [...item.path, OBJECT_ERROR] : item.path,
264295
item.error,
265296
);
266297
}

src/lib/unstable/core/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ export enum JsonSchemaType {
1414
export const EMPTY_OBJECT = {};
1515

1616
export const ARRAY_AND_OBJECT_ERRORS = 'ARRAY_AND_OBJECT_ERRORS';
17+
18+
export const OBJECT_ERROR = 'OBJECT_ERROR';

src/lib/unstable/core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export {JsonSchemaType, SchemaRendererMode} from './constants';
44
export {schemaRendererMutators} from './mutators';
55
export * from './types';
66
export * from './useSchemaRendererField';
7+
export * from './useSetErrors';
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import {setValidationCache, setValidationWaiters} from './async-validation';
2+
import {removeErrors, setErrors} from './set-errors';
23

34
export * from './async-validation/types';
5+
export * from './set-errors/types';
46

57
export const schemaRendererMutators = {
8+
removeErrors,
9+
setErrors,
610
setValidationCache,
711
setValidationWaiters,
812
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './set-errors';
2+
export * from './types';
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import omit from 'lodash/omit';
2+
3+
import type {ErrorsState, RemoveErrorsFunction, SetErrorsFunction} from './types';
4+
5+
export const setErrors: SetErrorsFunction = (
6+
[{serviceFieldName, priorityErrors, regularErrors}],
7+
mutableState,
8+
) => {
9+
const errorsState = mutableState.fields[serviceFieldName]?.data as ErrorsState | undefined;
10+
11+
if (errorsState && (priorityErrors || regularErrors)) {
12+
errorsState.priorityErrors = {
13+
...errorsState.priorityErrors,
14+
...(priorityErrors || {}),
15+
};
16+
errorsState.regularErrors = {
17+
...errorsState.regularErrors,
18+
...(regularErrors || {}),
19+
};
20+
}
21+
};
22+
23+
export const removeErrors: RemoveErrorsFunction = (
24+
[{removeFunctionOrNames, serviceFieldName}],
25+
mutableState,
26+
) => {
27+
const errorsState = mutableState.fields[serviceFieldName]?.data as ErrorsState | undefined;
28+
29+
if (errorsState && removeFunctionOrNames) {
30+
const {priorityErrors, regularErrors} = Array.isArray(removeFunctionOrNames)
31+
? {
32+
priorityErrors: omit(errorsState.priorityErrors, removeFunctionOrNames),
33+
regularErrors: omit(errorsState.regularErrors, removeFunctionOrNames),
34+
}
35+
: removeFunctionOrNames(errorsState);
36+
37+
errorsState.priorityErrors = priorityErrors;
38+
errorsState.regularErrors = regularErrors;
39+
}
40+
};

0 commit comments

Comments
 (0)