alchemymvc 1.2.8 → 1.3.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/lib/app/behaviour/sluggable_behaviour.js +4 -2
- package/lib/app/conduit/http_conduit.js +7 -2
- package/lib/app/conduit/loopback_conduit.js +2 -2
- package/lib/app/conduit/socket_conduit.js +20 -5
- package/lib/app/controller/alchemy_info_controller.js +4 -8
- package/lib/app/helper/backed_map.js +2 -2
- package/lib/app/helper/router_helper.js +98 -24
- package/lib/app/helper_controller/controller.js +45 -30
- package/lib/app/helper_datasource/00-nosql_datasource.js +44 -10
- package/lib/app/helper_field/enum_field.js +4 -4
- package/lib/app/helper_field/schema_field.js +50 -36
- package/lib/app/helper_model/document.js +81 -46
- package/lib/app/helper_model/field_set.js +11 -0
- package/lib/app/helper_model/model.js +107 -53
- package/lib/app/helper_validator/00_validator.js +38 -6
- package/lib/app/helper_validator/not_empty_validator.js +1 -3
- package/lib/app/routes.js +7 -1
- package/lib/bootstrap.js +1 -0
- package/lib/class/conduit.js +438 -290
- package/lib/class/controller.js +18 -15
- package/lib/class/datasource.js +19 -8
- package/lib/class/document.js +3 -3
- package/lib/class/field.js +34 -3
- package/lib/class/inode.js +27 -0
- package/lib/class/inode_file.js +204 -4
- package/lib/class/migration.js +2 -1
- package/lib/class/model.js +16 -5
- package/lib/class/path_definition.js +76 -120
- package/lib/class/path_param_definition.js +202 -0
- package/lib/class/postponement.js +573 -0
- package/lib/class/route.js +193 -33
- package/lib/class/router.js +22 -4
- package/lib/class/schema.js +47 -11
- package/lib/class/schema_client.js +65 -35
- package/lib/class/session.js +138 -12
- package/lib/class/sitemap.js +341 -0
- package/lib/core/base.js +13 -3
- package/lib/core/client_alchemy.js +78 -7
- package/lib/core/client_base.js +16 -10
- package/lib/core/middleware.js +56 -45
- package/lib/init/alchemy.js +124 -11
- package/lib/init/constants.js +11 -0
- package/lib/init/functions.js +163 -86
- package/lib/stages.js +18 -3
- package/package.json +6 -6
|
@@ -79,7 +79,7 @@ Sluggable.setStatic(function getSource(source, schema) {
|
|
|
79
79
|
*
|
|
80
80
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
81
81
|
* @since 0.2.0
|
|
82
|
-
* @version
|
|
82
|
+
* @version 1.3.0
|
|
83
83
|
*
|
|
84
84
|
* @param {Schema} schema
|
|
85
85
|
* @param {Object} options
|
|
@@ -113,7 +113,9 @@ Sluggable.setStatic(function attached(schema, new_options) {
|
|
|
113
113
|
// Create the target if it doesn't exist yet
|
|
114
114
|
if (!target) {
|
|
115
115
|
|
|
116
|
-
field_options = {
|
|
116
|
+
field_options = {
|
|
117
|
+
description: 'A human-readable yet unique identifier'
|
|
118
|
+
};
|
|
117
119
|
|
|
118
120
|
// See if the target field we're adding needs to be translatable
|
|
119
121
|
if (options.translatable || (options.translatable == null && source && source.is_translatable)) {
|
|
@@ -105,9 +105,9 @@ HttpConduit.enforceProperty(function fingerprint() {
|
|
|
105
105
|
/**
|
|
106
106
|
* Init
|
|
107
107
|
*
|
|
108
|
-
* @author Jelle De Loecker <jelle@
|
|
108
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
109
109
|
* @since 0.3.3
|
|
110
|
-
* @version 1.
|
|
110
|
+
* @version 1.3.1
|
|
111
111
|
*
|
|
112
112
|
* @param {IncomingMessage} req
|
|
113
113
|
* @param {ServerResponse} res
|
|
@@ -139,6 +139,11 @@ HttpConduit.setMethod(async function initHttp(req, res, router) {
|
|
|
139
139
|
|
|
140
140
|
this.debugMark(false);
|
|
141
141
|
|
|
142
|
+
if (this.shouldBePostponed()) {
|
|
143
|
+
this.postponeAndQueue();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
142
147
|
// Call the middleware, which will call the handler afterwards
|
|
143
148
|
this.callMiddleware();
|
|
144
149
|
});
|
|
@@ -78,7 +78,7 @@ LoopConduit.setMethod(function copyParentProperties(conduit) {
|
|
|
78
78
|
*
|
|
79
79
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
80
80
|
* @since 1.1.3
|
|
81
|
-
* @version 1.
|
|
81
|
+
* @version 1.3.0
|
|
82
82
|
*
|
|
83
83
|
* @param {Object} options
|
|
84
84
|
* @param {Function} callback
|
|
@@ -165,7 +165,7 @@ LoopConduit.setMethod(function setOptions(options, callback) {
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
if (options.params) {
|
|
168
|
-
this.
|
|
168
|
+
this.setRouteParameters(options.params);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
if (options.arguments) {
|
|
@@ -102,19 +102,34 @@ var SocketConduit = Function.inherits('Alchemy.Conduit', function Socket(socket,
|
|
|
102
102
|
/**
|
|
103
103
|
* Return the client IP address
|
|
104
104
|
*
|
|
105
|
-
* @author Jelle De Loecker <jelle@
|
|
105
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
106
106
|
* @since 0.2.1
|
|
107
|
-
* @version
|
|
107
|
+
* @version 1.3.1
|
|
108
108
|
*/
|
|
109
109
|
SocketConduit.setProperty(function ip() {
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
let handshake = this.socket?.handshake;
|
|
112
112
|
|
|
113
|
-
if (!
|
|
113
|
+
if (!handshake) {
|
|
114
114
|
return null;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
if (handshake.headers) {
|
|
118
|
+
let forwarded_for = handshake.headers['x-forwarded-for'] || handshake.headers['x-real-ip'];
|
|
119
|
+
|
|
120
|
+
if (forwarded_for) {
|
|
121
|
+
|
|
122
|
+
// Forwarded for can contain multiple ip addresses,
|
|
123
|
+
// return the first one
|
|
124
|
+
if (forwarded_for.indexOf(',') > -1) {
|
|
125
|
+
forwarded_for = forwarded_for.before(',');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return forwarded_for;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return handshake.address || null;
|
|
118
133
|
});
|
|
119
134
|
|
|
120
135
|
/**
|
|
@@ -130,20 +130,16 @@ Info.setAction(async function appcache(conduit) {
|
|
|
130
130
|
*
|
|
131
131
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
132
132
|
* @since 1.1.0
|
|
133
|
-
* @version 1.1
|
|
133
|
+
* @version 1.3.1
|
|
134
134
|
*/
|
|
135
135
|
Info.setAction(function postponed(conduit, id) {
|
|
136
136
|
|
|
137
137
|
var session = conduit.getSession(),
|
|
138
|
-
|
|
138
|
+
postponement = session.getPostponement(id);
|
|
139
139
|
|
|
140
|
-
if (!
|
|
140
|
+
if (!postponement) {
|
|
141
141
|
return conduit.notFound();
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
postponed_conduit._end(...postponed_conduit._end_arguments);
|
|
147
|
-
|
|
148
|
-
session.postponed.remove(id);
|
|
144
|
+
postponement.handleRequest(conduit);
|
|
149
145
|
});
|
|
@@ -77,12 +77,12 @@ Backed.enforceProperty(function backing(new_value, old_value) {
|
|
|
77
77
|
*
|
|
78
78
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
79
79
|
* @since 1.2.1
|
|
80
|
-
* @version 1.
|
|
80
|
+
* @version 1.3.1
|
|
81
81
|
*
|
|
82
82
|
* @return {Backed}
|
|
83
83
|
*/
|
|
84
84
|
Backed.setMethod(function clone() {
|
|
85
|
-
let result = new
|
|
85
|
+
let result = new this.constructor(this.backing);
|
|
86
86
|
result.local = new Map(this.local);
|
|
87
87
|
return result;
|
|
88
88
|
});
|
|
@@ -46,12 +46,49 @@ Router.setProperty(function current_url() {
|
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Check if the given URL is a local one
|
|
51
|
+
*
|
|
52
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
53
|
+
* @since 1.3.0
|
|
54
|
+
* @version 1.3.0
|
|
55
|
+
*
|
|
56
|
+
* @param {String|RURL} url
|
|
57
|
+
*
|
|
58
|
+
* @return {Boolean}
|
|
59
|
+
*/
|
|
60
|
+
Router.setMethod(function isLocalUrl(url) {
|
|
61
|
+
|
|
62
|
+
url = RURL.parse(url);
|
|
63
|
+
|
|
64
|
+
if (!url.hostname) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (Blast.isNode && alchemy.settings.url) {
|
|
69
|
+
// @TODO: Would be nice to not have to parse this every time
|
|
70
|
+
let server_url = RURL.parse(alchemy.settings.url);
|
|
71
|
+
|
|
72
|
+
if (server_url.hostname == url.hostname) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let current_url = this.current_url;
|
|
78
|
+
|
|
79
|
+
if (current_url && current_url.hostname == url.hostname) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return false;
|
|
84
|
+
});
|
|
85
|
+
|
|
49
86
|
/**
|
|
50
87
|
* Apply directive to an element
|
|
51
88
|
*
|
|
52
|
-
* @author Jelle De Loecker <jelle@
|
|
89
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
53
90
|
* @since 1.1.0
|
|
54
|
-
* @version 1.
|
|
91
|
+
* @version 1.3.1
|
|
55
92
|
*
|
|
56
93
|
* @param {Element} element The element to apply to
|
|
57
94
|
* @param {String} name The route name
|
|
@@ -83,14 +120,23 @@ Router.setMethod(function applyDirective(element, name, options) {
|
|
|
83
120
|
if (config.keys && config.keys.length) {
|
|
84
121
|
|
|
85
122
|
let key,
|
|
86
|
-
val
|
|
87
|
-
i;
|
|
123
|
+
val;
|
|
88
124
|
|
|
89
|
-
for (
|
|
90
|
-
key = config.keys[i];
|
|
125
|
+
for (key of config.keys) {
|
|
91
126
|
|
|
92
127
|
if (params[key] == null) {
|
|
93
|
-
|
|
128
|
+
|
|
129
|
+
val = element['route_' + key];
|
|
130
|
+
|
|
131
|
+
if (val == null) {
|
|
132
|
+
let variables = element[Hawkejs.VARIABLES];
|
|
133
|
+
|
|
134
|
+
if (variables) {
|
|
135
|
+
val = variables[key];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (val == null) {
|
|
94
140
|
val = element[key];
|
|
95
141
|
}
|
|
96
142
|
|
|
@@ -284,14 +330,14 @@ Router.setMethod(function routeConfig(name, socket_route) {
|
|
|
284
330
|
*
|
|
285
331
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
286
332
|
* @since 0.2.0
|
|
287
|
-
* @version 1.
|
|
333
|
+
* @version 1.3.0
|
|
288
334
|
*
|
|
289
335
|
* @param {String} name
|
|
290
336
|
* @param {Object} parameters
|
|
291
337
|
*
|
|
292
338
|
* @return {RURL}
|
|
293
339
|
*/
|
|
294
|
-
Router.setMethod(function routeUrl(name,
|
|
340
|
+
Router.setMethod(function routeUrl(name, parameters, options) {
|
|
295
341
|
|
|
296
342
|
var parameters,
|
|
297
343
|
base_url,
|
|
@@ -307,10 +353,9 @@ Router.setMethod(function routeUrl(name, _parameters, options) {
|
|
|
307
353
|
|
|
308
354
|
url = '';
|
|
309
355
|
config = options.config || this.routeConfig(name);
|
|
310
|
-
parameters = Blast.Bound.Object.assign({}, _parameters);
|
|
311
356
|
|
|
312
|
-
if (options.locale) {
|
|
313
|
-
locales = [options.locale];
|
|
357
|
+
if (options.locale || options.prefix) {
|
|
358
|
+
locales = [options.prefix || options.locale];
|
|
314
359
|
} else if (options.locales) {
|
|
315
360
|
locales = options.locales;
|
|
316
361
|
} else if (this.view) {
|
|
@@ -393,11 +438,24 @@ Router.setMethod(function routeUrl(name, _parameters, options) {
|
|
|
393
438
|
}
|
|
394
439
|
|
|
395
440
|
if (options.full || options.absolute) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
441
|
+
if (this.view) {
|
|
442
|
+
base_url = this.view.internal('url');
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (!base_url) {
|
|
446
|
+
if (Blast.isBrowser) {
|
|
447
|
+
base_url = RURL.parse(window.location);
|
|
448
|
+
} else {
|
|
449
|
+
base_url = RURL.parse(alchemy.settings.url);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (base_url) {
|
|
454
|
+
url.protocol = base_url.protocol;
|
|
455
|
+
url.host = base_url.host;
|
|
456
|
+
url.hostname = base_url.hostname;
|
|
457
|
+
url.port = base_url.port;
|
|
458
|
+
}
|
|
401
459
|
}
|
|
402
460
|
|
|
403
461
|
url._locales = locales;
|
|
@@ -631,11 +689,12 @@ Router.setMethod(function getRouteVariables() {
|
|
|
631
689
|
*
|
|
632
690
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
633
691
|
* @since 1.2.5
|
|
634
|
-
* @version 1.
|
|
692
|
+
* @version 1.3.0
|
|
635
693
|
*
|
|
636
694
|
* @param {Element} element The element to apply to
|
|
695
|
+
* @param {Object} variables
|
|
637
696
|
*/
|
|
638
|
-
Router.setMethod(function updateLanguageSwitcher(element) {
|
|
697
|
+
Router.setMethod(function updateLanguageSwitcher(element, variables) {
|
|
639
698
|
|
|
640
699
|
let language = element.getAttribute('data-alchemy-language-switch');
|
|
641
700
|
|
|
@@ -643,7 +702,7 @@ Router.setMethod(function updateLanguageSwitcher(element) {
|
|
|
643
702
|
return;
|
|
644
703
|
}
|
|
645
704
|
|
|
646
|
-
let url = this.translateCurrentRoute(language);
|
|
705
|
+
let url = this.translateCurrentRoute(language, variables);
|
|
647
706
|
|
|
648
707
|
if (!url) {
|
|
649
708
|
url = '/' + language;
|
|
@@ -657,11 +716,21 @@ Router.setMethod(function updateLanguageSwitcher(element) {
|
|
|
657
716
|
*
|
|
658
717
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
659
718
|
* @since 1.2.5
|
|
660
|
-
* @version 1.
|
|
719
|
+
* @version 1.3.0
|
|
661
720
|
*
|
|
662
721
|
* @param {String} prefix The prefix to use
|
|
722
|
+
* @param {Object} variables
|
|
663
723
|
*/
|
|
664
|
-
Router.setMethod(function translateCurrentRoute(prefix) {
|
|
724
|
+
Router.setMethod(function translateCurrentRoute(prefix, variables) {
|
|
725
|
+
|
|
726
|
+
let current_route_translations = variables?.__current_route_translations,
|
|
727
|
+
current_route_translation = current_route_translations?.[prefix] ?? null;
|
|
728
|
+
|
|
729
|
+
if (current_route_translation) {
|
|
730
|
+
return current_route_translation;
|
|
731
|
+
} else if (current_route_translation === false) {
|
|
732
|
+
return false;
|
|
733
|
+
}
|
|
665
734
|
|
|
666
735
|
let info = this.getRouteVariables();
|
|
667
736
|
|
|
@@ -685,6 +754,11 @@ Router.setMethod(function translateCurrentRoute(prefix) {
|
|
|
685
754
|
url.pathname = '/' + prefix + url.pathname;
|
|
686
755
|
}
|
|
687
756
|
|
|
757
|
+
// Don't return urls with missing parameters
|
|
758
|
+
if (url.pathname.indexOf('{') > -1) {
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
|
|
688
762
|
// Add the get queries
|
|
689
763
|
if (info.url && info.url.search) {
|
|
690
764
|
for (key in info.url.query) {
|
|
@@ -705,7 +779,7 @@ Router.setMethod(function translateCurrentRoute(prefix) {
|
|
|
705
779
|
*
|
|
706
780
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
707
781
|
* @since 1.2.5
|
|
708
|
-
* @version 1.
|
|
782
|
+
* @version 1.3.0
|
|
709
783
|
*
|
|
710
784
|
* @param {Element} element The element to apply to
|
|
711
785
|
* @param {String} language The actual language
|
|
@@ -718,7 +792,7 @@ Router.setMethod(function languageSwitcherDirective(element, language, options)
|
|
|
718
792
|
element.setAttribute('data-alchemy-language-switch', language);
|
|
719
793
|
element.setAttribute('rel', 'nofollow');
|
|
720
794
|
|
|
721
|
-
this.updateLanguageSwitcher(element);
|
|
795
|
+
this.updateLanguageSwitcher(element, element.hawkejs_renderer?.variables);
|
|
722
796
|
});
|
|
723
797
|
|
|
724
798
|
/**
|
|
@@ -159,6 +159,22 @@ Controller.setMethod(function addComponent(name, options) {
|
|
|
159
159
|
this.components[underscored] = new Blast.Classes.Alchemy.Client.Component[name](this, options);
|
|
160
160
|
}, false);
|
|
161
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Change the response URL (or disable it)
|
|
164
|
+
*
|
|
165
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
166
|
+
* @since 1.3.0
|
|
167
|
+
* @version 1.3.0
|
|
168
|
+
*
|
|
169
|
+
* @param {String|RURL|Boolean} new_url
|
|
170
|
+
*/
|
|
171
|
+
Controller.setMethod(function setResponseUrl(new_url) {
|
|
172
|
+
|
|
173
|
+
// @TODO: will only work when called on the server-side
|
|
174
|
+
if (this.conduit) {
|
|
175
|
+
this.conduit.setResponseUrl(new_url);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
162
178
|
|
|
163
179
|
/**
|
|
164
180
|
* Set a variable for ViewRender, through conduit
|
|
@@ -308,12 +324,12 @@ Controller.setMethod(function end(message) {
|
|
|
308
324
|
*
|
|
309
325
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
310
326
|
* @since 0.2.0
|
|
311
|
-
* @version 1.
|
|
327
|
+
* @version 1.3.0
|
|
312
328
|
*
|
|
313
329
|
* @param {String} name The name of the action to execute
|
|
314
330
|
* @param {Array} args Arguments to apply to the action
|
|
315
331
|
*/
|
|
316
|
-
Controller.setMethod(function doAction(name, args) {
|
|
332
|
+
Controller.setMethod(async function doAction(name, args) {
|
|
317
333
|
|
|
318
334
|
var that = this;
|
|
319
335
|
|
|
@@ -338,43 +354,42 @@ Controller.setMethod(function doAction(name, args) {
|
|
|
338
354
|
this.initial_action_arguments = args;
|
|
339
355
|
}
|
|
340
356
|
|
|
341
|
-
|
|
357
|
+
const route = this.conduit?.route;
|
|
342
358
|
|
|
343
|
-
|
|
359
|
+
if (route) {
|
|
344
360
|
|
|
345
|
-
if (
|
|
346
|
-
title
|
|
347
|
-
}
|
|
361
|
+
if (route.options?.title) {
|
|
362
|
+
let title = route.options.title;
|
|
348
363
|
|
|
349
|
-
|
|
350
|
-
|
|
364
|
+
if (alchemy.settings && alchemy.settings.title_suffix) {
|
|
365
|
+
title += alchemy.settings.title_suffix;
|
|
366
|
+
}
|
|
351
367
|
|
|
352
|
-
|
|
353
|
-
that.issueEvent('initializing', next);
|
|
354
|
-
}, function filtering(next) {
|
|
355
|
-
that.issueEvent('filtering', next);
|
|
356
|
-
}, function starting(next) {
|
|
357
|
-
that.issueEvent('starting', [name], next);
|
|
358
|
-
}, function actioning(next) {
|
|
359
|
-
|
|
360
|
-
var result = that.constructor.actions[name].apply(that, args);
|
|
361
|
-
|
|
362
|
-
if (result && typeof result.then == 'function') {
|
|
363
|
-
result.then(function() {
|
|
364
|
-
next();
|
|
365
|
-
}).catch(next);
|
|
366
|
-
} else {
|
|
367
|
-
next();
|
|
368
|
+
this.setTitle(title);
|
|
368
369
|
}
|
|
369
370
|
|
|
370
|
-
|
|
371
|
+
if (route.requires_data_for_translation && route.visible_location !== false && this.conduit.prefix) {
|
|
372
|
+
let route_translations = route.getRouteTranslations(this, this.conduit);
|
|
371
373
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
374
|
+
if (route_translations) {
|
|
375
|
+
route_translations = await route_translations;
|
|
376
|
+
this.internal('current_route_translations', route_translations);
|
|
377
|
+
}
|
|
375
378
|
}
|
|
376
379
|
|
|
377
|
-
|
|
380
|
+
if (route.visible_location !== true) {
|
|
381
|
+
this.setResponseUrl(route.visible_location);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
await this.issueEvent('initializing');
|
|
387
|
+
await this.issueEvent('filtering');
|
|
388
|
+
await this.issueEvent('starting', [name]);
|
|
389
|
+
await this.constructor.actions[name].apply(this, args);
|
|
390
|
+
} catch (err) {
|
|
391
|
+
this.conduit.error(err);
|
|
392
|
+
}
|
|
378
393
|
});
|
|
379
394
|
|
|
380
395
|
/**
|
|
@@ -590,7 +590,7 @@ NoSQL.setStatic(function areComparable(a, b) {
|
|
|
590
590
|
*
|
|
591
591
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
592
592
|
* @since 1.1.0
|
|
593
|
-
* @version 1.
|
|
593
|
+
* @version 1.3.0
|
|
594
594
|
*
|
|
595
595
|
* @param {Criteria} criteria
|
|
596
596
|
* @param {Group} group
|
|
@@ -710,12 +710,14 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
710
710
|
obj = {};
|
|
711
711
|
|
|
712
712
|
let field_entry = {},
|
|
713
|
-
name = entry.target_path
|
|
713
|
+
name = entry.target_path,
|
|
714
|
+
queries_property = name.indexOf('.') > -1;
|
|
714
715
|
|
|
715
716
|
// Do we need to look into an object itself?
|
|
716
717
|
// (Like the "timestamp" property of a date field when stored with units)
|
|
717
|
-
if (entry.db_property) {
|
|
718
|
+
if (entry.db_property && !queries_property) {
|
|
718
719
|
name += '.' + entry.db_property;
|
|
720
|
+
queries_property = true;
|
|
719
721
|
}
|
|
720
722
|
|
|
721
723
|
if (entry.association) {
|
|
@@ -815,15 +817,46 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
815
817
|
throw new Error('Unknown criteria expression: "' + item.type + '"');
|
|
816
818
|
}
|
|
817
819
|
|
|
820
|
+
let multiple_fields,
|
|
821
|
+
prefixed_name = name;
|
|
822
|
+
|
|
823
|
+
// Temporary fix to actually query translatable field contents
|
|
824
|
+
// (entry.field can be undefined if trying to query a path)
|
|
825
|
+
if (entry.field && entry.field.is_translatable) {
|
|
826
|
+
|
|
827
|
+
let prefix = criteria.options.locale;
|
|
828
|
+
|
|
829
|
+
// If a prefix is specified, only query that translation
|
|
830
|
+
if (prefix) {
|
|
831
|
+
prefixed_name = name + '.' + prefix;
|
|
832
|
+
} else {
|
|
833
|
+
multiple_fields = [];
|
|
834
|
+
|
|
835
|
+
// No prefixes specified, so look through all translations
|
|
836
|
+
for (let key in Prefix.all()) {
|
|
837
|
+
multiple_fields.push(name + '.' + key);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
818
842
|
if (obj && obj.$or) {
|
|
819
843
|
|
|
820
844
|
let $or = [],
|
|
821
845
|
i;
|
|
822
846
|
|
|
823
847
|
for (i = 0; i < obj.$or.length; i++) {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
848
|
+
|
|
849
|
+
if (multiple_fields) {
|
|
850
|
+
for (let name of multiple_fields) {
|
|
851
|
+
$or.push({
|
|
852
|
+
[name] : obj.$or[i]
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
} else {
|
|
856
|
+
$or.push({
|
|
857
|
+
[prefixed_name] : obj.$or[i]
|
|
858
|
+
});
|
|
859
|
+
}
|
|
827
860
|
}
|
|
828
861
|
|
|
829
862
|
if (not) {
|
|
@@ -861,18 +894,19 @@ NoSQL.setMethod(function compileCriteria(criteria, group) {
|
|
|
861
894
|
|
|
862
895
|
// Temporary fix to actually query translatable field contents
|
|
863
896
|
// (entry.field can be undefined if trying to query a path)
|
|
864
|
-
if (
|
|
897
|
+
if (multiple_fields) {
|
|
898
|
+
|
|
865
899
|
let $or = [];
|
|
866
900
|
|
|
867
|
-
for (let
|
|
901
|
+
for (let name of multiple_fields) {
|
|
868
902
|
let temp = {};
|
|
869
|
-
temp[name
|
|
903
|
+
temp[name] = obj;
|
|
870
904
|
$or.push(temp);
|
|
871
905
|
}
|
|
872
906
|
|
|
873
907
|
field_entry.$or = $or;
|
|
874
908
|
} else {
|
|
875
|
-
field_entry[
|
|
909
|
+
field_entry[prefixed_name] = obj;
|
|
876
910
|
}
|
|
877
911
|
}
|
|
878
912
|
|
|
@@ -45,7 +45,7 @@ Enum.setMethod(function cast(value) {
|
|
|
45
45
|
*
|
|
46
46
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
47
47
|
* @since 0.2.0
|
|
48
|
-
* @version 1.
|
|
48
|
+
* @version 1.3.0
|
|
49
49
|
*
|
|
50
50
|
* @return {EnumValues}
|
|
51
51
|
*/
|
|
@@ -55,10 +55,10 @@ Enum.setMethod(function getValues() {
|
|
|
55
55
|
// or its pluralized name, if nothing was found
|
|
56
56
|
if (this.options && this.options.values) {
|
|
57
57
|
return this.options.values;
|
|
58
|
-
} else if (this.schema.
|
|
59
|
-
return this.schema.
|
|
58
|
+
} else if (this.schema.enum_values[this.name]) {
|
|
59
|
+
return this.schema.enum_values[this.name];
|
|
60
60
|
} else {
|
|
61
|
-
return this.schema.
|
|
61
|
+
return this.schema.enum_values[this.name.pluralize()];
|
|
62
62
|
}
|
|
63
63
|
});
|
|
64
64
|
|