@decaf-ts/decorator-validation 1.11.16 → 1.11.18
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 +72 -421
- 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/constants/errors.cjs +6 -4
- package/lib/constants/errors.d.ts +6 -0
- package/lib/constants/errors.js.map +1 -1
- package/lib/constants/validation.cjs +9 -2
- package/lib/constants/validation.d.ts +9 -2
- package/lib/constants/validation.js.map +1 -1
- package/lib/esm/constants/errors.d.ts +6 -0
- package/lib/esm/constants/errors.js +6 -4
- package/lib/esm/constants/errors.js.map +1 -1
- package/lib/esm/constants/validation.d.ts +9 -2
- package/lib/esm/constants/validation.js +9 -2
- package/lib/esm/constants/validation.js.map +1 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/model/decorators.d.ts +8 -0
- package/lib/esm/model/decorators.js +8 -0
- package/lib/esm/model/decorators.js.map +1 -1
- package/lib/esm/overrides/types.d.ts +8 -0
- package/lib/esm/validation/decorators.js +1 -1
- package/lib/esm/validation/decorators.js.map +1 -1
- package/lib/esm/validation/index.d.ts +5 -0
- package/lib/esm/validation/index.js +5 -0
- package/lib/esm/validation/index.js.map +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/model/decorators.cjs +8 -0
- package/lib/model/decorators.d.ts +8 -0
- package/lib/model/decorators.js.map +1 -1
- package/lib/overrides/types.d.ts +8 -0
- package/lib/validation/decorators.cjs +1 -1
- package/lib/validation/decorators.js.map +1 -1
- package/lib/validation/index.cjs +5 -0
- package/lib/validation/index.d.ts +5 -0
- package/lib/validation/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,14 @@ A TypeScript decorator-driven validation and model framework. It lets you:
|
|
|
10
10
|
|
|
11
11
|
> Release docs refreshed on 2025-11-26. See [workdocs/reports/RELEASE_NOTES.md](./workdocs/reports/RELEASE_NOTES.md) for ticket summaries.
|
|
12
12
|
|
|
13
|
+
### Core Concepts
|
|
14
|
+
|
|
15
|
+
* **`@model()`**: A class decorator that turns a regular class into a validatable model.
|
|
16
|
+
* **Validation Decorators**: A rich set of decorators for defining validation rules on properties (e.g., `@required`, `@email`, `@minLength`).
|
|
17
|
+
* **`Model` Class**: An abstract base class that provides validation, serialization, hashing, and comparison methods.
|
|
18
|
+
* **`Validation` Class**: A static class for managing the validator registry and creating custom validation logic.
|
|
19
|
+
* **Builders and Registries**: Pluggable systems for controlling how models are constructed, serialized, and hashed.
|
|
20
|
+
|
|
13
21
|

|
|
14
22
|

|
|
15
23
|

|
|
@@ -80,498 +88,141 @@ Design principles
|
|
|
80
88
|
- Separation of concerns: Decorators express intent; Validator classes implement behavior; Model provides lifecycle utilities.
|
|
81
89
|
|
|
82
90
|
|
|
83
|
-
# How to Use
|
|
84
|
-
|
|
85
|
-
This guide shows concrete, TypeScript-accurate examples for the main public APIs exported by the library. Examples are inspired by patterns used across the repo tests and typical usage of decorator-driven validation and models.
|
|
86
|
-
|
|
87
|
-
Notes
|
|
88
|
-
- Import paths assume a consumer importing from the package entry and submodules as re-exported by src/index.ts.
|
|
89
|
-
- All snippets are valid TypeScript.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
## Model decorators and model lifecycle
|
|
93
|
-
|
|
94
|
-
### @model()
|
|
95
|
-
Description: Marks a class as a model. The constructor is wrapped to bind model utilities and run a global builder (if any).
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
import { model, Model, ModelArg } from "@decaf-ts/decorator-validation";
|
|
99
|
-
|
|
100
|
-
@model()
|
|
101
|
-
class User extends Model {
|
|
102
|
-
@prop()
|
|
103
|
-
id!: string;
|
|
104
|
-
@prop()
|
|
105
|
-
name!: string;
|
|
106
|
-
|
|
107
|
-
constructor(arg?: ModelArg<User>) {
|
|
108
|
-
super(arg);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const u = new User();
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Extending from the Model class is optional but highly recommended. Regardless, if decorated with `@model()`, the constructor signature must be compatible.
|
|
116
|
-
|
|
117
|
-
When using a class for validation, eg `hasErrors()` only, @model() is not required.
|
|
118
|
-
|
|
119
|
-
#### Model construction
|
|
120
|
-
|
|
121
|
-
When a class is decorated with @model(), the framework invokes a model building function right after the instance is constructed. This builder initializes your model from the argument you pass to the constructor.
|
|
122
|
-
|
|
123
|
-
There are two builder strategies:
|
|
124
|
-
- Model.fromObject: Accepts a plain object and performs a more permissive, best-effort mapping.
|
|
125
|
-
- Does not enforce nested Model classes
|
|
126
|
-
- Model.fromModel (default): does the same as fromObject, but also instantiates nested Model classes
|
|
127
|
-
|
|
128
|
-
Your model constructors should accept an optional argument and pass it to super so the builder can use it.
|
|
129
|
-
|
|
130
|
-
You can change between builder functions by using:
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
import { required, Model, model, ModelArg } from "@decaf-ts/decorator-validation";
|
|
134
|
-
|
|
135
|
-
@model()
|
|
136
|
-
class Child extends Model {
|
|
137
|
-
@required()
|
|
138
|
-
name!: string;
|
|
139
|
-
|
|
140
|
-
constructor(arg?: ModelArg<Child>) {
|
|
141
|
-
super(arg);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
@model()
|
|
146
|
-
class Parent extends Model {
|
|
147
|
-
@required()
|
|
148
|
-
name!: string;
|
|
149
|
-
@required()
|
|
150
|
-
child!: Child;
|
|
151
|
-
constructor(arg?: ModelArg<Parent>) {
|
|
152
|
-
super(arg);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// Default builder is Model.fromModel
|
|
156
|
-
|
|
157
|
-
let parent = new Parent({
|
|
158
|
-
child: {
|
|
159
|
-
name: "child"
|
|
160
|
-
}
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
parent.child instanceof Child; // true
|
|
164
|
-
|
|
165
|
-
Model.setBuilder(Model.fromObject);
|
|
166
|
-
|
|
167
|
-
parent = new Parent({
|
|
168
|
-
child: {
|
|
169
|
-
name: "child"
|
|
170
|
-
}
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
parent.child instanceof Child; // false
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### @hashedBy(algorithm, ...args)
|
|
177
|
-
Description: Declares which hashing strategy to use when hashing model instances.
|
|
91
|
+
# How to Use
|
|
178
92
|
|
|
179
|
-
|
|
180
|
-
import { model, hashedBy, ModelArg, prop } from "@decaf-ts/decorator-validation";
|
|
93
|
+
This guide provides examples of how to use the main features of the `@decaf-ts/decorator-validation` library.
|
|
181
94
|
|
|
182
|
-
|
|
183
|
-
@hashedBy("sha256", "utf8")
|
|
184
|
-
class FileInfo extends Model {
|
|
185
|
-
@prop()
|
|
186
|
-
path!: string;
|
|
187
|
-
@prop()
|
|
188
|
-
size!: number;
|
|
189
|
-
|
|
190
|
-
constructor(arg?: ModelArg<FileInfo>) {
|
|
191
|
-
super(arg)
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
```
|
|
95
|
+
## Creating a Model
|
|
195
96
|
|
|
196
|
-
|
|
197
|
-
Description: Declares which serializer to use for (de)serializing model instances.
|
|
97
|
+
The `@model()` decorator is the entry point for creating a validatable model.
|
|
198
98
|
|
|
199
99
|
```typescript
|
|
200
|
-
import {
|
|
100
|
+
import { model, Model } from '@decaf-ts/decorator-validation';
|
|
201
101
|
|
|
202
102
|
@model()
|
|
203
|
-
@serializedBy("json")
|
|
204
|
-
class Settings extends Model {
|
|
205
|
-
@prop()
|
|
206
|
-
theme!: string;
|
|
207
|
-
@prop()
|
|
208
|
-
locale!: string;
|
|
209
|
-
|
|
210
|
-
constructor(arg?: ModelArg<Settings>){
|
|
211
|
-
super(arg)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### @description(text)
|
|
217
|
-
Description: Applies textual documentation metadata to a class, property, or method.
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
import { model, description, Model } from "@decaf-ts/decorator-validation";
|
|
221
|
-
|
|
222
|
-
@model()
|
|
223
|
-
@description("Represents an application user")
|
|
224
103
|
class User extends Model {
|
|
225
|
-
@description("Unique identifier")
|
|
226
|
-
id!: string;
|
|
227
104
|
// ...
|
|
228
105
|
}
|
|
229
106
|
```
|
|
230
107
|
|
|
108
|
+
## Validation Decorators
|
|
231
109
|
|
|
232
|
-
|
|
233
|
-
Each decorator writes metadata for a corresponding Validator. Use them on model fields.
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
### @prop()
|
|
237
|
-
Description: Registers a property with the model system. This is required for model construction so the property participates in metadata, serialization, hashing, validation discovery, etc.
|
|
238
|
-
|
|
239
|
-
Important
|
|
240
|
-
- All other property decorators (e.g., @required, @min, @email, etc.) already apply @prop under the hood.
|
|
241
|
-
- Therefore, you only need to use @prop when a property has no other decorators.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
### @required(message?)
|
|
245
|
-
Description: Field must be present and non-empty.
|
|
110
|
+
The library provides a rich set of decorators for defining validation rules on properties.
|
|
246
111
|
|
|
247
112
|
```typescript
|
|
248
|
-
import { Model, required,
|
|
113
|
+
import { model, Model, required, email, minLength } from '@decaf-ts/decorator-validation';
|
|
249
114
|
|
|
250
115
|
@model()
|
|
251
116
|
class User extends Model {
|
|
252
117
|
@required()
|
|
253
|
-
|
|
254
|
-
//...
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### @min(value, message?) and @max(value, message?)
|
|
259
|
-
Description: Numeric or date boundaries.
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
import { model } from "@decaf-ts/decorator-validation";
|
|
263
|
-
import { min } from "@decaf-ts/decorator-validation";
|
|
264
|
-
import { max } from "@decaf-ts/decorator-validation";
|
|
265
|
-
|
|
266
|
-
@model()
|
|
267
|
-
class Product extends Model {
|
|
268
|
-
@min(0)
|
|
269
|
-
@max(1000)
|
|
270
|
-
price!: number;
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### @minLength(n, message?) and @maxLength(n, message?)
|
|
275
|
-
Description: String length boundaries.
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
import { model, Model } from "@decaf-ts/decorator-validation";
|
|
279
|
-
import { minLength, maxLength } from "@decaf-ts/decorator-validation";
|
|
280
|
-
|
|
281
|
-
@model()
|
|
282
|
-
class Credentials extends Model {
|
|
283
|
-
@minLength(8)
|
|
284
|
-
@maxLength(64)
|
|
285
|
-
password!: string;
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### @pattern(regex | string, message?)
|
|
290
|
-
Description: String must match a pattern.
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
import { model } from "@decaf-ts/decorator-validation";
|
|
294
|
-
import { pattern, model } from "@decaf-ts/decorator-validation";
|
|
295
|
-
|
|
296
|
-
@model()
|
|
297
|
-
class Vehicle extends Model {
|
|
298
|
-
@pattern(/^[A-Z]{2}-\d{2}-[A-Z]{2}$/)
|
|
299
|
-
plate!: string;
|
|
300
|
-
}
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### @email(message?)
|
|
304
|
-
Description: Must be a valid email.
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
307
|
-
import { model } from "@decaf-ts/decorator-validation";
|
|
308
|
-
import { email } from "@decaf-ts/decorator-validation";
|
|
118
|
+
name!: string;
|
|
309
119
|
|
|
310
|
-
@
|
|
311
|
-
class Contact extends Model {
|
|
120
|
+
@required()
|
|
312
121
|
@email()
|
|
313
122
|
email!: string;
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### @url(message?)
|
|
318
|
-
Description: Must be a valid URL.
|
|
319
|
-
|
|
320
|
-
```typescript
|
|
321
|
-
import { model } from "@decaf-ts/decorator-validation";
|
|
322
|
-
import { url } from "@decaf-ts/decorator-validation";
|
|
323
123
|
|
|
324
|
-
@
|
|
325
|
-
|
|
326
|
-
@url()
|
|
327
|
-
href!: string;
|
|
124
|
+
@minLength(8)
|
|
125
|
+
password!: string;
|
|
328
126
|
}
|
|
329
127
|
```
|
|
330
128
|
|
|
331
|
-
|
|
332
|
-
Description: Enforces a runtime type match (e.g., Number, String, Date).
|
|
129
|
+
## Validating a Model
|
|
333
130
|
|
|
334
|
-
|
|
335
|
-
import { model } from "@decaf-ts/decorator-validation";
|
|
336
|
-
import { type } from "@decaf-ts/decorator-validation";
|
|
337
|
-
|
|
338
|
-
@model()
|
|
339
|
-
class Measurement extends Model {
|
|
340
|
-
@type(Number)
|
|
341
|
-
value!: number;
|
|
342
|
-
}
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
### @equals(otherValueOrPath, message?)
|
|
346
|
-
Description: Value must equal the provided value or another property.
|
|
131
|
+
You can validate a model instance using the `hasErrors()` method.
|
|
347
132
|
|
|
348
133
|
```typescript
|
|
349
|
-
|
|
350
|
-
|
|
134
|
+
const user = new User();
|
|
135
|
+
const errors = user.hasErrors();
|
|
351
136
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
password!: string;
|
|
355
|
-
@equals(":password")
|
|
356
|
-
confirm!: string;
|
|
137
|
+
if (errors) {
|
|
138
|
+
console.log('Validation errors:', errors);
|
|
357
139
|
}
|
|
358
140
|
```
|
|
359
141
|
|
|
360
|
-
###
|
|
361
|
-
Description: Numeric or date comparisons.
|
|
142
|
+
### Ignoring Properties
|
|
362
143
|
|
|
363
|
-
|
|
364
|
-
import { model } from "@decaf-ts/decorator-validation";
|
|
365
|
-
import { greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual } from "@decaf-ts/decorator-validation";
|
|
366
|
-
|
|
367
|
-
@model()
|
|
368
|
-
class Range extends Model {
|
|
369
|
-
@greaterThan(0)
|
|
370
|
-
@lessThanOrEqual(100)
|
|
371
|
-
ratio!: number;
|
|
372
|
-
}
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### @step(step, message?)
|
|
376
|
-
Description: Numeric step constraints.
|
|
144
|
+
You can ignore properties during validation by passing their names to `hasErrors()`.
|
|
377
145
|
|
|
378
146
|
```typescript
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
@model()
|
|
383
|
-
class Slider extends Model {
|
|
384
|
-
@step(0.5)
|
|
385
|
-
value!: number;
|
|
386
|
-
}
|
|
147
|
+
const user = new User();
|
|
148
|
+
// Ignore the 'password' property during validation
|
|
149
|
+
const errors = user.hasErrors('password');
|
|
387
150
|
```
|
|
388
151
|
|
|
389
|
-
|
|
390
|
-
Description: Constrains value to be one of the provided list.
|
|
391
|
-
|
|
392
|
-
```typescript
|
|
393
|
-
import { model, Model } from "@decaf-ts/decorator-validation";
|
|
394
|
-
import { list } from "@decaf-ts/decorator-validation";
|
|
395
|
-
|
|
396
|
-
@model()
|
|
397
|
-
class ThemeSettingm extends Model {
|
|
398
|
-
@list(["light", "dark", "system"])
|
|
399
|
-
theme!: "light" | "dark" | "system";
|
|
400
|
-
}
|
|
401
|
-
```
|
|
152
|
+
## Serialization and Hashing
|
|
402
153
|
|
|
403
|
-
|
|
404
|
-
Description: Must be different from another property.
|
|
154
|
+
The `Model` class provides methods for serializing and hashing instances.
|
|
405
155
|
|
|
406
156
|
```typescript
|
|
407
|
-
|
|
408
|
-
import { diff } from "@decaf-ts/decorator-validation";
|
|
157
|
+
const user = new User({ name: 'John Doe', email: 'john.doe@example.com' });
|
|
409
158
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
username!: string;
|
|
413
|
-
@diff(":username")
|
|
414
|
-
password!: string;
|
|
415
|
-
}
|
|
159
|
+
const serializedUser = user.serialize();
|
|
160
|
+
const userHash = user.hash();
|
|
416
161
|
```
|
|
417
162
|
|
|
418
|
-
|
|
419
|
-
Description: Date constraints for a date-typed field.
|
|
420
|
-
|
|
421
|
-
```typescript
|
|
422
|
-
import { model, Model } from "@decaf-ts/decorator-validation";
|
|
423
|
-
import { date } from "@decaf-ts/decorator-validation";
|
|
424
|
-
|
|
425
|
-
@model()
|
|
426
|
-
class Booking extends Model {
|
|
427
|
-
@date({ min: new Date("2025-01-01"), max: new Date("2025-12-31") })
|
|
428
|
-
start!: Date;
|
|
429
|
-
}
|
|
430
|
-
```
|
|
163
|
+
## Model Construction
|
|
431
164
|
|
|
432
|
-
|
|
433
|
-
Description: Password strength constraints (e.g., min length, uppercase, digits, symbols) depending on validator configuration.
|
|
165
|
+
The library provides a flexible system for constructing model instances.
|
|
434
166
|
|
|
435
167
|
```typescript
|
|
436
|
-
import {
|
|
437
|
-
import { password, Model } from "@decaf-ts/decorator-validation";
|
|
438
|
-
|
|
439
|
-
@model()
|
|
440
|
-
class Account extends Model{
|
|
441
|
-
@password({ minLength: 10 })
|
|
442
|
-
password!: string;
|
|
443
|
-
}
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
### async()
|
|
447
|
-
Description: Marks a model as involving async validation rules (decorator flag helper).
|
|
168
|
+
import { Model } from '@decaf-ts/decorator-validation';
|
|
448
169
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
import { async } from "@decaf-ts/decorator-validation";
|
|
170
|
+
// Create a new instance
|
|
171
|
+
const user1 = new User({ name: 'Jane Doe' });
|
|
452
172
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
173
|
+
// Create an instance from a plain object
|
|
174
|
+
const user2 = Model.build({
|
|
175
|
+
[Model.ANCHOR]: 'User',
|
|
176
|
+
name: 'John Smith',
|
|
177
|
+
email: 'john.smith@example.com'
|
|
178
|
+
});
|
|
458
179
|
```
|
|
459
180
|
|
|
181
|
+
## Custom Validators
|
|
460
182
|
|
|
461
|
-
|
|
462
|
-
Use the model validation utilities to evaluate rules defined by decorators.
|
|
183
|
+
You can create custom validators by extending the `Validator` class and registering them with the `Validation` class.
|
|
463
184
|
|
|
464
185
|
```typescript
|
|
465
|
-
import {
|
|
186
|
+
import { Validator, Validation, metadata } from '@decaf-ts/decorator-validation';
|
|
466
187
|
|
|
467
|
-
|
|
468
|
-
class
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
email!: string;
|
|
472
|
-
|
|
473
|
-
constructor(arg?: ModelArg<Contact>) {
|
|
474
|
-
super(arg);
|
|
188
|
+
// 1. Create a custom validator
|
|
189
|
+
class MyCustomValidator extends Validator {
|
|
190
|
+
constructor() {
|
|
191
|
+
super('my-custom-validator', 'Invalid value');
|
|
475
192
|
}
|
|
476
|
-
}
|
|
477
193
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
let errs = c.hasErrors(); // resolves to a list of errors or undefined
|
|
483
|
-
|
|
484
|
-
@async()
|
|
485
|
-
@model()
|
|
486
|
-
class User extends Model {
|
|
487
|
-
@required()
|
|
488
|
-
@email()
|
|
489
|
-
email!: string;
|
|
490
|
-
|
|
491
|
-
constructor(arg?: ModelArg<User>) {
|
|
492
|
-
super(arg);
|
|
194
|
+
validate(value: any): boolean {
|
|
195
|
+
// Custom validation logic
|
|
196
|
+
return value === 'valid';
|
|
493
197
|
}
|
|
494
198
|
}
|
|
495
199
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
})
|
|
499
|
-
|
|
500
|
-
errs = await u.hasErrors(); // resolves to a list of errors or undefined
|
|
501
|
-
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
## Validation registry APIs (Validation)
|
|
506
|
-
|
|
507
|
-
### Validation.setRegistry(registry, migration?)
|
|
508
|
-
Description: Swap the active validator registry and optionally migrate validators.
|
|
509
|
-
|
|
510
|
-
```typescript
|
|
511
|
-
import { Validation, ValidatorRegistry } from "@decaf-ts/decorator-validation";
|
|
512
|
-
|
|
513
|
-
const custom = new ValidatorRegistry();
|
|
514
|
-
Validation.setRegistry(custom, v => v); // trivial migration
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
### Validation.register(...validators)
|
|
518
|
-
Description: Register one or more Validator implementations or definitions.
|
|
519
|
-
|
|
520
|
-
```typescript
|
|
521
|
-
import { Validation, Validator, validator } from "@decaf-ts/decorator-validation";
|
|
200
|
+
// 2. Register the validator
|
|
201
|
+
Validation.register(new MyCustomValidator());
|
|
522
202
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
203
|
+
// 3. Create a decorator for the validator
|
|
204
|
+
function myCustom() {
|
|
205
|
+
return metadata(Validation.key('my-custom-validator'), {});
|
|
526
206
|
}
|
|
527
207
|
|
|
528
|
-
|
|
208
|
+
// 4. Use the decorator
|
|
209
|
+
@model()
|
|
210
|
+
class MyModel extends Model {
|
|
211
|
+
@myCustom()
|
|
212
|
+
myProp: string;
|
|
213
|
+
}
|
|
529
214
|
```
|
|
530
215
|
|
|
531
|
-
|
|
532
|
-
Description: Retrieve a registered validator by key.
|
|
216
|
+
## Date Operations
|
|
533
217
|
|
|
534
|
-
|
|
535
|
-
import { Validation, ValidationKeys } from "@decaf-ts/decorator-validation";
|
|
536
|
-
|
|
537
|
-
const requiredValidator = Validation.get(ValidationKeys.REQUIRED);
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
### Validation.key(k) and Validation.keys()
|
|
541
|
-
Description: Build a reflect-metadata key or list all registered keys.
|
|
218
|
+
The library includes a `DateBuilder` for creating and manipulating dates.
|
|
542
219
|
|
|
543
220
|
```typescript
|
|
544
|
-
import {
|
|
221
|
+
import { DateBuilder } from '@decaf-ts/decorator-validation';
|
|
545
222
|
|
|
546
|
-
const
|
|
547
|
-
const allKeys = Validation.keys();
|
|
223
|
+
const date = new DateBuilder().addDays(5).build();
|
|
548
224
|
```
|
|
549
225
|
|
|
550
|
-
## Notes on tests and validity
|
|
551
|
-
- Patterns here reflect common test patterns found across the monorepo (e.g., model decoration, decorator application, registry customization).
|
|
552
|
-
- Each snippet is valid TypeScript and aligns with the re-exports provided by the package entry.
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
## Coding Principles
|
|
556
|
-
|
|
557
|
-
- group similar functionality in folders (analog to namespaces but without any namespace declaration)
|
|
558
|
-
- one class per file;
|
|
559
|
-
- one interface per file (unless interface is just used as a type);
|
|
560
|
-
- group types as other interfaces in a types.ts file per folder;
|
|
561
|
-
- group constants or enums in a constants.ts file per folder;
|
|
562
|
-
- group decorators in a decorators.ts file per folder;
|
|
563
|
-
- always import from the specific file, never from a folder or index file (exceptions for dependencies on other packages);
|
|
564
|
-
- prefer the usage of established design patters where applicable:
|
|
565
|
-
- Singleton (can be an anti-pattern. use with care);
|
|
566
|
-
- factory;
|
|
567
|
-
- observer;
|
|
568
|
-
- strategy;
|
|
569
|
-
- builder;
|
|
570
|
-
- etc;
|
|
571
|
-
|
|
572
|
-
## Release Documentation Hooks
|
|
573
|
-
Stay aligned with the automated release pipeline by reviewing [Release Notes](./workdocs/reports/RELEASE_NOTES.md) and [Dependencies](./workdocs/reports/DEPENDENCIES.md) after trying these recipes (updated on 2025-11-26).
|
|
574
|
-
|
|
575
226
|
|
|
576
227
|
### Related
|
|
577
228
|
|