alchemymvc 1.3.22 → 1.4.0-alpha.2
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/LICENSE +1 -1
- package/README.md +3 -3
- package/lib/app/behaviour/publishable_behaviour.js +5 -5
- package/lib/app/behaviour/revision_behaviour.js +96 -59
- package/lib/app/behaviour/sluggable_behaviour.js +14 -14
- package/lib/app/conduit/electron_conduit.js +9 -9
- package/lib/app/conduit/http_conduit.js +13 -13
- package/lib/app/conduit/loopback_conduit.js +15 -15
- package/lib/app/conduit/socket_conduit.js +43 -43
- package/lib/app/config/routes.js +26 -0
- package/lib/app/controller/00-default_app_controller.js +21 -0
- package/lib/app/controller/alchemy_info_controller.js +12 -12
- package/lib/app/datasource/mongo_datasource.js +27 -18
- package/lib/app/element/00-default_app_element.js +19 -0
- package/lib/app/element/time_ago.js +5 -5
- package/lib/app/helper/00-default_app_helper.js +11 -0
- package/lib/app/helper/alchemy_helper.js +22 -22
- package/lib/app/helper/backed_map.js +1 -1
- package/lib/app/helper/breadcrumb.js +10 -10
- package/lib/app/helper/client_collection.js +3 -3
- package/lib/app/helper/cron.js +29 -29
- package/lib/app/helper/enum_values.js +6 -6
- package/lib/app/helper/pagination_helper.js +36 -36
- package/lib/app/helper/router_helper.js +35 -35
- package/lib/app/helper/socket_helper.js +57 -57
- package/lib/app/helper/syncable.js +62 -62
- package/lib/app/helper_component/paginate_component.js +9 -9
- package/lib/app/helper_controller/component.js +1 -1
- package/lib/app/helper_controller/conduit.js +31 -31
- package/lib/app/helper_controller/controller.js +54 -39
- package/lib/app/helper_datasource/00-nosql_datasource.js +624 -70
- package/lib/app/helper_datasource/05-fallback_datasource.js +10 -10
- package/lib/app/helper_datasource/idb_datasource.js +6 -6
- package/lib/app/helper_datasource/indexed_db.js +22 -22
- package/lib/app/helper_datasource/remote_datasource.js +5 -5
- package/lib/app/helper_error/http_error.js +4 -4
- package/lib/app/helper_error/model_error.js +2 -2
- package/lib/app/helper_error/validation_error.js +12 -12
- package/lib/app/helper_field/00-objectid_field.js +7 -7
- package/lib/app/helper_field/05-string_field.js +16 -12
- package/lib/app/helper_field/06-text_field.js +2 -4
- package/lib/app/helper_field/10-number_field.js +9 -12
- package/lib/app/helper_field/11-date_field.js +15 -15
- package/lib/app/helper_field/15-local_temporal_field.js +10 -10
- package/lib/app/helper_field/20-decimal_field.js +8 -9
- package/lib/app/helper_field/belongsto_field.js +1 -1
- package/lib/app/helper_field/big_int_field.js +8 -8
- package/lib/app/helper_field/boolean_field.js +9 -11
- package/lib/app/helper_field/datetime_field.js +3 -3
- package/lib/app/helper_field/enum_field.js +13 -8
- package/lib/app/helper_field/fixed_decimal_field.js +6 -7
- package/lib/app/helper_field/geopoint_field.js +9 -10
- package/lib/app/helper_field/habtm_field.js +3 -3
- package/lib/app/helper_field/hasoneparent_field.js +1 -1
- package/lib/app/helper_field/html_field.js +2 -4
- package/lib/app/helper_field/integer_field.js +8 -11
- package/lib/app/helper_field/local_date_field.js +5 -5
- package/lib/app/helper_field/local_date_time_field.js +5 -5
- package/lib/app/helper_field/local_time_field.js +5 -5
- package/lib/app/helper_field/mixed_field.js +5 -5
- package/lib/app/helper_field/object_field.js +6 -6
- package/lib/app/helper_field/password_field.js +3 -3
- package/lib/app/helper_field/regexp_field.js +7 -9
- package/lib/app/helper_field/schema_field.js +91 -88
- package/lib/app/helper_field/settings_field.js +92 -0
- package/lib/app/helper_field/time_field.js +6 -6
- package/lib/app/helper_field/url_field.js +2 -4
- package/lib/app/helper_model/00-base_criteria.js +662 -0
- package/lib/app/helper_model/05-criteria_expressions.js +605 -0
- package/lib/app/helper_model/10-model_criteria.js +1182 -0
- package/lib/app/helper_model/data_provider.js +2 -2
- package/lib/app/helper_model/document.js +103 -92
- package/lib/app/helper_model/document_list.js +14 -14
- package/lib/app/helper_model/field_config.js +11 -11
- package/lib/app/helper_model/field_set.js +17 -17
- package/lib/app/helper_model/model.js +201 -123
- package/lib/app/helper_model/remote_data_provider.js +2 -2
- package/lib/app/helper_validator/00_validator.js +16 -16
- package/lib/app/helper_validator/not_empty_validator.js +9 -9
- package/lib/app/model/00-default_app_model.js +18 -0
- package/lib/app/model/05-system_model.js +27 -0
- package/lib/app/model/{alchemy_migration_model.js → system_migration_model.js} +4 -4
- package/lib/app/model/system_setting_model.js +154 -0
- package/lib/app/model/{alchemy_task_history_model.js → system_task_history_model.js} +7 -7
- package/lib/app/model/{alchemy_task_model.js → system_task_model.js} +11 -11
- package/lib/bootstrap.js +22 -312
- package/lib/class/accumulator.js +5 -5
- package/lib/class/behaviour.js +5 -5
- package/lib/class/component.js +3 -3
- package/lib/class/conduit.js +152 -150
- package/lib/class/controller.js +42 -42
- package/lib/class/datasource.js +74 -79
- package/lib/class/document.js +74 -95
- package/lib/class/document_list.js +5 -5
- package/lib/class/element.js +17 -17
- package/lib/class/error.js +3 -3
- package/lib/class/field.js +169 -91
- package/lib/class/field_value.js +6 -6
- package/lib/class/helper.js +3 -3
- package/lib/class/inode.js +17 -17
- package/lib/class/inode_dir.js +12 -12
- package/lib/class/inode_file.js +26 -26
- package/lib/class/inode_list.js +4 -4
- package/lib/class/migration.js +4 -4
- package/lib/class/model.js +146 -165
- package/lib/class/path_definition.js +22 -22
- package/lib/class/path_evaluator.js +5 -5
- package/lib/class/path_param_definition.js +7 -7
- package/lib/class/plugin.js +312 -0
- package/lib/class/postponement.js +29 -29
- package/lib/class/reciprocal.js +8 -8
- package/lib/class/route.js +33 -33
- package/lib/class/router.js +73 -73
- package/lib/class/schema.js +21 -21
- package/lib/class/schema_client.js +105 -82
- package/lib/class/session.js +63 -29
- package/lib/class/session_scene.js +4 -4
- package/lib/class/sitemap.js +16 -16
- package/lib/class/task.js +39 -39
- package/lib/class/task_service.js +43 -47
- package/lib/{init → core}/alchemy.js +411 -373
- package/lib/{init/functions.js → core/alchemy_functions.js} +113 -91
- package/lib/core/alchemy_load_functions.js +715 -0
- package/lib/core/base.js +50 -62
- package/lib/core/client_alchemy.js +144 -152
- package/lib/core/client_base.js +27 -50
- package/lib/core/discovery.js +16 -18
- package/lib/core/middleware.js +54 -43
- package/lib/core/{routing.js → prefix.js} +14 -16
- package/lib/core/setting.js +1684 -0
- package/lib/core/stage.js +758 -0
- package/lib/scripts/create_constants.js +119 -0
- package/lib/{init/languages.js → scripts/create_languages.js} +5 -5
- package/lib/scripts/create_settings.js +449 -0
- package/lib/scripts/create_shared_constants.js +95 -0
- package/lib/scripts/create_stages.js +55 -0
- package/lib/scripts/init_alchemy.js +51 -0
- package/lib/{init/requirements.js → scripts/preload_modules.js} +15 -2
- package/lib/scripts/setup_devwatch.js +238 -0
- package/lib/stages/00-load_core.js +342 -0
- package/lib/stages/05-load_app.js +57 -0
- package/lib/stages/10-datasource.js +61 -0
- package/lib/stages/15-tasks.js +27 -0
- package/lib/stages/20-settings.js +68 -0
- package/lib/stages/50-routes.js +218 -0
- package/lib/stages/90-server.js +347 -0
- package/package.json +5 -7
- package/lib/app/helper_model/criteria.js +0 -2294
- package/lib/app/helper_model/db_query.js +0 -1488
- package/lib/app/routes.js +0 -11
- package/lib/core/socket.js +0 -171
- package/lib/init/constants.js +0 -158
- package/lib/init/devwatch.js +0 -238
- package/lib/init/load_functions.js +0 -979
- package/lib/stages.js +0 -515
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NoSQL Datasource
|
|
3
3
|
*
|
|
4
|
-
* @author Jelle De Loecker
|
|
4
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
5
5
|
* @since 1.1.0
|
|
6
6
|
* @version 1.1.0
|
|
7
7
|
*/
|
|
8
|
-
var NoSQL = Function.inherits('Alchemy.Datasource',
|
|
9
|
-
Nosql.super.call(this, name, options);
|
|
10
|
-
});
|
|
8
|
+
var NoSQL = Function.inherits('Alchemy.Datasource', 'Nosql');
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* All comparison functions
|
|
14
12
|
*
|
|
15
|
-
* @author Jelle De Loecker
|
|
13
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
16
14
|
* @since 1.0.0
|
|
17
15
|
* @version 1.0.0
|
|
18
16
|
*/
|
|
@@ -21,7 +19,7 @@ NoSQL.setStatic('comparisons', {});
|
|
|
21
19
|
/**
|
|
22
20
|
* All logical operator functions
|
|
23
21
|
*
|
|
24
|
-
* @author Jelle De Loecker
|
|
22
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
25
23
|
* @since 1.0.0
|
|
26
24
|
* @version 1.0.0
|
|
27
25
|
*/
|
|
@@ -30,7 +28,7 @@ NoSQL.setStatic('logical_operators', {});
|
|
|
30
28
|
/**
|
|
31
29
|
* Add comparison function
|
|
32
30
|
*
|
|
33
|
-
* @author Jelle De Loecker
|
|
31
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
34
32
|
* @since 1.0.0
|
|
35
33
|
* @version 1.0.0
|
|
36
34
|
*/
|
|
@@ -41,7 +39,7 @@ NoSQL.setStatic(function addComparison(fnc) {
|
|
|
41
39
|
/**
|
|
42
40
|
* Add logical operator function
|
|
43
41
|
*
|
|
44
|
-
* @author Jelle De Loecker
|
|
42
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
45
43
|
* @since 1.0.0
|
|
46
44
|
* @version 1.0.0
|
|
47
45
|
*/
|
|
@@ -52,7 +50,7 @@ NoSQL.setStatic(function addLogicalOperator(fnc) {
|
|
|
52
50
|
/**
|
|
53
51
|
* Lower than comparison
|
|
54
52
|
*
|
|
55
|
-
* @author Jelle De Loecker
|
|
53
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
56
54
|
* @since 1.0.0
|
|
57
55
|
* @version 1.0.0
|
|
58
56
|
*/
|
|
@@ -63,7 +61,7 @@ NoSQL.addComparison(function $lt(a, b) {
|
|
|
63
61
|
/**
|
|
64
62
|
* Lower than or equal comparison
|
|
65
63
|
*
|
|
66
|
-
* @author Jelle De Loecker
|
|
64
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
67
65
|
* @since 1.0.0
|
|
68
66
|
* @version 1.0.0
|
|
69
67
|
*/
|
|
@@ -74,7 +72,7 @@ NoSQL.addComparison(function $lte(a, b) {
|
|
|
74
72
|
/**
|
|
75
73
|
* Greater than comparison
|
|
76
74
|
*
|
|
77
|
-
* @author Jelle De Loecker
|
|
75
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
78
76
|
* @since 1.0.0
|
|
79
77
|
* @version 1.0.0
|
|
80
78
|
*/
|
|
@@ -85,7 +83,7 @@ NoSQL.addComparison(function $gt(a, b) {
|
|
|
85
83
|
/**
|
|
86
84
|
* Greater than or equal comparison
|
|
87
85
|
*
|
|
88
|
-
* @author Jelle De Loecker
|
|
86
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
89
87
|
* @since 1.0.0
|
|
90
88
|
* @version 1.0.0
|
|
91
89
|
*/
|
|
@@ -96,7 +94,7 @@ NoSQL.addComparison(function $gte(a, b) {
|
|
|
96
94
|
/**
|
|
97
95
|
* Not equal comparison
|
|
98
96
|
*
|
|
99
|
-
* @author Jelle De Loecker
|
|
97
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
100
98
|
* @since 1.0.0
|
|
101
99
|
* @version 1.0.0
|
|
102
100
|
*/
|
|
@@ -112,7 +110,7 @@ NoSQL.addComparison(function $ne(a, b) {
|
|
|
112
110
|
/**
|
|
113
111
|
* In comparison
|
|
114
112
|
*
|
|
115
|
-
* @author Jelle De Loecker
|
|
113
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
116
114
|
* @since 1.0.0
|
|
117
115
|
* @version 1.0.0
|
|
118
116
|
*/
|
|
@@ -136,7 +134,7 @@ NoSQL.addComparison(function $in(a, b) {
|
|
|
136
134
|
/**
|
|
137
135
|
* Not in comparison
|
|
138
136
|
*
|
|
139
|
-
* @author Jelle De Loecker
|
|
137
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
140
138
|
* @since 1.0.0
|
|
141
139
|
* @version 1.0.0
|
|
142
140
|
*/
|
|
@@ -147,7 +145,7 @@ NoSQL.addComparison(function $nin(a, b) {
|
|
|
147
145
|
/**
|
|
148
146
|
* Regex comparison
|
|
149
147
|
*
|
|
150
|
-
* @author Jelle De Loecker
|
|
148
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
151
149
|
* @since 1.0.0
|
|
152
150
|
* @version 1.0.0
|
|
153
151
|
*/
|
|
@@ -167,7 +165,7 @@ NoSQL.addComparison(function $regex(a, b) {
|
|
|
167
165
|
/**
|
|
168
166
|
* Exists comparison
|
|
169
167
|
*
|
|
170
|
-
* @author Jelle De Loecker
|
|
168
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
171
169
|
* @since 1.0.0
|
|
172
170
|
* @version 1.0.0
|
|
173
171
|
*/
|
|
@@ -187,7 +185,7 @@ NoSQL.addComparison(function $exists(value, exists) {
|
|
|
187
185
|
/**
|
|
188
186
|
* Array size comparison
|
|
189
187
|
*
|
|
190
|
-
* @author Jelle De Loecker
|
|
188
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
191
189
|
* @since 1.0.0
|
|
192
190
|
* @version 1.0.0
|
|
193
191
|
*/
|
|
@@ -207,7 +205,7 @@ NoSQL.addComparison(function $size(obj, value) {
|
|
|
207
205
|
/**
|
|
208
206
|
* Array elemMatch comparison
|
|
209
207
|
*
|
|
210
|
-
* @author Jelle De Loecker
|
|
208
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
211
209
|
* @since 1.0.0
|
|
212
210
|
* @version 1.0.0
|
|
213
211
|
*/
|
|
@@ -231,7 +229,7 @@ NoSQL.addComparison(function $elemMatch(obj, value) {
|
|
|
231
229
|
/**
|
|
232
230
|
* Match any of the subqueries
|
|
233
231
|
*
|
|
234
|
-
* @author Jelle De Loecker
|
|
232
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
235
233
|
* @since 1.0.0
|
|
236
234
|
* @version 1.0.0
|
|
237
235
|
*/
|
|
@@ -255,7 +253,7 @@ NoSQL.addLogicalOperator(function $or(obj, query) {
|
|
|
255
253
|
/**
|
|
256
254
|
* Match all of the subqueries
|
|
257
255
|
*
|
|
258
|
-
* @author Jelle De Loecker
|
|
256
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
259
257
|
* @since 1.0.0
|
|
260
258
|
* @version 1.0.0
|
|
261
259
|
*/
|
|
@@ -279,7 +277,7 @@ NoSQL.addLogicalOperator(function $and(obj, query) {
|
|
|
279
277
|
/**
|
|
280
278
|
* Inverted match of the query
|
|
281
279
|
*
|
|
282
|
-
* @author Jelle De Loecker
|
|
280
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
283
281
|
* @since 1.0.0
|
|
284
282
|
* @version 1.0.0
|
|
285
283
|
*/
|
|
@@ -290,7 +288,7 @@ NoSQL.addLogicalOperator(function $not(obj, query) {
|
|
|
290
288
|
/**
|
|
291
289
|
* Use a function to match
|
|
292
290
|
*
|
|
293
|
-
* @author Jelle De Loecker
|
|
291
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
294
292
|
* @since 1.0.0
|
|
295
293
|
* @version 1.0.0
|
|
296
294
|
*/
|
|
@@ -316,14 +314,14 @@ NoSQL.addLogicalOperator(function $where(obj, fnc) {
|
|
|
316
314
|
* If the treatObjAsValue flag is set,
|
|
317
315
|
* don't try to match every part separately, but the array as a whole.
|
|
318
316
|
*
|
|
319
|
-
* @author Jelle De Loecker
|
|
317
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
320
318
|
* @since 1.0.0
|
|
321
319
|
* @version 1.0.6
|
|
322
320
|
*
|
|
323
321
|
* @param {Object} obj
|
|
324
322
|
* @param {Object} query
|
|
325
323
|
*
|
|
326
|
-
* @return {
|
|
324
|
+
* @return {boolean}
|
|
327
325
|
*/
|
|
328
326
|
NoSQL.setStatic(function matchQueryPart(obj, query_key, query_value, treat_obj_as_value) {
|
|
329
327
|
|
|
@@ -422,14 +420,14 @@ NoSQL.setStatic(function matchQueryPart(obj, query_key, query_value, treat_obj_a
|
|
|
422
420
|
/**
|
|
423
421
|
* Tell if a given document matches a query
|
|
424
422
|
*
|
|
425
|
-
* @author Jelle De Loecker
|
|
423
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
426
424
|
* @since 1.0.0
|
|
427
425
|
* @version 1.0.0
|
|
428
426
|
*
|
|
429
427
|
* @param {Object} obj
|
|
430
428
|
* @param {Object} query
|
|
431
429
|
*
|
|
432
|
-
* @return {
|
|
430
|
+
* @return {boolean}
|
|
433
431
|
*/
|
|
434
432
|
NoSQL.setStatic(function match(obj, query) {
|
|
435
433
|
|
|
@@ -471,11 +469,11 @@ NoSQL.setStatic(function match(obj, query) {
|
|
|
471
469
|
/**
|
|
472
470
|
* Parse a record path
|
|
473
471
|
*
|
|
474
|
-
* @author Jelle De Loecker
|
|
472
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
475
473
|
* @since 1.0.0
|
|
476
474
|
* @version 1.0.0
|
|
477
475
|
*
|
|
478
|
-
* @param {
|
|
476
|
+
* @param {string} path
|
|
479
477
|
*
|
|
480
478
|
* @return {Object}
|
|
481
479
|
*/
|
|
@@ -506,7 +504,7 @@ NoSQL.setStatic(function parseRecordPath(path) {
|
|
|
506
504
|
/**
|
|
507
505
|
* Get a value from object with dot notation
|
|
508
506
|
*
|
|
509
|
-
* @author Jelle De Loecker
|
|
507
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
510
508
|
* @since 1.0.0
|
|
511
509
|
* @version 1.0.0
|
|
512
510
|
*
|
|
@@ -562,11 +560,11 @@ NoSQL.setStatic(function getDotValue(obj, path) {
|
|
|
562
560
|
/**
|
|
563
561
|
* Are 2 values comparable
|
|
564
562
|
*
|
|
565
|
-
* @author Jelle De Loecker
|
|
563
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
566
564
|
* @since 1.0.0
|
|
567
565
|
* @version 1.0.0
|
|
568
566
|
*
|
|
569
|
-
* @return {
|
|
567
|
+
* @return {boolean}
|
|
570
568
|
*/
|
|
571
569
|
NoSQL.setStatic(function areComparable(a, b) {
|
|
572
570
|
|
|
@@ -588,18 +586,72 @@ NoSQL.setStatic(function areComparable(a, b) {
|
|
|
588
586
|
/**
|
|
589
587
|
* Compile criteria into a MongoDB query object
|
|
590
588
|
*
|
|
591
|
-
* @author Jelle De Loecker
|
|
589
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
592
590
|
* @since 1.1.0
|
|
593
|
-
* @version 1.
|
|
591
|
+
* @version 1.4.0
|
|
594
592
|
*
|
|
595
|
-
* @param {Criteria} criteria
|
|
596
|
-
* @param {
|
|
593
|
+
* @param {Criteria} criteria The criteria to convert
|
|
594
|
+
* @param {Object} context The optional context (for Trail retrieval)
|
|
597
595
|
*
|
|
598
596
|
* @return {Object}
|
|
599
597
|
*/
|
|
600
|
-
NoSQL.
|
|
598
|
+
NoSQL.setStatic(function convertCriteriaToConditions(criteria, context) {
|
|
599
|
+
|
|
600
|
+
let config = {
|
|
601
|
+
for_database: false,
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
return convertCriteriaToConditionsWithConfig(criteria, config, context);
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Compile criteria into a MongoDB query object with the given configuration
|
|
609
|
+
*
|
|
610
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
611
|
+
* @since 1.1.0
|
|
612
|
+
* @version 1.4.0
|
|
613
|
+
*
|
|
614
|
+
* @param {Criteria} criteria The criteria to convert
|
|
615
|
+
* @param {Object} config Configuration flags
|
|
616
|
+
* @param {Object} context The optional context
|
|
617
|
+
*
|
|
618
|
+
* @return {Object}
|
|
619
|
+
*/
|
|
620
|
+
function convertCriteriaToConditionsWithConfig(criteria, config, context) {
|
|
621
|
+
|
|
622
|
+
if (context) {
|
|
623
|
+
if (!Object.isPlainObject(context) || !context.$0) {
|
|
624
|
+
context = {$0: context};
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if (!config) {
|
|
629
|
+
config = {
|
|
630
|
+
for_database : false,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return convertCriteriaGroupToConditions(criteria, criteria.group, config, context);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Compile criteria into a MongoDB query object
|
|
639
|
+
*
|
|
640
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
641
|
+
* @since 1.1.0
|
|
642
|
+
* @version 1.4.0
|
|
643
|
+
*
|
|
644
|
+
* @param {Criteria} criteria The criteria to convert
|
|
645
|
+
* @param {Group} group The current group
|
|
646
|
+
* @param {Object} config Configuration flags
|
|
647
|
+
* @param {Object} context The optional context
|
|
648
|
+
*
|
|
649
|
+
* @return {Object}
|
|
650
|
+
*/
|
|
651
|
+
function convertCriteriaGroupToConditions(criteria, group, config, context) {
|
|
601
652
|
|
|
602
|
-
|
|
653
|
+
let is_for_database = config?.for_database,
|
|
654
|
+
assoc_model,
|
|
603
655
|
aggregate,
|
|
604
656
|
result = [],
|
|
605
657
|
entry,
|
|
@@ -607,10 +659,6 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
607
659
|
temp,
|
|
608
660
|
i;
|
|
609
661
|
|
|
610
|
-
if (!group) {
|
|
611
|
-
group = criteria.group;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
662
|
let getAggregate = () => {
|
|
615
663
|
if (!aggregate) {
|
|
616
664
|
aggregate = {
|
|
@@ -688,7 +736,7 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
688
736
|
}
|
|
689
737
|
|
|
690
738
|
if (entry.group_type) {
|
|
691
|
-
let compiled_group =
|
|
739
|
+
let compiled_group = convertCriteriaGroupToConditions(entry.criteria, entry, config, context),
|
|
692
740
|
obj = {};
|
|
693
741
|
|
|
694
742
|
if (compiled_group.$and) {
|
|
@@ -697,7 +745,7 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
697
745
|
// @TODO: this won't work
|
|
698
746
|
compiled_group = compiled_group.pipeline;
|
|
699
747
|
} else {
|
|
700
|
-
compiled_group =
|
|
748
|
+
compiled_group = Array.cast(compiled_group);
|
|
701
749
|
}
|
|
702
750
|
|
|
703
751
|
if (compiled_group) {
|
|
@@ -730,6 +778,13 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
730
778
|
for (let i = 0; i < entry.items.length; i++) {
|
|
731
779
|
item = entry.items[i];
|
|
732
780
|
|
|
781
|
+
if (context && item.value && typeof item.value == 'object') {
|
|
782
|
+
item = {
|
|
783
|
+
...item,
|
|
784
|
+
value : Classes.Develry.Placeholder.deepResolve(item.value, context),
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
|
|
733
788
|
// If the value is a RegExp, we might have to stringify the value
|
|
734
789
|
if (shouldStringify(entry, item) && RegExp.isRegExp(item.value)) {
|
|
735
790
|
|
|
@@ -765,7 +820,19 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
765
820
|
} else if (item.type == 'equals') {
|
|
766
821
|
obj = item.value;
|
|
767
822
|
} else if (item.type == 'contains') {
|
|
768
|
-
|
|
823
|
+
|
|
824
|
+
let do_regexp_search = true;
|
|
825
|
+
|
|
826
|
+
if (entry.field) {
|
|
827
|
+
if (entry.field.is_array || entry.field.options?.type == 'HasAndBelongsToMany') {
|
|
828
|
+
do_regexp_search = false;
|
|
829
|
+
obj = item.value;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
if (do_regexp_search) {
|
|
834
|
+
obj = RegExp.interpret(item.value);
|
|
835
|
+
}
|
|
769
836
|
} else if (item.type == 'in') {
|
|
770
837
|
|
|
771
838
|
// @TODO: This shouldn't be needed,
|
|
@@ -791,31 +858,35 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
791
858
|
}
|
|
792
859
|
} else if (item.type == 'isEmpty') {
|
|
793
860
|
|
|
794
|
-
|
|
795
|
-
|
|
861
|
+
if (is_for_database) {
|
|
862
|
+
let exists = false,
|
|
863
|
+
comparator = '$eq';
|
|
796
864
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
865
|
+
if (item.value === false) {
|
|
866
|
+
exists = true;
|
|
867
|
+
comparator = '$ne';
|
|
868
|
+
}
|
|
801
869
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
870
|
+
let $or = [
|
|
871
|
+
{$exists: exists}
|
|
872
|
+
];
|
|
805
873
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
874
|
+
if (!entry.field) {
|
|
875
|
+
throw new Error('Could not find field for path "' + entry.target_path + '" in model ' + entry.model?.name);
|
|
876
|
+
}
|
|
809
877
|
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
878
|
+
if (entry.field.is_array) {
|
|
879
|
+
$or.push({[comparator]: []});
|
|
880
|
+
} else if (entry.field instanceof Classes.Alchemy.Field.String) {
|
|
881
|
+
$or.push({[comparator]: ''});
|
|
882
|
+
}
|
|
815
883
|
|
|
816
|
-
|
|
884
|
+
$or.push({[comparator]: null});
|
|
817
885
|
|
|
818
|
-
|
|
886
|
+
obj.$or = $or;
|
|
887
|
+
} else {
|
|
888
|
+
obj = {$isEmpty: item.value ?? true};
|
|
889
|
+
}
|
|
819
890
|
} else {
|
|
820
891
|
throw new Error('Unknown criteria expression: "' + item.type + '"');
|
|
821
892
|
}
|
|
@@ -825,7 +896,7 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
825
896
|
|
|
826
897
|
// Temporary fix to actually query translatable field contents
|
|
827
898
|
// (entry.field can be undefined if trying to query a path)
|
|
828
|
-
if (entry.field
|
|
899
|
+
if (entry.field?.is_translatable) {
|
|
829
900
|
|
|
830
901
|
let prefix = criteria.options.locale,
|
|
831
902
|
specific_prefix = !!prefix;
|
|
@@ -937,16 +1008,36 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
937
1008
|
}
|
|
938
1009
|
|
|
939
1010
|
if (!result.length) {
|
|
940
|
-
|
|
1011
|
+
result = {};
|
|
1012
|
+
} else if (result.length === 1) {
|
|
1013
|
+
result = result[0];
|
|
1014
|
+
} else {
|
|
1015
|
+
result = {$and: result};
|
|
941
1016
|
}
|
|
942
1017
|
|
|
943
|
-
return
|
|
1018
|
+
return result;
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* Compile criteria into a MongoDB-compatible query object
|
|
1023
|
+
*
|
|
1024
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1025
|
+
* @since 1.1.0
|
|
1026
|
+
* @version 1.4.0
|
|
1027
|
+
*
|
|
1028
|
+
* @param {Criteria} criteria
|
|
1029
|
+
* @param {Group} group
|
|
1030
|
+
*
|
|
1031
|
+
* @return {Object}
|
|
1032
|
+
*/
|
|
1033
|
+
NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
1034
|
+
return convertCriteriaToConditionsWithConfig(criteria, {for_database: true}, group);
|
|
944
1035
|
});
|
|
945
1036
|
|
|
946
1037
|
/**
|
|
947
1038
|
* Is the given item about a string field?
|
|
948
1039
|
*
|
|
949
|
-
* @author Jelle De Loecker
|
|
1040
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
950
1041
|
* @since 1.2.0
|
|
951
1042
|
* @version 1.2.0
|
|
952
1043
|
*
|
|
@@ -971,10 +1062,473 @@ function shouldStringify(entry, item) {
|
|
|
971
1062
|
return false;
|
|
972
1063
|
}
|
|
973
1064
|
|
|
1065
|
+
/**
|
|
1066
|
+
* Compile an AQL string into a MongoDB-compatible query object
|
|
1067
|
+
*
|
|
1068
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1069
|
+
* @since 1.4.0
|
|
1070
|
+
* @version 1.4.0
|
|
1071
|
+
*
|
|
1072
|
+
* @param {string} query
|
|
1073
|
+
*
|
|
1074
|
+
* @return {Object}
|
|
1075
|
+
*/
|
|
1076
|
+
NoSQL.setStatic(function convertAQLToConditions(query) {
|
|
1077
|
+
|
|
1078
|
+
let tokens = tokenizeAQL(query);
|
|
1079
|
+
|
|
1080
|
+
let conditions = convertAQLTokens(tokens, (name, operator, value, not) => {
|
|
1081
|
+
|
|
1082
|
+
switch (operator) {
|
|
1083
|
+
case 'is':
|
|
1084
|
+
case 'eq':
|
|
1085
|
+
case '==':
|
|
1086
|
+
case '=':
|
|
1087
|
+
operator = '$eq';
|
|
1088
|
+
break;
|
|
1089
|
+
|
|
1090
|
+
case 'ne':
|
|
1091
|
+
case '!=':
|
|
1092
|
+
operator = '$ne';
|
|
1093
|
+
break;
|
|
1094
|
+
|
|
1095
|
+
case 'gt':
|
|
1096
|
+
case '>':
|
|
1097
|
+
operator = '$gt';
|
|
1098
|
+
break;
|
|
1099
|
+
|
|
1100
|
+
case 'gte':
|
|
1101
|
+
case '>=':
|
|
1102
|
+
operator = '$gte';
|
|
1103
|
+
break;
|
|
1104
|
+
|
|
1105
|
+
case 'lt':
|
|
1106
|
+
case '<':
|
|
1107
|
+
operator = '$lt';
|
|
1108
|
+
break;
|
|
1109
|
+
|
|
1110
|
+
case 'lte':
|
|
1111
|
+
case '<=':
|
|
1112
|
+
operator = '$lte';
|
|
1113
|
+
break;
|
|
1114
|
+
|
|
1115
|
+
case 'empty':
|
|
1116
|
+
operator = '$isEmpty';
|
|
1117
|
+
value = {value: !not};
|
|
1118
|
+
break;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
switch (value.type) {
|
|
1122
|
+
case 'name':
|
|
1123
|
+
value = Trail.fromDot(value.value);
|
|
1124
|
+
break;
|
|
1125
|
+
|
|
1126
|
+
case 'number':
|
|
1127
|
+
value = Number(value.value);
|
|
1128
|
+
break;
|
|
1129
|
+
|
|
1130
|
+
case 'boolean':
|
|
1131
|
+
value = value.value == 'true';
|
|
1132
|
+
break;
|
|
1133
|
+
|
|
1134
|
+
case 'string':
|
|
1135
|
+
value = String.parseQuoted(value.value);
|
|
1136
|
+
break;
|
|
1137
|
+
|
|
1138
|
+
default:
|
|
1139
|
+
value = value.value;
|
|
1140
|
+
break;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
let result = {
|
|
1144
|
+
[name]: {
|
|
1145
|
+
[operator]: value,
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1149
|
+
return result;
|
|
1150
|
+
});
|
|
1151
|
+
|
|
1152
|
+
return conditions;
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
/**
|
|
1156
|
+
* Parse the AQL query into tokens
|
|
1157
|
+
*
|
|
1158
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1159
|
+
* @since 1.4.0
|
|
1160
|
+
* @version 1.4.0
|
|
1161
|
+
*
|
|
1162
|
+
* @param {string} query
|
|
1163
|
+
*
|
|
1164
|
+
* @return {Array}
|
|
1165
|
+
*/
|
|
1166
|
+
function tokenizeAQL(query) {
|
|
1167
|
+
|
|
1168
|
+
const START_STATE = 1,
|
|
1169
|
+
NAME_STATE = 2,
|
|
1170
|
+
OPERATOR_STATE = 3,
|
|
1171
|
+
VALUE_STATE = 4;
|
|
1172
|
+
|
|
1173
|
+
let expressions = [],
|
|
1174
|
+
tokens = Function.tokenize(query, true),
|
|
1175
|
+
current_name,
|
|
1176
|
+
current_operator,
|
|
1177
|
+
current_value,
|
|
1178
|
+
current_not,
|
|
1179
|
+
lower,
|
|
1180
|
+
token,
|
|
1181
|
+
type,
|
|
1182
|
+
value,
|
|
1183
|
+
i;
|
|
1184
|
+
|
|
1185
|
+
let current_state = START_STATE;
|
|
1186
|
+
let states = [current_state];
|
|
1187
|
+
|
|
1188
|
+
const replaceState = state => {
|
|
1189
|
+
states[states.length - 1] = state;
|
|
1190
|
+
current_state = state;
|
|
1191
|
+
};
|
|
1192
|
+
|
|
1193
|
+
const pushState = state => {
|
|
1194
|
+
current_state = state;
|
|
1195
|
+
states.push(current_state);
|
|
1196
|
+
return current_state;
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
const popState = () => {
|
|
1200
|
+
current_state = states.pop();
|
|
1201
|
+
return current_state;
|
|
1202
|
+
};
|
|
1203
|
+
|
|
1204
|
+
const createGroup = () => {
|
|
1205
|
+
|
|
1206
|
+
if (hasCurrent()) {
|
|
1207
|
+
closeValue();
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
expressions.push(true);
|
|
1211
|
+
pushState(START_STATE);
|
|
1212
|
+
};
|
|
1213
|
+
|
|
1214
|
+
const closeGroup = () => {
|
|
1215
|
+
|
|
1216
|
+
if (hasCurrent()) {
|
|
1217
|
+
closeValue();
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
popState();
|
|
1221
|
+
expressions.push(false);
|
|
1222
|
+
};
|
|
1223
|
+
|
|
1224
|
+
const setValue = (token) => {
|
|
1225
|
+
|
|
1226
|
+
if (token === true) {
|
|
1227
|
+
current_value = true;
|
|
1228
|
+
} else {
|
|
1229
|
+
|
|
1230
|
+
let new_value = {
|
|
1231
|
+
type : token.type,
|
|
1232
|
+
value: token.value,
|
|
1233
|
+
not : !!current_not,
|
|
1234
|
+
};
|
|
1235
|
+
|
|
1236
|
+
if (current_value) {
|
|
1237
|
+
if (current_value.type == 'name') {
|
|
1238
|
+
current_value.value = current_value.value + new_value.value;
|
|
1239
|
+
} else {
|
|
1240
|
+
reject('Unexpected value');
|
|
1241
|
+
}
|
|
1242
|
+
} else {
|
|
1243
|
+
current_value = new_value;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
|
|
1248
|
+
const hasCurrent = () => !!(current_name || current_operator || current_value);
|
|
1249
|
+
|
|
1250
|
+
const closeValue = (next_logic_type) => {
|
|
1251
|
+
|
|
1252
|
+
if (!hasCurrent()) {
|
|
1253
|
+
reject('Incomplete statement');
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
let entry = [
|
|
1257
|
+
current_name,
|
|
1258
|
+
current_operator,
|
|
1259
|
+
current_value,
|
|
1260
|
+
current_not,
|
|
1261
|
+
next_logic_type,
|
|
1262
|
+
];
|
|
1263
|
+
|
|
1264
|
+
expressions.push(entry);
|
|
1265
|
+
|
|
1266
|
+
current_name = null;
|
|
1267
|
+
current_operator = null;
|
|
1268
|
+
current_value = null;
|
|
1269
|
+
current_not = null;
|
|
1270
|
+
replaceState(START_STATE);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
const reject = (message) => {
|
|
1274
|
+
throw new Error(message);
|
|
1275
|
+
};
|
|
1276
|
+
|
|
1277
|
+
for (i = 0; i < tokens.length; i++) {
|
|
1278
|
+
token = tokens[i];
|
|
1279
|
+
type = token.type;
|
|
1280
|
+
|
|
1281
|
+
// All whitespace can be ignored
|
|
1282
|
+
if (type == 'whitespace') {
|
|
1283
|
+
continue;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
value = token.value;
|
|
1287
|
+
|
|
1288
|
+
if (value == '(') {
|
|
1289
|
+
createGroup();
|
|
1290
|
+
continue;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
if (value == ')') {
|
|
1294
|
+
closeGroup();
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
lower = value.toLowerCase();
|
|
1299
|
+
|
|
1300
|
+
if (current_state == START_STATE) {
|
|
1301
|
+
if (type != 'name') {
|
|
1302
|
+
reject('Expected name');
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
if (lower == 'not' || lower == 'and' || lower == 'or') {
|
|
1306
|
+
expressions.push(lower);
|
|
1307
|
+
} else {
|
|
1308
|
+
current_name = value;
|
|
1309
|
+
pushState(NAME_STATE);
|
|
1310
|
+
}
|
|
1311
|
+
} else if (current_state == NAME_STATE) {
|
|
1312
|
+
|
|
1313
|
+
if (type == 'punct') {
|
|
1314
|
+
if (value == '.') {
|
|
1315
|
+
current_name += '.';
|
|
1316
|
+
} else {
|
|
1317
|
+
current_operator = value;
|
|
1318
|
+
replaceState(OPERATOR_STATE);
|
|
1319
|
+
}
|
|
1320
|
+
} else if (type == 'name') {
|
|
1321
|
+
if (lower == 'not') {
|
|
1322
|
+
current_not = !current_not;
|
|
1323
|
+
console.log('NOT! Current operator is', current_operator);
|
|
1324
|
+
replaceState(OPERATOR_STATE);
|
|
1325
|
+
} else if (lower == 'is') {
|
|
1326
|
+
current_operator = '==';
|
|
1327
|
+
replaceState(OPERATOR_STATE);
|
|
1328
|
+
} else {
|
|
1329
|
+
current_name += value;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
} else if (current_state == OPERATOR_STATE) {
|
|
1333
|
+
|
|
1334
|
+
// Is there already an operator?
|
|
1335
|
+
if (current_operator) {
|
|
1336
|
+
if (lower == 'not') {
|
|
1337
|
+
current_not = !current_not;
|
|
1338
|
+
} else if (type == 'name' && lower == 'empty') {
|
|
1339
|
+
current_operator = 'empty';
|
|
1340
|
+
setValue(true);
|
|
1341
|
+
replaceState(VALUE_STATE);
|
|
1342
|
+
} else {
|
|
1343
|
+
setValue(token);
|
|
1344
|
+
replaceState(VALUE_STATE);
|
|
1345
|
+
}
|
|
1346
|
+
} else if (type == 'name') {
|
|
1347
|
+
current_operator = lower;
|
|
1348
|
+
} else {
|
|
1349
|
+
reject('Expected operator');
|
|
1350
|
+
}
|
|
1351
|
+
} else if (current_state == VALUE_STATE) {
|
|
1352
|
+
|
|
1353
|
+
if (type == 'name') {
|
|
1354
|
+
if (lower == 'not' && !current_value) {
|
|
1355
|
+
current_not = !current_not;
|
|
1356
|
+
} else if (lower == 'or' || lower == 'and') {
|
|
1357
|
+
if (!current_value) {
|
|
1358
|
+
reject('Expected a value');
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
closeValue(lower);
|
|
1362
|
+
continue;
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
if (type == 'punct') {
|
|
1367
|
+
if (value == '.') {
|
|
1368
|
+
setValue(token);
|
|
1369
|
+
} else {
|
|
1370
|
+
reject('Unexpected punctuation');
|
|
1371
|
+
}
|
|
1372
|
+
} else if (type == 'name') {
|
|
1373
|
+
setValue(token);
|
|
1374
|
+
} else if (current_value) {
|
|
1375
|
+
reject('Unexpected string');
|
|
1376
|
+
} else {
|
|
1377
|
+
setValue(token);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
if (hasCurrent()) {
|
|
1383
|
+
closeValue();
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
return expressions;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
/**
|
|
1390
|
+
* Convert AQL tokens into a conditions object
|
|
1391
|
+
*
|
|
1392
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1393
|
+
* @since 1.4.0
|
|
1394
|
+
* @version 1.4.0
|
|
1395
|
+
*
|
|
1396
|
+
* @param {string} query
|
|
1397
|
+
*
|
|
1398
|
+
* @return {Object}
|
|
1399
|
+
*/
|
|
1400
|
+
function convertAQLTokens(expressions, expression_converter) {
|
|
1401
|
+
|
|
1402
|
+
let current_group,
|
|
1403
|
+
current_logic,
|
|
1404
|
+
next_is_not,
|
|
1405
|
+
expression,
|
|
1406
|
+
i;
|
|
1407
|
+
|
|
1408
|
+
// Make sure there currently exists a group with the given logic type
|
|
1409
|
+
const ensureGroup = (logic) => {
|
|
1410
|
+
|
|
1411
|
+
if (!current_group) {
|
|
1412
|
+
current_group = {
|
|
1413
|
+
logic,
|
|
1414
|
+
expressions: [],
|
|
1415
|
+
};
|
|
1416
|
+
} else {
|
|
1417
|
+
|
|
1418
|
+
if (!current_group.logic) {
|
|
1419
|
+
current_group.logic = logic;
|
|
1420
|
+
} else if (current_group.logic != logic) {
|
|
1421
|
+
pushGroup(logic);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
current_logic = current_group.logic;
|
|
1426
|
+
|
|
1427
|
+
return current_group;
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
// Create the root group
|
|
1431
|
+
let root = ensureGroup();
|
|
1432
|
+
|
|
1433
|
+
// Start a new group of the given logic type.
|
|
1434
|
+
const pushGroup = (logic) => {
|
|
1435
|
+
|
|
1436
|
+
let group = {
|
|
1437
|
+
logic,
|
|
1438
|
+
expressions: [],
|
|
1439
|
+
not: next_is_not
|
|
1440
|
+
};
|
|
1441
|
+
|
|
1442
|
+
if (logic == 'or') {
|
|
1443
|
+
group.expressions.push(simplifyGroups(current_group));
|
|
1444
|
+
current_group = current_group.parent;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
group.parent = current_group;
|
|
1448
|
+
|
|
1449
|
+
if (!current_group) {
|
|
1450
|
+
root = group;
|
|
1451
|
+
} else {
|
|
1452
|
+
current_group.child = group;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
current_group = group;
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
// Close the current group (& restore the parent group)
|
|
1459
|
+
const closeGroup = () => {
|
|
1460
|
+
let group = current_group;
|
|
1461
|
+
current_group = group.parent;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
const simplifyGroups = (group) => {
|
|
1465
|
+
|
|
1466
|
+
let result = {};
|
|
1467
|
+
let logic;
|
|
1468
|
+
|
|
1469
|
+
if (group.logic == 'and' || !group.logic) {
|
|
1470
|
+
logic = '$and';
|
|
1471
|
+
} else if (group.logic == 'or') {
|
|
1472
|
+
logic = '$or';
|
|
1473
|
+
} else {
|
|
1474
|
+
throw new Error('Unknown logic type');
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
result[logic] = group.expressions;
|
|
1478
|
+
|
|
1479
|
+
if (group.child) {
|
|
1480
|
+
result[logic].push(simplifyGroups(group.child));
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
if (group.not) {
|
|
1484
|
+
result = {
|
|
1485
|
+
$nor: result
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
return result;
|
|
1490
|
+
};
|
|
1491
|
+
|
|
1492
|
+
for (i = 0; i < expressions.length; i++) {
|
|
1493
|
+
expression = expressions[i];
|
|
1494
|
+
|
|
1495
|
+
if (expression === true) {
|
|
1496
|
+
pushGroup();
|
|
1497
|
+
} else if (expression === false) {
|
|
1498
|
+
closeGroup();
|
|
1499
|
+
} else if (expression === 'and' || expression === 'or') {
|
|
1500
|
+
ensureGroup(expression);
|
|
1501
|
+
} else if (expression === 'not') {
|
|
1502
|
+
next_is_not = true;
|
|
1503
|
+
continue;
|
|
1504
|
+
} else {
|
|
1505
|
+
|
|
1506
|
+
current_logic = expression[4];
|
|
1507
|
+
|
|
1508
|
+
// And gets precedence
|
|
1509
|
+
if (current_logic == 'and') {
|
|
1510
|
+
ensureGroup(current_logic);
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
expression = expression_converter(...expression);
|
|
1514
|
+
|
|
1515
|
+
current_group.expressions.push(expression);
|
|
1516
|
+
|
|
1517
|
+
if (current_logic == 'or') {
|
|
1518
|
+
ensureGroup(current_logic);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
next_is_not = false;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
return simplifyGroups(root);
|
|
1526
|
+
}
|
|
1527
|
+
|
|
974
1528
|
/**
|
|
975
1529
|
* Get the MongoDB options from this criteria
|
|
976
1530
|
*
|
|
977
|
-
* @author Jelle De Loecker
|
|
1531
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
978
1532
|
* @since 1.1.0
|
|
979
1533
|
* @version 1.1.0
|
|
980
1534
|
*
|
|
@@ -1011,7 +1565,7 @@ NoSQL.setMethod(function compileCriteriaOptions(criteria) {
|
|
|
1011
1565
|
/**
|
|
1012
1566
|
* Handle items from the datasource
|
|
1013
1567
|
*
|
|
1014
|
-
* @author Jelle De Loecker
|
|
1568
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1015
1569
|
* @since 1.1.0
|
|
1016
1570
|
* @version 1.1.0
|
|
1017
1571
|
*
|