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