@@ -43,6 +43,7 @@ export class ActionParameterHandler<T extends BaseDriver> {
43
43
44
44
// get parameter value from request and normalize it
45
45
const value = this . normalizeParamValue ( this . driver . getParamFromRequest ( action , param ) , param ) ;
46
+
46
47
if ( isPromiseLike ( value ) )
47
48
return value . then ( value => this . handleValue ( value , action , param ) ) ;
48
49
@@ -73,7 +74,7 @@ export class ActionParameterHandler<T extends BaseDriver> {
73
74
// check cases when parameter is required but its empty and throw errors in this case
74
75
if ( param . required ) {
75
76
const isValueEmpty = value === null || value === undefined || value === "" ;
76
- const isValueEmptyObject = value instanceof Object && Object . keys ( value ) . length === 0 ;
77
+ const isValueEmptyObject = typeof value === "object" && Object . keys ( value ) . length === 0 ;
77
78
78
79
if ( param . type === "body" && ! param . name && ( isValueEmpty || isValueEmptyObject ) ) { // body has a special check and error message
79
80
return Promise . reject ( new ParamRequiredError ( action , param ) ) ;
@@ -108,39 +109,40 @@ export class ActionParameterHandler<T extends BaseDriver> {
108
109
if ( value === null || value === undefined )
109
110
return value ;
110
111
111
- // map @QueryParams object properties from string to basic types ( normalize)
112
- if ( param . type === "queries " && typeof value === "object" ) {
112
+ // if param value is an object and param type match, normalize its string properties
113
+ if ( typeof value === "object " && [ "queries" , "headers" , "params" , "cookies" ] . indexOf ( param . type ) !== - 1 ) {
113
114
Object . keys ( value ) . map ( key => {
114
- const ParamType = Reflect . getMetadata ( "design:type" , param . targetType . prototype , key ) ;
115
- if ( ParamType ) {
116
- const typeString = typeof ParamType ( ) ; // reflected type is always constructor-like (?)
117
- value [ key ] = this . normalizeValue ( value [ key ] , typeString ) ;
115
+ const keyValue = ( value as any ) [ key ] ;
116
+ if ( typeof keyValue === "string" ) {
117
+ const ParamType = Reflect . getMetadata ( "design:type" , param . targetType . prototype , key ) ;
118
+ if ( ParamType ) {
119
+ const typeString = ParamType . name . toLowerCase ( ) ; // reflected type is always constructor-like (?)
120
+ ( value as any ) [ key ] = this . normalizeStringValue ( keyValue , param . name , typeString ) ;
121
+ }
118
122
}
119
123
} ) ;
120
124
}
125
+ // if value is a string, normalize it to demand type
126
+ else if ( typeof value === "string" ) {
127
+ switch ( param . targetName ) {
128
+ case "number" :
129
+ case "string" :
130
+ case "boolean" :
131
+ case "date" :
132
+ return this . normalizeStringValue ( value , param . name , param . targetName ) ;
133
+ }
134
+ }
121
135
122
- switch ( param . targetName ) {
123
-
124
- case "number" :
125
- case "string" :
126
- case "boolean" :
127
- return this . normalizeValue ( value , param . targetName ) ;
128
-
129
- case "date" :
130
- const parsedDate = new Date ( value ) ;
131
- if ( isNaN ( parsedDate . getTime ( ) ) ) {
132
- throw new BadRequestError ( `${ param . name } is invalid! It can't be parsed to date.` ) ;
133
- }
134
- return parsedDate ;
135
-
136
- default :
137
- if ( value && ( param . parse || param . isTargetObject ) ) {
138
- value = this . parseValue ( value , param ) ;
139
- value = this . transformValue ( value , param ) ;
140
- value = this . validateValue ( value , param ) ; // note this one can return promise
141
- }
142
- return value ;
136
+ // if target type is not primitive, transform and validate it
137
+ if ( ( [ "number" , "string" , "boolean" ] . indexOf ( param . targetName ) === - 1 )
138
+ && ( param . parse || param . isTargetObject )
139
+ ) {
140
+ value = this . parseValue ( value , param ) ;
141
+ value = this . transformValue ( value , param ) ;
142
+ value = this . validateValue ( value , param ) ; // note this one can return promise
143
143
}
144
+
145
+ return value ;
144
146
}
145
147
146
148
/**
@@ -168,7 +170,7 @@ export class ActionParameterHandler<T extends BaseDriver> {
168
170
} else {
169
171
throw new ParamNormalizationError ( value , parameterName , parameterType ) ;
170
172
}
171
-
173
+
172
174
case "date" :
173
175
const parsedDate = new Date ( value ) ;
174
176
if ( Number . isNaN ( parsedDate . getTime ( ) ) ) {
0 commit comments