tg-client-query-builder 2.14.2 → 2.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,3 +1,3 @@
1
- const QueryBuilder = require('./query-builder');
1
+ const QueryBuilder = require("./query-builder");
2
2
 
3
- module.exports = QueryBuilder;
3
+ module.exports = QueryBuilder;
package/package.json CHANGED
@@ -1,27 +1,10 @@
1
1
  {
2
2
  "name": "tg-client-query-builder",
3
- "version": "2.14.2",
3
+ "version": "2.14.3",
4
4
  "description": "Teselagen Client Side (browser) SQL Query Builder",
5
- "main": "build/query-builder/index.js",
6
- "repository": "https://github.com/TeselaGen/tg-query.git",
7
5
  "author": "TeselaGen",
8
6
  "license": "ISC",
9
- "scripts": {
10
- "prepublishOnly": "yarn build",
11
- "build": "babel --presets=es2015 query-builder/ --out-dir build/query-builder/",
12
- "test": "jest"
13
- },
14
7
  "dependencies": {
15
8
  "lodash": "^4.17.4"
16
- },
17
- "devDependencies": {
18
- "babel-cli": "^6.26.0",
19
- "babel-preset-latest": "^6.24.1",
20
- "chai": "^4.0.2",
21
- "fs-extra": "^3.0.1",
22
- "jest": "^28.1.2",
23
- "json-beautify": "^1.0.1",
24
- "json-format": "^1.0.1",
25
- "jsonfile": "^3.0.0"
26
9
  }
27
10
  }
@@ -1,22 +1,27 @@
1
+ module.exports = function combineQueries(qry1, qry2, joinOperator, opts) {
2
+ if (qry1.__objectType !== "query")
3
+ throw new Error("First query is not a query type.");
4
+ if (qry2.__objectType !== "query")
5
+ throw new Error("Second query is not a query type.");
6
+ if (qry1.entity != qry2.entity)
7
+ throw new Error(
8
+ "Queries are for different entities " +
9
+ qry1.entity +
10
+ " and " +
11
+ qry2.entity
12
+ );
1
13
 
14
+ if (joinOperator !== "or") joinOperator = "and";
2
15
 
3
- module.exports = function combineQueries(qry1, qry2, joinOperator, opts){
4
- if(qry1.__objectType !== 'query') throw new Error("First query is not a query type.");
5
- if(qry2.__objectType !== 'query') throw new Error("Second query is not a query type.");
6
- if(qry1.entity != qry2.entity) throw new Error("Queries are for different entities " + qry1.entity + " and " + qry2.entity);
16
+ var combinedFilters = {
17
+ type: "group",
18
+ operator: joinOperator,
19
+ filters: []
20
+ };
7
21
 
8
- if(joinOperator !== 'or') joinOperator = 'and';
22
+ combinedFilters.filters = qry1.filters.concat(qry2.filters);
9
23
 
10
- var combinedFilters =
11
- {
12
- type: "group",
13
- operator: joinOperator,
14
- filters: [ ]
15
- };
16
-
17
- combinedFilters.filters = qry1.filters.concat(qry2.filters);
18
-
19
- qry1.filters = [combinedFilters];
24
+ qry1.filters = [combinedFilters];
20
25
 
21
- return qry1;
22
- }
26
+ return qry1;
27
+ };
@@ -1,20 +1,17 @@
1
+ module.exports = (function() {
2
+ function FilterExpression(opName, args) {
3
+ this.name = opName;
4
+ this.args = args;
5
+ }
1
6
 
2
-
3
-
4
- module.exports = (function(){
5
- function FilterExpression(opName, args){
6
- this.name = opName;
7
- this.args = args;
8
- }
9
-
10
- FilterExpression.prototype.toFilter = function(filterBuilder, argName){
11
- var filterDef = {
12
- type: "expression",
13
- operator: this.name,
14
- field: argName,
15
- args: this.args
16
- };
17
- return filterDef;
18
- }
19
- return FilterExpression;
20
- })();
7
+ FilterExpression.prototype.toFilter = function(filterBuilder, argName) {
8
+ var filterDef = {
9
+ type: "expression",
10
+ operator: this.name,
11
+ field: argName,
12
+ args: this.args
13
+ };
14
+ return filterDef;
15
+ };
16
+ return FilterExpression;
17
+ })();
@@ -32,25 +32,33 @@ function isDateOrNumber(opName) {
32
32
  return () => {
33
33
  var args = [].slice.call(arguments);
34
34
  if (
35
- args.some((arg) => {
35
+ args.some(arg => {
36
36
  return !(_.isDate(arg) || _.isString(arg) || _.isNumber(arg));
37
37
  })
38
38
  ) {
39
- throw new Error(`QueryBuilderError: You must pass a date or number as args to ${opName}. You passed: Args ${args.join(",")}`);
39
+ throw new Error(
40
+ `QueryBuilderError: You must pass a date or number as args to ${opName}. You passed: Args ${args.join(
41
+ ","
42
+ )}`
43
+ );
40
44
  }
41
45
  };
42
46
  }
43
47
  function isArray(opName) {
44
- return (arg) => {
48
+ return arg => {
45
49
  if (!_.isArray(arg)) {
46
- throw new Error(`QueryBuilderError: You must pass an array for ${opName} filters. You passed: ${arg}`);
50
+ throw new Error(
51
+ `QueryBuilderError: You must pass an array for ${opName} filters. You passed: ${arg}`
52
+ );
47
53
  }
48
54
  };
49
55
  }
50
56
  function isString(opName) {
51
- return (arg) => {
57
+ return arg => {
52
58
  if (!_.isString(arg)) {
53
- throw new Error(`QueryBuilderError: You must pass a string for ${opName} filters. You passed: ${arg}`);
59
+ throw new Error(
60
+ `QueryBuilderError: You must pass a string for ${opName} filters. You passed: ${arg}`
61
+ );
54
62
  }
55
63
  };
56
64
  }
@@ -58,7 +66,9 @@ function isString(opName) {
58
66
  function numberOfArgs(opName, argLength) {
59
67
  return (...args) => {
60
68
  if (args.length !== argLength) {
61
- throw new Error(`QueryBuilderError: Args for ${opName} are of length ${args.length}, but they should be of length ${argLength}`);
69
+ throw new Error(
70
+ `QueryBuilderError: Args for ${opName} are of length ${args.length}, but they should be of length ${argLength}`
71
+ );
62
72
  }
63
73
  };
64
74
  }
@@ -66,124 +76,139 @@ function numberOfArgs(opName, argLength) {
66
76
  const expressionOperators = [
67
77
  {
68
78
  opName: "greaterThan",
69
- sanityChecks: [numberOfArgs("greaterThan", 1), isDateOrNumber("greaterThan")],
79
+ sanityChecks: [
80
+ numberOfArgs("greaterThan", 1),
81
+ isDateOrNumber("greaterThan")
82
+ ]
70
83
  },
71
84
  {
72
85
  opName: "inList",
73
- sanityChecks: [numberOfArgs("inList", 1), isArray("inList")],
86
+ sanityChecks: [numberOfArgs("inList", 1), isArray("inList")]
74
87
  },
75
88
  {
76
89
  opName: "lessThan",
77
- sanityChecks: [numberOfArgs("lessThan", 1), isDateOrNumber("lessThan")],
90
+ sanityChecks: [numberOfArgs("lessThan", 1), isDateOrNumber("lessThan")]
78
91
  },
79
92
  {
80
93
  opName: "lessThanOrEqual",
81
- sanityChecks: [numberOfArgs("lessThanOrEqual", 1), isDateOrNumber("lessThanOrEqual")],
94
+ sanityChecks: [
95
+ numberOfArgs("lessThanOrEqual", 1),
96
+ isDateOrNumber("lessThanOrEqual")
97
+ ]
82
98
  },
83
99
  {
84
100
  opName: "equals",
85
- sanityChecks: [numberOfArgs("equals", 1)],
101
+ sanityChecks: [numberOfArgs("equals", 1)]
86
102
  },
87
103
  {
88
104
  opName: "greaterThanOrEqual",
89
- sanityChecks: [numberOfArgs("greaterThanOrEqual", 1), isDateOrNumber("greaterThanOrEqual")],
105
+ sanityChecks: [
106
+ numberOfArgs("greaterThanOrEqual", 1),
107
+ isDateOrNumber("greaterThanOrEqual")
108
+ ]
90
109
  },
91
110
  {
92
111
  opName: "notEquals",
93
- sanityChecks: [numberOfArgs("notEquals", 1)],
112
+ sanityChecks: [numberOfArgs("notEquals", 1)]
94
113
  },
95
114
  {
96
115
  opName: "notNull",
97
- sanityChecks: [numberOfArgs("notNull", 0)],
116
+ sanityChecks: [numberOfArgs("notNull", 0)]
98
117
  },
99
118
  {
100
119
  opName: "isNull",
101
- sanityChecks: [numberOfArgs("isNull", 0)],
120
+ sanityChecks: [numberOfArgs("isNull", 0)]
102
121
  },
103
122
  {
104
123
  opName: "between",
105
- sanityChecks: [numberOfArgs("between", 2), isDateOrNumber("between")],
124
+ sanityChecks: [numberOfArgs("between", 2), isDateOrNumber("between")]
106
125
  },
107
126
  {
108
127
  opName: "notInList",
109
- sanityChecks: [numberOfArgs("notInList", 1), isArray("notInList")],
128
+ sanityChecks: [numberOfArgs("notInList", 1), isArray("notInList")]
110
129
  },
111
130
  {
112
131
  opName: "startsWithExactly",
113
- sanityChecks: [numberOfArgs("startsWith", 1), isString("startsWith")],
132
+ sanityChecks: [numberOfArgs("startsWith", 1), isString("startsWith")]
114
133
  },
115
134
  {
116
135
  opName: "endsWithExactly",
117
- sanityChecks: [numberOfArgs("endsWith", 1), isString("endsWith")],
136
+ sanityChecks: [numberOfArgs("endsWith", 1), isString("endsWith")]
118
137
  },
119
138
  {
120
139
  opName: "containsExactly",
121
- sanityChecks: [numberOfArgs("contains", 1), isString("contains")],
140
+ sanityChecks: [numberOfArgs("contains", 1), isString("contains")]
122
141
  },
123
142
  {
124
143
  opName: "startsWith",
125
- sanityChecks: [numberOfArgs("startsWith", 1), isString("startsWith")],
144
+ sanityChecks: [numberOfArgs("startsWith", 1), isString("startsWith")]
126
145
  },
127
146
  {
128
147
  opName: "notStartsWith",
129
- sanityChecks: [numberOfArgs("notStartsWith", 1), isString("notStartsWith")],
148
+ sanityChecks: [numberOfArgs("notStartsWith", 1), isString("notStartsWith")]
130
149
  },
131
150
  {
132
151
  opName: "endsWith",
133
- sanityChecks: [numberOfArgs("endsWith", 1), isString("endsWith")],
152
+ sanityChecks: [numberOfArgs("endsWith", 1), isString("endsWith")]
134
153
  },
135
154
  {
136
155
  opName: "notEndsWith",
137
- sanityChecks: [numberOfArgs("notEndsWith", 1), isString("notEndsWith")],
156
+ sanityChecks: [numberOfArgs("notEndsWith", 1), isString("notEndsWith")]
138
157
  },
139
158
  {
140
159
  opName: "contains",
141
- sanityChecks: [numberOfArgs("contains", 1), isString("contains")],
160
+ sanityChecks: [numberOfArgs("contains", 1), isString("contains")]
142
161
  },
143
162
  {
144
163
  opName: "notContains",
145
- sanityChecks: [numberOfArgs("notContains", 1), isString("notContains")],
164
+ sanityChecks: [numberOfArgs("notContains", 1), isString("notContains")]
146
165
  },
147
166
  {
148
167
  opName: "upperCase",
149
- sanityChecks: [numberOfArgs("upperCase", 1), isString("upperCase")],
168
+ sanityChecks: [numberOfArgs("upperCase", 1), isString("upperCase")]
150
169
  },
151
170
  {
152
171
  opName: "lowerCase",
153
- sanityChecks: [numberOfArgs("lowerCase", 1), isString("lowerCase")],
172
+ sanityChecks: [numberOfArgs("lowerCase", 1), isString("lowerCase")]
154
173
  },
155
174
  {
156
175
  opName: "matchesRegex",
157
- sanityChecks: [numberOfArgs("matchesRegex", 1), isString("matchesRegex")],
176
+ sanityChecks: [numberOfArgs("matchesRegex", 1), isString("matchesRegex")]
158
177
  },
159
178
  {
160
179
  opName: "matchesSimilar",
161
- sanityChecks: [numberOfArgs("matchesSimilar", 1), isString("matchesSimilar")],
180
+ sanityChecks: [
181
+ numberOfArgs("matchesSimilar", 1),
182
+ isString("matchesSimilar")
183
+ ]
162
184
  },
163
185
  {
164
186
  opName: "fuzzy",
165
187
  sanityChecks: [numberOfArgs("fuzzy", 1), isString("fuzzy")],
166
- transform: (arg) => {
188
+ transform: arg => {
167
189
  // Build Regex String
168
190
  var matchTerm = "";
169
191
  // Split all the search terms
170
- var terms = arg.replace(/\W/g, "").replace(" ", "").split("");
192
+ var terms = arg
193
+ .replace(/\W/g, "")
194
+ .replace(" ", "")
195
+ .split("");
171
196
  for (var i = 0; i < terms.length; i++) {
172
197
  matchTerm += ".*" + terms[i];
173
198
  }
174
199
  matchTerm += ".*";
175
200
  return {
176
201
  newOpName: "matchesRegex",
177
- newArgs: [matchTerm],
202
+ newArgs: [matchTerm]
178
203
  };
179
- },
180
- },
204
+ }
205
+ }
181
206
 
182
207
  // 'subString', //tnr: not yet implemented
183
208
  // 'dateOnly', //tnr: not yet implemented
184
209
  ];
185
210
 
186
- module.exports = (function () {
211
+ module.exports = (function() {
187
212
  // to be implemented
188
213
  //
189
214
  // filter - done
@@ -217,14 +242,15 @@ module.exports = (function () {
217
242
  function QueryBuilder(entity) {
218
243
  this.query = {};
219
244
 
220
- if (entity == null) throw new Error("You must pass the name of the model being filtered!");
245
+ if (entity == null)
246
+ throw new Error("You must pass the name of the model being filtered!");
221
247
 
222
248
  if (typeof entity === "string") {
223
249
  this.query = {
224
250
  __objectType: "query",
225
251
  type: "root",
226
252
  entity,
227
- filters: [],
253
+ filters: []
228
254
  };
229
255
  } else {
230
256
  let subQuery = entity;
@@ -236,10 +262,10 @@ module.exports = (function () {
236
262
  modifier: subQuery.modifier,
237
263
  isArrayRelation: subQuery.isArrayRelation,
238
264
  filters: [],
239
- countExpression: undefined,
265
+ countExpression: undefined
240
266
  };
241
267
  this.parentBuilder = subQuery.parentBuilder;
242
- this.toFilter = function (filterBuilder, name) {
268
+ this.toFilter = function(filterBuilder, name) {
243
269
  this.query.foreignKey = name;
244
270
  return this.toJSON();
245
271
  };
@@ -248,14 +274,14 @@ module.exports = (function () {
248
274
 
249
275
  QueryBuilder.combineQueries = combineQueries;
250
276
 
251
- QueryBuilder.prototype.field = function (fieldName) {
277
+ QueryBuilder.prototype.field = function(fieldName) {
252
278
  return {
253
279
  __objectType: "field",
254
- field: fieldName,
280
+ field: fieldName
255
281
  };
256
282
  };
257
283
 
258
- QueryBuilder.prototype.related = function (relatedEntity, isArrayRelation) {
284
+ QueryBuilder.prototype.related = function(relatedEntity, isArrayRelation) {
259
285
  var tokens = relatedEntity.split(".");
260
286
  var entity = tokens[0];
261
287
  var key = tokens[1];
@@ -266,7 +292,7 @@ module.exports = (function () {
266
292
  return createSubQueryBuilder(this, entity, key, isArrayRelation);
267
293
  };
268
294
 
269
- QueryBuilder.prototype.notRelated = function (relatedEntity, isArrayRelation) {
295
+ QueryBuilder.prototype.notRelated = function(relatedEntity, isArrayRelation) {
270
296
  var tokens = relatedEntity.split(".");
271
297
  var entity = tokens[0];
272
298
  var key = tokens[1];
@@ -277,7 +303,7 @@ module.exports = (function () {
277
303
  return createSubQueryBuilder(this, entity, key, isArrayRelation, "not");
278
304
  };
279
305
 
280
- QueryBuilder.prototype.toJSON = function () {
306
+ QueryBuilder.prototype.toJSON = function() {
281
307
  let qry = JSON.parse(JSON.stringify(this.query));
282
308
  if (qry.filters.length > 1) {
283
309
  qry.filters = [
@@ -285,14 +311,14 @@ module.exports = (function () {
285
311
  type: "group",
286
312
  operator: "and",
287
313
  chainedWith: "and",
288
- filters: qry.filters,
289
- },
314
+ filters: qry.filters
315
+ }
290
316
  ];
291
317
  }
292
318
  return qry;
293
319
  };
294
320
 
295
- QueryBuilder.prototype.convertToFilter = function (argDef, operator) {
321
+ QueryBuilder.prototype.convertToFilter = function(argDef, operator) {
296
322
  var whereArgs = {};
297
323
  var filters = [];
298
324
 
@@ -318,7 +344,7 @@ module.exports = (function () {
318
344
  if (_.keys(whereArgs).length > 0) {
319
345
  filters.unshift({
320
346
  type: "where",
321
- args: whereArgs,
347
+ args: whereArgs
322
348
  });
323
349
  }
324
350
 
@@ -328,61 +354,63 @@ module.exports = (function () {
328
354
  var filterDef = {
329
355
  type: "group",
330
356
  operator: operator || "and",
331
- filters,
357
+ filters
332
358
  };
333
359
  return filterDef;
334
360
  };
335
361
 
336
- QueryBuilder.prototype.where = function () {
362
+ QueryBuilder.prototype.where = function() {
337
363
  var args = [].slice.call(arguments);
338
364
  return this.whereAll(args);
339
365
  };
340
366
 
341
- QueryBuilder.prototype.orWhere = function () {
367
+ QueryBuilder.prototype.orWhere = function() {
342
368
  var args = [].slice.call(arguments);
343
369
  return this.orWhereAll(args);
344
370
  };
345
371
 
346
- QueryBuilder.prototype.andWhere = function () {
372
+ QueryBuilder.prototype.andWhere = function() {
347
373
  var args = [].slice.call(arguments);
348
374
  return this.andWhereAll(args);
349
375
  };
350
376
 
351
- QueryBuilder.prototype.whereAny = function () {
377
+ QueryBuilder.prototype.whereAny = function() {
352
378
  var args = [].slice.call(arguments);
353
379
  return whereAny(this, args);
354
380
  };
355
381
 
356
- QueryBuilder.prototype.whereAll = function () {
382
+ QueryBuilder.prototype.whereAll = function() {
357
383
  var args = [].slice.call(arguments);
358
384
  return whereAll(this, args);
359
385
  };
360
386
 
361
- QueryBuilder.prototype.andWhereAny = function () {
387
+ QueryBuilder.prototype.andWhereAny = function() {
362
388
  var args = [].slice.call(arguments);
363
389
  return whereAny(this, args, "and");
364
390
  };
365
391
 
366
- QueryBuilder.prototype.orWhereAny = function () {
392
+ QueryBuilder.prototype.orWhereAny = function() {
367
393
  var args = [].slice.call(arguments);
368
394
  return whereAny(this, args, "or");
369
395
  };
370
396
 
371
- QueryBuilder.prototype.andWhereAll = function () {
397
+ QueryBuilder.prototype.andWhereAll = function() {
372
398
  var args = [].slice.call(arguments);
373
399
  return whereAll(this, args, "and");
374
400
  };
375
401
 
376
- QueryBuilder.prototype.orWhereAll = function () {
402
+ QueryBuilder.prototype.orWhereAll = function() {
377
403
  var args = [].slice.call(arguments);
378
404
  return whereAll(this, args, "or");
379
405
  };
380
406
 
381
- QueryBuilder.prototype.count = function () {
407
+ QueryBuilder.prototype.count = function() {
382
408
  var args = [].slice.call(arguments);
383
409
  if (this.query.type === "subquery") {
384
410
  if (this.query.countExpression) {
385
- throw new Error("QueryBuilder subquery can only have one count expression");
411
+ throw new Error(
412
+ "QueryBuilder subquery can only have one count expression"
413
+ );
386
414
  }
387
415
  this.query.countExpression = args[0].toFilter(this, "count");
388
416
  } else {
@@ -396,13 +424,19 @@ module.exports = (function () {
396
424
 
397
425
  return QueryBuilder;
398
426
 
399
- function createSubQueryBuilder(qb, entity, key, isArrayRelation = true, modifier) {
427
+ function createSubQueryBuilder(
428
+ qb,
429
+ entity,
430
+ key,
431
+ isArrayRelation = true,
432
+ modifier
433
+ ) {
400
434
  return new QueryBuilder({
401
435
  parentBuilder: qb,
402
436
  entity,
403
437
  key,
404
438
  modifier,
405
- isArrayRelation,
439
+ isArrayRelation
406
440
  });
407
441
  }
408
442
 
@@ -416,7 +450,7 @@ module.exports = (function () {
416
450
  argsToUse = newArgs;
417
451
  opNameToUse = newOpName;
418
452
  }
419
- sanityChecks.forEach((sanityCheck) => {
453
+ sanityChecks.forEach(sanityCheck => {
420
454
  sanityCheck(...args);
421
455
  });
422
456
  return new FilterExpression(opNameToUse, argsToUse);
@@ -441,16 +475,17 @@ module.exports = (function () {
441
475
  }
442
476
 
443
477
  function where(filterBuilder, operator, whereArgs, chainedWith) {
444
- if (!Array.isArray(whereArgs)) return where(filterBuilder, operator, [whereArgs], chainedWith);
478
+ if (!Array.isArray(whereArgs))
479
+ return where(filterBuilder, operator, [whereArgs], chainedWith);
445
480
 
446
481
  var filterDef = {
447
482
  type: "group",
448
483
  operator,
449
484
  chainedWith,
450
- filters: [],
485
+ filters: []
451
486
  };
452
487
 
453
- whereArgs.forEach((arg) => {
488
+ whereArgs.forEach(arg => {
454
489
  //add check for object type TODO
455
490
  var filter = filterBuilder.convertToFilter(arg, operator);
456
491
  filterDef.filters.push(filter);
@@ -1,21 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = function combineQueries(qry1, qry2, joinOperator, opts) {
4
- if (qry1.__objectType !== 'query') throw new Error("First query is not a query type.");
5
- if (qry2.__objectType !== 'query') throw new Error("Second query is not a query type.");
6
- if (qry1.entity != qry2.entity) throw new Error("Queries are for different entities " + qry1.entity + " and " + qry2.entity);
7
-
8
- if (joinOperator !== 'or') joinOperator = 'and';
9
-
10
- var combinedFilters = {
11
- type: "group",
12
- operator: joinOperator,
13
- filters: []
14
- };
15
-
16
- combinedFilters.filters = qry1.filters.concat(qry2.filters);
17
-
18
- qry1.filters = [combinedFilters];
19
-
20
- return qry1;
21
- };
@@ -1,19 +0,0 @@
1
- "use strict";
2
-
3
- module.exports = function () {
4
- function FilterExpression(opName, args) {
5
- this.name = opName;
6
- this.args = args;
7
- }
8
-
9
- FilterExpression.prototype.toFilter = function (filterBuilder, argName) {
10
- var filterDef = {
11
- type: "expression",
12
- operator: this.name,
13
- field: argName,
14
- args: this.args
15
- };
16
- return filterDef;
17
- };
18
- return FilterExpression;
19
- }();
@@ -1,454 +0,0 @@
1
- "use strict";
2
-
3
- // valid filters:
4
- // greaterThan
5
- // inList
6
- // lessThan
7
- // lessThanOrEqual
8
- // equals
9
- // greaterThanOrEqual
10
- // notEquals
11
- // notNull
12
- // isNull
13
- // between
14
- // notInList
15
- // startsWithExactly
16
- // endsWithExactly
17
- // containsExactly
18
- // startsWith
19
- // notStartsWith
20
- // endsWith
21
- // notEndsWith
22
- // contains
23
- // notContains
24
- // upperCase
25
- // lowerCase
26
- // matchesRegex (note: this takes a string like "thomas.*is.*cool", don't include the outer slashes like /asdf/ and don't pass a regex object )
27
- // fuzzy
28
- var FilterExpression = require("./filter-expression");
29
- var _ = require("lodash");
30
-
31
- var combineQueries = require("./combine-queries");
32
-
33
- function isDateOrNumber(opName) {
34
- var _arguments = arguments;
35
-
36
- return function () {
37
- var args = [].slice.call(_arguments);
38
- if (args.some(function (arg) {
39
- return !(_.isDate(arg) || _.isString(arg) || _.isNumber(arg));
40
- })) {
41
- throw new Error("QueryBuilderError: You must pass a date or number as args to " + opName + ". You passed: Args " + args.join(","));
42
- }
43
- };
44
- }
45
- function isArray(opName) {
46
- return function (arg) {
47
- if (!_.isArray(arg)) {
48
- throw new Error("QueryBuilderError: You must pass an array for " + opName + " filters. You passed: " + arg);
49
- }
50
- };
51
- }
52
- function isString(opName) {
53
- return function (arg) {
54
- if (!_.isString(arg)) {
55
- throw new Error("QueryBuilderError: You must pass a string for " + opName + " filters. You passed: " + arg);
56
- }
57
- };
58
- }
59
-
60
- function numberOfArgs(opName, argLength) {
61
- return function () {
62
- if (arguments.length !== argLength) {
63
- throw new Error("QueryBuilderError: Args for " + opName + " are of length " + arguments.length + ", but they should be of length " + argLength);
64
- }
65
- };
66
- }
67
-
68
- var expressionOperators = [{
69
- opName: "greaterThan",
70
- sanityChecks: [numberOfArgs("greaterThan", 1), isDateOrNumber("greaterThan")]
71
- }, {
72
- opName: "inList",
73
- sanityChecks: [numberOfArgs("inList", 1), isArray("inList")]
74
- }, {
75
- opName: "lessThan",
76
- sanityChecks: [numberOfArgs("lessThan", 1), isDateOrNumber("lessThan")]
77
- }, {
78
- opName: "lessThanOrEqual",
79
- sanityChecks: [numberOfArgs("lessThanOrEqual", 1), isDateOrNumber("lessThanOrEqual")]
80
- }, {
81
- opName: "equals",
82
- sanityChecks: [numberOfArgs("equals", 1)]
83
- }, {
84
- opName: "greaterThanOrEqual",
85
- sanityChecks: [numberOfArgs("greaterThanOrEqual", 1), isDateOrNumber("greaterThanOrEqual")]
86
- }, {
87
- opName: "notEquals",
88
- sanityChecks: [numberOfArgs("notEquals", 1)]
89
- }, {
90
- opName: "notNull",
91
- sanityChecks: [numberOfArgs("notNull", 0)]
92
- }, {
93
- opName: "isNull",
94
- sanityChecks: [numberOfArgs("isNull", 0)]
95
- }, {
96
- opName: "between",
97
- sanityChecks: [numberOfArgs("between", 2), isDateOrNumber("between")]
98
- }, {
99
- opName: "notInList",
100
- sanityChecks: [numberOfArgs("notInList", 1), isArray("notInList")]
101
- }, {
102
- opName: "startsWithExactly",
103
- sanityChecks: [numberOfArgs("startsWith", 1), isString("startsWith")]
104
- }, {
105
- opName: "endsWithExactly",
106
- sanityChecks: [numberOfArgs("endsWith", 1), isString("endsWith")]
107
- }, {
108
- opName: "containsExactly",
109
- sanityChecks: [numberOfArgs("contains", 1), isString("contains")]
110
- }, {
111
- opName: "startsWith",
112
- sanityChecks: [numberOfArgs("startsWith", 1), isString("startsWith")]
113
- }, {
114
- opName: "notStartsWith",
115
- sanityChecks: [numberOfArgs("notStartsWith", 1), isString("notStartsWith")]
116
- }, {
117
- opName: "endsWith",
118
- sanityChecks: [numberOfArgs("endsWith", 1), isString("endsWith")]
119
- }, {
120
- opName: "notEndsWith",
121
- sanityChecks: [numberOfArgs("notEndsWith", 1), isString("notEndsWith")]
122
- }, {
123
- opName: "contains",
124
- sanityChecks: [numberOfArgs("contains", 1), isString("contains")]
125
- }, {
126
- opName: "notContains",
127
- sanityChecks: [numberOfArgs("notContains", 1), isString("notContains")]
128
- }, {
129
- opName: "upperCase",
130
- sanityChecks: [numberOfArgs("upperCase", 1), isString("upperCase")]
131
- }, {
132
- opName: "lowerCase",
133
- sanityChecks: [numberOfArgs("lowerCase", 1), isString("lowerCase")]
134
- }, {
135
- opName: "matchesRegex",
136
- sanityChecks: [numberOfArgs("matchesRegex", 1), isString("matchesRegex")]
137
- }, {
138
- opName: "matchesSimilar",
139
- sanityChecks: [numberOfArgs("matchesSimilar", 1), isString("matchesSimilar")]
140
- }, {
141
- opName: "fuzzy",
142
- sanityChecks: [numberOfArgs("fuzzy", 1), isString("fuzzy")],
143
- transform: function transform(arg) {
144
- // Build Regex String
145
- var matchTerm = "";
146
- // Split all the search terms
147
- var terms = arg.replace(/\W/g, "").replace(" ", "").split("");
148
- for (var i = 0; i < terms.length; i++) {
149
- matchTerm += ".*" + terms[i];
150
- }
151
- matchTerm += ".*";
152
- return {
153
- newOpName: "matchesRegex",
154
- newArgs: [matchTerm]
155
- };
156
- }
157
- }];
158
-
159
- module.exports = function () {
160
- // to be implemented
161
- //
162
- // filter - done
163
- // lessThan - done
164
- // lessThanOrEqual - done
165
- // greaterThan - done
166
- // greaterThanOrEqual - done
167
- // equals - done
168
- // notEquals - done
169
- // notNull
170
- // isNull
171
- // between
172
- // inList - done
173
- // notInList
174
- // related - done
175
- // notRelated - done
176
- // startsWith LIKE adsd%
177
- // endsWith
178
- // contains LIKE
179
- // notContains NOT LIKE
180
- // dateOnly
181
- // upperCase
182
- // lowerCase
183
- // subString
184
- // matchesRegex
185
- // count - Done
186
-
187
- // log("FilterBuilder in QueryBuilder");
188
- // log(FilterBuilder);
189
-
190
- function QueryBuilder(entity) {
191
- this.query = {};
192
-
193
- if (entity == null) throw new Error("You must pass the name of the model being filtered!");
194
-
195
- if (typeof entity === "string") {
196
- this.query = {
197
- __objectType: "query",
198
- type: "root",
199
- entity: entity,
200
- filters: []
201
- };
202
- } else {
203
- var subQuery = entity;
204
- this.query = {
205
- type: "subquery",
206
- key: subQuery.key,
207
- entity: subQuery.entity,
208
- foreignKey: subQuery.foreignKey,
209
- modifier: subQuery.modifier,
210
- isArrayRelation: subQuery.isArrayRelation,
211
- filters: [],
212
- countExpression: undefined
213
- };
214
- this.parentBuilder = subQuery.parentBuilder;
215
- this.toFilter = function (filterBuilder, name) {
216
- this.query.foreignKey = name;
217
- return this.toJSON();
218
- };
219
- }
220
- }
221
-
222
- QueryBuilder.combineQueries = combineQueries;
223
-
224
- QueryBuilder.prototype.field = function (fieldName) {
225
- return {
226
- __objectType: "field",
227
- field: fieldName
228
- };
229
- };
230
-
231
- QueryBuilder.prototype.related = function (relatedEntity, isArrayRelation) {
232
- var tokens = relatedEntity.split(".");
233
- var entity = tokens[0];
234
- var key = tokens[1];
235
-
236
- // log("FilterBuilder in related");
237
- // log(FilterBuilder);
238
-
239
- return createSubQueryBuilder(this, entity, key, isArrayRelation);
240
- };
241
-
242
- QueryBuilder.prototype.notRelated = function (relatedEntity, isArrayRelation) {
243
- var tokens = relatedEntity.split(".");
244
- var entity = tokens[0];
245
- var key = tokens[1];
246
-
247
- // log("FilterBuilder in notRelated");
248
- // log(FilterBuilder);
249
-
250
- return createSubQueryBuilder(this, entity, key, isArrayRelation, "not");
251
- };
252
-
253
- QueryBuilder.prototype.toJSON = function () {
254
- var qry = JSON.parse(JSON.stringify(this.query));
255
- if (qry.filters.length > 1) {
256
- qry.filters = [{
257
- type: "group",
258
- operator: "and",
259
- chainedWith: "and",
260
- filters: qry.filters
261
- }];
262
- }
263
- return qry;
264
- };
265
-
266
- QueryBuilder.prototype.convertToFilter = function (argDef, operator) {
267
- var _this = this;
268
-
269
- var whereArgs = {};
270
- var filters = [];
271
-
272
- _.each(argDef, function (arg, name) {
273
- // log(name);
274
- // if(arg.constructor){
275
- // log(arg.constructor.name)
276
- // }else{
277
- // log("not a prototype")
278
- // }
279
- if (!isFilterExpresionOrSubQuery(name, arg)) {
280
- if (Array.isArray(arg)) {
281
- filters.push(_this.inList(arg).toFilter(_this, name));
282
- } else {
283
- //log("Is Where Filter: " + name);
284
- whereArgs[name] = arg;
285
- }
286
- } else {
287
- //log("Is Expression or SubQuery Filter: " + name);
288
- filters.push(arg.toFilter(_this, name));
289
- }
290
- });
291
- if (_.keys(whereArgs).length > 0) {
292
- filters.unshift({
293
- type: "where",
294
- args: whereArgs
295
- });
296
- }
297
-
298
- if (filters.length === 1) {
299
- return filters[0];
300
- }
301
- var filterDef = {
302
- type: "group",
303
- operator: operator || "and",
304
- filters: filters
305
- };
306
- return filterDef;
307
- };
308
-
309
- QueryBuilder.prototype.where = function () {
310
- var args = [].slice.call(arguments);
311
- return this.whereAll(args);
312
- };
313
-
314
- QueryBuilder.prototype.orWhere = function () {
315
- var args = [].slice.call(arguments);
316
- return this.orWhereAll(args);
317
- };
318
-
319
- QueryBuilder.prototype.andWhere = function () {
320
- var args = [].slice.call(arguments);
321
- return this.andWhereAll(args);
322
- };
323
-
324
- QueryBuilder.prototype.whereAny = function () {
325
- var args = [].slice.call(arguments);
326
- return whereAny(this, args);
327
- };
328
-
329
- QueryBuilder.prototype.whereAll = function () {
330
- var args = [].slice.call(arguments);
331
- return whereAll(this, args);
332
- };
333
-
334
- QueryBuilder.prototype.andWhereAny = function () {
335
- var args = [].slice.call(arguments);
336
- return whereAny(this, args, "and");
337
- };
338
-
339
- QueryBuilder.prototype.orWhereAny = function () {
340
- var args = [].slice.call(arguments);
341
- return whereAny(this, args, "or");
342
- };
343
-
344
- QueryBuilder.prototype.andWhereAll = function () {
345
- var args = [].slice.call(arguments);
346
- return whereAll(this, args, "and");
347
- };
348
-
349
- QueryBuilder.prototype.orWhereAll = function () {
350
- var args = [].slice.call(arguments);
351
- return whereAll(this, args, "or");
352
- };
353
-
354
- QueryBuilder.prototype.count = function () {
355
- var args = [].slice.call(arguments);
356
- if (this.query.type === "subquery") {
357
- if (this.query.countExpression) {
358
- throw new Error("QueryBuilder subquery can only have one count expression");
359
- }
360
- this.query.countExpression = args[0].toFilter(this, "count");
361
- } else {
362
- throw new Error("QueryBuilder is not subquery type on count expression");
363
- }
364
-
365
- return this;
366
- };
367
- QueryBuilder.ExpressionJson = {};
368
- attachExpressionFunctions();
369
-
370
- return QueryBuilder;
371
-
372
- function createSubQueryBuilder(qb, entity, key) {
373
- var isArrayRelation = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
374
- var modifier = arguments[4];
375
-
376
- return new QueryBuilder({
377
- parentBuilder: qb,
378
- entity: entity,
379
- key: key,
380
- modifier: modifier,
381
- isArrayRelation: isArrayRelation
382
- });
383
- }
384
-
385
- function attachExpressionFunctions() {
386
- expressionOperators.forEach(function (_ref) {
387
- var opName = _ref.opName,
388
- sanityChecks = _ref.sanityChecks,
389
- transform = _ref.transform;
390
-
391
- var filter = function filter() {
392
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
393
- args[_key] = arguments[_key];
394
- }
395
-
396
- var argsToUse = args;
397
- var opNameToUse = opName;
398
- if (transform) {
399
- var _transform = transform.apply(undefined, args),
400
- newOpName = _transform.newOpName,
401
- newArgs = _transform.newArgs;
402
-
403
- argsToUse = newArgs;
404
- opNameToUse = newOpName;
405
- }
406
- sanityChecks.forEach(function (sanityCheck) {
407
- sanityCheck.apply(undefined, args);
408
- });
409
- return new FilterExpression(opNameToUse, argsToUse);
410
- };
411
- QueryBuilder.prototype[opName] = filter;
412
- QueryBuilder.ExpressionJson[opName] = filter;
413
- });
414
- }
415
-
416
- function isFilterExpresionOrSubQuery(name, arg) {
417
- if (arg instanceof FilterExpression) return true;
418
- if (arg instanceof QueryBuilder) return true;
419
- return false;
420
- }
421
-
422
- function whereAny(filterBuilder, whereArgs, chainedWith) {
423
- return where(filterBuilder, "or", whereArgs, chainedWith);
424
- }
425
-
426
- function whereAll(filterBuilder, whereArgs, chainedWith) {
427
- return where(filterBuilder, "and", whereArgs, chainedWith);
428
- }
429
-
430
- function where(filterBuilder, operator, whereArgs, chainedWith) {
431
- if (!Array.isArray(whereArgs)) return where(filterBuilder, operator, [whereArgs], chainedWith);
432
-
433
- var filterDef = {
434
- type: "group",
435
- operator: operator,
436
- chainedWith: chainedWith,
437
- filters: []
438
- };
439
-
440
- whereArgs.forEach(function (arg) {
441
- //add check for object type TODO
442
- var filter = filterBuilder.convertToFilter(arg, operator);
443
- filterDef.filters.push(filter);
444
- });
445
-
446
- // if (filterDef.filters.length === 1) {
447
- // filterBuilder.query.filters.push(filterDef.filters[0]);
448
- // } else {
449
- // filterBuilder.query.filters.push(filterDef);
450
- // }
451
- filterBuilder.query.filters.push(filterDef);
452
- return filterBuilder;
453
- }
454
- }();