@decaf-ts/decorator-validation 1.10.5 → 1.11.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.
- package/README.md +1 -1
- package/dist/decorator-validation.cjs +1 -1
- package/dist/decorator-validation.cjs.map +1 -1
- package/dist/decorator-validation.js +1 -1
- package/dist/decorator-validation.js.map +1 -1
- package/lib/esm/index.d.ts +2 -1
- package/lib/esm/index.js +2 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/model/Builder.d.ts +84 -0
- package/lib/esm/model/Builder.js +395 -129
- package/lib/esm/model/Builder.js.map +1 -1
- package/lib/esm/model/Model.d.ts +21 -19
- package/lib/esm/model/Model.js +112 -105
- package/lib/esm/model/Model.js.map +1 -1
- package/lib/esm/model/constants.d.ts +8 -8
- package/lib/esm/model/constants.js +8 -9
- package/lib/esm/model/constants.js.map +1 -1
- package/lib/esm/model/decorators.d.ts +2 -12
- package/lib/esm/model/decorators.js +5 -39
- package/lib/esm/model/decorators.js.map +1 -1
- package/lib/esm/model/index.d.ts +1 -0
- package/lib/esm/model/index.js +1 -0
- package/lib/esm/model/index.js.map +1 -1
- package/lib/esm/model/types.d.ts +0 -12
- package/lib/esm/model/utils.d.ts +0 -3
- package/lib/esm/model/utils.js +0 -10
- package/lib/esm/model/utils.js.map +1 -1
- package/lib/esm/model/validation.d.ts +4 -37
- package/lib/esm/model/validation.js +30 -106
- package/lib/esm/model/validation.js.map +1 -1
- package/lib/esm/overrides/Metadata.d.ts +128 -0
- package/lib/esm/overrides/Metadata.js +2 -0
- package/lib/esm/overrides/Metadata.js.map +1 -0
- package/lib/esm/overrides/index.d.ts +3 -0
- package/lib/esm/overrides/index.js +4 -0
- package/lib/esm/overrides/index.js.map +1 -0
- package/lib/esm/overrides/overrides.d.ts +1 -0
- package/lib/esm/overrides/overrides.js +79 -0
- package/lib/esm/overrides/overrides.js.map +1 -0
- package/lib/esm/overrides/types.d.ts +9 -0
- package/lib/esm/overrides/types.js +2 -0
- package/lib/esm/overrides/types.js.map +1 -0
- package/lib/esm/types/validation.d.ts +4 -2
- package/lib/esm/utils/constants.d.ts +4 -18
- package/lib/esm/utils/constants.js +4 -17
- package/lib/esm/utils/constants.js.map +1 -1
- package/lib/esm/utils/dates.d.ts +0 -1
- package/lib/esm/utils/dates.js +0 -1
- package/lib/esm/utils/dates.js.map +1 -1
- package/lib/esm/utils/equality.d.ts +56 -0
- package/lib/esm/utils/equality.js +160 -0
- package/lib/esm/utils/equality.js.map +1 -0
- package/lib/esm/utils/index.d.ts +1 -2
- package/lib/esm/utils/index.js +1 -2
- package/lib/esm/utils/index.js.map +1 -1
- package/lib/esm/utils/registry.d.ts +1 -1
- package/lib/esm/utils/serialization.d.ts +2 -2
- package/lib/esm/utils/serialization.js +10 -2
- package/lib/esm/utils/serialization.js.map +1 -1
- package/lib/esm/utils/types.d.ts +0 -102
- package/lib/esm/validation/Validation.d.ts +2 -3
- package/lib/esm/validation/Validation.js +11 -6
- package/lib/esm/validation/Validation.js.map +1 -1
- package/lib/esm/validation/Validators/BaseValidator.js +7 -3
- package/lib/esm/validation/Validators/BaseValidator.js.map +1 -1
- package/lib/esm/validation/Validators/DiffValidator.js +1 -1
- package/lib/esm/validation/Validators/DiffValidator.js.map +1 -1
- package/lib/esm/validation/Validators/EqualsValidator.js +1 -1
- package/lib/esm/validation/Validators/EqualsValidator.js.map +1 -1
- package/lib/esm/validation/Validators/GreaterThanOrEqualValidator.js +1 -1
- package/lib/esm/validation/Validators/GreaterThanOrEqualValidator.js.map +1 -1
- package/lib/esm/validation/Validators/LessThanOrEqualValidator.js +1 -1
- package/lib/esm/validation/Validators/LessThanOrEqualValidator.js.map +1 -1
- package/lib/esm/validation/Validators/ListValidator.js +4 -4
- package/lib/esm/validation/Validators/ListValidator.js.map +1 -1
- package/lib/esm/validation/Validators/MaxLengthValidator.js +3 -2
- package/lib/esm/validation/Validators/MaxLengthValidator.js.map +1 -1
- package/lib/esm/validation/Validators/MaxValidator.js +1 -1
- package/lib/esm/validation/Validators/MaxValidator.js.map +1 -1
- package/lib/esm/validation/Validators/MinLengthValidator.js +3 -2
- package/lib/esm/validation/Validators/MinLengthValidator.js.map +1 -1
- package/lib/esm/validation/Validators/MinValidator.js +1 -1
- package/lib/esm/validation/Validators/MinValidator.js.map +1 -1
- package/lib/esm/validation/Validators/OptionValidator.d.ts +29 -0
- package/lib/esm/validation/Validators/OptionValidator.js +61 -0
- package/lib/esm/validation/Validators/OptionValidator.js.map +1 -0
- package/lib/esm/validation/Validators/TypeValidator.js +2 -2
- package/lib/esm/validation/Validators/TypeValidator.js.map +1 -1
- package/lib/esm/validation/Validators/constants.d.ts +2 -1
- package/lib/esm/validation/Validators/constants.js +3 -2
- package/lib/esm/validation/Validators/constants.js.map +1 -1
- package/lib/esm/validation/Validators/decorators.d.ts +1 -1
- package/lib/esm/validation/Validators/decorators.js +2 -2
- package/lib/esm/validation/Validators/decorators.js.map +1 -1
- package/lib/esm/validation/Validators/index.d.ts +1 -0
- package/lib/esm/validation/Validators/index.js +1 -0
- package/lib/esm/validation/Validators/index.js.map +1 -1
- package/lib/esm/validation/Validators/utils.d.ts +33 -0
- package/lib/esm/validation/Validators/utils.js +62 -0
- package/lib/esm/validation/Validators/utils.js.map +1 -1
- package/lib/esm/validation/decorators.d.ts +28 -17
- package/lib/esm/validation/decorators.js +86 -55
- package/lib/esm/validation/decorators.js.map +1 -1
- package/lib/esm/validation/types.d.ts +15 -5
- package/lib/esm/validation/types.js.map +1 -1
- package/lib/index.cjs +2 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js.map +1 -1
- package/lib/model/Builder.cjs +399 -128
- package/lib/model/Builder.d.ts +84 -0
- package/lib/model/Builder.js.map +1 -1
- package/lib/model/Model.cjs +114 -107
- package/lib/model/Model.d.ts +21 -19
- package/lib/model/Model.js.map +1 -1
- package/lib/model/constants.cjs +8 -9
- package/lib/model/constants.d.ts +8 -8
- package/lib/model/constants.js.map +1 -1
- package/lib/model/decorators.cjs +4 -39
- package/lib/model/decorators.d.ts +2 -12
- package/lib/model/decorators.js.map +1 -1
- package/lib/model/index.cjs +1 -0
- package/lib/model/index.d.ts +1 -0
- package/lib/model/index.js.map +1 -1
- package/lib/model/types.d.ts +0 -12
- package/lib/model/utils.cjs +0 -12
- package/lib/model/utils.d.ts +0 -3
- package/lib/model/utils.js.map +1 -1
- package/lib/model/validation.cjs +30 -108
- package/lib/model/validation.d.ts +4 -37
- package/lib/model/validation.js.map +1 -1
- package/lib/overrides/Metadata.cjs +3 -0
- package/lib/overrides/Metadata.d.ts +128 -0
- package/lib/overrides/Metadata.js.map +1 -0
- package/lib/overrides/index.cjs +20 -0
- package/lib/overrides/index.d.ts +3 -0
- package/lib/overrides/index.js.map +1 -0
- package/lib/overrides/overrides.cjs +81 -0
- package/lib/overrides/overrides.d.ts +1 -0
- package/lib/overrides/overrides.js.map +1 -0
- package/lib/overrides/types.cjs +3 -0
- package/lib/overrides/types.d.ts +9 -0
- package/lib/overrides/types.js.map +1 -0
- package/lib/types/validation.d.ts +4 -2
- package/lib/utils/constants.cjs +5 -18
- package/lib/utils/constants.d.ts +4 -18
- package/lib/utils/constants.js.map +1 -1
- package/lib/utils/dates.cjs +0 -1
- package/lib/utils/dates.d.ts +0 -1
- package/lib/utils/dates.js.map +1 -1
- package/lib/utils/equality.cjs +163 -0
- package/lib/utils/equality.d.ts +56 -0
- package/lib/utils/equality.js.map +1 -0
- package/lib/utils/index.cjs +1 -2
- package/lib/utils/index.d.ts +1 -2
- package/lib/utils/index.js.map +1 -1
- package/lib/utils/registry.d.ts +1 -1
- package/lib/utils/serialization.cjs +10 -2
- package/lib/utils/serialization.d.ts +2 -2
- package/lib/utils/serialization.js.map +1 -1
- package/lib/utils/types.d.ts +0 -102
- package/lib/validation/Validation.cjs +11 -6
- package/lib/validation/Validation.d.ts +2 -3
- package/lib/validation/Validation.js.map +1 -1
- package/lib/validation/Validators/BaseValidator.cjs +7 -3
- package/lib/validation/Validators/BaseValidator.js.map +1 -1
- package/lib/validation/Validators/DiffValidator.cjs +2 -2
- package/lib/validation/Validators/DiffValidator.js.map +1 -1
- package/lib/validation/Validators/EqualsValidator.cjs +2 -2
- package/lib/validation/Validators/EqualsValidator.js.map +1 -1
- package/lib/validation/Validators/GreaterThanOrEqualValidator.cjs +2 -2
- package/lib/validation/Validators/GreaterThanOrEqualValidator.js.map +1 -1
- package/lib/validation/Validators/LessThanOrEqualValidator.cjs +2 -2
- package/lib/validation/Validators/LessThanOrEqualValidator.js.map +1 -1
- package/lib/validation/Validators/ListValidator.cjs +4 -4
- package/lib/validation/Validators/ListValidator.js.map +1 -1
- package/lib/validation/Validators/MaxLengthValidator.cjs +3 -2
- package/lib/validation/Validators/MaxLengthValidator.js.map +1 -1
- package/lib/validation/Validators/MaxValidator.cjs +1 -1
- package/lib/validation/Validators/MaxValidator.js.map +1 -1
- package/lib/validation/Validators/MinLengthValidator.cjs +3 -2
- package/lib/validation/Validators/MinLengthValidator.js.map +1 -1
- package/lib/validation/Validators/MinValidator.cjs +1 -1
- package/lib/validation/Validators/MinValidator.js.map +1 -1
- package/lib/validation/Validators/OptionValidator.cjs +64 -0
- package/lib/validation/Validators/OptionValidator.d.ts +29 -0
- package/lib/validation/Validators/OptionValidator.js.map +1 -0
- package/lib/validation/Validators/TypeValidator.cjs +2 -2
- package/lib/validation/Validators/TypeValidator.js.map +1 -1
- package/lib/validation/Validators/constants.cjs +5 -4
- package/lib/validation/Validators/constants.d.ts +2 -1
- package/lib/validation/Validators/constants.js.map +1 -1
- package/lib/validation/Validators/decorators.cjs +3 -3
- package/lib/validation/Validators/decorators.d.ts +1 -1
- package/lib/validation/Validators/decorators.js.map +1 -1
- package/lib/validation/Validators/index.cjs +1 -0
- package/lib/validation/Validators/index.d.ts +1 -0
- package/lib/validation/Validators/index.js.map +1 -1
- package/lib/validation/Validators/utils.cjs +66 -0
- package/lib/validation/Validators/utils.d.ts +33 -0
- package/lib/validation/Validators/utils.js.map +1 -1
- package/lib/validation/decorators.cjs +102 -69
- package/lib/validation/decorators.d.ts +28 -17
- package/lib/validation/decorators.js.map +1 -1
- package/lib/validation/types.d.ts +15 -5
- package/lib/validation/types.js.map +1 -1
- package/package.json +2 -3
- package/lib/esm/utils/Decoration.d.ts +0 -135
- package/lib/esm/utils/Decoration.js +0 -227
- package/lib/esm/utils/Decoration.js.map +0 -1
- package/lib/esm/utils/decorators.d.ts +0 -38
- package/lib/esm/utils/decorators.js +0 -64
- package/lib/esm/utils/decorators.js.map +0 -1
- package/lib/utils/Decoration.cjs +0 -231
- package/lib/utils/Decoration.d.ts +0 -135
- package/lib/utils/Decoration.js.map +0 -1
- package/lib/utils/decorators.cjs +0 -68
- package/lib/utils/decorators.d.ts +0 -38
- package/lib/utils/decorators.js.map +0 -1
package/lib/model/Builder.cjs
CHANGED
|
@@ -1,130 +1,401 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ModelBuilder = exports.AttributeBuilder = void 0;
|
|
4
|
+
const Model_1 = require("./Model.cjs");
|
|
5
|
+
const typed_object_accumulator_1 = require("typed-object-accumulator");
|
|
6
|
+
const decoration_1 = require("@decaf-ts/decoration");
|
|
7
|
+
const decorators_1 = require("./decorators.cjs");
|
|
8
|
+
const decorators_2 = require("./../validation/decorators.cjs");
|
|
9
|
+
const constants_1 = require("./../validation/Validators/constants.cjs");
|
|
10
|
+
const Validation_1 = require("./../validation/Validation.cjs");
|
|
11
|
+
class AttributeBuilder {
|
|
12
|
+
constructor(parent, attr, declaredType) {
|
|
13
|
+
this.parent = parent;
|
|
14
|
+
this.attr = attr;
|
|
15
|
+
this.declaredType = declaredType;
|
|
16
|
+
this.decorators = [];
|
|
17
|
+
}
|
|
18
|
+
decorate(...decorators) {
|
|
19
|
+
for (const decorator of decorators) {
|
|
20
|
+
if (this.decorators.includes(decorator))
|
|
21
|
+
throw new Error(`Decorator "${decorator}" has already been used`);
|
|
22
|
+
this.decorators.push(decorator);
|
|
23
|
+
}
|
|
24
|
+
return this.parent;
|
|
25
|
+
}
|
|
26
|
+
undecorate(...decorators) {
|
|
27
|
+
for (const decorator of decorators) {
|
|
28
|
+
const index = this.decorators.indexOf(decorator);
|
|
29
|
+
if (index < 0)
|
|
30
|
+
throw new Error(`Decorator "${decorator}" is not applied to ${this.attr}`);
|
|
31
|
+
this.decorators.splice(index, 1);
|
|
32
|
+
}
|
|
33
|
+
return this.parent;
|
|
34
|
+
}
|
|
35
|
+
required(messageOrMeta) {
|
|
36
|
+
const meta = AttributeBuilder.asMeta(messageOrMeta);
|
|
37
|
+
const message = typeof messageOrMeta === "string"
|
|
38
|
+
? messageOrMeta
|
|
39
|
+
: AttributeBuilder.resolveMessage(meta);
|
|
40
|
+
return this.decorate((0, decorators_2.required)(message));
|
|
41
|
+
}
|
|
42
|
+
min(valueOrMeta, message) {
|
|
43
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
44
|
+
const value = meta?.[constants_1.ValidationKeys.MIN] ??
|
|
45
|
+
(meta ? undefined : valueOrMeta);
|
|
46
|
+
if (value === undefined)
|
|
47
|
+
throw new Error(`Missing ${constants_1.ValidationKeys.MIN} for ${String(this.attr)}`);
|
|
48
|
+
return this.decorate((0, decorators_2.min)(value, AttributeBuilder.resolveMessage(meta, message)));
|
|
49
|
+
}
|
|
50
|
+
max(valueOrMeta, message) {
|
|
51
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
52
|
+
const value = meta?.[constants_1.ValidationKeys.MAX] ??
|
|
53
|
+
(meta ? undefined : valueOrMeta);
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
throw new Error(`Missing ${constants_1.ValidationKeys.MAX} for ${String(this.attr)}`);
|
|
56
|
+
return this.decorate((0, decorators_2.max)(value, AttributeBuilder.resolveMessage(meta, message)));
|
|
57
|
+
}
|
|
58
|
+
step(valueOrMeta, message) {
|
|
59
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
60
|
+
const value = meta?.[constants_1.ValidationKeys.STEP] ??
|
|
61
|
+
(meta ? undefined : valueOrMeta);
|
|
62
|
+
if (value === undefined)
|
|
63
|
+
throw new Error(`Missing ${constants_1.ValidationKeys.STEP} for ${String(this.attr)}`);
|
|
64
|
+
return this.decorate((0, decorators_2.step)(value, AttributeBuilder.resolveMessage(meta, message)));
|
|
65
|
+
}
|
|
66
|
+
minlength(valueOrMeta, message) {
|
|
67
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
68
|
+
const value = meta?.[constants_1.ValidationKeys.MIN_LENGTH] ??
|
|
69
|
+
(meta ? undefined : valueOrMeta);
|
|
70
|
+
if (value === undefined)
|
|
71
|
+
throw new Error(`Missing ${constants_1.ValidationKeys.MIN_LENGTH} for ${String(this.attr)}`);
|
|
72
|
+
return this.decorate((0, decorators_2.minlength)(value, AttributeBuilder.resolveMessage(meta, message)));
|
|
73
|
+
}
|
|
74
|
+
maxlength(valueOrMeta, message) {
|
|
75
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
76
|
+
const value = meta?.[constants_1.ValidationKeys.MAX_LENGTH] ??
|
|
77
|
+
(meta ? undefined : valueOrMeta);
|
|
78
|
+
if (value === undefined)
|
|
79
|
+
throw new Error(`Missing ${constants_1.ValidationKeys.MAX_LENGTH} for ${String(this.attr)}`);
|
|
80
|
+
return this.decorate((0, decorators_2.maxlength)(value, AttributeBuilder.resolveMessage(meta, message)));
|
|
81
|
+
}
|
|
82
|
+
pattern(valueOrMeta, message) {
|
|
83
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
84
|
+
const rawPattern = meta?.[constants_1.ValidationKeys.PATTERN] ??
|
|
85
|
+
(meta ? undefined : valueOrMeta);
|
|
86
|
+
const regex = AttributeBuilder.patternFromString(rawPattern) ?? /.*/;
|
|
87
|
+
return this.decorate((0, decorators_2.pattern)(regex, AttributeBuilder.resolveMessage(meta, message)));
|
|
88
|
+
}
|
|
89
|
+
email(messageOrMeta) {
|
|
90
|
+
const meta = AttributeBuilder.asMeta(messageOrMeta);
|
|
91
|
+
const message = typeof messageOrMeta === "string"
|
|
92
|
+
? messageOrMeta
|
|
93
|
+
: AttributeBuilder.resolveMessage(meta);
|
|
94
|
+
return this.decorate((0, decorators_2.email)(message));
|
|
95
|
+
}
|
|
96
|
+
url(messageOrMeta) {
|
|
97
|
+
const meta = AttributeBuilder.asMeta(messageOrMeta);
|
|
98
|
+
const message = typeof messageOrMeta === "string"
|
|
99
|
+
? messageOrMeta
|
|
100
|
+
: AttributeBuilder.resolveMessage(meta);
|
|
101
|
+
return this.decorate((0, decorators_2.url)(message));
|
|
102
|
+
}
|
|
103
|
+
type(valueOrMeta, message) {
|
|
104
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
105
|
+
const types = meta?.customTypes ?? meta?.type ?? (meta ? undefined : valueOrMeta);
|
|
106
|
+
return this.decorate((0, decorators_2.type)(types, AttributeBuilder.resolveMessage(meta, message)));
|
|
107
|
+
}
|
|
108
|
+
date(formatOrMeta, message) {
|
|
109
|
+
const meta = AttributeBuilder.asMeta(formatOrMeta);
|
|
110
|
+
const format = meta?.[constants_1.ValidationKeys.FORMAT] ??
|
|
111
|
+
(meta ? undefined : formatOrMeta);
|
|
112
|
+
return this.decorate((0, decorators_2.date)(format, AttributeBuilder.resolveMessage(meta, message)));
|
|
113
|
+
}
|
|
114
|
+
password(valueOrMeta, message) {
|
|
115
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
116
|
+
const rawPattern = meta?.[constants_1.ValidationKeys.PATTERN] ??
|
|
117
|
+
(meta ? undefined : valueOrMeta);
|
|
118
|
+
const regex = AttributeBuilder.patternFromString(rawPattern);
|
|
119
|
+
return this.decorate((0, decorators_2.password)(regex, AttributeBuilder.resolveMessage(meta, message)));
|
|
120
|
+
}
|
|
121
|
+
list(clazzOrMeta, collection, message) {
|
|
122
|
+
const meta = AttributeBuilder.asMeta(clazzOrMeta);
|
|
123
|
+
const clazz = meta?.clazz ?? (meta ? undefined : clazzOrMeta);
|
|
124
|
+
const typeOfCollection = meta?.type ?? collection;
|
|
125
|
+
return this.decorate((0, decorators_2.list)(clazz, typeOfCollection, AttributeBuilder.resolveMessage(meta, message)));
|
|
126
|
+
}
|
|
127
|
+
set(clazzOrMeta, message) {
|
|
128
|
+
if (AttributeBuilder.isMetadataPayload(clazzOrMeta))
|
|
129
|
+
return this.list(clazzOrMeta);
|
|
130
|
+
return this.list(clazzOrMeta, "Set", message);
|
|
131
|
+
}
|
|
132
|
+
enum(valueOrMeta, message) {
|
|
133
|
+
const meta = AttributeBuilder.asMeta(valueOrMeta);
|
|
134
|
+
const values = meta?.[constants_1.ValidationKeys.ENUM] ?? (meta ? undefined : valueOrMeta);
|
|
135
|
+
return this.decorate((0, decorators_2.option)(values, AttributeBuilder.resolveMessage(meta, message)));
|
|
136
|
+
}
|
|
137
|
+
option(value, message) {
|
|
138
|
+
return this.enum(value, message);
|
|
139
|
+
}
|
|
140
|
+
static isMetadataPayload(value) {
|
|
141
|
+
if (!value)
|
|
142
|
+
return false;
|
|
143
|
+
if (value instanceof Date)
|
|
144
|
+
return false;
|
|
145
|
+
if (value instanceof RegExp)
|
|
146
|
+
return false;
|
|
147
|
+
if (Array.isArray(value))
|
|
148
|
+
return false;
|
|
149
|
+
return typeof value === "object";
|
|
150
|
+
}
|
|
151
|
+
static asMeta(value) {
|
|
152
|
+
return AttributeBuilder.isMetadataPayload(value)
|
|
153
|
+
? value
|
|
154
|
+
: undefined;
|
|
155
|
+
}
|
|
156
|
+
static resolveMessage(meta, fallback) {
|
|
157
|
+
return meta?.message ?? fallback;
|
|
158
|
+
}
|
|
159
|
+
static patternFromString(pattern) {
|
|
160
|
+
if (!pattern)
|
|
161
|
+
return undefined;
|
|
162
|
+
if (pattern instanceof RegExp)
|
|
163
|
+
return pattern;
|
|
164
|
+
const match = pattern.match(/^\/(.+)\/([gimsuy]*)$/);
|
|
165
|
+
if (match)
|
|
166
|
+
return new RegExp(match[1], match[2]);
|
|
167
|
+
return new RegExp(pattern);
|
|
168
|
+
}
|
|
169
|
+
resolveComparison(propertyOrMeta, key, options) {
|
|
170
|
+
const meta = AttributeBuilder.asMeta(propertyOrMeta);
|
|
171
|
+
if (meta) {
|
|
172
|
+
return {
|
|
173
|
+
target: meta[key],
|
|
174
|
+
options: {
|
|
175
|
+
label: meta.label,
|
|
176
|
+
message: meta.message,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return { target: propertyOrMeta, options };
|
|
181
|
+
}
|
|
182
|
+
equals(propertyOrMeta, options) {
|
|
183
|
+
const { target, options: resolvedOptions } = this.resolveComparison(propertyOrMeta, constants_1.ValidationKeys.EQUALS, options);
|
|
184
|
+
return this.decorate((0, decorators_2.eq)(target, resolvedOptions));
|
|
185
|
+
}
|
|
186
|
+
eq(propertyOrMeta, options) {
|
|
187
|
+
return this.equals(propertyOrMeta, options);
|
|
188
|
+
}
|
|
189
|
+
different(propertyOrMeta, options) {
|
|
190
|
+
const { target, options: resolvedOptions } = this.resolveComparison(propertyOrMeta, constants_1.ValidationKeys.DIFF, options);
|
|
191
|
+
return this.decorate((0, decorators_2.diff)(target, resolvedOptions));
|
|
192
|
+
}
|
|
193
|
+
diff(propertyOrMeta, options) {
|
|
194
|
+
return this.different(propertyOrMeta, options);
|
|
195
|
+
}
|
|
196
|
+
lessThan(propertyOrMeta, options) {
|
|
197
|
+
const { target, options: resolvedOptions } = this.resolveComparison(propertyOrMeta, constants_1.ValidationKeys.LESS_THAN, options);
|
|
198
|
+
return this.decorate((0, decorators_2.lt)(target, resolvedOptions));
|
|
199
|
+
}
|
|
200
|
+
lt(propertyOrMeta, options) {
|
|
201
|
+
return this.lessThan(propertyOrMeta, options);
|
|
202
|
+
}
|
|
203
|
+
lessThanOrEqual(propertyOrMeta, options) {
|
|
204
|
+
const { target, options: resolvedOptions } = this.resolveComparison(propertyOrMeta, constants_1.ValidationKeys.LESS_THAN_OR_EQUAL, options);
|
|
205
|
+
return this.decorate((0, decorators_2.lte)(target, resolvedOptions));
|
|
206
|
+
}
|
|
207
|
+
lte(propertyOrMeta, options) {
|
|
208
|
+
return this.lessThanOrEqual(propertyOrMeta, options);
|
|
209
|
+
}
|
|
210
|
+
greaterThan(propertyOrMeta, options) {
|
|
211
|
+
const { target, options: resolvedOptions } = this.resolveComparison(propertyOrMeta, constants_1.ValidationKeys.GREATER_THAN, options);
|
|
212
|
+
return this.decorate((0, decorators_2.gt)(target, resolvedOptions));
|
|
213
|
+
}
|
|
214
|
+
gt(propertyOrMeta, options) {
|
|
215
|
+
return this.greaterThan(propertyOrMeta, options);
|
|
216
|
+
}
|
|
217
|
+
greaterThanOrEqual(propertyOrMeta, options) {
|
|
218
|
+
const { target, options: resolvedOptions } = this.resolveComparison(propertyOrMeta, constants_1.ValidationKeys.GREATER_THAN_OR_EQUAL, options);
|
|
219
|
+
return this.decorate((0, decorators_2.gte)(target, resolvedOptions));
|
|
220
|
+
}
|
|
221
|
+
gte(propertyOrMeta, options) {
|
|
222
|
+
return this.greaterThanOrEqual(propertyOrMeta, options);
|
|
223
|
+
}
|
|
224
|
+
description(desc) {
|
|
225
|
+
return this.decorate((0, decoration_1.description)(desc));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Applies the attribute metadata and decorators to the provided constructor.
|
|
229
|
+
*/
|
|
230
|
+
build(constructor) {
|
|
231
|
+
const target = constructor.prototype;
|
|
232
|
+
const propKey = this.attr;
|
|
233
|
+
if (!Object.getOwnPropertyDescriptor(target, propKey)) {
|
|
234
|
+
Object.defineProperty(target, propKey, {
|
|
235
|
+
configurable: true,
|
|
236
|
+
enumerable: true,
|
|
237
|
+
writable: true,
|
|
238
|
+
value: undefined,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
if (this.declaredType) {
|
|
242
|
+
Reflect.defineMetadata(decoration_1.DecorationKeys.DESIGN_TYPE, this.declaredType, target, propKey);
|
|
243
|
+
}
|
|
244
|
+
(0, decoration_1.prop)()(target, propKey);
|
|
245
|
+
this.decorators.forEach((decorator) => {
|
|
246
|
+
try {
|
|
247
|
+
decorator(target, propKey);
|
|
248
|
+
}
|
|
249
|
+
catch (e) {
|
|
250
|
+
throw new Error(`Failed to apply decorator to property "${this.attr}": ${e}`);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
exports.AttributeBuilder = AttributeBuilder;
|
|
256
|
+
class ListAttributeBuilder {
|
|
257
|
+
constructor(parent, attribute, collection) {
|
|
258
|
+
this.parent = parent;
|
|
259
|
+
this.attribute = attribute;
|
|
260
|
+
this.collection = collection;
|
|
261
|
+
}
|
|
262
|
+
ofPrimitives(clazz, message) {
|
|
263
|
+
this.attribute.list(clazz, this.collection, message);
|
|
264
|
+
return this.parent;
|
|
265
|
+
}
|
|
266
|
+
ofModel() {
|
|
267
|
+
const nestedBuilder = ModelBuilder.builder();
|
|
268
|
+
const originalBuild = nestedBuilder.build;
|
|
269
|
+
let cachedConstructor;
|
|
270
|
+
const factory = (() => {
|
|
271
|
+
return function () {
|
|
272
|
+
if (!cachedConstructor) {
|
|
273
|
+
cachedConstructor = Reflect.apply(originalBuild, nestedBuilder, []);
|
|
274
|
+
}
|
|
275
|
+
return cachedConstructor;
|
|
276
|
+
};
|
|
277
|
+
})();
|
|
278
|
+
this.attribute.list(factory, this.collection);
|
|
279
|
+
nestedBuilder.build = new Proxy(originalBuild, {
|
|
280
|
+
apply: (target, thisArg, argArray) => {
|
|
281
|
+
cachedConstructor = Reflect.apply(target, thisArg, argArray);
|
|
282
|
+
return this.parent;
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
return nestedBuilder;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
class ModelBuilder extends typed_object_accumulator_1.ObjectAccumulator {
|
|
289
|
+
constructor() {
|
|
290
|
+
super(...arguments);
|
|
291
|
+
this.attributes = new Map();
|
|
292
|
+
}
|
|
293
|
+
setName(name) {
|
|
294
|
+
this._name = name;
|
|
295
|
+
return this;
|
|
296
|
+
}
|
|
297
|
+
description(desc) {
|
|
298
|
+
this._description = desc;
|
|
299
|
+
return this;
|
|
300
|
+
}
|
|
301
|
+
attribute(attr, type) {
|
|
302
|
+
const existing = this.attributes.get(attr);
|
|
303
|
+
if (existing) {
|
|
304
|
+
if (existing.declaredType !== type)
|
|
305
|
+
throw new Error(`Attribute "${String(attr)}" already exists with a different type`);
|
|
306
|
+
return existing;
|
|
307
|
+
}
|
|
308
|
+
const attributeBuilder = new AttributeBuilder(this, attr, type);
|
|
309
|
+
this.attributes.set(attr, attributeBuilder);
|
|
310
|
+
return attributeBuilder;
|
|
311
|
+
}
|
|
312
|
+
string(attr) {
|
|
313
|
+
return this.attribute(attr, String);
|
|
314
|
+
}
|
|
315
|
+
number(attr) {
|
|
316
|
+
return this.attribute(attr, Number);
|
|
317
|
+
}
|
|
318
|
+
date(attr) {
|
|
319
|
+
return this.attribute(attr, Date);
|
|
320
|
+
}
|
|
321
|
+
bigint(attr) {
|
|
322
|
+
return this.attribute(attr, BigInt);
|
|
323
|
+
}
|
|
324
|
+
instance(clazz, attr) {
|
|
325
|
+
return this.attribute(attr, clazz);
|
|
326
|
+
}
|
|
327
|
+
model(attr) {
|
|
328
|
+
const mm = new ModelBuilder();
|
|
329
|
+
mm.build = new Proxy(mm.build, {
|
|
330
|
+
apply: (target, thisArg, argArray) => {
|
|
331
|
+
const built = Reflect.apply(target, thisArg, argArray);
|
|
332
|
+
return this.instance(built, attr);
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
return mm;
|
|
336
|
+
}
|
|
337
|
+
listOf(attr, collection = "Array") {
|
|
338
|
+
const listType = (collection === "Set" ? Set : Array);
|
|
339
|
+
const attribute = this.attribute(attr, listType);
|
|
340
|
+
return new ListAttributeBuilder(this, attribute, collection);
|
|
341
|
+
}
|
|
342
|
+
build() {
|
|
343
|
+
if (!this._name)
|
|
344
|
+
throw new Error("name is required");
|
|
345
|
+
const Parent = this._parent ?? Model_1.Model;
|
|
346
|
+
class DynamicBuiltClass extends Parent {
|
|
347
|
+
constructor(arg) {
|
|
348
|
+
super(arg);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
Object.defineProperty(DynamicBuiltClass, "name", {
|
|
352
|
+
value: this._name,
|
|
353
|
+
writable: false,
|
|
354
|
+
});
|
|
355
|
+
for (const attribute of this.attributes.values()) {
|
|
356
|
+
attribute.build(DynamicBuiltClass);
|
|
357
|
+
}
|
|
358
|
+
let result = (0, decorators_1.model)()(DynamicBuiltClass);
|
|
359
|
+
if (this._description)
|
|
360
|
+
result = (0, decoration_1.description)(this._description)(result);
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
static builder() {
|
|
364
|
+
return new ModelBuilder();
|
|
365
|
+
}
|
|
366
|
+
static from(meta, name) {
|
|
367
|
+
if (!meta)
|
|
368
|
+
throw new Error("metadata is required");
|
|
369
|
+
const builder = ModelBuilder.builder();
|
|
370
|
+
const derivedName = name ?? `GeneratedModel${Date.now()}`;
|
|
371
|
+
builder.setName(derivedName);
|
|
372
|
+
const properties = meta.properties || {};
|
|
373
|
+
const validations = meta.validation || {};
|
|
374
|
+
for (const [prop, designType] of Object.entries(properties)) {
|
|
375
|
+
const attribute = builder.attribute(prop, designType || Object);
|
|
376
|
+
const propValidation = validations[prop];
|
|
377
|
+
if (propValidation) {
|
|
378
|
+
for (const [key, validationMeta] of Object.entries(propValidation)) {
|
|
379
|
+
const handler = attribute[key];
|
|
380
|
+
if (typeof handler === "function") {
|
|
381
|
+
handler.call(attribute, validationMeta);
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
try {
|
|
385
|
+
const decoratorFactory = Validation_1.Validation.decoratorFromKey(key);
|
|
386
|
+
const decorator = typeof decoratorFactory === "function"
|
|
387
|
+
? decoratorFactory(validationMeta)
|
|
388
|
+
: decoratorFactory;
|
|
389
|
+
attribute.decorate(decorator);
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
// ignore unknown decorators
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return builder.build();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
exports.ModelBuilder = ModelBuilder;
|
|
130
401
|
//# sourceMappingURL=Builder.js.map
|
package/lib/model/Builder.d.ts
CHANGED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Model } from "./Model";
|
|
2
|
+
import { ObjectAccumulator } from "typed-object-accumulator";
|
|
3
|
+
import { Constructor } from "@decaf-ts/decoration";
|
|
4
|
+
import { ComparisonValidatorOptions } from "../validation/types";
|
|
5
|
+
import { ExtendedMetadata } from "../overrides/types";
|
|
6
|
+
type BuildableModel = Model & Record<PropertyKey, any>;
|
|
7
|
+
export interface DecorateOption<M extends Model> {
|
|
8
|
+
decorate(...decorators: PropertyDecorator[]): ModelBuilder<M>;
|
|
9
|
+
}
|
|
10
|
+
export declare class AttributeBuilder<M extends BuildableModel, N extends keyof M, T> implements DecorateOption<M> {
|
|
11
|
+
protected parent: ModelBuilder<M>;
|
|
12
|
+
readonly attr: N;
|
|
13
|
+
readonly declaredType: T;
|
|
14
|
+
constructor(parent: ModelBuilder<M>, attr: N, declaredType: T);
|
|
15
|
+
private decorators;
|
|
16
|
+
decorate(...decorators: PropertyDecorator[]): ModelBuilder<M>;
|
|
17
|
+
undecorate(...decorators: PropertyDecorator[]): ModelBuilder<M>;
|
|
18
|
+
required(messageOrMeta?: string | Record<string, any>): ModelBuilder<M>;
|
|
19
|
+
min(valueOrMeta: number | Date | string | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
20
|
+
max(valueOrMeta: number | Date | string | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
21
|
+
step(valueOrMeta: number | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
22
|
+
minlength(valueOrMeta: number | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
23
|
+
maxlength(valueOrMeta: number | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
24
|
+
pattern(valueOrMeta: RegExp | string | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
25
|
+
email(messageOrMeta?: string | Record<string, any>): ModelBuilder<M>;
|
|
26
|
+
url(messageOrMeta?: string | Record<string, any>): ModelBuilder<M>;
|
|
27
|
+
type(valueOrMeta: Constructor | (() => Constructor) | (Constructor | (() => Constructor))[] | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
28
|
+
date(formatOrMeta?: string | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
29
|
+
password(valueOrMeta?: RegExp | string | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
30
|
+
list(clazzOrMeta: Constructor | (() => Constructor) | (Constructor | (() => Constructor))[] | Record<string, any>, collection?: "Array" | "Set", message?: string): ModelBuilder<M>;
|
|
31
|
+
set(clazzOrMeta: Constructor | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
32
|
+
enum(valueOrMeta: any[] | Record<any, any> | Record<string, any>, message?: string): ModelBuilder<M>;
|
|
33
|
+
option(value: any[] | Record<any, any>, message?: string): ModelBuilder<M>;
|
|
34
|
+
private static isMetadataPayload;
|
|
35
|
+
private static asMeta;
|
|
36
|
+
private static resolveMessage;
|
|
37
|
+
private static patternFromString;
|
|
38
|
+
private resolveComparison;
|
|
39
|
+
equals(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
40
|
+
eq(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
41
|
+
different(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
42
|
+
diff(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
43
|
+
lessThan(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
44
|
+
lt(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
45
|
+
lessThanOrEqual(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
46
|
+
lte(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
47
|
+
greaterThan(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
48
|
+
gt(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
49
|
+
greaterThanOrEqual(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
50
|
+
gte(propertyOrMeta: string | Record<string, any>, options?: Omit<ComparisonValidatorOptions, "async" | "description">): ModelBuilder<M>;
|
|
51
|
+
description(desc: string): ModelBuilder<M>;
|
|
52
|
+
/**
|
|
53
|
+
* Applies the attribute metadata and decorators to the provided constructor.
|
|
54
|
+
*/
|
|
55
|
+
build(constructor: Constructor<M>): void;
|
|
56
|
+
}
|
|
57
|
+
declare class ListAttributeBuilder<M extends BuildableModel, N extends keyof M> {
|
|
58
|
+
private readonly parent;
|
|
59
|
+
private readonly attribute;
|
|
60
|
+
private readonly collection;
|
|
61
|
+
constructor(parent: ModelBuilder<M>, attribute: AttributeBuilder<M, N, any>, collection: "Array" | "Set");
|
|
62
|
+
ofPrimitives(clazz: Constructor | (() => Constructor) | (Constructor | (() => Constructor))[], message?: string): ModelBuilder<M>;
|
|
63
|
+
ofModel<MM extends BuildableModel>(): ModelBuilder<MM>;
|
|
64
|
+
}
|
|
65
|
+
export declare class ModelBuilder<M extends BuildableModel = BuildableModel> extends ObjectAccumulator<M> {
|
|
66
|
+
private attributes;
|
|
67
|
+
private _name?;
|
|
68
|
+
private _description?;
|
|
69
|
+
private _parent?;
|
|
70
|
+
setName(name: string): this;
|
|
71
|
+
description(desc: string): this;
|
|
72
|
+
private attribute;
|
|
73
|
+
string<N extends keyof M>(attr: N): AttributeBuilder<M, N, StringConstructor>;
|
|
74
|
+
number<N extends keyof M>(attr: N): AttributeBuilder<M, N, NumberConstructor>;
|
|
75
|
+
date<N extends keyof M>(attr: N): AttributeBuilder<M, N, DateConstructor>;
|
|
76
|
+
bigint<N extends keyof M>(attr: N): AttributeBuilder<M, N, BigIntConstructor>;
|
|
77
|
+
instance<N extends keyof M>(clazz: Constructor<any>, attr: N): AttributeBuilder<M, N, Constructor<any>>;
|
|
78
|
+
model<MM extends Model, N extends keyof M>(attr: N): ModelBuilder<MM>;
|
|
79
|
+
listOf<N extends keyof M>(attr: N, collection?: "Array" | "Set"): ListAttributeBuilder<M, N>;
|
|
80
|
+
build(): Constructor<M>;
|
|
81
|
+
static builder<M extends BuildableModel = BuildableModel>(): ModelBuilder<M>;
|
|
82
|
+
static from<N extends Model, M extends ExtendedMetadata<N>>(meta: M, name?: string): Constructor<N>;
|
|
83
|
+
}
|
|
84
|
+
export {};
|