-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathvalidate-exercise-action.ts
60 lines (55 loc) · 2.39 KB
/
validate-exercise-action.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
import { plainToInstance } from 'class-transformer';
import type {
ValidationArguments,
ValidationError,
ValidationOptions,
} from 'class-validator';
import { validateSync } from 'class-validator';
import type { Constructor } from '../utils';
import type { GenericPropertyDecorator } from '../utils/validators/generic-property-decorator';
import { makeValidator } from '../utils/validators/make-validator';
import type { ExerciseAction } from './action-reducers';
import { getExerciseActionTypeDictionary } from './action-reducers';
import { defaultValidateOptions } from './validation-options';
/**
*
* @param action A json object that should be checked for validity.
* @returns An array of errors validating {@link action}. An empty array indicates a valid action object.
*/
export function validateExerciseAction(
action: ExerciseAction
): (ValidationError | string)[] {
// Be aware that `action` could be any json object. We need to program defensively here.
if (typeof action.type !== 'string') {
return ['Action type is not a string.'];
}
// Defensive, see comment above
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const actionClass = getExerciseActionTypeDictionary()[action.type]?.action;
// if the action.type is not a valid action type, the actionClass is undefined.
// Defensive, see comment above
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!actionClass) {
return [`Unknown action type: ${action.type}`];
}
// This works - no idea about the type error though...
return validateSync(
plainToInstance(actionClass as Constructor<ExerciseAction>, action),
defaultValidateOptions
);
}
// Decorators for validation
// Placed here instead of in utils/validators to prevent circular imports
export function isExerciseAction(value: unknown): value is ExerciseAction {
return validateExerciseAction(value as ExerciseAction).length === 0;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
export function IsExerciseAction<Each extends boolean>(
validationOptions?: ValidationOptions & { each?: Each }
): GenericPropertyDecorator<ExerciseAction, Each> {
return makeValidator<ExerciseAction, Each>(
'isExerciseAction',
(value: unknown, args?: ValidationArguments) => isExerciseAction(value),
validationOptions
);
}