@@ -11,20 +11,16 @@ var Parse = require('parse/node').Parse;
1111//
1212// There are several options that can help transform:
1313//
14- // query: true indicates that query constraints like $lt are allowed in
15- // the value.
16- //
1714// update: true indicates that __op operators like Add and Delete
1815// in the value are converted to a mongo update form. Otherwise they are
1916// converted to static data.
2017//
2118// validate: true indicates that key names are to be validated.
2219//
2320// Returns an object with {key: key, value: value}.
24- export function transformKeyValue ( schema , className , restKey , restValue , {
21+ function transformKeyValue ( schema , className , restKey , restValue , {
2522 inArray,
2623 inObject,
27- query,
2824 update,
2925 validate,
3026} = { } ) {
@@ -66,47 +62,17 @@ export function transformKeyValue(schema, className, restKey, restValue, {
6662 return { key : key , value : restValue } ;
6763 break ;
6864 case '$or' :
69- if ( ! query ) {
70- throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME ,
71- 'you can only use $or in queries' ) ;
72- }
73- if ( ! ( restValue instanceof Array ) ) {
74- throw new Parse . Error ( Parse . Error . INVALID_QUERY ,
75- 'bad $or format - use an array value' ) ;
76- }
77- var mongoSubqueries = restValue . map ( ( s ) => {
78- return transformWhere ( schema , className , s ) ;
79- } ) ;
80- return { key : '$or' , value : mongoSubqueries } ;
65+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'you can only use $or in queries' ) ;
8166 case '$and' :
82- if ( ! query ) {
83- throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME ,
84- 'you can only use $and in queries' ) ;
85- }
86- if ( ! ( restValue instanceof Array ) ) {
87- throw new Parse . Error ( Parse . Error . INVALID_QUERY ,
88- 'bad $and format - use an array value' ) ;
89- }
90- var mongoSubqueries = restValue . map ( ( s ) => {
91- return transformWhere ( schema , className , s ) ;
92- } ) ;
93- return { key : '$and' , value : mongoSubqueries } ;
67+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'you can only use $and in queries' ) ;
9468 default :
9569 // Other auth data
9670 var authDataMatch = key . match ( / ^ a u t h D a t a \. ( [ a - z A - Z 0 - 9 _ ] + ) \. i d $ / ) ;
9771 if ( authDataMatch ) {
98- if ( query ) {
99- var provider = authDataMatch [ 1 ] ;
100- // Special-case auth data.
101- return { key : '_auth_data_' + provider + '.id' , value : restValue } ;
102- }
103- throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME ,
104- 'can only query on ' + key ) ;
105- break ;
106- } ;
72+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'can only query on ' + key ) ;
73+ }
10774 if ( validate && ! key . match ( / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 _ \. ] * $ / ) ) {
108- throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME ,
109- 'invalid key name: ' + key ) ;
75+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'invalid key name: ' + key ) ;
11076 }
11177 }
11278
@@ -123,20 +89,6 @@ export function transformKeyValue(schema, className, restKey, restValue, {
12389 }
12490 var expectedTypeIsArray = ( expected && expected . type === 'Array' ) ;
12591
126- // Handle query constraints
127- if ( query ) {
128- value = transformConstraint ( restValue , expectedTypeIsArray ) ;
129- if ( value !== CannotTransform ) {
130- return { key : key , value : value } ;
131- }
132- }
133-
134- if ( expectedTypeIsArray && query && ! ( restValue instanceof Array ) ) {
135- return {
136- key : key , value : { '$all' : [ restValue ] }
137- } ;
138- }
139-
14092 // Handle atomic values
14193 var value = transformAtom ( restValue , false , { inArray, inObject } ) ;
14294 if ( value !== CannotTransform ) {
@@ -154,10 +106,6 @@ export function transformKeyValue(schema, className, restKey, restValue, {
154106
155107 // Handle arrays
156108 if ( restValue instanceof Array ) {
157- if ( query ) {
158- throw new Parse . Error ( Parse . Error . INVALID_JSON ,
159- 'cannot use array as query param' ) ;
160- }
161109 value = restValue . map ( ( restObj ) => {
162110 var out = transformKeyValue ( schema , className , restKey , restObj , { inArray : true } ) ;
163111 return out . value ;
@@ -182,20 +130,105 @@ export function transformKeyValue(schema, className, restKey, restValue, {
182130 return { key : key , value : value } ;
183131}
184132
133+ const valueAsDate = value => {
134+ if ( typeof value === 'string' ) {
135+ return new Date ( value ) ;
136+ } else if ( value instanceof Date ) {
137+ return value ;
138+ }
139+ return false ;
140+ }
141+
142+ function transformQueryKeyValue ( className , key , value , { validate } = { } , schema ) {
143+ switch ( key ) {
144+ case 'createdAt' :
145+ if ( valueAsDate ( value ) ) {
146+ return { key : '_created_at' , value : valueAsDate ( value ) }
147+ }
148+ key = '_created_at' ;
149+ break ;
150+ case 'updatedAt' :
151+ if ( valueAsDate ( value ) ) {
152+ return { key : '_updated_at' , value : valueAsDate ( value ) }
153+ }
154+ key = '_updated_at' ;
155+ break ;
156+ case 'expiresAt' :
157+ if ( valueAsDate ( value ) ) {
158+ return { key : 'expiresAt' , value : valueAsDate ( value ) }
159+ }
160+ break ;
161+ case 'objectId' : return { key : '_id' , value}
162+ case 'sessionToken' : return { key : '_session_token' , value}
163+ case '_rperm' :
164+ case '_wperm' :
165+ case '_perishable_token' :
166+ case '_email_verify_token' : return { key, value}
167+ case '$or' :
168+ if ( ! ( value instanceof Array ) ) {
169+ throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'bad $or format - use an array value' ) ;
170+ }
171+ return { key : '$or' , value : value . map ( subQuery => transformWhere ( className , subQuery , { } , schema ) ) } ;
172+ case '$and' :
173+ if ( ! ( value instanceof Array ) ) {
174+ throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'bad $and format - use an array value' ) ;
175+ }
176+ return { key : '$and' , value : value . map ( subQuery => transformWhere ( className , subQuery , { } , schema ) ) } ;
177+ default :
178+ // Other auth data
179+ const authDataMatch = key . match ( / ^ a u t h D a t a \. ( [ a - z A - Z 0 - 9 _ ] + ) \. i d $ / ) ;
180+ if ( authDataMatch ) {
181+ const provider = authDataMatch [ 1 ] ;
182+ // Special-case auth data.
183+ return { key : `_auth_data_${ provider } .id` , value} ;
184+ }
185+ if ( validate && ! key . match ( / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 _ \. ] * $ / ) ) {
186+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'invalid key name: ' + key ) ;
187+ }
188+ }
189+
190+ const expectedTypeIsArray =
191+ schema &&
192+ schema . fields [ key ] &&
193+ schema . fields [ key ] . type === 'Array' ;
194+
195+ const expectedTypeIsPointer =
196+ schema &&
197+ schema . fields [ key ] &&
198+ schema . fields [ key ] . type === 'Pointer' ;
199+
200+ if ( expectedTypeIsPointer || ! schema && value && value . __type === 'Pointer' ) {
201+ key = '_p_' + key ;
202+ }
203+
204+ // Handle query constraints
205+ if ( transformConstraint ( value , expectedTypeIsArray ) !== CannotTransform ) {
206+ return { key, value : transformConstraint ( value , expectedTypeIsArray ) } ;
207+ }
208+
209+ if ( expectedTypeIsArray && ! ( value instanceof Array ) ) {
210+ return { key, value : { '$all' : [ value ] } } ;
211+ }
212+
213+ // Handle atomic values
214+ if ( transformAtom ( value , false ) !== CannotTransform ) {
215+ return { key, value : transformAtom ( value , false ) } ;
216+ } else {
217+ throw new Parse . Error ( Parse . Error . INVALID_JSON , `You cannot use ${ value } as a query parameter.` ) ;
218+ }
219+ }
185220
186221// Main exposed method to help run queries.
187222// restWhere is the "where" clause in REST API form.
188223// Returns the mongo form of the query.
189224// Throws a Parse.Error if the input query is invalid.
190- function transformWhere ( schema , className , restWhere , options = { validate : true } ) {
225+ function transformWhere ( className , restWhere , { validate = true } = { } , schema ) {
191226 let mongoWhere = { } ;
192227 if ( restWhere [ 'ACL' ] ) {
193228 throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'Cannot query on ACL.' ) ;
194229 }
195- let transformKeyOptions = { query : true } ;
196- transformKeyOptions . validate = options . validate ;
197230 for ( let restKey in restWhere ) {
198- let out = transformKeyValue ( schema , className , restKey , restWhere [ restKey ] , transformKeyOptions ) ;
231+ let out = transformQueryKeyValue ( className , restKey , restWhere [ restKey ] , { validate } , schema ) ;
199232 mongoWhere [ out . key ] = out . value ;
200233 }
201234 return mongoWhere ;
0 commit comments