@@ -11,20 +11,16 @@ var Parse = require('parse/node').Parse;
11
11
//
12
12
// There are several options that can help transform:
13
13
//
14
- // query: true indicates that query constraints like $lt are allowed in
15
- // the value.
16
- //
17
14
// update: true indicates that __op operators like Add and Delete
18
15
// in the value are converted to a mongo update form. Otherwise they are
19
16
// converted to static data.
20
17
//
21
18
// validate: true indicates that key names are to be validated.
22
19
//
23
20
// Returns an object with {key: key, value: value}.
24
- export function transformKeyValue ( schema , className , restKey , restValue , {
21
+ function transformKeyValue ( schema , className , restKey , restValue , {
25
22
inArray,
26
23
inObject,
27
- query,
28
24
update,
29
25
validate,
30
26
} = { } ) {
@@ -66,26 +62,128 @@ export function transformKeyValue(schema, className, restKey, restValue, {
66
62
return { key : key , value : restValue } ;
67
63
break ;
68
64
case '$or' :
69
- if ( ! query ) {
70
- throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME ,
71
- 'you can only use $or in queries' ) ;
65
+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'you can only use $or in queries' ) ;
66
+ case '$and' :
67
+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'you can only use $and in queries' ) ;
68
+ default :
69
+ // Other auth data
70
+ var authDataMatch = key . match ( / ^ a u t h D a t a \. ( [ a - z A - Z 0 - 9 _ ] + ) \. i d $ / ) ;
71
+ if ( authDataMatch ) {
72
+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'can only query on ' + key ) ;
73
+ }
74
+ if ( validate && ! key . match ( / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 _ \. ] * $ / ) ) {
75
+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'invalid key name: ' + key ) ;
72
76
}
77
+ }
78
+
79
+ // Handle special schema key changes
80
+ // TODO: it seems like this is likely to have edge cases where
81
+ // pointer types are missed
82
+ var expected = undefined ;
83
+ if ( schema && schema . getExpectedType ) {
84
+ expected = schema . getExpectedType ( className , key ) ;
85
+ }
86
+ if ( ( expected && expected . type == 'Pointer' ) ||
87
+ ( ! expected && restValue && restValue . __type == 'Pointer' ) ) {
88
+ key = '_p_' + key ;
89
+ }
90
+ var expectedTypeIsArray = ( expected && expected . type === 'Array' ) ;
91
+
92
+ // Handle atomic values
93
+ var value = transformAtom ( restValue , false , { inArray, inObject } ) ;
94
+ if ( value !== CannotTransform ) {
95
+ if ( timeField && ( typeof value === 'string' ) ) {
96
+ value = new Date ( value ) ;
97
+ }
98
+ return { key : key , value : value } ;
99
+ }
100
+
101
+ // ACLs are handled before this method is called
102
+ // If an ACL key still exists here, something is wrong.
103
+ if ( key === 'ACL' ) {
104
+ throw 'There was a problem transforming an ACL.' ;
105
+ }
106
+
107
+ // Handle arrays
108
+ if ( restValue instanceof Array ) {
109
+ value = restValue . map ( ( restObj ) => {
110
+ var out = transformKeyValue ( schema , className , restKey , restObj , { inArray : true } ) ;
111
+ return out . value ;
112
+ } ) ;
113
+ return { key : key , value : value } ;
114
+ }
115
+
116
+ // Handle update operators
117
+ value = transformUpdateOperator ( restValue , ! update ) ;
118
+ if ( value !== CannotTransform ) {
119
+ return { key : key , value : value } ;
120
+ }
121
+
122
+ // Handle normal objects by recursing
123
+ value = { } ;
124
+ for ( var subRestKey in restValue ) {
125
+ var subRestValue = restValue [ subRestKey ] ;
126
+ var out = transformKeyValue ( schema , className , subRestKey , subRestValue , { inObject : true } ) ;
127
+ // For recursed objects, keep the keys in rest format
128
+ value [ subRestKey ] = out . value ;
129
+ }
130
+ return { key : key , value : value } ;
131
+ }
132
+
133
+ function transformQueryKeyValue ( schema , className , restKey , restValue , {
134
+ inArray,
135
+ inObject,
136
+ update,
137
+ validate,
138
+ } = { } ) {
139
+ // Check if the schema is known since it's a built-in field.
140
+ var key = restKey ;
141
+ var timeField = false ;
142
+ switch ( key ) {
143
+ case 'objectId' :
144
+ case '_id' :
145
+ key = '_id' ;
146
+ break ;
147
+ case 'createdAt' :
148
+ case '_created_at' :
149
+ key = '_created_at' ;
150
+ timeField = true ;
151
+ break ;
152
+ case 'updatedAt' :
153
+ case '_updated_at' :
154
+ key = '_updated_at' ;
155
+ timeField = true ;
156
+ break ;
157
+ case '_email_verify_token' :
158
+ key = "_email_verify_token" ;
159
+ break ;
160
+ case '_perishable_token' :
161
+ key = "_perishable_token" ;
162
+ break ;
163
+ case 'sessionToken' :
164
+ case '_session_token' :
165
+ key = '_session_token' ;
166
+ break ;
167
+ case 'expiresAt' :
168
+ case '_expiresAt' :
169
+ key = 'expiresAt' ;
170
+ timeField = true ;
171
+ break ;
172
+ case '_rperm' :
173
+ case '_wperm' :
174
+ return { key : key , value : restValue } ;
175
+ break ;
176
+ case '$or' :
73
177
if ( ! ( restValue instanceof Array ) ) {
74
- throw new Parse . Error ( Parse . Error . INVALID_QUERY ,
75
- 'bad $or format - use an array value' ) ;
178
+ throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'bad $or format - use an array value' ) ;
76
179
}
77
180
var mongoSubqueries = restValue . map ( ( s ) => {
78
181
return transformWhere ( schema , className , s ) ;
79
182
} ) ;
80
183
return { key : '$or' , value : mongoSubqueries } ;
81
184
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
185
if ( ! ( restValue instanceof Array ) ) {
87
- throw new Parse . Error ( Parse . Error . INVALID_QUERY ,
88
- 'bad $and format - use an array value' ) ;
186
+ throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'bad $and format - use an array value' ) ;
89
187
}
90
188
var mongoSubqueries = restValue . map ( ( s ) => {
91
189
return transformWhere ( schema , className , s ) ;
@@ -94,19 +192,13 @@ export function transformKeyValue(schema, className, restKey, restValue, {
94
192
default :
95
193
// Other auth data
96
194
var authDataMatch = key . match ( / ^ a u t h D a t a \. ( [ a - z A - Z 0 - 9 _ ] + ) \. i d $ / ) ;
97
- 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
- } ;
195
+ if ( authDataMatch ) {
196
+ var provider = authDataMatch [ 1 ] ;
197
+ // Special-case auth data.
198
+ return { key : '_auth_data_' + provider + '.id' , value : restValue } ;
199
+ }
107
200
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 ) ;
201
+ throw new Parse . Error ( Parse . Error . INVALID_KEY_NAME , 'invalid key name: ' + key ) ;
110
202
}
111
203
}
112
204
@@ -124,14 +216,12 @@ export function transformKeyValue(schema, className, restKey, restValue, {
124
216
var expectedTypeIsArray = ( expected && expected . type === 'Array' ) ;
125
217
126
218
// Handle query constraints
127
- if ( query ) {
128
- value = transformConstraint ( restValue , expectedTypeIsArray ) ;
129
- if ( value !== CannotTransform ) {
130
- return { key : key , value : value } ;
131
- }
219
+ value = transformConstraint ( restValue , expectedTypeIsArray ) ;
220
+ if ( value !== CannotTransform ) {
221
+ return { key : key , value : value } ;
132
222
}
133
223
134
- if ( expectedTypeIsArray && query && ! ( restValue instanceof Array ) ) {
224
+ if ( expectedTypeIsArray && ! ( restValue instanceof Array ) ) {
135
225
return {
136
226
key : key , value : { '$all' : [ restValue ] }
137
227
} ;
@@ -154,15 +244,7 @@ export function transformKeyValue(schema, className, restKey, restValue, {
154
244
155
245
// Handle arrays
156
246
if ( restValue instanceof Array ) {
157
- if ( query ) {
158
- throw new Parse . Error ( Parse . Error . INVALID_JSON ,
159
- 'cannot use array as query param' ) ;
160
- }
161
- value = restValue . map ( ( restObj ) => {
162
- var out = transformKeyValue ( schema , className , restKey , restObj , { inArray : true } ) ;
163
- return out . value ;
164
- } ) ;
165
- return { key : key , value : value } ;
247
+ throw new Parse . Error ( Parse . Error . INVALID_JSON , 'cannot use array as query param' ) ;
166
248
}
167
249
168
250
// Handle update operators
@@ -182,7 +264,6 @@ export function transformKeyValue(schema, className, restKey, restValue, {
182
264
return { key : key , value : value } ;
183
265
}
184
266
185
-
186
267
// Main exposed method to help run queries.
187
268
// restWhere is the "where" clause in REST API form.
188
269
// Returns the mongo form of the query.
@@ -193,7 +274,7 @@ function transformWhere(schema, className, restWhere, { validate = true } = {})
193
274
throw new Parse . Error ( Parse . Error . INVALID_QUERY , 'Cannot query on ACL.' ) ;
194
275
}
195
276
for ( let restKey in restWhere ) {
196
- let out = transformKeyValue ( schema , className , restKey , restWhere [ restKey ] , { query : true , validate } ) ;
277
+ let out = transformQueryKeyValue ( schema , className , restKey , restWhere [ restKey ] , { validate } ) ;
197
278
mongoWhere [ out . key ] = out . value ;
198
279
}
199
280
return mongoWhere ;
0 commit comments