1
1
import * as Joi from 'joi' ;
2
2
import { PropertyMetadata , PropertyRule } from '../lib/decorators' ;
3
3
import { ModeEnum , TypeEnum } from '../lib/enums' ;
4
- import { BaseEntity , EntityRef , EntityTransformer } from '../lib/entity' ;
4
+ import { BaseEntity , EntityRef , EntityTransformer , EntityOptions } from '../lib/entity' ;
5
5
import { decorators } from '../lib/symbols' ;
6
6
7
7
interface PropertySchema {
@@ -12,14 +12,21 @@ interface PropertySchema {
12
12
13
13
export { ObjectSchema as SchemaType } from 'joi' ;
14
14
15
- export class JoiTransformer implements EntityTransformer < Joi . ObjectSchema > {
15
+ export class JoiTransformer implements EntityTransformer < Joi . ObjectSchema | Joi . ArraySchema > {
16
16
17
17
private objectIdRegex = / ^ [ 0 - 9 a - f A - F ] { 24 } $ / ;
18
18
19
- build ( source : PropertyMetadata [ ] , mode : ModeEnum , more : Joi . ObjectSchema = Joi . object ( ) , parent ?: BaseEntity ) : Joi . ObjectSchema {
20
- return ! source ? undefined : more . concat (
21
- this . reduceSchema ( source . map ( _ => this . propertyHandler ( _ , mode ) ) , ! ! parent ? parent . schema ( mode ) : undefined )
19
+ build ( source : PropertyMetadata [ ] , opts : EntityOptions , more : Joi . ObjectSchema = Joi . object ( ) ,
20
+ parent ?: BaseEntity ) : Joi . ObjectSchema | Joi . ArraySchema {
21
+ opts . unknown = opts . unknown === undefined || opts . unknown === null ? true : opts . unknown ;
22
+ const result = ! source ? undefined : more . concat (
23
+ this . reduceSchema ( source . map ( _ => this . propertyHandler ( _ , opts . mode , opts . unknown ) ) ,
24
+ opts . unknown , ! ! parent ? parent . schema ( opts ) : undefined )
22
25
) ;
26
+ if ( ! ! opts . array ) {
27
+ return Joi . array ( ) . items ( result ) ;
28
+ }
29
+ return result ;
23
30
}
24
31
25
32
isValid ( data : BaseEntity , schema : Joi . ObjectSchema ) : boolean {
@@ -43,9 +50,9 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
43
50
* @param {PropertySchema[] } source
44
51
* @returns Joi.ObjectSchema
45
52
*/
46
- private reduceSchema ( source : PropertySchema [ ] , parent ?: Joi . ObjectSchema ) : Joi . ObjectSchema {
53
+ private reduceSchema ( source : PropertySchema [ ] , unknown : boolean , parent ?: Joi . ObjectSchema ) : Joi . ObjectSchema {
47
54
const _s = ! ! parent ? parent : Joi . object ( ) ;
48
- return _s . keys (
55
+ const res = _s . keys (
49
56
source
50
57
. map ( _ => ( {
51
58
property : _ . property ,
@@ -55,7 +62,8 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
55
62
acc [ cur . property ] = cur . schema ;
56
63
return acc ;
57
64
} , { } )
58
- ) . unknown ( ) ;
65
+ ) ;
66
+ return ! ! unknown ? res . unknown ( ) : res ;
59
67
}
60
68
61
69
/**
@@ -67,19 +75,19 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
67
75
* @param {ModeEnum } mode
68
76
* @returns PropertySchema
69
77
*/
70
- private propertyHandler ( source : PropertyMetadata , mode : ModeEnum ) : PropertySchema {
78
+ private propertyHandler ( source : PropertyMetadata , mode : ModeEnum , unknown : boolean ) : PropertySchema {
71
79
const base = source
72
80
. rules
73
81
. filter ( _ => _ . key === decorators . KEY_TYPE || _ . key === decorators . KEY_ARRAY || _ . key === decorators . KEY_OBJECT_PATTERN )
74
- . map ( _ => this . ruleHandler ( _ , mode ) )
82
+ . map ( _ => this . ruleHandler ( _ , mode , unknown ) )
75
83
. shift ( ) || Joi . any ( ) ;
76
84
return {
77
85
property : source . property ,
78
86
base,
79
87
schemas : source
80
88
. rules
81
89
. filter ( _ => ( _ . key !== decorators . KEY_TYPE && _ . key !== decorators . KEY_ARRAY && _ . key !== decorators . KEY_OBJECT_PATTERN ) )
82
- . map ( _ => this . ruleHandler ( _ , mode , base ) )
90
+ . map ( _ => this . ruleHandler ( _ , mode , unknown , base ) )
83
91
. filter ( _ => ! ! _ )
84
92
}
85
93
}
@@ -94,12 +102,12 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
94
102
* @param {Joi.Schema } base
95
103
* @returns Joi.Schema
96
104
*/
97
- private ruleHandler ( rule : PropertyRule , mode : ModeEnum , base ?: Joi . Schema ) : Joi . Schema {
105
+ private ruleHandler ( rule : PropertyRule , mode : ModeEnum , unknown : boolean , base ?: Joi . Schema ) : Joi . Schema {
98
106
switch ( rule . key ) {
99
107
case decorators . KEY_TYPE :
100
- return this . typeMapper ( rule , mode ) ;
108
+ return this . typeMapper ( rule , mode , unknown ) ;
101
109
case decorators . KEY_ARRAY :
102
- return Joi . array ( ) . items ( this . typeMapper ( rule , mode ) ) ;
110
+ return Joi . array ( ) . items ( this . typeMapper ( rule , mode , unknown ) ) ;
103
111
case decorators . KEY_REQUIRED :
104
112
return this . requireMapper ( rule , mode ) ;
105
113
case decorators . KEY_STRIP :
@@ -119,7 +127,9 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
119
127
case decorators . KEY_LENGTH :
120
128
return this . lengthMapper ( rule , base ) ;
121
129
case decorators . KEY_OBJECT_PATTERN :
122
- return this . objectPatternMapper ( rule ) ;
130
+ return this . objectPatternMapper ( rule , unknown ) ;
131
+ case decorators . KEY_REGEX :
132
+ return this . regexMapper ( rule ) ;
123
133
/* istanbul ignore next */
124
134
default :
125
135
return Joi . any ( ) ;
@@ -132,7 +142,7 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
132
142
* @param {PropertyRule } rule
133
143
* @returns Joi.Schema
134
144
*/
135
- private typeMapper ( rule : PropertyRule , mode : ModeEnum ) : Joi . Schema {
145
+ private typeMapper ( rule : PropertyRule , mode : ModeEnum , unknown : boolean ) : Joi . Schema {
136
146
switch ( rule . value ) {
137
147
case String :
138
148
return Joi . string ( ) ;
@@ -141,7 +151,7 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
141
151
case Boolean :
142
152
return Joi . boolean ( ) ;
143
153
case Object :
144
- return Joi . object ( ) . unknown ( ) ;
154
+ return unknown ? Joi . object ( ) . unknown ( ) : Joi . object ( ) ;
145
155
case Buffer :
146
156
return Joi . binary ( ) ;
147
157
case Date :
@@ -160,6 +170,10 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
160
170
return Joi . string ( ) . ip ( ) ;
161
171
case TypeEnum . URI :
162
172
return Joi . string ( ) . uri ( ) ;
173
+ case TypeEnum . Email :
174
+ return Joi . string ( ) . email ( ) ;
175
+ case TypeEnum . Timestamp :
176
+ return Joi . date ( ) . timestamp ( ) ;
163
177
/* istanbul ignore next */
164
178
default :
165
179
if ( typeof rule . value === 'function' && new rule . value ( null , { strict : false } ) instanceof BaseEntity ) {
@@ -317,13 +331,28 @@ export class JoiTransformer implements EntityTransformer<Joi.ObjectSchema> {
317
331
* @param {PropertyRule } rule
318
332
* @returns Joi.Schema
319
333
*/
320
- private objectPatternMapper ( rule : PropertyRule ) : Joi . Schema {
334
+ private objectPatternMapper ( rule : PropertyRule , unknown : boolean ) : Joi . Schema {
321
335
if ( ! rule . value . schema ) {
322
336
throw new Error ( 'Wrong schema provided' ) ;
323
337
} else if ( rule . value . schema instanceof BaseEntity ) {
324
338
return Joi . object ( ) . pattern ( rule . value . pattern , rule . value . schema . schema ( ) ) ;
325
339
} else {
326
- return Joi . object ( ) . pattern ( rule . value . pattern , this . typeMapper ( { key : null , value : rule . value . schema } , ModeEnum . READ ) ) ;
340
+ return Joi . object ( ) . pattern ( rule . value . pattern ,
341
+ this . typeMapper ( { key : null , value : rule . value . schema } , ModeEnum . READ , unknown ) ) ;
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Regex mapping
347
+ *
348
+ * @param {PropertyRule } rule
349
+ * @returns Joi.Schema
350
+ */
351
+ private regexMapper ( rule : PropertyRule ) : Joi . Schema {
352
+ if ( ! ( rule . value instanceof RegExp ) ) {
353
+ throw new Error ( 'Wrong regex provided' ) ;
354
+ } else {
355
+ return Joi . string ( ) . regex ( rule . value ) ;
327
356
}
328
357
}
329
358
}
0 commit comments