alchemymvc 1.3.21 → 1.4.0-alpha.1
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 +10 -10
- 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 +16 -16
- 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 +84 -59
- 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 +8 -8
- 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 +203 -124
- 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 +203 -163
- 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 +50 -25
- package/lib/class/inode_list.js +4 -4
- package/lib/class/migration.js +4 -4
- package/lib/class/model.js +182 -168
- 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 +73 -67
- 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 +413 -374
- package/lib/{init/functions.js → core/alchemy_functions.js} +171 -108
- 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 +39 -52
- 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 -973
- package/lib/stages.js +0 -513
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Base Criteria Expression class
|
|
3
|
+
*
|
|
4
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
5
|
+
* @since 1.1.0
|
|
6
|
+
* @version 1.1.0
|
|
7
|
+
*/
|
|
8
|
+
const Expression = Function.inherits('Alchemy.Base', 'Alchemy.Criteria.Expression', function Expression(criteria) {
|
|
9
|
+
|
|
10
|
+
// The parent criteria instance
|
|
11
|
+
this.criteria = criteria;
|
|
12
|
+
|
|
13
|
+
// The current group it's in
|
|
14
|
+
this.current_group = null;
|
|
15
|
+
|
|
16
|
+
// The items this contains
|
|
17
|
+
this.items = [];
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Revive an object
|
|
22
|
+
*
|
|
23
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
24
|
+
* @since 1.1.0
|
|
25
|
+
* @version 1.1.0
|
|
26
|
+
*
|
|
27
|
+
* @return {Expression}
|
|
28
|
+
*/
|
|
29
|
+
Expression.setStatic(function revive(data, criteria) {
|
|
30
|
+
|
|
31
|
+
if (data._type == 'group') {
|
|
32
|
+
return Group.revive(data, criteria);
|
|
33
|
+
} else if (data._type == 'field') {
|
|
34
|
+
return FieldExpression.revive(data, criteria);
|
|
35
|
+
} else {
|
|
36
|
+
throw new Error('Unable to revive "' + data._type + '" expression');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Does this expression do something with an association,
|
|
43
|
+
* and do we need to normalize this on the current given datasource?
|
|
44
|
+
*
|
|
45
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
46
|
+
* @since 1.1.0
|
|
47
|
+
* @version 1.1.0
|
|
48
|
+
*
|
|
49
|
+
* @type {boolean}
|
|
50
|
+
*/
|
|
51
|
+
Expression.setProperty(function requires_association_normalization() {
|
|
52
|
+
|
|
53
|
+
if (!this.association) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!this.datasource.supports('querying_associations')) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return false;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create a reference to the datasource
|
|
66
|
+
*
|
|
67
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
68
|
+
* @since 1.1.0
|
|
69
|
+
* @version 1.1.0
|
|
70
|
+
*
|
|
71
|
+
* @type {Datasource}
|
|
72
|
+
*/
|
|
73
|
+
Expression.setProperty(function datasource() {
|
|
74
|
+
if (this.criteria) {
|
|
75
|
+
return this.criteria.datasource;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Create a reference to the model
|
|
81
|
+
*
|
|
82
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
83
|
+
* @since 1.1.0
|
|
84
|
+
* @version 1.1.0
|
|
85
|
+
*
|
|
86
|
+
* @type {Model}
|
|
87
|
+
*/
|
|
88
|
+
Expression.setProperty(function model() {
|
|
89
|
+
if (this.criteria) {
|
|
90
|
+
return this.criteria.model;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Create a reference to the field instance
|
|
96
|
+
*
|
|
97
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
98
|
+
* @since 1.1.0
|
|
99
|
+
* @version 1.1.0
|
|
100
|
+
*
|
|
101
|
+
* @type {FieldType}
|
|
102
|
+
*/
|
|
103
|
+
Expression.setProperty(function field() {
|
|
104
|
+
if (this.criteria && this.criteria.model) {
|
|
105
|
+
return this.criteria.model.schema.getField(this.target_path);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Return the elements to checksum in place of this object
|
|
111
|
+
*
|
|
112
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
113
|
+
* @since 1.1.0
|
|
114
|
+
* @version 1.1.0
|
|
115
|
+
*/
|
|
116
|
+
Expression.setMethod(Blast.checksumSymbol, function toChecksum() {
|
|
117
|
+
return this.items;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get a clone without any Criteria or Group links
|
|
122
|
+
*
|
|
123
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
124
|
+
* @since 1.1.0
|
|
125
|
+
* @version 1.1.0
|
|
126
|
+
*
|
|
127
|
+
* @return {Expression}
|
|
128
|
+
*/
|
|
129
|
+
Expression.setMethod(function getCleanClone() {
|
|
130
|
+
|
|
131
|
+
var result = new this.constructor();
|
|
132
|
+
|
|
133
|
+
// Add the cloned array
|
|
134
|
+
result.items = JSON.clone(this.items);
|
|
135
|
+
|
|
136
|
+
if (this.association) {
|
|
137
|
+
result.association = this.association;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (this.target_path) {
|
|
141
|
+
result.target_path = this.target_path;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (this.group_type) {
|
|
145
|
+
result.group_type = this.group_type;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (this.db_property) {
|
|
149
|
+
result.db_property = this.db_property;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return result;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Move the expression to the given group (object)
|
|
157
|
+
* or the given group type (and/or)
|
|
158
|
+
*
|
|
159
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
160
|
+
* @since 1.1.0
|
|
161
|
+
* @version 1.1.0
|
|
162
|
+
*
|
|
163
|
+
* @param {Object|string} group
|
|
164
|
+
*/
|
|
165
|
+
Expression.setMethod(function moveToGroup(group) {
|
|
166
|
+
|
|
167
|
+
var context = this.criteria;
|
|
168
|
+
|
|
169
|
+
// Move to a specific type?
|
|
170
|
+
if (typeof group == 'string') {
|
|
171
|
+
|
|
172
|
+
// Is it already part of the same type of group?
|
|
173
|
+
// Then we can ignore this call
|
|
174
|
+
if (this.current_group && this.current_group.group_type == group) {
|
|
175
|
+
return context;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Create a new group of the given type
|
|
179
|
+
context = context.createGroup(group);
|
|
180
|
+
group = context.group;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (this.current_group) {
|
|
184
|
+
this.current_group.removeItem(this);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.current_group = group;
|
|
188
|
+
group.addItem(this);
|
|
189
|
+
|
|
190
|
+
return context;
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Remove this expression from the criteria
|
|
195
|
+
*
|
|
196
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
197
|
+
* @since 1.1.0
|
|
198
|
+
* @version 1.1.0
|
|
199
|
+
*/
|
|
200
|
+
Expression.setMethod(function remove() {
|
|
201
|
+
|
|
202
|
+
if (arguments.length) {
|
|
203
|
+
throw new Error('Expression#remove() can only remove itself');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let index = this.criteria.all_expressions.indexOf(this);
|
|
207
|
+
|
|
208
|
+
if (index > -1) {
|
|
209
|
+
this.criteria.all_expressions.splice(index, 1);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (this.current_group) {
|
|
213
|
+
this.current_group.removeItem(this);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Add an item
|
|
219
|
+
*
|
|
220
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
221
|
+
* @since 1.1.0
|
|
222
|
+
* @version 1.1.0
|
|
223
|
+
*
|
|
224
|
+
* @param {Object} item
|
|
225
|
+
*/
|
|
226
|
+
Expression.setMethod(function addItem(item) {
|
|
227
|
+
this.items.push(item);
|
|
228
|
+
return item;
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Remove an item from this expression
|
|
233
|
+
*
|
|
234
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
235
|
+
* @since 1.1.0
|
|
236
|
+
* @version 1.1.0
|
|
237
|
+
*
|
|
238
|
+
* @param {Object} item
|
|
239
|
+
*/
|
|
240
|
+
Expression.setMethod(function removeItem(item) {
|
|
241
|
+
|
|
242
|
+
var index = this.items.indexOf(item);
|
|
243
|
+
|
|
244
|
+
// If this expression was found in the current group, remove it
|
|
245
|
+
if (index > -1) {
|
|
246
|
+
this.items.splice(index, 1);
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return false;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* The Field Expression class
|
|
255
|
+
*
|
|
256
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
257
|
+
* @since 1.1.0
|
|
258
|
+
* @version 1.1.0
|
|
259
|
+
*/
|
|
260
|
+
const FieldExpression = Function.inherits('Alchemy.Criteria.Expression', function Field(criteria, field) {
|
|
261
|
+
|
|
262
|
+
Field.super.call(this, criteria);
|
|
263
|
+
|
|
264
|
+
if (arguments.length) {
|
|
265
|
+
// Set the target
|
|
266
|
+
this.setTargetPath(field);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Revive an object
|
|
272
|
+
*
|
|
273
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
274
|
+
* @since 1.1.0
|
|
275
|
+
* @version 1.1.0
|
|
276
|
+
*
|
|
277
|
+
* @return {FieldExpression}
|
|
278
|
+
*/
|
|
279
|
+
FieldExpression.setStatic(function revive(data, criteria) {
|
|
280
|
+
|
|
281
|
+
var result = new FieldExpression();
|
|
282
|
+
|
|
283
|
+
result.criteria = criteria;
|
|
284
|
+
|
|
285
|
+
criteria.all_expressions.push(result);
|
|
286
|
+
|
|
287
|
+
if (data.association) {
|
|
288
|
+
result.association = data.association;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (data.target_path) {
|
|
292
|
+
result.target_path = data.target_path;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (data.items) {
|
|
296
|
+
result.items = data.items;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (data.db_property) {
|
|
300
|
+
result.db_property = data.db_property;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return result;
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Return object to jsonify
|
|
308
|
+
*
|
|
309
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
310
|
+
* @since 1.1.0
|
|
311
|
+
* @version 1.4.0
|
|
312
|
+
*
|
|
313
|
+
* @return {Object}
|
|
314
|
+
*/
|
|
315
|
+
FieldExpression.setMethod(function toJSON() {
|
|
316
|
+
|
|
317
|
+
let result = {
|
|
318
|
+
_type : 'field',
|
|
319
|
+
target_path : this.target_path,
|
|
320
|
+
items : this.items,
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
if (this.association) {
|
|
324
|
+
result.association = this.association;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (this.db_property) {
|
|
328
|
+
result.db_property = this.db_property;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return result;
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Return the elements to checksum in place of this object
|
|
336
|
+
*
|
|
337
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
338
|
+
* @since 1.1.0
|
|
339
|
+
* @version 1.4.0
|
|
340
|
+
*/
|
|
341
|
+
FieldExpression.setMethod(Blast.checksumSymbol, function toChecksum() {
|
|
342
|
+
return this.toJSON();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Set the target
|
|
347
|
+
*
|
|
348
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
349
|
+
* @since 1.1.0
|
|
350
|
+
* @version 1.1.0
|
|
351
|
+
*
|
|
352
|
+
* @param {string} path
|
|
353
|
+
*/
|
|
354
|
+
FieldExpression.setMethod(function setTargetPath(path) {
|
|
355
|
+
|
|
356
|
+
var pieces;
|
|
357
|
+
|
|
358
|
+
if (typeof path == 'string') {
|
|
359
|
+
if (path.indexOf('.') > -1) {
|
|
360
|
+
pieces = path.split('.');
|
|
361
|
+
}
|
|
362
|
+
} else if (Array.isArray(path)) {
|
|
363
|
+
pieces = path;
|
|
364
|
+
} else {
|
|
365
|
+
throw new Error('Field#setTargetPath(path) requires a string or an array');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (!pieces) {
|
|
369
|
+
this.target_path = path;
|
|
370
|
+
} else {
|
|
371
|
+
let first = pieces[0];
|
|
372
|
+
|
|
373
|
+
// @TODO: better check if the first part is an association
|
|
374
|
+
if (first[0].isUpperCase()) {
|
|
375
|
+
this.association = first;
|
|
376
|
+
pieces.shift();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
this.target_path = pieces.join('.');
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Add a new condition item
|
|
386
|
+
*
|
|
387
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
388
|
+
* @since 1.1.0
|
|
389
|
+
* @version 1.1.5
|
|
390
|
+
*
|
|
391
|
+
* @param {Object|string} group
|
|
392
|
+
*
|
|
393
|
+
* @return {Object}
|
|
394
|
+
*/
|
|
395
|
+
FieldExpression.setMethod(function addItem(type, value) {
|
|
396
|
+
|
|
397
|
+
var entry = {
|
|
398
|
+
type : type
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
if (arguments.length > 1) {
|
|
402
|
+
|
|
403
|
+
if (typeof value == 'object' && value && value instanceof Classes.Alchemy.Base) {
|
|
404
|
+
throw new Classes.Alchemy.Error.Model('"' + value.constructor.getClassPath() + '" instance was given as a "' + this.target_path + '" condition');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
entry.value = value;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
this.items.push(entry);
|
|
411
|
+
|
|
412
|
+
return entry;
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Normalize the values (like casting strings to objectids)
|
|
417
|
+
*
|
|
418
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
419
|
+
* @since 1.1.0
|
|
420
|
+
* @version 1.1.0
|
|
421
|
+
*
|
|
422
|
+
* @return {Pledge|Null}
|
|
423
|
+
*/
|
|
424
|
+
FieldExpression.setMethod(function normalize() {
|
|
425
|
+
|
|
426
|
+
var field = this.field;
|
|
427
|
+
|
|
428
|
+
if (!field) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
let item,
|
|
433
|
+
i;
|
|
434
|
+
|
|
435
|
+
for (i = 0; i < this.items.length; i++) {
|
|
436
|
+
item = this.items[i];
|
|
437
|
+
|
|
438
|
+
// Skip field_expression items
|
|
439
|
+
// (like $exists: true and such)
|
|
440
|
+
// or items where `cast` is explicitly false
|
|
441
|
+
if (item.field_expression || item.cast === false) {
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (item.value != null) {
|
|
446
|
+
if (Array.isArray(item.value)) {
|
|
447
|
+
let result = [],
|
|
448
|
+
i;
|
|
449
|
+
|
|
450
|
+
for (i = 0; i < item.value.length; i++) {
|
|
451
|
+
result[i] = field.castCondition(item.value[i], this);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
item.value = result;
|
|
455
|
+
} else {
|
|
456
|
+
item.value = field.castCondition(item.value, this);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Normalize association values by separately querying them
|
|
464
|
+
* and adding the found values to the criteria
|
|
465
|
+
*
|
|
466
|
+
* @WARNING: this can be extremely resource intensive when using
|
|
467
|
+
* on big collections.
|
|
468
|
+
*
|
|
469
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
470
|
+
* @since 1.1.0
|
|
471
|
+
* @version 1.4.0
|
|
472
|
+
*
|
|
473
|
+
* @return {Pledge}
|
|
474
|
+
*/
|
|
475
|
+
FieldExpression.setMethod(function normalizeAssociationValues() {
|
|
476
|
+
|
|
477
|
+
if (!this.association) {
|
|
478
|
+
return Pledge.reject(new Error('Unable to normalize a field without an association'));
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
let that = this,
|
|
482
|
+
association = this.model.getAssociation(this.association),
|
|
483
|
+
assoc_model = this.model.getModel(association.modelName),
|
|
484
|
+
assoc_crit = new Classes.Alchemy.Criteria.Model(),
|
|
485
|
+
pledge = new Pledge(),
|
|
486
|
+
clone = this.getCleanClone(),
|
|
487
|
+
item,
|
|
488
|
+
i;
|
|
489
|
+
|
|
490
|
+
// Unset the association
|
|
491
|
+
clone.association = null;
|
|
492
|
+
|
|
493
|
+
// Add the clone
|
|
494
|
+
assoc_crit.addNewExpression(clone);
|
|
495
|
+
|
|
496
|
+
// Only select the wanted field
|
|
497
|
+
assoc_crit.select(association.options.foreignKey);
|
|
498
|
+
|
|
499
|
+
assoc_model.find('all', {criteria: assoc_crit, document: false}, function gotAssocItems(err, items) {
|
|
500
|
+
|
|
501
|
+
if (err) {
|
|
502
|
+
return pledge.reject(err);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
let values = [],
|
|
506
|
+
record,
|
|
507
|
+
i;
|
|
508
|
+
|
|
509
|
+
for (i = 0; i < items.length; i++) {
|
|
510
|
+
values.push(items[i][association.options.foreignKey]);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (!values.length) {
|
|
514
|
+
// @TODO: make this more elegant
|
|
515
|
+
values.push('_impossible_');
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Remove the expression from the criteria
|
|
519
|
+
that.remove();
|
|
520
|
+
|
|
521
|
+
// And add this new one
|
|
522
|
+
that.criteria.where(association.options.localKey).in(values);
|
|
523
|
+
|
|
524
|
+
pledge.resolve();
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
return pledge;
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* The Group Expression class
|
|
532
|
+
*
|
|
533
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
534
|
+
* @since 1.1.0
|
|
535
|
+
* @version 1.1.0
|
|
536
|
+
*/
|
|
537
|
+
const Group = Function.inherits('Alchemy.Criteria.Expression', function Group(criteria, type) {
|
|
538
|
+
|
|
539
|
+
Group.super.call(this, criteria);
|
|
540
|
+
|
|
541
|
+
// The group type
|
|
542
|
+
this.group_type = type;
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Revive an object
|
|
547
|
+
*
|
|
548
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
549
|
+
* @since 1.1.0
|
|
550
|
+
* @version 1.1.0
|
|
551
|
+
*
|
|
552
|
+
* @return {Group}
|
|
553
|
+
*/
|
|
554
|
+
Group.setStatic(function revive(data, criteria) {
|
|
555
|
+
|
|
556
|
+
let result = new Group(criteria);
|
|
557
|
+
|
|
558
|
+
result.group_type = data.group_type;
|
|
559
|
+
|
|
560
|
+
if (data.items) {
|
|
561
|
+
let i;
|
|
562
|
+
result.items = [];
|
|
563
|
+
|
|
564
|
+
for (i = 0; i < data.items.length; i++) {
|
|
565
|
+
result.items.push(Expression.revive(data.items[i], criteria));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return result;
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Return object to jsonify
|
|
574
|
+
*
|
|
575
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
576
|
+
* @since 1.1.0
|
|
577
|
+
* @version 1.4.0
|
|
578
|
+
*
|
|
579
|
+
* @return {Object}
|
|
580
|
+
*/
|
|
581
|
+
Group.setMethod(function toJSON() {
|
|
582
|
+
|
|
583
|
+
let result = {
|
|
584
|
+
_type : 'group',
|
|
585
|
+
group_type : this.group_type,
|
|
586
|
+
items : this.items.slice(0)
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
if (this.association) {
|
|
590
|
+
result.association = this.association;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return result;
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Return the elements to checksum in place of this object
|
|
598
|
+
*
|
|
599
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
600
|
+
* @since 1.1.0
|
|
601
|
+
* @version 1.1.0
|
|
602
|
+
*/
|
|
603
|
+
Group.setMethod(Blast.checksumSymbol, function toChecksum() {
|
|
604
|
+
return this.toJSON();
|
|
605
|
+
});
|