@oscarpalmer/jhunal 0.21.0 → 0.23.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 (47) hide show
  1. package/dist/constants.d.mts +7 -3
  2. package/dist/constants.mjs +34 -12
  3. package/dist/helpers/message.helper.d.mts +11 -0
  4. package/dist/helpers/message.helper.mjs +70 -0
  5. package/dist/helpers/misc.helper.d.mts +22 -0
  6. package/dist/helpers/misc.helper.mjs +56 -0
  7. package/dist/index.d.mts +318 -328
  8. package/dist/index.mjs +324 -295
  9. package/dist/models/schema.plain.model.d.mts +2 -8
  10. package/dist/models/validation.model.d.mts +26 -59
  11. package/dist/schematic.d.mts +28 -10
  12. package/dist/schematic.mjs +15 -16
  13. package/dist/validator/base.validator.d.mts +6 -0
  14. package/dist/validator/base.validator.mjs +19 -0
  15. package/dist/validator/function.validator.d.mts +6 -0
  16. package/dist/validator/function.validator.mjs +9 -0
  17. package/dist/validator/named.handler.d.mts +6 -0
  18. package/dist/validator/named.handler.mjs +22 -0
  19. package/dist/validator/named.validator.d.mts +7 -0
  20. package/dist/validator/named.validator.mjs +39 -0
  21. package/dist/validator/object.validator.d.mts +7 -0
  22. package/dist/validator/object.validator.mjs +167 -0
  23. package/dist/validator/schematic.validator.d.mts +7 -0
  24. package/dist/validator/schematic.validator.mjs +16 -0
  25. package/package.json +1 -1
  26. package/src/constants.ts +42 -10
  27. package/src/helpers/message.helper.ts +152 -0
  28. package/src/helpers/misc.helper.ts +93 -0
  29. package/src/index.ts +7 -2
  30. package/src/models/schema.plain.model.ts +1 -8
  31. package/src/models/validation.model.ts +55 -77
  32. package/src/schematic.ts +49 -27
  33. package/src/validator/base.validator.ts +31 -0
  34. package/src/validator/function.validator.ts +9 -0
  35. package/src/validator/named.handler.ts +50 -0
  36. package/src/validator/named.validator.ts +62 -0
  37. package/src/validator/object.validator.ts +340 -0
  38. package/src/validator/schematic.validator.ts +25 -0
  39. package/dist/helpers.d.mts +0 -28
  40. package/dist/helpers.mjs +0 -119
  41. package/dist/validation/property.validation.d.mts +0 -7
  42. package/dist/validation/property.validation.mjs +0 -92
  43. package/dist/validation/value.validation.d.mts +0 -7
  44. package/dist/validation/value.validation.mjs +0 -162
  45. package/src/helpers.ts +0 -246
  46. package/src/validation/property.validation.ts +0 -217
  47. package/src/validation/value.validation.ts +0 -293
@@ -1,28 +0,0 @@
1
- import { ReportingInformation, ValidatedPropertyType, ValidationParameters } from "./models/validation.model.mjs";
2
- import { Schematic } from "./schematic.mjs";
3
- import { ValueName } from "./models/misc.model.mjs";
4
- import { Constructor } from "@oscarpalmer/atoms/models";
5
-
6
- //#region src/helpers.d.ts
7
- declare function getInvalidInputMessage(actual: unknown): string;
8
- declare function getInvalidMissingMessage(key: string, types: ValidatedPropertyType[]): string;
9
- declare function getInvalidTypeMessage(key: string, types: ValidatedPropertyType[], actual: unknown): string;
10
- declare function getInvalidValidatorMessage(key: string, type: ValueName, index: number, length: number): string;
11
- declare function getParameters(input?: unknown): ValidationParameters;
12
- declare function getReporting(value: unknown): ReportingInformation;
13
- declare function getUnknownKeysMessage(keys: string[]): string;
14
- /**
15
- * Creates a validator function for a given constructor
16
- * @param constructor - Constructor to check against
17
- * @throws Will throw a `TypeError` if the provided argument is not a valid constructor
18
- * @returns Validator function that checks if a value is an instance of the constructor
19
- */
20
- declare function instanceOf<Instance>(constructor: Constructor<Instance>): (value: unknown) => value is Instance;
21
- /**
22
- * Is the value a schematic?
23
- * @param value Value to check
24
- * @returns `true` if the value is a schematic, `false` otherwise
25
- */
26
- declare function isSchematic(value: unknown): value is Schematic<never>;
27
- //#endregion
28
- export { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getParameters, getReporting, getUnknownKeysMessage, instanceOf, isSchematic };
package/dist/helpers.mjs DELETED
@@ -1,119 +0,0 @@
1
- import { CONJUNCTION_AND, CONJUNCTION_AND_COMMA, CONJUNCTION_OR, CONJUNCTION_OR_COMMA, MESSAGE_CONSTRUCTOR, NAME_SCHEMATIC, REPORTING_FIRST, REPORTING_NONE, REPORTING_THROW, REPORTING_TYPES, TYPE_ARRAY, TYPE_NULL, TYPE_OBJECT, TYPE_UNDEFINED, VALIDATION_MESSAGE_INVALID_INPUT, VALIDATION_MESSAGE_INVALID_REQUIRED, VALIDATION_MESSAGE_INVALID_TYPE, VALIDATION_MESSAGE_INVALID_VALUE, VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX, VALIDATION_MESSAGE_UNKNOWN_KEYS } from "./constants.mjs";
2
- import { isConstructor, isPlainObject } from "@oscarpalmer/atoms/is";
3
- //#region src/helpers.ts
4
- function getInvalidInputMessage(actual) {
5
- return VALIDATION_MESSAGE_INVALID_INPUT.replace("<>", getValueType(actual));
6
- }
7
- function getInvalidMissingMessage(key, types) {
8
- let message = VALIDATION_MESSAGE_INVALID_REQUIRED.replace("<>", renderTypes(types));
9
- message = message.replace("<>", key);
10
- return message;
11
- }
12
- function getInvalidTypeMessage(key, types, actual) {
13
- let message = VALIDATION_MESSAGE_INVALID_TYPE.replace("<>", renderTypes(types));
14
- message = message.replace("<>", key);
15
- message = message.replace("<>", getValueType(actual));
16
- return message;
17
- }
18
- function getInvalidValidatorMessage(key, type, index, length) {
19
- let message = VALIDATION_MESSAGE_INVALID_VALUE.replace("<>", key);
20
- message = message.replace("<>", type);
21
- if (length > 1) message += VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX.replace("<>", String(index));
22
- return message;
23
- }
24
- function getParameters(input) {
25
- if (typeof input === "boolean") return {
26
- output: {},
27
- reporting: getReporting(REPORTING_NONE),
28
- strict: input
29
- };
30
- if (REPORTING_TYPES.has(input)) return {
31
- output: {},
32
- reporting: getReporting(input),
33
- strict: false
34
- };
35
- const options = isPlainObject(input) ? input : {};
36
- return {
37
- output: {},
38
- reporting: getReporting(options.errors),
39
- strict: typeof options.strict === "boolean" ? options.strict : false
40
- };
41
- }
42
- function getPropertyType(original) {
43
- if (typeof original === "function") return "a validated value";
44
- if (Array.isArray(original)) return `'${TYPE_OBJECT}'`;
45
- if (isSchematic(original)) return `a ${NAME_SCHEMATIC}`;
46
- return `'${String(original)}'`;
47
- }
48
- function getReporting(value) {
49
- const type = REPORTING_TYPES.has(value) ? value : REPORTING_NONE;
50
- return {
51
- type,
52
- ["all"]: type === "all",
53
- [REPORTING_FIRST]: type === REPORTING_FIRST,
54
- [REPORTING_NONE]: type === REPORTING_NONE,
55
- [REPORTING_THROW]: type === REPORTING_THROW
56
- };
57
- }
58
- function getUnknownKeysMessage(keys) {
59
- return VALIDATION_MESSAGE_UNKNOWN_KEYS.replace("<>", renderKeys(keys));
60
- }
61
- function getValueType(value) {
62
- const valueType = typeof value;
63
- switch (true) {
64
- case value === null: return `'${TYPE_NULL}'`;
65
- case value === void 0: return `'${TYPE_UNDEFINED}'`;
66
- case valueType !== TYPE_OBJECT: return `'${valueType}'`;
67
- case Array.isArray(value): return `'${TYPE_ARRAY}'`;
68
- case isPlainObject(value): return `'${TYPE_OBJECT}'`;
69
- case isSchematic(value): return `a ${NAME_SCHEMATIC}`;
70
- default: return value.constructor.name;
71
- }
72
- }
73
- /**
74
- * Creates a validator function for a given constructor
75
- * @param constructor - Constructor to check against
76
- * @throws Will throw a `TypeError` if the provided argument is not a valid constructor
77
- * @returns Validator function that checks if a value is an instance of the constructor
78
- */
79
- function instanceOf(constructor) {
80
- if (!isConstructor(constructor)) throw new TypeError(MESSAGE_CONSTRUCTOR);
81
- return (value) => {
82
- return value instanceof constructor;
83
- };
84
- }
85
- /**
86
- * Is the value a schematic?
87
- * @param value Value to check
88
- * @returns `true` if the value is a schematic, `false` otherwise
89
- */
90
- function isSchematic(value) {
91
- return typeof value === "object" && value !== null && "$schematic" in value && value["$schematic"] === true;
92
- }
93
- function renderKeys(keys) {
94
- return renderParts(keys.map((key) => `'${key}'`), CONJUNCTION_AND, CONJUNCTION_AND_COMMA);
95
- }
96
- function renderParts(parts, delimiterShort, delimiterLong) {
97
- const { length } = parts;
98
- if (length === 1) return parts[0];
99
- let rendered = "";
100
- for (let index = 0; index < length; index += 1) {
101
- rendered += parts[index];
102
- if (index < length - 2) rendered += ", ";
103
- else if (index === length - 2) rendered += parts.length > 2 ? delimiterLong : delimiterShort;
104
- }
105
- return rendered;
106
- }
107
- function renderTypes(types) {
108
- const unique = /* @__PURE__ */ new Set();
109
- const parts = [];
110
- for (let index = 0; index < types.length; index += 1) {
111
- const rendered = getPropertyType(types[index]);
112
- if (unique.has(rendered)) continue;
113
- unique.add(rendered);
114
- parts.push(rendered);
115
- }
116
- return renderParts(parts, CONJUNCTION_OR, CONJUNCTION_OR_COMMA);
117
- }
118
- //#endregion
119
- export { getInvalidInputMessage, getInvalidMissingMessage, getInvalidTypeMessage, getInvalidValidatorMessage, getParameters, getReporting, getUnknownKeysMessage, instanceOf, isSchematic };
@@ -1,7 +0,0 @@
1
- import { ValidatedProperty } from "../models/validation.model.mjs";
2
- import { PlainObject } from "@oscarpalmer/atoms/models";
3
-
4
- //#region src/validation/property.validation.d.ts
5
- declare function getProperties(original: PlainObject, prefix?: string, fromType?: boolean): ValidatedProperty[];
6
- //#endregion
7
- export { getProperties };
@@ -1,92 +0,0 @@
1
- import { PROPERTY_REQUIRED, PROPERTY_TYPE, PROPERTY_VALIDATORS, SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED, SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE, SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE, TYPE_ALL, TYPE_UNDEFINED, VALIDATABLE_TYPES } from "../constants.mjs";
2
- import { instanceOf, isSchematic } from "../helpers.mjs";
3
- import { SchematicError } from "../models/validation.model.mjs";
4
- import { isConstructor, isPlainObject } from "@oscarpalmer/atoms/is";
5
- import { join } from "@oscarpalmer/atoms/string";
6
- //#region src/validation/property.validation.ts
7
- function getDisallowedProperty(obj) {
8
- if ("$required" in obj) return PROPERTY_REQUIRED;
9
- if ("$type" in obj) return PROPERTY_TYPE;
10
- if ("$validators" in obj) return PROPERTY_VALIDATORS;
11
- }
12
- function getProperties(original, prefix, fromType) {
13
- if (Object.keys(original).length === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_EMPTY);
14
- if (fromType ?? false) {
15
- const property = getDisallowedProperty(original);
16
- if (property != null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_DISALLOWED.replace("<>", prefix).replace("<>", property));
17
- }
18
- const keys = Object.keys(original);
19
- const keysLength = keys.length;
20
- const properties = [];
21
- for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
22
- const key = keys[keyIndex];
23
- const value = original[key];
24
- if (value == null) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_NULLABLE.replace("<>", join([prefix, key], ".")));
25
- const types = [];
26
- let required = true;
27
- let validators = {};
28
- if (isPlainObject(value)) {
29
- required = getRequired(key, value) ?? required;
30
- validators = getValidators(value[PROPERTY_VALIDATORS]);
31
- const hasType = PROPERTY_TYPE in value;
32
- types.push(...getTypes(key, hasType ? value[PROPERTY_TYPE] : value, prefix, hasType));
33
- } else types.push(...getTypes(key, value, prefix));
34
- if (!required && !types.includes("undefined")) types.push(TYPE_UNDEFINED);
35
- properties.push({
36
- key,
37
- types,
38
- validators,
39
- required: required && !types.includes("undefined")
40
- });
41
- }
42
- return properties;
43
- }
44
- function getRequired(key, obj) {
45
- if (!("$required" in obj)) return;
46
- if (typeof obj["$required"] !== "boolean") throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_REQUIRED.replace("<>", key));
47
- return obj[PROPERTY_REQUIRED];
48
- }
49
- function getTypes(key, original, prefix, fromType) {
50
- const array = Array.isArray(original) ? original : [original];
51
- const { length } = array;
52
- const types = [];
53
- for (let index = 0; index < length; index += 1) {
54
- const value = array[index];
55
- switch (true) {
56
- case typeof value === "function":
57
- types.push(isConstructor(value) ? instanceOf(value) : value);
58
- break;
59
- case isPlainObject(value):
60
- types.push(getProperties(value, join([prefix, key], "."), fromType));
61
- break;
62
- case isSchematic(value):
63
- types.push(value);
64
- break;
65
- case TYPE_ALL.has(value):
66
- types.push(value);
67
- break;
68
- default: throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", join([prefix, key], ".")));
69
- }
70
- }
71
- if (types.length === 0) throw new SchematicError(SCHEMATIC_MESSAGE_SCHEMA_INVALID_PROPERTY_TYPE.replace("<>", join([prefix, key], ".")));
72
- return types;
73
- }
74
- function getValidators(original) {
75
- const validators = {};
76
- if (original == null) return validators;
77
- if (!isPlainObject(original)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_TYPE);
78
- const keys = Object.keys(original);
79
- const { length } = keys;
80
- for (let index = 0; index < length; index += 1) {
81
- const key = keys[index];
82
- if (!VALIDATABLE_TYPES.has(key)) throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_KEY.replace("<>", key));
83
- const value = original[key];
84
- validators[key] = (Array.isArray(value) ? value : [value]).map((item) => {
85
- if (typeof item !== "function") throw new TypeError(SCHEMATIC_MESSAGE_VALIDATOR_INVALID_VALUE.replace("<>", key));
86
- return item;
87
- });
88
- }
89
- return validators;
90
- }
91
- //#endregion
92
- export { getProperties };
@@ -1,7 +0,0 @@
1
- import { ValidatedProperty, ValidationInformation, ValidationParameters } from "../models/validation.model.mjs";
2
- import { PlainObject } from "@oscarpalmer/atoms/models";
3
-
4
- //#region src/validation/value.validation.d.ts
5
- declare function validateObject(obj: unknown, properties: ValidatedProperty[], parameters: ValidationParameters, get: boolean): PlainObject | ValidationInformation[] | undefined;
6
- //#endregion
7
- export { validateObject };
@@ -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 };
package/src/helpers.ts DELETED
@@ -1,246 +0,0 @@
1
- import {isConstructor, isPlainObject} from '@oscarpalmer/atoms/is';
2
- import type {Constructor} from '@oscarpalmer/atoms/models';
3
- import {
4
- COMMA,
5
- CONJUNCTION_AND,
6
- CONJUNCTION_AND_COMMA,
7
- CONJUNCTION_OR,
8
- CONJUNCTION_OR_COMMA,
9
- MESSAGE_CONSTRUCTOR,
10
- NAME_SCHEMATIC,
11
- PROPERTY_SCHEMATIC,
12
- REPORTING_ALL,
13
- REPORTING_FIRST,
14
- REPORTING_NONE,
15
- REPORTING_THROW,
16
- REPORTING_TYPES,
17
- TEMPLATE_PATTERN,
18
- TYPE_ARRAY,
19
- TYPE_NULL,
20
- TYPE_OBJECT,
21
- TYPE_UNDEFINED,
22
- VALIDATION_MESSAGE_INVALID_INPUT,
23
- VALIDATION_MESSAGE_INVALID_REQUIRED,
24
- VALIDATION_MESSAGE_INVALID_TYPE,
25
- VALIDATION_MESSAGE_INVALID_VALUE,
26
- VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX,
27
- VALIDATION_MESSAGE_UNKNOWN_KEYS,
28
- } from './constants';
29
- import type {ValueName} from './models/misc.model';
30
- import type {
31
- ReportingInformation,
32
- ReportingType,
33
- ValidatedProperty,
34
- ValidatedPropertyType,
35
- ValidationParameters,
36
- } from './models/validation.model';
37
- import type {Schematic} from './schematic';
38
-
39
- export function getInvalidInputMessage(actual: unknown): string {
40
- return VALIDATION_MESSAGE_INVALID_INPUT.replace(TEMPLATE_PATTERN, getValueType(actual));
41
- }
42
-
43
- export function getInvalidMissingMessage(key: string, types: ValidatedPropertyType[]): string {
44
- let message = VALIDATION_MESSAGE_INVALID_REQUIRED.replace(TEMPLATE_PATTERN, renderTypes(types));
45
-
46
- message = message.replace(TEMPLATE_PATTERN, key);
47
-
48
- return message;
49
- }
50
-
51
- export function getInvalidTypeMessage(
52
- key: string,
53
- types: ValidatedPropertyType[],
54
- actual: unknown,
55
- ): string {
56
- let message = VALIDATION_MESSAGE_INVALID_TYPE.replace(TEMPLATE_PATTERN, renderTypes(types));
57
-
58
- message = message.replace(TEMPLATE_PATTERN, key);
59
- message = message.replace(TEMPLATE_PATTERN, getValueType(actual));
60
-
61
- return message;
62
- }
63
-
64
- export function getInvalidValidatorMessage(
65
- key: string,
66
- type: ValueName,
67
- index: number,
68
- length: number,
69
- ): string {
70
- let message = VALIDATION_MESSAGE_INVALID_VALUE.replace(TEMPLATE_PATTERN, key);
71
-
72
- message = message.replace(TEMPLATE_PATTERN, type);
73
-
74
- if (length > 1) {
75
- message += VALIDATION_MESSAGE_INVALID_VALUE_SUFFIX.replace(TEMPLATE_PATTERN, String(index));
76
- }
77
-
78
- return message;
79
- }
80
-
81
- export function getParameters(input?: unknown): ValidationParameters {
82
- if (typeof input === 'boolean') {
83
- return {
84
- output: {},
85
- reporting: getReporting(REPORTING_NONE),
86
- strict: input,
87
- };
88
- }
89
-
90
- if (REPORTING_TYPES.has(input as ReportingType)) {
91
- return {
92
- output: {},
93
- reporting: getReporting(input as ReportingType),
94
- strict: false,
95
- };
96
- }
97
-
98
- const options = isPlainObject(input) ? input : {};
99
-
100
- return {
101
- output: {},
102
- reporting: getReporting(options.errors),
103
- strict: typeof options.strict === 'boolean' ? options.strict : false,
104
- };
105
- }
106
-
107
- function getPropertyType(original: ValidatedPropertyType): string {
108
- if (typeof original === 'function') {
109
- return 'a validated value';
110
- }
111
-
112
- if (Array.isArray(original)) {
113
- return `'${TYPE_OBJECT}'`;
114
- }
115
-
116
- if (isSchematic(original)) {
117
- return `a ${NAME_SCHEMATIC}`;
118
- }
119
-
120
- return `'${String(original)}'`;
121
- }
122
-
123
- export function getReporting(value: unknown): ReportingInformation {
124
- const type = REPORTING_TYPES.has(value as ReportingType)
125
- ? (value as ReportingType)
126
- : REPORTING_NONE;
127
-
128
- return {
129
- type,
130
- [REPORTING_ALL]: type === REPORTING_ALL,
131
- [REPORTING_FIRST]: type === REPORTING_FIRST,
132
- [REPORTING_NONE]: type === REPORTING_NONE,
133
- [REPORTING_THROW]: type === REPORTING_THROW,
134
- } as ReportingInformation;
135
- }
136
-
137
- export function getUnknownKeysMessage(keys: string[]): string {
138
- return VALIDATION_MESSAGE_UNKNOWN_KEYS.replace(TEMPLATE_PATTERN, renderKeys(keys));
139
- }
140
-
141
- function getValueType(value: unknown): string {
142
- const valueType = typeof value;
143
-
144
- switch (true) {
145
- case value === null:
146
- return `'${TYPE_NULL}'`;
147
-
148
- case value === undefined:
149
- return `'${TYPE_UNDEFINED}'`;
150
-
151
- case valueType !== TYPE_OBJECT:
152
- return `'${valueType}'`;
153
-
154
- case Array.isArray(value):
155
- return `'${TYPE_ARRAY}'`;
156
-
157
- case isPlainObject(value):
158
- return `'${TYPE_OBJECT}'`;
159
-
160
- case isSchematic(value):
161
- return `a ${NAME_SCHEMATIC}`;
162
-
163
- default:
164
- return value.constructor.name;
165
- }
166
- }
167
-
168
- /**
169
- * Creates a validator function for a given constructor
170
- * @param constructor - Constructor to check against
171
- * @throws Will throw a `TypeError` if the provided argument is not a valid constructor
172
- * @returns Validator function that checks if a value is an instance of the constructor
173
- */
174
- export function instanceOf<Instance>(
175
- constructor: Constructor<Instance>,
176
- ): (value: unknown) => value is Instance {
177
- if (!isConstructor(constructor)) {
178
- throw new TypeError(MESSAGE_CONSTRUCTOR);
179
- }
180
-
181
- return (value: unknown): value is Instance => {
182
- return value instanceof constructor;
183
- };
184
- }
185
-
186
- /**
187
- * Is the value a schematic?
188
- * @param value Value to check
189
- * @returns `true` if the value is a schematic, `false` otherwise
190
- */
191
- export function isSchematic(value: unknown): value is Schematic<never> {
192
- return (
193
- typeof value === 'object' &&
194
- value !== null &&
195
- PROPERTY_SCHEMATIC in value &&
196
- value[PROPERTY_SCHEMATIC] === true
197
- );
198
- }
199
-
200
- function renderKeys(keys: string[]): string {
201
- return renderParts(
202
- keys.map(key => `'${key}'`),
203
- CONJUNCTION_AND,
204
- CONJUNCTION_AND_COMMA,
205
- );
206
- }
207
-
208
- function renderParts(parts: string[], delimiterShort: string, delimiterLong: string): string {
209
- const {length} = parts;
210
-
211
- if (length === 1) {
212
- return parts[0];
213
- }
214
-
215
- let rendered = '';
216
-
217
- for (let index = 0; index < length; index += 1) {
218
- rendered += parts[index];
219
-
220
- if (index < length - 2) {
221
- rendered += COMMA;
222
- } else if (index === length - 2) {
223
- rendered += parts.length > 2 ? delimiterLong : delimiterShort;
224
- }
225
- }
226
-
227
- return rendered;
228
- }
229
-
230
- function renderTypes(types: ValidatedPropertyType[]): string {
231
- const unique = new Set<string>();
232
- const parts: string[] = [];
233
-
234
- for (let index = 0; index < types.length; index += 1) {
235
- const rendered = getPropertyType(types[index]);
236
-
237
- if (unique.has(rendered)) {
238
- continue;
239
- }
240
-
241
- unique.add(rendered);
242
- parts.push(rendered);
243
- }
244
-
245
- return renderParts(parts, CONJUNCTION_OR, CONJUNCTION_OR_COMMA);
246
- }