@itzworking/decorated-class 0.0.162 → 0.0.196
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.
- package/{dist → dist-cjs}/decorators/attribute/attribute.js +0 -16
- package/{dist → dist-cjs}/decorators/attribute/types/attribute-type.js +0 -1
- package/{dist → dist-cjs}/decorators/attribute/utils/update-attributes.js +0 -2
- package/{dist → dist-cjs}/decorators/validation/utils/register-constraint.js +0 -56
- package/dist-cjs/types.js +2 -0
- package/{dist → dist-cjs}/validator/list-validation-errors.js +0 -1
- package/dist-es/decorated-class.js +77 -0
- package/dist-es/decorators/attribute/attribute.js +29 -0
- package/dist-es/decorators/attribute/index.js +4 -0
- package/dist-es/decorators/attribute/is-attribute.js +4 -0
- package/dist-es/decorators/attribute/list-attributes.js +11 -0
- package/dist-es/decorators/attribute/symbol.js +1 -0
- package/dist-es/decorators/attribute/types/attribute-decorator.js +1 -0
- package/dist-es/decorators/attribute/types/attribute-definition.js +1 -0
- package/dist-es/decorators/attribute/types/attribute-type-alias.js +2 -0
- package/dist-es/decorators/attribute/types/attribute-type.js +10 -0
- package/dist-es/decorators/attribute/types/index.js +5 -0
- package/dist-es/decorators/attribute/types/primitive-type.js +8 -0
- package/dist-es/decorators/attribute/utils/index.js +1 -0
- package/dist-es/decorators/attribute/utils/update-attributes.js +27 -0
- package/dist-es/decorators/index.js +4 -0
- package/dist-es/decorators/validation/index.js +7 -0
- package/dist-es/decorators/validation/max.js +17 -0
- package/dist-es/decorators/validation/min.js +17 -0
- package/dist-es/decorators/validation/not-blank.js +11 -0
- package/dist-es/decorators/validation/not-null.js +2 -0
- package/dist-es/decorators/validation/pattern.js +12 -0
- package/dist-es/decorators/validation/types/index.js +2 -0
- package/dist-es/decorators/validation/types/validation-definition.js +1 -0
- package/dist-es/decorators/validation/types/validation-type.js +1 -0
- package/dist-es/decorators/validation/utils/index.js +1 -0
- package/dist-es/decorators/validation/utils/register-constraint.js +43 -0
- package/dist-es/errors/attributes-not-valid-error.js +9 -0
- package/dist-es/errors/index.js +3 -0
- package/dist-es/errors/invalid-target-error.js +6 -0
- package/dist-es/errors/unsupported-decorator-error.js +15 -0
- package/dist-es/index.js +5 -0
- package/dist-es/types.js +1 -0
- package/dist-es/validator/index.js +1 -0
- package/dist-es/validator/list-validation-errors.js +49 -0
- package/dist-es/validator/validate.js +8 -0
- package/dist-es/validator/validator.js +6 -0
- package/{dist → dist-types}/decorated-class.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/attribute.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/is-attribute.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/list-attributes.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/symbol.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/types/attribute-decorator.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/types/attribute-definition.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/types/attribute-type-alias.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/types/attribute-type.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/types/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/types/primitive-type.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/utils/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/attribute/utils/update-attributes.d.ts +0 -1
- package/{dist → dist-types}/decorators/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/max.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/min.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/not-blank.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/not-null.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/pattern.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/types/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/types/validation-definition.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/types/validation-type.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/utils/index.d.ts +0 -1
- package/{dist → dist-types}/decorators/validation/utils/register-constraint.d.ts +0 -1
- package/{dist → dist-types}/errors/attributes-not-valid-error.d.ts +0 -1
- package/{dist → dist-types}/errors/index.d.ts +0 -1
- package/{dist → dist-types}/errors/invalid-target-error.d.ts +0 -1
- package/{dist → dist-types}/errors/unsupported-decorator-error.d.ts +0 -1
- package/{dist → dist-types}/index.d.ts +0 -1
- package/{dist → dist-types}/types.d.ts +0 -1
- package/dist-types/validator/index.d.ts +1 -0
- package/{dist → dist-types}/validator/list-validation-errors.d.ts +0 -1
- package/{dist → dist-types}/validator/validate.d.ts +0 -1
- package/{dist → dist-types}/validator/validator.d.ts +0 -1
- package/package.json +21 -21
- package/dist/decorated-class.d.ts.map +0 -1
- package/dist/decorators/attribute/attribute.d.ts.map +0 -1
- package/dist/decorators/attribute/index.d.ts.map +0 -1
- package/dist/decorators/attribute/is-attribute.d.ts.map +0 -1
- package/dist/decorators/attribute/list-attributes.d.ts.map +0 -1
- package/dist/decorators/attribute/symbol.d.ts.map +0 -1
- package/dist/decorators/attribute/types/attribute-decorator.d.ts.map +0 -1
- package/dist/decorators/attribute/types/attribute-definition.d.ts.map +0 -1
- package/dist/decorators/attribute/types/attribute-type-alias.d.ts.map +0 -1
- package/dist/decorators/attribute/types/attribute-type.d.ts.map +0 -1
- package/dist/decorators/attribute/types/index.d.ts.map +0 -1
- package/dist/decorators/attribute/types/primitive-type.d.ts.map +0 -1
- package/dist/decorators/attribute/utils/index.d.ts.map +0 -1
- package/dist/decorators/attribute/utils/update-attributes.d.ts.map +0 -1
- package/dist/decorators/index.d.ts.map +0 -1
- package/dist/decorators/validation/index.d.ts.map +0 -1
- package/dist/decorators/validation/max.d.ts.map +0 -1
- package/dist/decorators/validation/min.d.ts.map +0 -1
- package/dist/decorators/validation/not-blank.d.ts.map +0 -1
- package/dist/decorators/validation/not-null.d.ts.map +0 -1
- package/dist/decorators/validation/pattern.d.ts.map +0 -1
- package/dist/decorators/validation/types/index.d.ts.map +0 -1
- package/dist/decorators/validation/types/validation-definition.d.ts.map +0 -1
- package/dist/decorators/validation/types/validation-type.d.ts.map +0 -1
- package/dist/decorators/validation/utils/index.d.ts.map +0 -1
- package/dist/decorators/validation/utils/register-constraint.d.ts.map +0 -1
- package/dist/errors/attributes-not-valid-error.d.ts.map +0 -1
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/invalid-target-error.d.ts.map +0 -1
- package/dist/errors/unsupported-decorator-error.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/validator/index.d.ts +0 -2
- package/dist/validator/index.d.ts.map +0 -1
- package/dist/validator/list-validation-errors.d.ts.map +0 -1
- package/dist/validator/validate.d.ts.map +0 -1
- package/dist/validator/validator.d.ts.map +0 -1
- /package/{dist → dist-cjs}/decorated-class.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/is-attribute.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/list-attributes.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/symbol.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/types/attribute-decorator.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/types/attribute-definition.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/types/attribute-type-alias.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/types/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/types/primitive-type.js +0 -0
- /package/{dist → dist-cjs}/decorators/attribute/utils/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/max.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/min.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/not-blank.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/not-null.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/pattern.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/types/index.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/types/validation-definition.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/types/validation-type.js +0 -0
- /package/{dist → dist-cjs}/decorators/validation/utils/index.js +0 -0
- /package/{dist → dist-cjs}/errors/attributes-not-valid-error.js +0 -0
- /package/{dist → dist-cjs}/errors/index.js +0 -0
- /package/{dist → dist-cjs}/errors/invalid-target-error.js +0 -0
- /package/{dist → dist-cjs}/errors/unsupported-decorator-error.js +0 -0
- /package/{dist → dist-cjs}/index.js +0 -0
- /package/{dist → dist-cjs}/validator/index.js +0 -0
- /package/{dist → dist-cjs}/validator/validate.js +0 -0
- /package/{dist → dist-cjs}/validator/validator.js +0 -0
|
@@ -31,19 +31,3 @@ const Attribute = (attributeType, options = {}) => {
|
|
|
31
31
|
return (0, utils_1.updateAttributes)(attributeType, isValidType, options);
|
|
32
32
|
};
|
|
33
33
|
exports.Attribute = Attribute;
|
|
34
|
-
// export const OldAttribute = {
|
|
35
|
-
// List: (type: PrimitiveType | any) =>
|
|
36
|
-
// updateAttributes(
|
|
37
|
-
// "List",
|
|
38
|
-
// (value: any) =>
|
|
39
|
-
// value === undefined || value === null || Array.isArray(value),
|
|
40
|
-
// type
|
|
41
|
-
// ),
|
|
42
|
-
// Object: (type: any) =>
|
|
43
|
-
// updateAttributes(
|
|
44
|
-
// "Object",
|
|
45
|
-
// (value: any) =>
|
|
46
|
-
// value === undefined || value === null || typeof value === type,
|
|
47
|
-
// type
|
|
48
|
-
// ),
|
|
49
|
-
// };
|
|
@@ -15,7 +15,6 @@ const updateAttributes = (attributeType, isValidType, options = {}) => (target,
|
|
|
15
15
|
attributeName,
|
|
16
16
|
attributeType,
|
|
17
17
|
constraints: [],
|
|
18
|
-
// isMethod: typeof target[attributeName] === "function",
|
|
19
18
|
nestedType: options?.nestedType,
|
|
20
19
|
isValidTypeInTarget,
|
|
21
20
|
};
|
|
@@ -23,7 +22,6 @@ const updateAttributes = (attributeType, isValidType, options = {}) => (target,
|
|
|
23
22
|
}
|
|
24
23
|
else {
|
|
25
24
|
currentAttribute.attributeType = attributeType;
|
|
26
|
-
// currentAttribute.isMethod = typeof target[attributeName] === "function";
|
|
27
25
|
currentAttribute.nestedType = options?.nestedType;
|
|
28
26
|
currentAttribute.isValidTypeInTarget = isValidTypeInTarget;
|
|
29
27
|
}
|
|
@@ -3,34 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.registerConstraint = exports.registerConstraintWithoutProps = exports.registerConstraintWithProps = void 0;
|
|
4
4
|
const symbol_1 = require("../../attribute/symbol");
|
|
5
5
|
const errors_1 = require("../../../errors");
|
|
6
|
-
/**
|
|
7
|
-
* Registers a constraint validator with properties.
|
|
8
|
-
*
|
|
9
|
-
* This utility function allows the creation and registration of a constraint validator
|
|
10
|
-
* that takes a parameter, such as @Max(5), which can be applied as a decorator on a class attribute.
|
|
11
|
-
*
|
|
12
|
-
* @param constraintId - A unique identifier for the constraint. This ID will be used to reference
|
|
13
|
-
* the constraint validator when validating properties.
|
|
14
|
-
* @param constraintValidator - The constraint validator function that validates the property based
|
|
15
|
-
* on the given parameter. It returns a function that accepts the property
|
|
16
|
-
* value and performs the validation.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* // Register the constraint validator with a unique ID
|
|
21
|
-
* const Max = registerConstraintWithProps(
|
|
22
|
-
* "Max",
|
|
23
|
-
* (max: number) => (value: any) => typeof value === "number" && value <= max
|
|
24
|
-
* );
|
|
25
|
-
*
|
|
26
|
-
* // Use the constraint as a decorator on a class attribute
|
|
27
|
-
* class ExampleClass {
|
|
28
|
-
* @Attribute(AttributeType.Integer)
|
|
29
|
-
* @Max(5)
|
|
30
|
-
* numberValue: number;
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
6
|
const registerConstraintWithProps = (constraintId, constraintValidator) => {
|
|
35
7
|
return (props) => (target, context) => {
|
|
36
8
|
const attributes = Reflect.getOwnMetadata(symbol_1.symbol, target) || [];
|
|
@@ -69,34 +41,6 @@ const registerConstraintWithProps = (constraintId, constraintValidator) => {
|
|
|
69
41
|
};
|
|
70
42
|
};
|
|
71
43
|
exports.registerConstraintWithProps = registerConstraintWithProps;
|
|
72
|
-
/**
|
|
73
|
-
* Registers a constraint validator without properties.
|
|
74
|
-
*
|
|
75
|
-
* This utility function allows the creation and registration of a constraint validator
|
|
76
|
-
* that does not take any parameters, such as @NotBlank, which can be applied as a decorator
|
|
77
|
-
* on a class attribute.
|
|
78
|
-
*
|
|
79
|
-
* @param constraintId - A unique identifier for the constraint. This ID will be used to reference
|
|
80
|
-
* the constraint validator when validating properties.
|
|
81
|
-
* @param constraintValidator - The constraint validator function that validates the property without
|
|
82
|
-
* any parameters. It accepts only the property value.
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* ```typescript
|
|
86
|
-
* // Register the constraint validator with a unique ID
|
|
87
|
-
* const NotBlank = registerConstraintWithoutProps(
|
|
88
|
-
* 'NotBlank',
|
|
89
|
-
* (value: any) => typeof value === 'string' && value.trim().length > 0
|
|
90
|
-
* );
|
|
91
|
-
*
|
|
92
|
-
* // Use the constraint as a decorator on a class attribute
|
|
93
|
-
* class ExampleClass {
|
|
94
|
-
* @Attribute(AttributeType.String)
|
|
95
|
-
* @NotBlank
|
|
96
|
-
* textValue: string;
|
|
97
|
-
* }
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
44
|
const registerConstraintWithoutProps = (constraintId, constraintValidator) => {
|
|
101
45
|
return (0, exports.registerConstraintWithProps)(constraintId, () => constraintValidator)();
|
|
102
46
|
};
|
|
@@ -15,7 +15,6 @@ const listValidationErrors = (target) => {
|
|
|
15
15
|
validations.push({
|
|
16
16
|
attributeName: attribute.attributeName,
|
|
17
17
|
constraintId: "AttributeTypeIsDefined",
|
|
18
|
-
// constraintProps: "",
|
|
19
18
|
message: `${attribute.attributeName} has no @Attribute(AttributeType) defined`,
|
|
20
19
|
});
|
|
21
20
|
continue;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { AttributeType, listAttributes, PrimitiveType } from "./decorators";
|
|
2
|
+
const parseBoolean = (value) => {
|
|
3
|
+
switch (value) {
|
|
4
|
+
case true:
|
|
5
|
+
case "true":
|
|
6
|
+
case 1:
|
|
7
|
+
case "1":
|
|
8
|
+
case "on":
|
|
9
|
+
case "yes":
|
|
10
|
+
return true;
|
|
11
|
+
case false:
|
|
12
|
+
case "false":
|
|
13
|
+
case 0:
|
|
14
|
+
case "0":
|
|
15
|
+
case "off":
|
|
16
|
+
case "no":
|
|
17
|
+
return false;
|
|
18
|
+
default:
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const isPrimitiveType = (type) => {
|
|
23
|
+
return Object.values(PrimitiveType).includes(type);
|
|
24
|
+
};
|
|
25
|
+
const parseType = (value, type, nestedType) => {
|
|
26
|
+
if (type === AttributeType.Float) {
|
|
27
|
+
return parseFloat(value);
|
|
28
|
+
}
|
|
29
|
+
if (type === AttributeType.Integer) {
|
|
30
|
+
return parseInt(value);
|
|
31
|
+
}
|
|
32
|
+
if (type === AttributeType.Boolean) {
|
|
33
|
+
return parseBoolean(value);
|
|
34
|
+
}
|
|
35
|
+
if (type === AttributeType.Date) {
|
|
36
|
+
return new Date(value);
|
|
37
|
+
}
|
|
38
|
+
if (type === AttributeType.Object &&
|
|
39
|
+
nestedType &&
|
|
40
|
+
nestedType.prototype instanceof DecoratedClass) {
|
|
41
|
+
return new nestedType(value);
|
|
42
|
+
}
|
|
43
|
+
if (type === AttributeType.List) {
|
|
44
|
+
if (!value || !Array.isArray(value)) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
if (nestedType) {
|
|
48
|
+
if (isPrimitiveType(nestedType)) {
|
|
49
|
+
return value.map((item) => parseType(item, nestedType));
|
|
50
|
+
}
|
|
51
|
+
else if (nestedType.prototype instanceof DecoratedClass) {
|
|
52
|
+
return value.map((item) => parseType(item, AttributeType.Object, nestedType));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
};
|
|
58
|
+
export class DecoratedClass {
|
|
59
|
+
constructor(props = {}) {
|
|
60
|
+
if (!props) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const attributes = listAttributes(this);
|
|
64
|
+
const self = this;
|
|
65
|
+
for (const attribute of attributes) {
|
|
66
|
+
const { attributeName: key, attributeType, nestedType } = attribute;
|
|
67
|
+
if (self[key] !== undefined || props[key] === undefined) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const value = parseType(props[key], attributeType, nestedType);
|
|
71
|
+
if (value === undefined) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
self[key] = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { updateAttributes } from "./utils";
|
|
2
|
+
import { AttributeType } from "./types";
|
|
3
|
+
export const Attribute = (attributeType, options = {}) => {
|
|
4
|
+
let isValidType = () => true;
|
|
5
|
+
if (attributeType === AttributeType.String) {
|
|
6
|
+
isValidType = (value) => value === undefined || value === null || typeof value === "string";
|
|
7
|
+
}
|
|
8
|
+
else if (attributeType === AttributeType.Integer) {
|
|
9
|
+
isValidType = (value) => value === undefined ||
|
|
10
|
+
value === null ||
|
|
11
|
+
(Number(value) === value && value % 1 === 0);
|
|
12
|
+
}
|
|
13
|
+
else if (attributeType === AttributeType.Float) {
|
|
14
|
+
isValidType = (value) => value === undefined || value === null || Number(value) === value;
|
|
15
|
+
}
|
|
16
|
+
else if (attributeType === AttributeType.Boolean) {
|
|
17
|
+
isValidType = (value) => value === undefined || value === null || typeof value === "boolean";
|
|
18
|
+
}
|
|
19
|
+
else if (attributeType === AttributeType.Date) {
|
|
20
|
+
isValidType = (value) => value === undefined || value === null || value instanceof Date;
|
|
21
|
+
}
|
|
22
|
+
else if (attributeType === AttributeType.List) {
|
|
23
|
+
isValidType = (value) => value === undefined || value === null || Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
else if (attributeType === AttributeType.Object) {
|
|
26
|
+
isValidType = (value) => value === undefined || value === null || typeof value === "object";
|
|
27
|
+
}
|
|
28
|
+
return updateAttributes(attributeType, isValidType, options);
|
|
29
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { symbol } from "./symbol";
|
|
2
|
+
export const listAttributes = (target) => {
|
|
3
|
+
let attributes = [];
|
|
4
|
+
let targetToUse = Object.getPrototypeOf(target);
|
|
5
|
+
while (targetToUse && targetToUse !== Object.prototype) {
|
|
6
|
+
const parentAttributes = Reflect.getOwnMetadata(symbol, targetToUse) || [];
|
|
7
|
+
attributes = [...parentAttributes, ...attributes];
|
|
8
|
+
targetToUse = Object.getPrototypeOf(targetToUse);
|
|
9
|
+
}
|
|
10
|
+
return attributes;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const symbol = Symbol("itw_attribute");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export var AttributeType;
|
|
2
|
+
(function (AttributeType) {
|
|
3
|
+
AttributeType["String"] = "String";
|
|
4
|
+
AttributeType["Float"] = "Float";
|
|
5
|
+
AttributeType["Integer"] = "Integer";
|
|
6
|
+
AttributeType["Boolean"] = "Boolean";
|
|
7
|
+
AttributeType["Date"] = "Date";
|
|
8
|
+
AttributeType["List"] = "List";
|
|
9
|
+
AttributeType["Object"] = "Object";
|
|
10
|
+
})(AttributeType || (AttributeType = {}));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export var PrimitiveType;
|
|
2
|
+
(function (PrimitiveType) {
|
|
3
|
+
PrimitiveType["String"] = "String";
|
|
4
|
+
PrimitiveType["Integer"] = "Integer";
|
|
5
|
+
PrimitiveType["Float"] = "Float";
|
|
6
|
+
PrimitiveType["Boolean"] = "Boolean";
|
|
7
|
+
PrimitiveType["Date"] = "Date";
|
|
8
|
+
})(PrimitiveType || (PrimitiveType = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./update-attributes";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { symbol } from "../symbol";
|
|
3
|
+
export const updateAttributes = (attributeType, isValidType, options = {}) => (target, context) => {
|
|
4
|
+
const attributes = Reflect.getOwnMetadata(symbol, target) || [];
|
|
5
|
+
const attributeName = typeof context === "string" ? context : context.name;
|
|
6
|
+
let currentAttribute = attributes.find((attribute) => attribute.attributeName === attributeName);
|
|
7
|
+
const isValidTypeInTarget = (target) => isValidType(typeof target[attributeName] === "function"
|
|
8
|
+
? target[attributeName]()
|
|
9
|
+
: target[attributeName]);
|
|
10
|
+
if (!currentAttribute) {
|
|
11
|
+
currentAttribute = {
|
|
12
|
+
attributeName,
|
|
13
|
+
attributeType,
|
|
14
|
+
constraints: [],
|
|
15
|
+
nestedType: options?.nestedType,
|
|
16
|
+
isValidTypeInTarget,
|
|
17
|
+
};
|
|
18
|
+
attributes.push(currentAttribute);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
currentAttribute.attributeType = attributeType;
|
|
22
|
+
currentAttribute.nestedType = options?.nestedType;
|
|
23
|
+
currentAttribute.isValidTypeInTarget = isValidTypeInTarget;
|
|
24
|
+
}
|
|
25
|
+
Reflect.defineMetadata(symbol, attributes, target);
|
|
26
|
+
Reflect.defineMetadata(symbol, currentAttribute, target, attributeName);
|
|
27
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { registerConstraintWithProps } from "./utils";
|
|
2
|
+
import { UnsupportedDecoratorError } from "../../errors";
|
|
3
|
+
export const Max = registerConstraintWithProps("Max", (max) => (value) => {
|
|
4
|
+
if (value === null || value === undefined) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (typeof value === "string") {
|
|
8
|
+
return value.length <= max;
|
|
9
|
+
}
|
|
10
|
+
if (typeof value === "number") {
|
|
11
|
+
return value <= max;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
return value.length <= max;
|
|
15
|
+
}
|
|
16
|
+
throw new UnsupportedDecoratorError();
|
|
17
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { registerConstraintWithProps } from "./utils";
|
|
2
|
+
import { UnsupportedDecoratorError } from "../../errors";
|
|
3
|
+
export const Min = registerConstraintWithProps("Min", (min) => (value) => {
|
|
4
|
+
if (value === null || value === undefined) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (typeof value === "string") {
|
|
8
|
+
return value.length >= min;
|
|
9
|
+
}
|
|
10
|
+
if (typeof value === "number") {
|
|
11
|
+
return value >= min;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
return value.length >= min;
|
|
15
|
+
}
|
|
16
|
+
throw new UnsupportedDecoratorError();
|
|
17
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { registerConstraintWithoutProps } from "./utils";
|
|
2
|
+
import { UnsupportedDecoratorError } from "../../errors";
|
|
3
|
+
export const NotBlank = registerConstraintWithoutProps("NotBlank", (value) => {
|
|
4
|
+
if (value === null || value === undefined) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (typeof value !== "string") {
|
|
8
|
+
throw new UnsupportedDecoratorError();
|
|
9
|
+
}
|
|
10
|
+
return value.trim().length > 0;
|
|
11
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { registerConstraintWithProps } from "./utils";
|
|
2
|
+
import { UnsupportedDecoratorError } from "../../errors";
|
|
3
|
+
export const Pattern = registerConstraintWithProps("Pattern", (pattern) => (value) => {
|
|
4
|
+
if (value === null || value === undefined) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (typeof value !== "string") {
|
|
8
|
+
throw new UnsupportedDecoratorError();
|
|
9
|
+
}
|
|
10
|
+
const r = value.match(pattern);
|
|
11
|
+
return !!r && r.length > 0;
|
|
12
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./register-constraint";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { symbol } from "../../attribute/symbol";
|
|
2
|
+
import { UnsupportedDecoratorError } from "../../../errors";
|
|
3
|
+
export const registerConstraintWithProps = (constraintId, constraintValidator) => {
|
|
4
|
+
return (props) => (target, context) => {
|
|
5
|
+
const attributes = Reflect.getOwnMetadata(symbol, target) || [];
|
|
6
|
+
const attributeName = typeof context === "string" ? context : context.name;
|
|
7
|
+
let currentAttribute = attributes.find((attribute) => attribute.attributeName === attributeName);
|
|
8
|
+
const constraint = {
|
|
9
|
+
constraintId,
|
|
10
|
+
isValid: (target) => {
|
|
11
|
+
try {
|
|
12
|
+
return constraintValidator(props)(typeof target[attributeName] === "function"
|
|
13
|
+
? target[attributeName]()
|
|
14
|
+
: target[attributeName], target);
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
if (e instanceof UnsupportedDecoratorError) {
|
|
18
|
+
e.setErrorProps(constraintId, `${target.constructor.name}.${attributeName}`, typeof target[attributeName]);
|
|
19
|
+
}
|
|
20
|
+
throw e;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
constraintProps: props,
|
|
24
|
+
};
|
|
25
|
+
if (!currentAttribute) {
|
|
26
|
+
currentAttribute = {
|
|
27
|
+
attributeName,
|
|
28
|
+
constraints: [constraint],
|
|
29
|
+
isValidTypeInTarget: () => false,
|
|
30
|
+
};
|
|
31
|
+
attributes.push(currentAttribute);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
currentAttribute.constraints.push(constraint);
|
|
35
|
+
}
|
|
36
|
+
Reflect.defineMetadata(symbol, attributes, target);
|
|
37
|
+
Reflect.defineMetadata(symbol, currentAttribute, target, attributeName);
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export const registerConstraintWithoutProps = (constraintId, constraintValidator) => {
|
|
41
|
+
return registerConstraintWithProps(constraintId, () => constraintValidator)();
|
|
42
|
+
};
|
|
43
|
+
export const registerConstraint = registerConstraintWithoutProps;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export class AttributesNotValidError extends Error {
|
|
2
|
+
validations;
|
|
3
|
+
constructor(validations) {
|
|
4
|
+
super(validations.map((error) => error.message).join(", "));
|
|
5
|
+
this.name = "AttributesNotValidError";
|
|
6
|
+
this.validations = validations;
|
|
7
|
+
Object.setPrototypeOf(this, AttributesNotValidError.prototype);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class UnsupportedDecoratorError extends Error {
|
|
2
|
+
decorator;
|
|
3
|
+
attributePath;
|
|
4
|
+
attributeType;
|
|
5
|
+
constructor() {
|
|
6
|
+
super("UnsupportedDecoratorError");
|
|
7
|
+
this.name = "UnsupportedDecoratorError";
|
|
8
|
+
}
|
|
9
|
+
setErrorProps(decorator, attributePath, attributeType) {
|
|
10
|
+
this.decorator = decorator;
|
|
11
|
+
this.attributePath = attributePath;
|
|
12
|
+
this.attributeType = attributeType;
|
|
13
|
+
this.message = `@${decorator} is not supported for ${attributePath}`;
|
|
14
|
+
}
|
|
15
|
+
}
|
package/dist-es/index.js
ADDED
package/dist-es/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./validator";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { listAttributes } from "../decorators/attribute";
|
|
2
|
+
import { InvalidTargetError } from "../errors";
|
|
3
|
+
import { DecoratedClass } from "../decorated-class";
|
|
4
|
+
export const listValidationErrors = (target) => {
|
|
5
|
+
if (!target) {
|
|
6
|
+
throw new InvalidTargetError("Target is not defined");
|
|
7
|
+
}
|
|
8
|
+
const attributes = listAttributes(target);
|
|
9
|
+
const validations = [];
|
|
10
|
+
for (const attribute of attributes) {
|
|
11
|
+
if (!attribute.attributeType) {
|
|
12
|
+
validations.push({
|
|
13
|
+
attributeName: attribute.attributeName,
|
|
14
|
+
constraintId: "AttributeTypeIsDefined",
|
|
15
|
+
message: `${attribute.attributeName} has no @Attribute(AttributeType) defined`,
|
|
16
|
+
});
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (!attribute.isValidTypeInTarget(target)) {
|
|
20
|
+
const attributeToUse = attribute.attributeType === "Object" && attribute.nestedType
|
|
21
|
+
? attribute.nestedType
|
|
22
|
+
: attribute.attributeType;
|
|
23
|
+
validations.push({
|
|
24
|
+
attributeName: attribute.attributeName,
|
|
25
|
+
constraintId: "CorrectAttributeType",
|
|
26
|
+
constraintProps: attributeToUse,
|
|
27
|
+
message: `${attribute.attributeName} is not of type ${attributeToUse}`,
|
|
28
|
+
});
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (attribute.attributeType === "Object" &&
|
|
32
|
+
attribute.nestedType &&
|
|
33
|
+
attribute.nestedType.prototype instanceof DecoratedClass &&
|
|
34
|
+
target[attribute.attributeName]) {
|
|
35
|
+
validations.push(...listValidationErrors(target[attribute.attributeName]));
|
|
36
|
+
}
|
|
37
|
+
for (const validation of attribute.constraints) {
|
|
38
|
+
if (!validation.isValid(target)) {
|
|
39
|
+
validations.push({
|
|
40
|
+
attributeName: attribute.attributeName,
|
|
41
|
+
constraintId: validation.constraintId,
|
|
42
|
+
constraintProps: validation.constraintProps,
|
|
43
|
+
message: `Attribute ${attribute.attributeName} is not valid`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return validations;
|
|
49
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AttributesNotValidError } from "../errors";
|
|
2
|
+
import { listValidationErrors } from "./list-validation-errors";
|
|
3
|
+
export const validate = (target) => {
|
|
4
|
+
const validations = listValidationErrors(target);
|
|
5
|
+
if (validations.length) {
|
|
6
|
+
throw new AttributesNotValidError(validations);
|
|
7
|
+
}
|
|
8
|
+
};
|