@oscarpalmer/jhunal 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/constants.d.mts +15 -7
  2. package/dist/constants.mjs +15 -6
  3. package/dist/handler/base.handler.d.mts +6 -0
  4. package/dist/{validator/base.validator.mjs → handler/base.handler.mjs} +5 -5
  5. package/dist/handler/function.handler.d.mts +6 -0
  6. package/dist/handler/function.handler.mjs +9 -0
  7. package/dist/handler/object.handler.d.mts +7 -0
  8. package/dist/handler/object.handler.mjs +130 -0
  9. package/dist/handler/schema.handler.d.mts +7 -0
  10. package/dist/handler/schema.handler.mjs +16 -0
  11. package/dist/handler/type.handler.d.mts +9 -0
  12. package/dist/handler/type.handler.mjs +71 -0
  13. package/dist/handler/validator.handler.d.mts +10 -0
  14. package/dist/handler/validator.handler.mjs +34 -0
  15. package/dist/handler/value.handler.d.mts +14 -0
  16. package/dist/handler/value.handler.mjs +98 -0
  17. package/dist/helpers/message.helper.d.mts +9 -7
  18. package/dist/helpers/message.helper.mjs +34 -16
  19. package/dist/helpers/misc.helper.d.mts +13 -6
  20. package/dist/helpers/misc.helper.mjs +12 -4
  21. package/dist/helpers/report.helper.d.mts +23 -0
  22. package/dist/helpers/report.helper.mjs +19 -0
  23. package/dist/helpers/result.helper.d.mts +7 -0
  24. package/dist/helpers/result.helper.mjs +17 -0
  25. package/dist/index.d.mts +170 -71
  26. package/dist/index.mjs +354 -215
  27. package/dist/models/infer.model.d.mts +11 -8
  28. package/dist/models/misc.model.d.mts +8 -8
  29. package/dist/models/schematic.plain.model.d.mts +10 -9
  30. package/dist/models/schematic.typed.model.d.mts +1 -1
  31. package/dist/models/transform.model.d.mts +2 -2
  32. package/dist/models/validation.model.d.mts +56 -25
  33. package/dist/models/validation.model.mjs +11 -2
  34. package/dist/schema.d.mts +32 -32
  35. package/dist/schema.mjs +11 -19
  36. package/dist/validator.d.mts +83 -0
  37. package/dist/validator.mjs +25 -0
  38. package/package.json +2 -2
  39. package/src/constants.ts +30 -8
  40. package/src/{validator/base.validator.ts → handler/base.handler.ts} +6 -6
  41. package/src/handler/function.handler.ts +9 -0
  42. package/src/handler/object.handler.ts +245 -0
  43. package/src/handler/schema.handler.ts +25 -0
  44. package/src/handler/type.handler.ts +160 -0
  45. package/src/handler/validator.handler.ts +49 -0
  46. package/src/handler/value.handler.ts +202 -0
  47. package/src/helpers/message.helper.ts +72 -30
  48. package/src/helpers/misc.helper.ts +23 -6
  49. package/src/helpers/report.helper.ts +72 -0
  50. package/src/helpers/result.helper.ts +33 -0
  51. package/src/index.ts +1 -0
  52. package/src/models/infer.model.ts +31 -13
  53. package/src/models/misc.model.ts +9 -9
  54. package/src/models/schematic.plain.model.ts +12 -9
  55. package/src/models/schematic.typed.model.ts +3 -3
  56. package/src/models/transform.model.ts +2 -2
  57. package/src/models/validation.model.ts +75 -37
  58. package/src/schema.ts +42 -70
  59. package/src/validator.ts +135 -0
  60. package/dist/validator/base.validator.d.mts +0 -6
  61. package/dist/validator/function.validator.d.mts +0 -6
  62. package/dist/validator/function.validator.mjs +0 -9
  63. package/dist/validator/named.handler.d.mts +0 -6
  64. package/dist/validator/named.handler.mjs +0 -23
  65. package/dist/validator/named.validator.d.mts +0 -7
  66. package/dist/validator/named.validator.mjs +0 -38
  67. package/dist/validator/object.validator.d.mts +0 -7
  68. package/dist/validator/object.validator.mjs +0 -207
  69. package/dist/validator/schema.validator.d.mts +0 -7
  70. package/dist/validator/schema.validator.mjs +0 -16
  71. package/src/validator/function.validator.ts +0 -9
  72. package/src/validator/named.handler.ts +0 -65
  73. package/src/validator/named.validator.ts +0 -61
  74. package/src/validator/object.validator.ts +0 -426
  75. package/src/validator/schema.validator.ts +0 -25
@@ -0,0 +1,25 @@
1
+ import { PROPERTY_VALIDATOR } from "./constants.mjs";
2
+ import { getValidatorHandler } from "./handler/validator.handler.mjs";
3
+ import { isResult } from "./helpers/result.helper.mjs";
4
+ //#region src/validator.ts
5
+ var Validator = class {
6
+ #handler;
7
+ constructor(handler, types) {
8
+ Object.defineProperty(this, PROPERTY_VALIDATOR, { value: true });
9
+ this.#handler = handler;
10
+ validatorHandlers.set(this, handler);
11
+ validatorTypes.set(this, types);
12
+ }
13
+ is(value, options) {
14
+ return isResult(this.#handler, value, options);
15
+ }
16
+ };
17
+ function validator(value, validators) {
18
+ if (value instanceof Validator) return value;
19
+ const { handler, types } = getValidatorHandler(value, validators);
20
+ return new Validator(handler, types);
21
+ }
22
+ const validatorHandlers = /* @__PURE__ */ new WeakMap();
23
+ const validatorTypes = /* @__PURE__ */ new WeakMap();
24
+ //#endregion
25
+ export { Validator, validator, validatorHandlers, validatorTypes };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/jhunal",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Flies free beneath the glistening moons…",
5
5
  "keywords": [
6
6
  "schema",
@@ -41,7 +41,7 @@
41
41
  "@oscarpalmer/atoms": "^0.170"
42
42
  },
43
43
  "devDependencies": {
44
- "@types/node": "^25.5",
44
+ "@types/node": "^25.6",
45
45
  "@vitest/coverage-istanbul": "^4.1",
46
46
  "jsdom": "^29.0",
47
47
  "tsdown": "^0.21",
package/src/constants.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type {ValueName} from './models/misc.model';
1
+ import type {ValueType} from './models/misc.model';
2
2
  import type {ReportingType} from './models/validation.model';
3
3
 
4
4
  // #region Grammar
@@ -31,6 +31,8 @@ export const NAME_ERROR_SCHEMATIC = 'SchematicError';
31
31
 
32
32
  export const NAME_ERROR_VALIDATION = 'ValidationError';
33
33
 
34
+ export const NAME_ERROR_VALIDATOR = 'ValidatorError';
35
+
34
36
  // #endregion
35
37
 
36
38
  // #region Properties
@@ -43,22 +45,29 @@ export const PROPERTY_SCHEMA = '$schema';
43
45
 
44
46
  export const PROPERTY_TYPE = '$type';
45
47
 
48
+ export const PROPERTY_VALIDATOR = '$validator';
49
+
46
50
  export const PROPERTY_VALIDATORS = '$validators';
47
51
 
48
52
  // #endregion
49
53
 
50
- // #region Property validation
54
+ // #region Value validation
51
55
 
52
56
  export const VALIDATION_MESSAGE_INVALID_INPUT = 'Expected an object as input but received <>';
53
57
 
54
58
  export const VALIDATION_MESSAGE_INVALID_REQUIRED = "Expected <> for required property '<>'";
55
59
 
56
- export const VALIDATION_MESSAGE_INVALID_TYPE = "Expected <> for '<>' but received <>";
60
+ export const VALIDATION_MESSAGE_INVALID_PROPERTY_TYPE = "Expected <> for '<>' but received <>";
57
61
 
58
- export const VALIDATION_MESSAGE_INVALID_VALUE =
62
+ export const VALIDATION_MESSAGE_INVALID_PROPERTY_VALIDATOR =
59
63
  "Value does not satisfy validator for '<>' and type '<>'";
60
64
 
61
- export const VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX = ' at index <>';
65
+ export const VALIDATION_MESSAGE_INVALID_VALIDATOR_SUFFIX = ' at index <>';
66
+
67
+ export const VALIDATION_MESSAGE_INVALID_VALUE_TYPE = 'Expected <> but received <>';
68
+
69
+ export const VALIDATION_MESSAGE_INVALID_VALUE_VALIDATOR =
70
+ "Value does not satisfy validator for type '<>'";
62
71
 
63
72
  export const VALIDATION_MESSAGE_UNKNOWN_KEYS = 'Found keys that are not defined in the schema: <>';
64
73
 
@@ -72,12 +81,15 @@ export const REPORTING_FIRST: ReportingType = 'first';
72
81
 
73
82
  export const REPORTING_NONE: ReportingType = 'none';
74
83
 
84
+ export const REPORTING_RESULT: ReportingType = 'result';
85
+
75
86
  export const REPORTING_THROW: ReportingType = 'throw';
76
87
 
77
88
  export const REPORTING_TYPES = new Set<ReportingType>([
78
89
  REPORTING_ALL,
79
90
  REPORTING_FIRST,
80
91
  REPORTING_NONE,
92
+ REPORTING_RESULT,
81
93
  REPORTING_THROW,
82
94
  ]);
83
95
 
@@ -136,7 +148,7 @@ export const TYPE_OBJECT = 'object';
136
148
 
137
149
  export const TYPE_UNDEFINED = 'undefined';
138
150
 
139
- export const VALIDATABLE_TYPES = new Set<ValueName>([
151
+ export const VALIDATABLE_TYPES = new Set<ValueType>([
140
152
  TYPE_ARRAY,
141
153
  'bigint',
142
154
  'boolean',
@@ -148,9 +160,9 @@ export const VALIDATABLE_TYPES = new Set<ValueName>([
148
160
  'symbol',
149
161
  ]);
150
162
 
151
- export const TYPE_ALL = new Set<ValueName>([...VALIDATABLE_TYPES, TYPE_NULL, TYPE_UNDEFINED]);
163
+ export const TYPES_ALL = new Set<ValueType>([...VALIDATABLE_TYPES, TYPE_NULL, TYPE_UNDEFINED]);
152
164
 
153
- export const PREFIXED_TYPES: Record<ValueName, string> = {
165
+ export const TYPES_PREFIXED: Record<ValueType, string> = {
154
166
  [TYPE_ARRAY]: `an ${TYPE_ARRAY}`,
155
167
  bigint: `a bigint`,
156
168
  boolean: `a boolean`,
@@ -165,3 +177,13 @@ export const PREFIXED_TYPES: Record<ValueName, string> = {
165
177
  };
166
178
 
167
179
  // #endregion
180
+
181
+ // #region Validator validation
182
+
183
+ export const VALIDATOR_MESSAGE_INVALID_PROPERTY_NULLABLE =
184
+ "Validator must not be 'null' or 'undefined'";
185
+
186
+ export const VALIDATOR_MESSAGE_INVALID_PROPERTY_TYPE = 'Validator must be of a valid type';
187
+
188
+ export const VALIDATOR_MESSAGE_INVALID_VALIDATOR =
189
+ 'Validator must be a function or an array of functions';
@@ -1,19 +1,19 @@
1
- import type {ValidationInformation, Validator} from '../models/validation.model';
1
+ import type {ValidationHandler, PropertyValidation} from '../models/validation.model';
2
2
 
3
- export function getBaseValidator(validators: Validator[]): Validator {
4
- const {length} = validators;
3
+ export function getBaseHandler(handlers: ValidationHandler[]): ValidationHandler {
4
+ const {length} = handlers;
5
5
 
6
6
  return (input, parameters, get) => {
7
- const allInformation: ValidationInformation[] = [];
7
+ const allInformation: PropertyValidation[] = [];
8
8
 
9
9
  for (let index = 0; index < length; index += 1) {
10
10
  const previousInformation = parameters.information;
11
11
 
12
- const nextInformation: ValidationInformation[] = [];
12
+ const nextInformation: PropertyValidation[] = [];
13
13
 
14
14
  parameters.information = nextInformation;
15
15
 
16
- const result = validators[index](input, parameters, get);
16
+ const result = handlers[index](input, parameters, get);
17
17
 
18
18
  parameters.information = previousInformation;
19
19
 
@@ -0,0 +1,9 @@
1
+ import {isConstructor} from '@oscarpalmer/atoms/is';
2
+ import {instanceOf} from '../helpers/misc.helper';
3
+ import type {ValidationHandler} from '../models/validation.model';
4
+
5
+ export function getFunctionHandler(fn: Function): ValidationHandler {
6
+ const handler = isConstructor(fn) ? instanceOf(fn) : fn;
7
+
8
+ return input => (handler(input) ? true : []);
9
+ }
@@ -0,0 +1,245 @@
1
+ import {isPlainObject} from '@oscarpalmer/atoms/is';
2
+ import type {PlainObject} from '@oscarpalmer/atoms/models';
3
+ import {clone} from '@oscarpalmer/atoms/value/clone';
4
+ import {
5
+ PROPERTY_DEFAULT,
6
+ PROPERTY_REQUIRED,
7
+ PROPERTY_TYPE,
8
+ PROPERTY_VALIDATORS,
9
+ SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY,
10
+ } from '../constants';
11
+ import {
12
+ getDisallowedMessage,
13
+ getInputPropertyMissingMessage,
14
+ getInputPropertyTypeMessage,
15
+ getInputTypeMessage,
16
+ getUnknownKeysMessage,
17
+ } from '../helpers/message.helper';
18
+ import {report} from '../helpers/report.helper';
19
+ import {
20
+ SchematicError,
21
+ ValidationError,
22
+ type PropertyValidation,
23
+ type PropertyValidationKey,
24
+ type ValidationHandler,
25
+ type ValidationHandlerItem,
26
+ } from '../models/validation.model';
27
+ import {getValueHandler} from './value.handler';
28
+
29
+ function getDisallowedProperty(obj: PlainObject): string | undefined {
30
+ if (PROPERTY_DEFAULT in obj) {
31
+ return PROPERTY_DEFAULT;
32
+ }
33
+
34
+ if (PROPERTY_REQUIRED in obj) {
35
+ return PROPERTY_REQUIRED;
36
+ }
37
+
38
+ if (PROPERTY_TYPE in obj) {
39
+ return PROPERTY_TYPE;
40
+ }
41
+
42
+ if (PROPERTY_VALIDATORS in obj) {
43
+ return PROPERTY_VALIDATORS;
44
+ }
45
+ }
46
+
47
+ export function getObjectHandler(
48
+ original: PlainObject,
49
+ origin?: PropertyValidationKey,
50
+ fromType?: boolean,
51
+ ): ValidationHandler {
52
+ const keys = Object.keys(original);
53
+ const keysLength = keys.length;
54
+
55
+ if (keysLength === 0) {
56
+ throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY);
57
+ }
58
+
59
+ if (fromType ?? false) {
60
+ const property = getDisallowedProperty(original);
61
+
62
+ if (property != null) {
63
+ throw new SchematicError(getDisallowedMessage(origin!.full, property));
64
+ }
65
+ }
66
+
67
+ const set = new Set<string>();
68
+
69
+ const items: ValidationHandlerItem[] = [];
70
+
71
+ for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
72
+ const key = keys[keyIndex];
73
+
74
+ const {
75
+ defaults,
76
+ handler,
77
+ key: fullKey,
78
+ required,
79
+ types,
80
+ } = getValueHandler(
81
+ {
82
+ value: original[key],
83
+ },
84
+ {
85
+ key,
86
+ origin,
87
+ },
88
+ );
89
+
90
+ items.push({
91
+ defaults,
92
+ handler,
93
+ required,
94
+ types,
95
+ key: fullKey,
96
+ });
97
+
98
+ set.add(key);
99
+ }
100
+
101
+ const validatorsLength = items.length;
102
+
103
+ return (input, parameters, get) => {
104
+ if (!isPlainObject(input)) {
105
+ return origin == null
106
+ ? report(
107
+ {
108
+ message: {
109
+ arguments: [input],
110
+ callback: getInputTypeMessage,
111
+ },
112
+ original: parameters,
113
+ value: input,
114
+ },
115
+ true,
116
+ )
117
+ : [];
118
+ }
119
+
120
+ if (parameters.strict) {
121
+ const inputKeys = Object.keys(input);
122
+ const unknownKeys = inputKeys.filter(key => !set.has(key));
123
+
124
+ if (unknownKeys.length > 0) {
125
+ const information: PropertyValidation = {
126
+ key: origin,
127
+ message: getUnknownKeysMessage(unknownKeys),
128
+ value: input,
129
+ };
130
+
131
+ if (parameters.reporting.throw) {
132
+ throw new ValidationError([information]);
133
+ }
134
+
135
+ parameters.information?.push(information);
136
+
137
+ return [information];
138
+ }
139
+ }
140
+
141
+ const getAndClone = get && parameters.clone;
142
+
143
+ const allInformation: PropertyValidation[] = [];
144
+ const output: PlainObject = {};
145
+
146
+ for (let validatorIndex = 0; validatorIndex < validatorsLength; validatorIndex += 1) {
147
+ const {defaults, handler, key, required, types} = items[validatorIndex];
148
+
149
+ const value = (input as PlainObject)[key.short];
150
+
151
+ if (value === undefined) {
152
+ if (required) {
153
+ if (get && defaults != null) {
154
+ const defaultValue = clone(defaults.value);
155
+
156
+ if (parameters.clone) {
157
+ output[key.short] = defaultValue;
158
+ } else {
159
+ input[key.short] = defaultValue;
160
+ }
161
+
162
+ continue;
163
+ }
164
+
165
+ if (parameters.reporting.none) {
166
+ return [];
167
+ }
168
+
169
+ const reported = report({
170
+ key,
171
+ value,
172
+ information: {
173
+ all: allInformation,
174
+ },
175
+ message: {
176
+ arguments: [key.full, types],
177
+ callback: getInputPropertyMissingMessage,
178
+ },
179
+ original: parameters,
180
+ });
181
+
182
+ if (reported == null) {
183
+ continue;
184
+ }
185
+
186
+ return reported;
187
+ }
188
+
189
+ continue;
190
+ }
191
+
192
+ const previousOutput = parameters.output;
193
+
194
+ parameters.key = key.full;
195
+ parameters.output = output;
196
+
197
+ const result = handler(value, parameters, get);
198
+
199
+ parameters.output = previousOutput;
200
+
201
+ if (result === true) {
202
+ if (getAndClone && !isPlainObject(value)) {
203
+ output[key.short] = clone(value);
204
+ }
205
+
206
+ continue;
207
+ }
208
+
209
+ if (parameters.reporting.none) {
210
+ return [];
211
+ }
212
+
213
+ const reported = report({
214
+ key,
215
+ value,
216
+ extract: false,
217
+ information: {
218
+ all: allInformation,
219
+ existing: typeof result !== 'boolean' && result.length > 0 ? result : undefined,
220
+ },
221
+ message: {
222
+ arguments: [key.full, types, value],
223
+ callback: getInputPropertyTypeMessage,
224
+ },
225
+ original: parameters,
226
+ });
227
+
228
+ if (reported == null) {
229
+ continue;
230
+ }
231
+
232
+ return reported;
233
+ }
234
+
235
+ if (getAndClone) {
236
+ if (origin == null) {
237
+ parameters.output = output;
238
+ } else {
239
+ parameters.output[origin.short] = output;
240
+ }
241
+ }
242
+
243
+ return allInformation.length === 0 ? true : allInformation;
244
+ };
245
+ }
@@ -0,0 +1,25 @@
1
+ import {isPlainObject} from '@oscarpalmer/atoms/is';
2
+ import type {ValidationHandler} from '../models/validation.model';
3
+ import {Schema, schemaHandlers} from '../schema';
4
+
5
+ export function getSchemaHandler(schematic: Schema<unknown>): ValidationHandler {
6
+ const handler = schemaHandlers.get(schematic)!;
7
+
8
+ return (input, parameters, get) => {
9
+ let result: ReturnType<ValidationHandler>;
10
+
11
+ if (isPlainObject(input)) {
12
+ result = handler(input, parameters, get);
13
+ } else {
14
+ result = [];
15
+ }
16
+
17
+ if (result === true) {
18
+ return result;
19
+ }
20
+
21
+ parameters.information?.push(...result);
22
+
23
+ return result;
24
+ };
25
+ }
@@ -0,0 +1,160 @@
1
+ import {isPlainObject} from '@oscarpalmer/atoms/is';
2
+ import {
3
+ PROPERTY_VALIDATORS,
4
+ SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED,
5
+ SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY,
6
+ SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE,
7
+ SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE,
8
+ TEMPLATE_PATTERN,
9
+ TYPES_ALL,
10
+ VALIDATOR_MESSAGE_INVALID_VALIDATOR,
11
+ } from '../constants';
12
+ import {
13
+ getInputPropertyValidatorMessage,
14
+ getInputValueValidatorMessage,
15
+ } from '../helpers/message.helper';
16
+ import type {ValueType} from '../models/misc.model';
17
+ import {
18
+ type PropertyValidation,
19
+ type PropertyValidationKey,
20
+ type TypeValidators,
21
+ type ValidationHandler,
22
+ type ValidationHandlerType,
23
+ type Validators,
24
+ SchematicError,
25
+ ValidatorError,
26
+ } from '../models/validation.model';
27
+
28
+ export function getTypeHandler(
29
+ type: ValueType,
30
+ validators: Validators,
31
+ key?: PropertyValidationKey,
32
+ ): ValidationHandler {
33
+ const validator = typeValidators[type];
34
+
35
+ const typedValidators = validators[type] ?? [];
36
+ const {length} = typedValidators;
37
+
38
+ return (input, parameters) => {
39
+ if (!validator(input)) {
40
+ return [];
41
+ }
42
+
43
+ for (let index = 0; index < length; index += 1) {
44
+ const validator = typedValidators[index];
45
+
46
+ if (validator(input) === true) {
47
+ continue;
48
+ }
49
+
50
+ const information: PropertyValidation = {
51
+ validator,
52
+ message:
53
+ key == null
54
+ ? getInputValueValidatorMessage(type, index, length)
55
+ : getInputPropertyValidatorMessage(key.full, type, index, length),
56
+ value: input,
57
+ };
58
+
59
+ if (key != null) {
60
+ information.key = key;
61
+ }
62
+
63
+ parameters.information?.push(information);
64
+
65
+ return parameters.reporting.none ? [] : [information];
66
+ }
67
+
68
+ return true;
69
+ };
70
+ }
71
+
72
+ export function getTypeValidators(types: ValidationHandlerType[], original: unknown): Validators {
73
+ const values = types.filter(type => TYPES_ALL.has(type as ValueType)) as ValueType[];
74
+ const {length} = values;
75
+
76
+ const validators: Validators = {};
77
+
78
+ if (original == null || length === 0) {
79
+ return validators;
80
+ }
81
+
82
+ if (typeof original === 'function' || Array.isArray(original)) {
83
+ if (length > 1) {
84
+ throw new ValidatorError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
85
+ }
86
+
87
+ return getValidators({[values[0]]: original}, true);
88
+ }
89
+
90
+ return getValidators(original, true);
91
+ }
92
+
93
+ export function getValidators(original: unknown, allowed: boolean, prefix?: string): Validators {
94
+ const validators: Validators = {};
95
+
96
+ if (original == null) {
97
+ return validators;
98
+ }
99
+
100
+ if (!allowed) {
101
+ throw new SchematicError(
102
+ SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace(
103
+ TEMPLATE_PATTERN,
104
+ prefix!,
105
+ ).replace(TEMPLATE_PATTERN, PROPERTY_VALIDATORS),
106
+ );
107
+ }
108
+
109
+ if (!isPlainObject(original)) {
110
+ throw new SchematicError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
111
+ }
112
+
113
+ const keys = Object.keys(original);
114
+ const {length} = keys;
115
+
116
+ for (let index = 0; index < length; index += 1) {
117
+ const key = keys[index];
118
+
119
+ if (!TYPES_ALL.has(key as never)) {
120
+ throw new SchematicError(
121
+ SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace(TEMPLATE_PATTERN, key),
122
+ );
123
+ }
124
+
125
+ const value = original[key];
126
+
127
+ validators[key as ValueType] = (Array.isArray(value) ? value : [value]).map(item => {
128
+ if (typeof item !== 'function') {
129
+ if (prefix == null) {
130
+ throw new ValidatorError(VALIDATOR_MESSAGE_INVALID_VALIDATOR);
131
+ } else {
132
+ throw new SchematicError(
133
+ SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace(TEMPLATE_PATTERN, key).replace(
134
+ TEMPLATE_PATTERN,
135
+ prefix,
136
+ ),
137
+ );
138
+ }
139
+ }
140
+
141
+ return item;
142
+ });
143
+ }
144
+
145
+ return validators;
146
+ }
147
+
148
+ const typeValidators: TypeValidators = {
149
+ array: Array.isArray,
150
+ bigint: value => typeof value === 'bigint',
151
+ boolean: value => typeof value === 'boolean',
152
+ date: value => value instanceof Date,
153
+ function: value => typeof value === 'function',
154
+ null: value => value === null,
155
+ number: value => typeof value === 'number',
156
+ object: value => typeof value === 'object' && value !== null,
157
+ string: value => typeof value === 'string',
158
+ symbol: value => typeof value === 'symbol',
159
+ undefined: value => value === undefined,
160
+ };
@@ -0,0 +1,49 @@
1
+ import {getInputValueTypeMessage} from '../helpers/message.helper';
2
+ import {report} from '../helpers/report.helper';
3
+ import type {ValidationHandler, ValidationHandlerType} from '../models/validation.model';
4
+ import {getValueHandler} from './value.handler';
5
+
6
+ type ValidatorHandler = {
7
+ handler: ValidationHandler;
8
+ types: ValidationHandlerType[];
9
+ };
10
+
11
+ export function getValidatorHandler(value: unknown, validators?: unknown): ValidatorHandler {
12
+ const {handler, types} = getValueHandler({
13
+ validators,
14
+ value,
15
+ });
16
+
17
+ const validator: ValidationHandler = (input, parameters, get) => {
18
+ const result = handler(input, parameters, get);
19
+
20
+ if (result === true) {
21
+ return true;
22
+ }
23
+
24
+ if (parameters.key != null) {
25
+ return [];
26
+ }
27
+
28
+ const reported = report({
29
+ value: input,
30
+ extract: false,
31
+ information: {
32
+ all: parameters.information ?? [],
33
+ existing: result.length > 0 ? result : undefined,
34
+ },
35
+ message: {
36
+ arguments: [types, input],
37
+ callback: getInputValueTypeMessage,
38
+ },
39
+ original: parameters,
40
+ })!;
41
+
42
+ return reported;
43
+ };
44
+
45
+ return {
46
+ types,
47
+ handler: validator,
48
+ };
49
+ }