@oscarpalmer/jhunal 0.20.0 → 0.22.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.
@@ -1,140 +0,0 @@
1
- import "../constants.mjs";
2
- import { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getUnknownKeysMessage, isSchematic } from "../helpers.mjs";
3
- import { ValidationError } from "../models/validation.model.mjs";
4
- import { schematicProperties } from "../schematic.mjs";
5
- import { isPlainObject } from "@oscarpalmer/atoms/is";
6
- import { join } from "@oscarpalmer/atoms/string";
7
- //#region src/validation/value.validation.ts
8
- function validateNamed(property, name, value, validation) {
9
- if (!validators[name](value)) return false;
10
- const propertyValidators = property.validators[name];
11
- if (propertyValidators == null || propertyValidators.length === 0) return true;
12
- const { length } = propertyValidators;
13
- for (let index = 0; index < length; index += 1) {
14
- const validator = propertyValidators[index];
15
- if (!validator(value)) {
16
- validation.push({
17
- value,
18
- key: { ...property.key },
19
- message: getInvalidValidatorMessage(property, name, index, length),
20
- validator
21
- });
22
- return false;
23
- }
24
- }
25
- return true;
26
- }
27
- function validateObject(obj, properties, options, origin, validation) {
28
- if (!isPlainObject(obj)) {
29
- const key = origin == null ? {
30
- full: "",
31
- short: ""
32
- } : { ...origin.key };
33
- const information = {
34
- key,
35
- message: origin == null ? getInvalidInputMessage(obj) : getInvalidTypeMessage({
36
- ...origin,
37
- key
38
- }, obj),
39
- value: obj
40
- };
41
- if (options.reporting.throw) throw new ValidationError([information]);
42
- validation?.push(information);
43
- return options.reporting.none ? false : [information];
44
- }
45
- if (options.strict) {
46
- const objKeys = Object.keys(obj);
47
- const propertiesKeys = new Set(properties.map((property) => property.key.short));
48
- const unknownKeys = objKeys.filter((key) => !propertiesKeys.has(key));
49
- if (unknownKeys.length > 0) {
50
- const information = {
51
- key: origin == null ? {
52
- full: "",
53
- short: ""
54
- } : { ...origin.key },
55
- message: getUnknownKeysMessage(unknownKeys.map((key) => join([origin?.key.full, key], "."))),
56
- value: obj
57
- };
58
- if (options.reporting.throw) throw new ValidationError([information]);
59
- validation?.push(information);
60
- return options.reporting.none ? false : [information];
61
- }
62
- }
63
- const allInformation = [];
64
- const propertiesLength = properties.length;
65
- outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
66
- let property = properties[propertyIndex];
67
- property = {
68
- ...property,
69
- key: {
70
- full: join([origin?.key.full, property.key.short], "."),
71
- short: property.key.short
72
- }
73
- };
74
- const { key, required, types } = property;
75
- const value = obj[key.short];
76
- if (value === void 0 && required) {
77
- const information = {
78
- value,
79
- key: { ...key },
80
- message: getInvalidMissingMessage(property)
81
- };
82
- if (options.reporting.throw && validation == null) throw new ValidationError([information]);
83
- if (validation != null) validation.push(information);
84
- if (options.reporting.all) {
85
- allInformation.push(information);
86
- continue;
87
- }
88
- return options.reporting.none ? false : [information];
89
- }
90
- const typesLength = types.length;
91
- const information = [];
92
- for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
93
- const type = types[typeIndex];
94
- if (validateValue(type, property, value, options, information)) continue outer;
95
- }
96
- if (information.length === 0) information.push({
97
- value,
98
- key: { ...key },
99
- message: getInvalidTypeMessage(property, value)
100
- });
101
- if (options.reporting.throw && validation == null) throw new ValidationError(information);
102
- validation?.push(...information);
103
- if (options.reporting.all) {
104
- allInformation.push(...information);
105
- continue;
106
- }
107
- return options.reporting.none ? false : information;
108
- }
109
- return options.reporting.none || allInformation.length === 0 ? true : allInformation;
110
- }
111
- function validateSchematic(property, schematic, value, options, validation) {
112
- const result = validateObject(value, schematicProperties.get(schematic), options, property, validation);
113
- return typeof result === "boolean" ? result : result.length === 0;
114
- }
115
- function validateValue(type, property, value, options, validation) {
116
- switch (true) {
117
- case typeof type === "function": return type(value);
118
- case Array.isArray(type): {
119
- const validated = validateObject(value, type, options, property, validation);
120
- return typeof validated === "boolean" ? validated : false;
121
- }
122
- case isSchematic(type): return validateSchematic(property, type, value, options, validation);
123
- default: return validateNamed(property, type, value, validation);
124
- }
125
- }
126
- const validators = {
127
- array: Array.isArray,
128
- bigint: (value) => typeof value === "bigint",
129
- boolean: (value) => typeof value === "boolean",
130
- date: (value) => value instanceof Date,
131
- function: (value) => typeof value === "function",
132
- null: (value) => value === null,
133
- number: (value) => typeof value === "number",
134
- object: (value) => typeof value === "object" && value !== null,
135
- string: (value) => typeof value === "string",
136
- symbol: (value) => typeof value === "symbol",
137
- undefined: (value) => value === void 0
138
- };
139
- //#endregion
140
- export { validateObject };
@@ -1,219 +0,0 @@
1
- import {isConstructor, isPlainObject} from '@oscarpalmer/atoms/is';
2
- import type {PlainObject} from '@oscarpalmer/atoms/models';
3
- import {join} from '@oscarpalmer/atoms/string';
4
- import {
5
- PROPERTY_REQUIRED,
6
- PROPERTY_TYPE,
7
- PROPERTY_VALIDATORS,
8
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY,
9
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED,
10
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE,
11
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED,
12
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE,
13
- SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY,
14
- SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE,
15
- SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE,
16
- TEMPLATE_PATTERN,
17
- TYPE_ALL,
18
- TYPE_UNDEFINED,
19
- VALIDATABLE_TYPES,
20
- } from '../constants';
21
- import {instanceOf, isSchematic} from '../helpers';
22
- import type {ValueName} from '../models/misc.model';
23
- import {
24
- SchematicError,
25
- type ValidatedProperty,
26
- type ValidatedPropertyType,
27
- type ValidatedPropertyValidators,
28
- } from '../models/validation.model';
29
-
30
- function getDisallowedProperty(obj: PlainObject): string | undefined {
31
- if (PROPERTY_REQUIRED in obj) {
32
- return PROPERTY_REQUIRED;
33
- }
34
-
35
- if (PROPERTY_TYPE in obj) {
36
- return PROPERTY_TYPE;
37
- }
38
-
39
- if (PROPERTY_VALIDATORS in obj) {
40
- return PROPERTY_VALIDATORS;
41
- }
42
- }
43
-
44
- export function getProperties(
45
- original: PlainObject,
46
- prefix?: string,
47
- fromType?: boolean,
48
- ): ValidatedProperty[] {
49
- if (Object.keys(original).length === 0) {
50
- throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY);
51
- }
52
-
53
- if (fromType ?? false) {
54
- const property = getDisallowedProperty(original);
55
-
56
- if (property != null) {
57
- throw new SchematicError(
58
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace(
59
- TEMPLATE_PATTERN,
60
- prefix!,
61
- ).replace(TEMPLATE_PATTERN, property),
62
- );
63
- }
64
- }
65
-
66
- const keys = Object.keys(original);
67
- const keysLength = keys.length;
68
-
69
- const properties: ValidatedProperty[] = [];
70
-
71
- for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
72
- const key = keys[keyIndex];
73
-
74
- const prefixed = join([prefix, key], '.');
75
- const value = original[key];
76
-
77
- if (value == null) {
78
- throw new SchematicError(
79
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace(TEMPLATE_PATTERN, prefixed),
80
- );
81
- }
82
-
83
- const types: ValidatedPropertyType[] = [];
84
-
85
- let required = true;
86
- let validators: ValidatedPropertyValidators = {};
87
-
88
- if (isPlainObject(value)) {
89
- required = getRequired(key, value) ?? required;
90
- validators = getValidators(value[PROPERTY_VALIDATORS]);
91
-
92
- const hasType = PROPERTY_TYPE in value;
93
-
94
- types.push(...getTypes(key, hasType ? value[PROPERTY_TYPE] : value, prefix, hasType));
95
- } else {
96
- types.push(...getTypes(key, value, prefix));
97
- }
98
-
99
- if (!required && !types.includes(TYPE_UNDEFINED)) {
100
- types.push(TYPE_UNDEFINED);
101
- }
102
-
103
- properties.push({
104
- types,
105
- validators,
106
- key: {
107
- full: prefixed,
108
- short: key,
109
- },
110
- required: required && !types.includes(TYPE_UNDEFINED),
111
- });
112
- }
113
-
114
- return properties;
115
- }
116
-
117
- function getRequired(key: string, obj: PlainObject): boolean | undefined {
118
- if (!(PROPERTY_REQUIRED in obj)) {
119
- return;
120
- }
121
-
122
- if (typeof obj[PROPERTY_REQUIRED] !== 'boolean') {
123
- throw new SchematicError(
124
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED.replace(TEMPLATE_PATTERN, key),
125
- );
126
- }
127
-
128
- return obj[PROPERTY_REQUIRED];
129
- }
130
-
131
- function getTypes(
132
- key: string,
133
- original: unknown,
134
- prefix?: string,
135
- fromType?: boolean,
136
- ): ValidatedPropertyType[] {
137
- const array = Array.isArray(original) ? original : [original];
138
- const {length} = array;
139
-
140
- const types: ValidatedPropertyType[] = [];
141
-
142
- for (let index = 0; index < length; index += 1) {
143
- const value = array[index];
144
-
145
- switch (true) {
146
- case typeof value === 'function':
147
- types.push(isConstructor(value) ? instanceOf(value) : value);
148
- break;
149
-
150
- case isPlainObject(value):
151
- types.push(getProperties(value, join([prefix, key], '.'), fromType));
152
- break;
153
-
154
- case isSchematic(value):
155
- types.push(value);
156
- break;
157
-
158
- case TYPE_ALL.has(value as never):
159
- types.push(value as never);
160
- break;
161
-
162
- default:
163
- throw new SchematicError(
164
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace(
165
- TEMPLATE_PATTERN,
166
- join([prefix, key], '.'),
167
- ),
168
- );
169
- }
170
- }
171
-
172
- if (types.length === 0) {
173
- throw new SchematicError(
174
- SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace(
175
- TEMPLATE_PATTERN,
176
- join([prefix, key], '.'),
177
- ),
178
- );
179
- }
180
-
181
- return types;
182
- }
183
-
184
- function getValidators(original: unknown): ValidatedPropertyValidators {
185
- const validators: ValidatedPropertyValidators = {};
186
-
187
- if (original == null) {
188
- return validators;
189
- }
190
-
191
- if (!isPlainObject(original)) {
192
- throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
193
- }
194
-
195
- const keys = Object.keys(original);
196
- const {length} = keys;
197
-
198
- for (let index = 0; index < length; index += 1) {
199
- const key = keys[index];
200
-
201
- if (!VALIDATABLE_TYPES.has(key as never)) {
202
- throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace(TEMPLATE_PATTERN, key));
203
- }
204
-
205
- const value = (original as PlainObject)[key];
206
-
207
- validators[key as ValueName] = (Array.isArray(value) ? value : [value]).map(item => {
208
- if (typeof item !== 'function') {
209
- throw new TypeError(
210
- SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace(TEMPLATE_PATTERN, key),
211
- );
212
- }
213
-
214
- return item;
215
- });
216
- }
217
-
218
- return validators;
219
- }
@@ -1,253 +0,0 @@
1
- import {isPlainObject} from '@oscarpalmer/atoms/is';
2
- import type {GenericCallback} from '@oscarpalmer/atoms/models';
3
- import {join} from '@oscarpalmer/atoms/string';
4
- import {TYPE_OBJECT} from '../constants';
5
- import {
6
- getInvalidInputMessage,
7
- getInvalidMissingMessage,
8
- getInvalidTypeMessage,
9
- getInvalidValidatorMessage,
10
- getUnknownKeysMessage,
11
- isSchematic,
12
- } from '../helpers';
13
- import type {ValueName} from '../models/misc.model';
14
- import {
15
- ValidationError,
16
- type ValidatedProperty,
17
- type ValidatedPropertyType,
18
- type ValidationInformation,
19
- type ValidationOptionsExtended,
20
- } from '../models/validation.model';
21
- import {schematicProperties, type Schematic} from '../schematic';
22
-
23
- function validateNamed(
24
- property: ValidatedProperty,
25
- name: ValueName,
26
- value: unknown,
27
- validation: ValidationInformation[],
28
- ): boolean {
29
- if (!validators[name](value)) {
30
- return false;
31
- }
32
-
33
- const propertyValidators = property.validators[name];
34
-
35
- if (propertyValidators == null || propertyValidators.length === 0) {
36
- return true;
37
- }
38
-
39
- const {length} = propertyValidators;
40
-
41
- for (let index = 0; index < length; index += 1) {
42
- const validator = propertyValidators[index];
43
-
44
- if (!validator(value)) {
45
- validation.push({
46
- value,
47
- key: {...property.key},
48
- message: getInvalidValidatorMessage(property, name, index, length),
49
- validator: validator as GenericCallback,
50
- });
51
-
52
- return false;
53
- }
54
- }
55
-
56
- return true;
57
- }
58
-
59
- export function validateObject(
60
- obj: unknown,
61
- properties: ValidatedProperty[],
62
- options: ValidationOptionsExtended,
63
- origin?: ValidatedProperty,
64
- validation?: ValidationInformation[],
65
- ): boolean | ValidationInformation[] {
66
- if (!isPlainObject(obj)) {
67
- const key = origin == null ? {full: '', short: ''} : {...origin.key};
68
-
69
- const information = {
70
- key,
71
- message:
72
- origin == null
73
- ? getInvalidInputMessage(obj)
74
- : getInvalidTypeMessage(
75
- {
76
- ...origin,
77
- key,
78
- },
79
- obj,
80
- ),
81
- value: obj,
82
- };
83
-
84
- if (options.reporting.throw) {
85
- throw new ValidationError([information]);
86
- }
87
-
88
- validation?.push(information);
89
-
90
- return options.reporting.none ? false : [information];
91
- }
92
-
93
- if (options.strict) {
94
- const objKeys = Object.keys(obj);
95
-
96
- const propertiesKeys = new Set(properties.map(property => property.key.short));
97
-
98
- const unknownKeys = objKeys.filter(key => !propertiesKeys.has(key));
99
-
100
- if (unknownKeys.length > 0) {
101
- const key = origin == null ? {full: '', short: ''} : {...origin.key};
102
-
103
- const information: ValidationInformation = {
104
- key,
105
- message: getUnknownKeysMessage(unknownKeys.map(key => join([origin?.key.full, key], '.'))),
106
- value: obj,
107
- };
108
-
109
- if (options.reporting.throw) {
110
- throw new ValidationError([information]);
111
- }
112
-
113
- validation?.push(information);
114
-
115
- return options.reporting.none ? false : [information];
116
- }
117
- }
118
-
119
- const allInformation: ValidationInformation[] = [];
120
-
121
- const propertiesLength = properties.length;
122
-
123
- outer: for (let propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex += 1) {
124
- let property = properties[propertyIndex];
125
-
126
- property = {
127
- ...property,
128
- key: {
129
- full: join([origin?.key.full, property.key.short], '.'),
130
- short: property.key.short,
131
- },
132
- };
133
-
134
- const {key, required, types} = property;
135
-
136
- const value = obj[key.short];
137
-
138
- if (value === undefined && required) {
139
- const information: ValidationInformation = {
140
- value,
141
- key: {...key},
142
- message: getInvalidMissingMessage(property),
143
- };
144
-
145
- if (options.reporting.throw && validation == null) {
146
- throw new ValidationError([information]);
147
- }
148
-
149
- if (validation != null) {
150
- validation.push(information);
151
- }
152
-
153
- if (options.reporting.all) {
154
- allInformation.push(information);
155
-
156
- continue;
157
- }
158
-
159
- return options.reporting.none ? false : [information];
160
- }
161
-
162
- const typesLength = types.length;
163
-
164
- const information: ValidationInformation[] = [];
165
-
166
- for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
167
- const type = types[typeIndex];
168
-
169
- if (validateValue(type, property, value, options, information)) {
170
- continue outer;
171
- }
172
- }
173
-
174
- if (information.length === 0) {
175
- information.push({
176
- value,
177
- key: {...key},
178
- message: getInvalidTypeMessage(property, value),
179
- });
180
- }
181
-
182
- if (options.reporting.throw && validation == null) {
183
- throw new ValidationError(information);
184
- }
185
-
186
- validation?.push(...information);
187
-
188
- if (options.reporting.all) {
189
- allInformation.push(...information);
190
-
191
- continue;
192
- }
193
-
194
- return options.reporting.none ? false : information;
195
- }
196
-
197
- return options.reporting.none || allInformation.length === 0 ? true : allInformation;
198
- }
199
-
200
- function validateSchematic(
201
- property: ValidatedProperty,
202
- schematic: Schematic<unknown>,
203
- value: unknown,
204
- options: ValidationOptionsExtended,
205
- validation: ValidationInformation[],
206
- ): boolean {
207
- const properties = schematicProperties.get(schematic)!;
208
-
209
- const result = validateObject(value, properties, options, property, validation);
210
-
211
- return typeof result === 'boolean' ? result : result.length === 0;
212
- }
213
-
214
- function validateValue(
215
- type: ValidatedPropertyType,
216
- property: ValidatedProperty,
217
- value: unknown,
218
- options: ValidationOptionsExtended,
219
- validation: ValidationInformation[],
220
- ): boolean {
221
- switch (true) {
222
- case typeof type === 'function':
223
- return (type as GenericCallback)(value);
224
-
225
- case Array.isArray(type): {
226
- const validated = validateObject(value, type, options, property, validation);
227
-
228
- return typeof validated === 'boolean' ? validated : false;
229
- }
230
-
231
- case isSchematic(type):
232
- return validateSchematic(property, type, value, options, validation);
233
-
234
- default:
235
- return validateNamed(property, type as ValueName, value, validation);
236
- }
237
- }
238
-
239
- //
240
-
241
- const validators: Record<ValueName, (value: unknown) => boolean> = {
242
- array: Array.isArray,
243
- bigint: value => typeof value === 'bigint',
244
- boolean: value => typeof value === 'boolean',
245
- date: value => value instanceof Date,
246
- function: value => typeof value === 'function',
247
- null: value => value === null,
248
- number: value => typeof value === 'number',
249
- object: value => typeof value === TYPE_OBJECT && value !== null,
250
- string: value => typeof value === 'string',
251
- symbol: value => typeof value === 'symbol',
252
- undefined: value => value === undefined,
253
- };