@decaf-ts/decorator-validation 1.7.1 → 1.7.3

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 (50) hide show
  1. package/README.md +312 -20
  2. package/dist/decorator-validation.cjs +245 -94
  3. package/dist/decorator-validation.esm.cjs +245 -95
  4. package/lib/constants/validation.cjs +6 -8
  5. package/lib/constants/validation.d.ts +4 -6
  6. package/lib/esm/constants/validation.d.ts +4 -6
  7. package/lib/esm/constants/validation.js +6 -8
  8. package/lib/esm/index.d.ts +8 -1
  9. package/lib/esm/index.js +9 -2
  10. package/lib/esm/model/Model.d.ts +164 -40
  11. package/lib/esm/model/Model.js +165 -41
  12. package/lib/esm/model/construction.d.ts +4 -2
  13. package/lib/esm/model/construction.js +4 -2
  14. package/lib/esm/model/decorators.d.ts +25 -1
  15. package/lib/esm/model/decorators.js +26 -2
  16. package/lib/esm/model/types.d.ts +48 -31
  17. package/lib/esm/model/types.js +1 -1
  18. package/lib/esm/utils/decorators.d.ts +7 -12
  19. package/lib/esm/utils/decorators.js +8 -13
  20. package/lib/esm/validation/Validators/EmailValidator.js +2 -1
  21. package/lib/esm/validation/Validators/PasswordValidator.js +3 -2
  22. package/lib/esm/validation/Validators/URLValidator.js +2 -1
  23. package/lib/esm/validation/Validators/decorators.d.ts +1 -1
  24. package/lib/esm/validation/Validators/decorators.js +2 -2
  25. package/lib/esm/validation/Validators/utils.d.ts +4 -0
  26. package/lib/esm/validation/Validators/utils.js +5 -1
  27. package/lib/esm/validation/decorators.d.ts +20 -26
  28. package/lib/esm/validation/decorators.js +21 -27
  29. package/lib/index.cjs +9 -2
  30. package/lib/index.d.ts +8 -1
  31. package/lib/model/Model.cjs +165 -41
  32. package/lib/model/Model.d.ts +164 -40
  33. package/lib/model/construction.cjs +4 -2
  34. package/lib/model/construction.d.ts +4 -2
  35. package/lib/model/decorators.cjs +26 -2
  36. package/lib/model/decorators.d.ts +25 -1
  37. package/lib/model/types.cjs +1 -1
  38. package/lib/model/types.d.ts +48 -31
  39. package/lib/utils/decorators.cjs +8 -13
  40. package/lib/utils/decorators.d.ts +7 -12
  41. package/lib/validation/Validators/EmailValidator.cjs +2 -1
  42. package/lib/validation/Validators/PasswordValidator.cjs +2 -1
  43. package/lib/validation/Validators/URLValidator.cjs +2 -1
  44. package/lib/validation/Validators/decorators.cjs +2 -2
  45. package/lib/validation/Validators/decorators.d.ts +1 -1
  46. package/lib/validation/Validators/utils.cjs +5 -1
  47. package/lib/validation/Validators/utils.d.ts +4 -0
  48. package/lib/validation/decorators.cjs +21 -27
  49. package/lib/validation/decorators.d.ts +20 -26
  50. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  ![Banner](./workdocs/assets/Banner.png)
2
2
  ## Simple Decorator based Model Validation Engine
3
3
 
4
+ A comprehensive TypeScript library that provides a powerful model validation framework using decorators. It enables type-safe, declarative validation for your TypeScript models with features for serialization, comparison, and hashing. The library offers a rich set of validation decorators for various data types and constraints, making it easy to define and enforce validation rules on your model properties.
5
+
6
+
4
7
  ![Licence](https://img.shields.io/github/license/decaf-ts/decorator-validation.svg?style=plastic)
5
8
  ![GitHub language count](https://img.shields.io/github/languages/count/decaf-ts/decorator-validation?style=plastic)
6
9
  ![GitHub top language](https://img.shields.io/github/languages/top/decaf-ts/decorator-validation?style=plastic)
@@ -15,12 +18,6 @@
15
18
  ![Pull Requests](https://img.shields.io/github/issues-pr-closed/decaf-ts/decorator-validation.svg)
16
19
  ![Maintained](https://img.shields.io/badge/Maintained%3F-yes-green.svg)
17
20
 
18
- ![Line Coverage](workdocs/reports/coverage/badge-lines.svg)
19
- ![Function Coverage](workdocs/reports/coverage/badge-functions.svg)
20
- ![Statement Coverage](workdocs/reports/coverage/badge-statements.svg)
21
- ![Branch Coverage](workdocs/reports/coverage/badge-branches.svg)
22
-
23
-
24
21
  ![Forks](https://img.shields.io/github/forks/decaf-ts/decorator-validation.svg)
25
22
  ![Stars](https://img.shields.io/github/stars/decaf-ts/decorator-validation.svg)
26
23
  ![Watchers](https://img.shields.io/github/watchers/decaf-ts/decorator-validation.svg)
@@ -32,21 +29,42 @@ Documentation available [here](https://decaf-ts.github.io/decorator-validation/)
32
29
 
33
30
  ### Description
34
31
 
35
- Simple implementation of a Typescript decorator based validation system.
32
+ The decorator-validation library is a comprehensive TypeScript implementation of a decorator-based validation system. It provides a robust framework for defining, validating, and managing model objects in TypeScript applications.
33
+
34
+ Meant to be easily extended, customized, and integrated with browser input validation mechanisms, this library offers a declarative approach to validation through TypeScript decorators.
35
+
36
+ #### Core Components
36
37
 
37
- Meant to be easily extended, customized and integrated with the browser's input validation mechanisms
38
+ ##### Model System
39
+ The library is built around the abstract `Model` class, which serves as the foundation for all model objects. The Model system provides:
40
+
41
+ - A registry mechanism for storing and retrieving model constructors
42
+ - Serialization and deserialization capabilities
43
+ - Hashing functionality for model objects
44
+ - Equality comparison between model objects
45
+ - Support for nested model instantiation and validation
46
+
47
+ ##### Validation Framework
48
+ The validation framework offers a rich set of decorators for validating model properties:
49
+
50
+ - **Basic Validation**: `required()`, `min()`, `max()`, `step()`, `minlength()`, `maxlength()`, `pattern()`
51
+ - **Type-Specific Validation**: `email()`, `url()`, `type()`, `date()`, `password()`, `list()`, `set()`
52
+ - **Comparison Validation**: `eq()`, `diff()`, `lt()`, `lte()`, `gt()`, `gte()` for comparing properties
53
+
54
+ ##### Key Features
55
+ - **Decorator-based validation API** with recursive validation for nested models
56
+ - **Customizable Model building factories** enabling nested instantiation
57
+ - **Model serialization/deserialization** with configurable serializers
58
+ - **Model Hashing** with configurable algorithms
59
+ - **Model Equality** comparison with support for excluding properties
60
+ - **Easily extended custom validation** through the decorator system
61
+ - **Java-like date handling** (format and serialization)
62
+ - **Configurable error messages** for all validation rules
63
+ - **Comparative validation** between attributes, supporting various comparison operators
64
+ - **Type safety** through TypeScript's static typing system
65
+
66
+ The library is designed with extensibility in mind, allowing developers to create custom validators and decorators to meet specific application requirements. It integrates seamlessly with TypeScript's type system to provide compile-time type checking alongside runtime validation.
38
67
 
39
- Standalone module, defines the base Model class:
40
- - decorator based validation api with recursive validation;
41
- - Customizable Model building factories enabling nested instantiation;
42
- - Model serialization/deserialization;
43
- - Model Hashing;
44
- - Model Equality;
45
- - Easily extended custom validation;
46
- - Java like date handling (format and serialization);
47
- - Configurable error messages;
48
- - TODO: comparative validation (between attributes, hierarchical, dates);
49
- - TODO: Model Deep Cloning;
50
68
 
51
69
  ### How to Use
52
70
 
@@ -55,7 +73,281 @@ Standalone module, defines the base Model class:
55
73
 
56
74
  ### Examples
57
75
 
58
-
76
+ #### Creating a Model Class
77
+
78
+ ```typescript
79
+ import { Model, model, required, email, minlength, maxlength, min, hashedBy, serializedBy } from 'decorator-validation';
80
+
81
+ @model()
82
+ @hashedBy('sha256')
83
+ @serializedBy('json')
84
+ class User extends Model {
85
+ @required()
86
+ @minlength(3)
87
+ @maxlength(50)
88
+ username!: string;
89
+
90
+ @required()
91
+ @email()
92
+ email!: string;
93
+
94
+ @required()
95
+ @min(18, "User must be at least 18 years old")
96
+ age!: number;
97
+
98
+ constructor(data?: any) {
99
+ super(data);
100
+ Model.fromModel(this, data);
101
+ }
102
+ }
103
+ ```
104
+
105
+ #### Basic Validation
106
+
107
+ ```typescript
108
+ // Create a user with invalid data
109
+ const invalidUser = new User({
110
+ username: "jo", // too short
111
+ email: "not-an-email",
112
+ age: 16 // below minimum
113
+ });
114
+
115
+ // Check for validation errors
116
+ const errors = invalidUser.hasErrors();
117
+ console.log(errors);
118
+ // Output will contain validation errors for username, email, and age
119
+
120
+ // Create a valid user
121
+ const validUser = new User({
122
+ username: "john_doe",
123
+ email: "john@example.com",
124
+ age: 25
125
+ });
126
+
127
+ // Check for validation errors
128
+ const validErrors = validUser.hasErrors();
129
+ console.log(validErrors); // undefined - no errors
130
+ ```
131
+
132
+ #### Using Different Validation Decorators
133
+
134
+ ##### Numeric Validation
135
+
136
+ ```typescript
137
+ class Product {
138
+ @required()
139
+ name!: string;
140
+
141
+ @required()
142
+ @min(0, "Price cannot be negative")
143
+ @max(10000, "Price cannot exceed 10,000")
144
+ @step(0.01, "Price must have at most 2 decimal places")
145
+ price!: number;
146
+
147
+ constructor(data?: any) {
148
+ Model.fromModel(this, data);
149
+ }
150
+ }
151
+ ```
152
+
153
+ ##### String Validation
154
+
155
+ ```typescript
156
+ class Article {
157
+ @required()
158
+ @minlength(5)
159
+ @maxlength(100)
160
+ title!: string;
161
+
162
+ @required()
163
+ @minlength(50)
164
+ @maxlength(5000)
165
+ content!: string;
166
+
167
+ @pattern(/^[a-z0-9-]+$/, "Slug must contain only lowercase letters, numbers, and hyphens")
168
+ slug!: string;
169
+
170
+ constructor(data?: any) {
171
+ Model.fromModel(this, data);
172
+ }
173
+ }
174
+ ```
175
+
176
+ ##### Special Types Validation
177
+
178
+ ```typescript
179
+ class Contact {
180
+ @required()
181
+ name!: string;
182
+
183
+ @required()
184
+ @email()
185
+ email!: string;
186
+
187
+ @url()
188
+ website?: string;
189
+
190
+ @date("yyyy-MM-dd")
191
+ birthdate?: Date;
192
+
193
+ @password()
194
+ password!: string;
195
+
196
+ constructor(data?: any) {
197
+ Model.fromModel(this, data);
198
+ }
199
+ }
200
+ ```
201
+
202
+ ##### Comparison Validation
203
+
204
+ ```typescript
205
+ class DateRange {
206
+ @required()
207
+ @date("yyyy-MM-dd")
208
+ startDate!: Date;
209
+
210
+ @required()
211
+ @date("yyyy-MM-dd")
212
+ @gt("startDate", "End date must be after start date")
213
+ endDate!: Date;
214
+
215
+ constructor(data?: any) {
216
+ Model.fromModel(this, data);
217
+ }
218
+ }
219
+
220
+ class PriceRange {
221
+ @required()
222
+ @min(0)
223
+ minPrice!: number;
224
+
225
+ @required()
226
+ @min(0)
227
+ @gte("minPrice", "Maximum price must be greater than or equal to minimum price")
228
+ maxPrice!: number;
229
+
230
+ constructor(data?: any) {
231
+ Model.fromModel(this, data);
232
+ }
233
+ }
234
+ ```
235
+
236
+ ##### Collection Validation
237
+
238
+ ```typescript
239
+ class Tag {
240
+ @required()
241
+ name!: string;
242
+
243
+ constructor(data?: any) {
244
+ Model.fromModel(this, data);
245
+ }
246
+ }
247
+
248
+ class BlogPost {
249
+ @required()
250
+ title!: string;
251
+
252
+ @required()
253
+ content!: string;
254
+
255
+ @list(Tag)
256
+ tags!: Tag[];
257
+
258
+ @set(Tag)
259
+ uniqueTags!: Set<Tag>;
260
+
261
+ constructor(data?: any) {
262
+ Model.fromModel(this, data);
263
+ }
264
+ }
265
+ ```
266
+
267
+ #### Model Registry and Building
268
+
269
+ ```typescript
270
+ // Register models
271
+ Model.register(User);
272
+ Model.register(BlogPost);
273
+ Model.register(Tag);
274
+
275
+ // Build a model from plain object
276
+ const userData = {
277
+ username: "jane_doe",
278
+ email: "jane@example.com",
279
+ age: 28
280
+ };
281
+
282
+ const user = Model.build(userData, "User");
283
+
284
+ // Bulk register models
285
+ bulkModelRegister(User, BlogPost, Tag);
286
+ ```
287
+
288
+ #### Serialization and Deserialization
289
+
290
+ ```typescript
291
+ // Create a user
292
+ const user = new User({
293
+ username: "john_doe",
294
+ email: "john@example.com",
295
+ age: 25
296
+ });
297
+
298
+ // Serialize to string
299
+ const serialized = user.serialize();
300
+ console.log(serialized);
301
+ // Output: JSON string representation of the user
302
+
303
+ // Deserialize from string
304
+ const deserialized = Model.deserialize(serialized);
305
+ console.log(deserialized);
306
+ // Output: User object with the same properties
307
+ ```
308
+
309
+ #### Comparing Models
310
+
311
+ ```typescript
312
+ const user1 = new User({
313
+ username: "john_doe",
314
+ email: "john@example.com",
315
+ age: 25
316
+ });
317
+
318
+ const user2 = new User({
319
+ username: "john_doe",
320
+ email: "john@example.com",
321
+ age: 25
322
+ });
323
+
324
+ const user3 = new User({
325
+ username: "jane_doe",
326
+ email: "jane@example.com",
327
+ age: 28
328
+ });
329
+
330
+ console.log(user1.equals(user2)); // true - same properties
331
+ console.log(user1.equals(user3)); // false - different properties
332
+
333
+ // Compare ignoring specific properties
334
+ console.log(user1.equals(user3, "username", "email")); // true - only comparing age
335
+ ```
336
+
337
+ #### Hashing Models
338
+
339
+ ```typescript
340
+ const user = new User({
341
+ username: "john_doe",
342
+ email: "john@example.com",
343
+ age: 25
344
+ });
345
+
346
+ // Get hash of the model
347
+ const hash = user.hash();
348
+ console.log(hash);
349
+ // Output: Hash string based on the configured algorithm (sha256)
350
+ ```
59
351
 
60
352
 
61
353
  ### Related