44 * Author: Twaha Mukammel (t.mukammel@gmail.com)
55 */
66
7- 'use strict'
7+ 'use strict' ;
88
99const Promise = require ( 'bluebird' ) ;
1010
1111/**
1212 * Pass `db` connection object which has `Sequelize.Op`
13- * @param {* } db
13+ * @param {* } db
1414 * @returns object {parse}
1515 */
1616module . exports = function ( db ) {
@@ -24,115 +24,110 @@ module.exports = function (db) {
2424 ne : Op . ne ,
2525 eq : Op . eq ,
2626 not : Op . not ,
27- like : Op . like , // LIKE '%hat'
28- notLike : Op . notLike , // NOT LIKE '%hat'
27+ like : Op . like , // LIKE '%hat'
28+ notLike : Op . notLike , // NOT LIKE '%hat'
2929 // iLike: Op.iLike, // ILIKE '%hat' (case insensitive) (PG only)
3030 // notILike: Op.notILike, // NOT ILIKE '%hat' (PG only)
31- regexp : Op . regexp , // REGEXP/~ '^[h|a|t]' (MySQL/PG only)
32- notRegexp : Op . notRegexp , // NOT REGEXP/!~ '^[h|a|t]' (MySQL/PG only)
31+ regexp : Op . regexp , // REGEXP/~ '^[h|a|t]' (MySQL/PG only)
32+ notRegexp : Op . notRegexp , // NOT REGEXP/!~ '^[h|a|t]' (MySQL/PG only)
3333 // iRegexp: Op.iRegexp, // ~* '^[h|a|t]' (PG only)
3434 // notIRegexp: Op.notIRegexp // !~* '^[h|a|t]' (PG only)
35- and : Op . and , // AND (a = 5)
36- or : Op . or , // (a = 5 OR a = 6)
37- between : Op . between , // BETWEEN 6 AND 10
38- notBetween : Op . notBetween , // NOT BETWEEN 11 AND 15
39- in : Op . in , // IN [1, 2]
40- notIn : Op . notIn , // NOT IN [1, 2]
35+ and : Op . and , // AND (a = 5)
36+ or : Op . or , // (a = 5 OR a = 6)
37+ between : Op . between , // BETWEEN 6 AND 10
38+ notBetween : Op . notBetween , // NOT BETWEEN 11 AND 15
39+ in : Op . in , // IN [1, 2]
40+ notIn : Op . notIn // NOT IN [1, 2]
4141 // overlap: Op.overlap, // && [1, 2] (PG array overlap operator)
4242 // contains: Op.contains, // @> [1, 2] (PG array contains operator)
4343 // contained: Op.contained, // <@ [1, 2] (PG array contained by operator)
4444 // col: Op.col // = "user"."organization_id", with dialect specific column identifiers, PG in this example
4545 // any: Op.any // ANY ARRAY[2, 3]::INTEGER (PG only)
46- }
47-
46+ } ;
47+
4848 /**
4949 * Split '.' or ',' seperated strings to array
50- * @param {JSON } obj
51- * @param {array } array
50+ * @param {JSON } obj
51+ * @param {array } array
5252 */
5353 const splitStringAndBuildArray = ( obj , array ) => {
5454 let elements = obj . split ( ',' ) ;
55-
55+
5656 if ( elements && elements . length > 0 ) {
57- elements . forEach ( element => {
57+ elements . forEach ( ( element ) => {
5858 var fields = element . split ( '.' ) ;
5959 if ( fields && fields . length > 0 ) {
60- array . push ( fields )
60+ array . push ( fields ) ;
6161 }
6262 } ) ;
6363 }
64- }
65-
64+ } ;
65+
6666 /**
6767 * Parse query params
6868 * @param {string|Array } query
6969 * @returns {Array } sequelize formatted DB query array
7070 */
7171 const parseFields = ( query ) => {
7272 let array = null ;
73-
73+
7474 if ( query !== null ) {
7575 array = [ ] ;
76-
76+
7777 if ( Array . isArray ( query ) == true ) {
78- query . forEach ( obj => {
78+ query . forEach ( ( obj ) => {
7979 splitStringAndBuildArray ( obj , array ) ;
8080 } ) ;
81- }
82- else {
81+ } else {
8382 splitStringAndBuildArray ( query , array ) ;
8483 }
8584 }
86-
85+
8786 return array ;
88- }
89-
87+ } ;
88+
9089 /**
9190 * Replaces operator (json object key) with Sequelize operator.
92- * @param {JSON } json
93- * @param {string } key
91+ * @param {JSON } json
92+ * @param {string } key
9493 * @param {Sequelize.op } op
9594 */
9695 const replaceKeyWithOperator = ( json , key , op ) => {
9796 let value = json [ key ] ;
9897 delete json [ key ] ;
9998 json [ op ] = value ;
100- }
101-
99+ } ;
100+
102101 /**
103102 * Iteratively replace json keys with Sequelize formated query operators.
104103 * @param {JSON } json next json
105104 */
106105 const iterativeReplace = ( json ) => {
107106 Object . keys ( json ) . forEach ( function ( key ) {
108107 if ( json [ key ] !== null && typeof json [ key ] === 'object' ) {
109-
110108 // console.debug("key: ", key);
111109 let op = operators [ key ] ;
112110 // console.debug("operation: ", op);
113-
111+
114112 if ( op ) {
115113 replaceKeyWithOperator ( json , key , op ) ;
116114 // console.debug("next: ", JSON.stringify(json[op], null, 4));
117115 iterativeReplace ( json [ op ] ) ;
118- }
119- else {
116+ } else {
120117 // console.debug("next: ", JSON.stringify(json[key], null, 4));
121118 iterativeReplace ( json [ key ] ) ;
122119 }
123- }
124- else if ( key == 'model' && db [ json [ key ] ] != null ) {
120+ } else if ( key == 'model' && db [ json [ key ] ] != null ) {
125121 // json['as'] = json[key].replace(/^./, char => char.toLowerCase());// /^\w/
126122 json [ 'model' ] = db [ json [ key ] ] ;
127- }
128- else {
123+ } else {
129124 let op = operators [ key ] ;
130125 if ( op ) replaceKeyWithOperator ( json , key , op ) ;
131126 }
132-
127+
133128 // console.debug("After Key:", key, " Query fields: ", JSON.stringify(json, null, 4))
134129 } ) ;
135- }
130+ } ;
136131
137132 /**
138133 * Unescape escaped sequences in string.
@@ -143,32 +138,32 @@ module.exports = function (db) {
143138 const queryString = query . toString ( ) ;
144139 const queryStringUnescaped = unescape ( queryString ) ;
145140 return queryStringUnescaped ;
146- }
147-
141+ } ;
142+
148143 /**
149144 * Parse and build Sequelize format query
150- * @param {JSON } query
145+ * @param {JSON } query
151146 * @returns {JSON } sequelize formatted DB query params JSON
152147 */
153148 const parseQueryFields = ( query ) => {
154149 let json = JSON . parse ( unescapeEscapedQuery ( query ) ) ;
155150 iterativeReplace ( json ) ;
156151 // console.debug("Resultent query fields: ", json);
157152 return json ;
158- }
159-
153+ } ;
154+
160155 /**
161156 * Parse and build Sequelize format query
162- * @param {JSON } query
157+ * @param {JSON } query
163158 * @returns {JSON } sequelize formatted DB include params JSON
164159 */
165160 const parseIncludeFields = ( query ) => {
166161 let json = JSON . parse ( unescapeEscapedQuery ( query ) ) ;
167162 iterativeReplace ( json ) ;
168163 // console.debug("Resultent include fields: ", json);
169164 return json ;
170- }
171-
165+ } ;
166+
172167 /**
173168 * Parse single query parameter
174169 * @param {string } query
@@ -179,122 +174,122 @@ module.exports = function (db) {
179174 // console.debug("Query param: ", JSON.stringify(elements, null, 4));
180175 if ( elements && elements . length > 1 ) {
181176 var param = { } ;
182- const elementsArray = elements [ 1 ] . split ( ',' )
183- if ( elementsArray ) {
184- if ( elementsArray . length > 1 ) {
185- param [ operators [ elements [ 0 ] ] ] = elementsArray
186- }
187- else {
188- param [ operators [ elements [ 0 ] ] ] = elementsArray [ 0 ]
177+ const elementsArray = elements [ 1 ] . split ( ',' ) ;
178+ if ( elementsArray ) {
179+ if ( elementsArray . length > 1 ) {
180+ param [ operators [ elements [ 0 ] ] ] = elementsArray ;
181+ } else {
182+ param [ operators [ elements [ 0 ] ] ] = elementsArray [ 0 ] ;
189183 }
190184 // console.debug("Query param: ", param);
191185 return param ;
192186 }
193187 }
194188 // console.debug("Query param: ", elements[0]);
195189 return elements [ 0 ] ;
196- }
197-
190+ } ;
191+
198192 // Max page size limit is set to 200
199193 const pageSizeLimit = 200 ;
200-
194+
201195 /**
202- * Sequelize Query Parser is a very simple package that
196+ * Sequelize Query Parser is a very simple package that
203197 * turns your RESTful APIs into a basic set of Graph APIs.
204- *
198+ *
205199 * Parses - filter, query, sorting, paging, group, relational object queries
206- *
200+ *
207201 * fields=field01,field02...
208- *
202+ *
209203 * limit=value&&offset=value
210- *
204+ *
211205 * sort_by=field01.asc|field02.desc
212- *
206+ *
213207 * group_by=field01,field02
214- *
208+ *
215209 * query=JSON
216- *
210+ *
217211 * include=JSON
218- *
212+ *
219213 * filedName=unaryOperator:value
220- *
214+ *
221215 * @param {JSON } req
222216 * @returns {JSON } sequelize formatted DB query
223217 */
224218 function parse ( req ) {
225- console . debug ( " Request query: " , req . query ) ;
226-
219+ console . debug ( ' Request query: ' , req . query ) ;
220+
227221 return new Promise ( ( resolve , reject ) => {
228222 try {
229- var offset = 0 , limit = pageSizeLimit ;
223+ var offset = 0 ,
224+ limit = pageSizeLimit ;
230225 var dbQuery = {
231- where : { }
226+ where : { } ,
227+ offset,
228+ limit
232229 } ;
233- const Op = db . Sequelize . Op ;
234-
230+
235231 for ( const key in req . query ) {
236232 switch ( key ) {
237233 // Fields
238234 case 'fields' :
239235 // split the field names (attributes) and assign to an array
240- let fields = req . query . fields . split ( "," ) ;
236+ let fields = req . query . fields . split ( ',' ) ;
241237 // assign fields array to .attributes
242238 if ( fields && fields . length > 0 ) dbQuery . attributes = fields ;
243239 break ;
244-
240+
245241 // pagination page size
246242 case 'limit' :
247243 dbQuery . limit = Math . min ( Math . max ( parseInt ( req . query . limit ) , 1 ) , pageSizeLimit ) ;
248244 limit = dbQuery . limit ;
249245 break ;
250-
246+
251247 // pagination page offset
252248 case 'offset' :
253249 offset = Math . max ( parseInt ( req . query . offset ) , 0 ) ;
254250 break ;
255-
251+
256252 // Sort by field order
257253 case 'sort_by' :
258254 dbQuery . order = parseFields ( req . query . sort_by ) ;
259255 break ;
260-
256+
261257 // Group by field
262258 // TODO: Check array
263259 case 'group_by' :
264260 dbQuery . group = parseFields ( req . query . group_by ) ;
265261 break ;
266-
262+
267263 // JSON (nested) query
268264 case 'query' :
269265 let parsed = parseQueryFields ( req . query . query ) ;
270266 dbQuery . where = { ...dbQuery . where , ...parsed } ;
271267 break ;
272-
268+
273269 // include and query on associated tables
274270 case 'include' :
275271 dbQuery . include = parseIncludeFields ( req . query . include ) ;
276272 break ;
277-
273+
278274 // Simple filter query
279275 default :
280276 dbQuery . where [ key ] = parseQueryParam ( req . query [ key ] ) ;
281277 break ;
282278 }
283279 }
284-
280+
285281 dbQuery . offset = offset * limit ;
286-
287- console . debug ( " Final sequelize query:" ) ;
282+
283+ console . debug ( ' Final sequelize query:' ) ;
288284 console . debug ( JSON . stringify ( dbQuery , null , 4 ) ) ;
289-
285+
290286 resolve ( dbQuery ) ;
287+ } catch ( error ) {
288+ console . debug ( 'Error: ' , error . message ) ;
289+ reject ( [ { msg : error . message } ] ) ;
291290 }
292- catch ( error ) {
293- console . debug ( "Error: " , error . message )
294- reject ( [ { msg : error . message } ] ) ;
295- }
296- } )
291+ } ) ;
297292 }
298-
299- return { parse }
300- }
293+
294+ return { parse } ;
295+ } ;
0 commit comments