alchemymvc 1.1.5 → 1.1.9
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/CHANGELOG.md +458 -429
- package/lib/app/behaviour/sluggable_behaviour.js +2 -4
- package/lib/app/conduit/http_conduit.js +173 -192
- package/lib/app/conduit/loopback_conduit.js +23 -5
- package/lib/app/element/time_ago.js +7 -4
- package/lib/app/helper_datasource/remote_datasource.js +3 -2
- package/lib/app/helper_field/05-string_field.js +21 -0
- package/lib/app/helper_field/schema_field.js +7 -2
- package/lib/app/helper_model/criteria.js +3 -0
- package/lib/app/helper_model/field_config.js +37 -5
- package/lib/app/helper_model/model.js +27 -1
- package/lib/class/conduit.js +2474 -2386
- package/lib/class/controller.js +0 -0
- package/lib/class/datasource.js +6 -6
- package/lib/class/inode.js +62 -0
- package/lib/class/inode_dir.js +115 -0
- package/lib/class/inode_file.js +112 -111
- package/lib/class/model.js +1773 -1769
- package/lib/class/reciprocal.js +8 -2
- package/lib/class/router.js +47 -57
- package/lib/class/schema_client.js +10 -5
- package/lib/core/base.js +37 -10
- package/lib/core/client_base.js +1 -9
- package/lib/core/middleware.js +24 -15
- package/lib/init/alchemy.js +20 -1
- package/lib/init/devwatch.js +2 -2
- package/lib/init/functions.js +2 -56
- package/lib/stages.js +12 -0
- package/package.json +74 -76
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
var slug = alchemy.use('mollusc');
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* The Sluggable Behaviour class
|
|
5
3
|
*
|
|
@@ -293,7 +291,7 @@ Sluggable.setMethod(function createSlug(record, new_value, callback) {
|
|
|
293
291
|
*
|
|
294
292
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
295
293
|
* @since 0.1.0
|
|
296
|
-
* @version 1.1.
|
|
294
|
+
* @version 1.1.8
|
|
297
295
|
*
|
|
298
296
|
* @param {String} title
|
|
299
297
|
* @param {String} path
|
|
@@ -336,7 +334,7 @@ Sluggable.setMethod(function generateSlug(title, key, record, callback) {
|
|
|
336
334
|
return callback();
|
|
337
335
|
}
|
|
338
336
|
|
|
339
|
-
baseSlug = slug(
|
|
337
|
+
baseSlug = title.slug(that.replacement || '-').toLowerCase();
|
|
340
338
|
current = baseSlug;
|
|
341
339
|
model = Model.get(this.model.name);
|
|
342
340
|
count = 1;
|
|
@@ -1,193 +1,174 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Http Conduit Class
|
|
3
|
-
*
|
|
4
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
5
|
-
* @since 0.2.0
|
|
6
|
-
* @version 1.1.3
|
|
7
|
-
*
|
|
8
|
-
* @param {IncomingMessage} req
|
|
9
|
-
* @param {ServerResponse} res
|
|
10
|
-
* @param {Router} router
|
|
11
|
-
*/
|
|
12
|
-
var HttpConduit = Function.inherits('Alchemy.Conduit.Conduit', function Http(req, res, router) {
|
|
13
|
-
|
|
14
|
-
// Initialize basic conduit values
|
|
15
|
-
Http.super.call(this);
|
|
16
|
-
|
|
17
|
-
this.initHttp(req, res, router);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Has the client aborted the request?
|
|
22
|
-
*
|
|
23
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
24
|
-
* @since 1.1.0
|
|
25
|
-
* @version 1.1.0
|
|
26
|
-
*
|
|
27
|
-
* @type {Boolean}
|
|
28
|
-
*/
|
|
29
|
-
HttpConduit.setProperty(function aborted() {
|
|
30
|
-
|
|
31
|
-
if (this.request && this.request.aborted != null) {
|
|
32
|
-
return this.request.aborted;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return false;
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Return the IP address
|
|
40
|
-
*
|
|
41
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
42
|
-
* @since 0.2.0
|
|
43
|
-
* @version 1.1.0
|
|
44
|
-
*/
|
|
45
|
-
HttpConduit.setProperty(function ip() {
|
|
46
|
-
|
|
47
|
-
var req = this.request;
|
|
48
|
-
|
|
49
|
-
if (!req) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let forwarded_for = req.headers['x-forwarded-for'] || req.headers['x-real-ip'];
|
|
54
|
-
|
|
55
|
-
if (forwarded_for) {
|
|
56
|
-
|
|
57
|
-
// Forwarded for can contain multiple ip addresses,
|
|
58
|
-
// return the first one
|
|
59
|
-
if (forwarded_for.indexOf(',') > -1) {
|
|
60
|
-
forwarded_for = forwarded_for.before(',');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return forwarded_for;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
let remote_address;
|
|
67
|
-
|
|
68
|
-
if (req.connection) {
|
|
69
|
-
remote_address = req.connection.remoteAddress;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (!remote_address && req.socket) {
|
|
73
|
-
remote_address = req.socket.remoteAddress;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!remote_address && req.connection && req.connection.socket) {
|
|
77
|
-
remote_address = req.connection.socket.remoteAddress;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return remote_address;
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Get a simple fingerprint of the client
|
|
85
|
-
* based on ip, accept-language & user-agent
|
|
86
|
-
*
|
|
87
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
88
|
-
* @since 1.1.0
|
|
89
|
-
* @version 1.1.0
|
|
90
|
-
*
|
|
91
|
-
* @type {String}
|
|
92
|
-
*/
|
|
93
|
-
HttpConduit.enforceProperty(function fingerprint() {
|
|
94
|
-
|
|
95
|
-
let result,
|
|
96
|
-
language = this.headers['accept-language'] || 'all',
|
|
97
|
-
ua = this.headers['user-agent'] || 'unknown',
|
|
98
|
-
ip = this.ip || '';
|
|
99
|
-
|
|
100
|
-
result = Object.checksum(ip + '_' + language + '_' + ua);
|
|
101
|
-
|
|
102
|
-
return result;
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Init
|
|
107
|
-
*
|
|
108
|
-
* @author Jelle De Loecker <jelle@kipdola.be>
|
|
109
|
-
* @since 0.3.3
|
|
110
|
-
* @version 1.
|
|
111
|
-
*
|
|
112
|
-
* @param {IncomingMessage} req
|
|
113
|
-
* @param {ServerResponse} res
|
|
114
|
-
* @param {Router} router
|
|
115
|
-
*/
|
|
116
|
-
HttpConduit.setMethod(async function initHttp(req, res, router) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* @
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
HttpConduit.setProperty(function original_path() {
|
|
175
|
-
return this.original_url.path;
|
|
176
|
-
}, function setPath(value) {
|
|
177
|
-
return this.original_url.path = value;
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Get the original url pathname
|
|
182
|
-
*
|
|
183
|
-
* @author Jelle De Loecker <jelle@kipdola.be>
|
|
184
|
-
* @since 1.1.0
|
|
185
|
-
* @version 1.1.0
|
|
186
|
-
*
|
|
187
|
-
* @type {String}
|
|
188
|
-
*/
|
|
189
|
-
HttpConduit.setProperty(function original_pathname() {
|
|
190
|
-
return this.original_url.pathname;
|
|
191
|
-
}, function setPathname(value) {
|
|
192
|
-
return this.original_url.pathname = value;
|
|
1
|
+
/**
|
|
2
|
+
* The Http Conduit Class
|
|
3
|
+
*
|
|
4
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
5
|
+
* @since 0.2.0
|
|
6
|
+
* @version 1.1.3
|
|
7
|
+
*
|
|
8
|
+
* @param {IncomingMessage} req
|
|
9
|
+
* @param {ServerResponse} res
|
|
10
|
+
* @param {Router} router
|
|
11
|
+
*/
|
|
12
|
+
var HttpConduit = Function.inherits('Alchemy.Conduit.Conduit', function Http(req, res, router) {
|
|
13
|
+
|
|
14
|
+
// Initialize basic conduit values
|
|
15
|
+
Http.super.call(this);
|
|
16
|
+
|
|
17
|
+
this.initHttp(req, res, router);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Has the client aborted the request?
|
|
22
|
+
*
|
|
23
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
24
|
+
* @since 1.1.0
|
|
25
|
+
* @version 1.1.0
|
|
26
|
+
*
|
|
27
|
+
* @type {Boolean}
|
|
28
|
+
*/
|
|
29
|
+
HttpConduit.setProperty(function aborted() {
|
|
30
|
+
|
|
31
|
+
if (this.request && this.request.aborted != null) {
|
|
32
|
+
return this.request.aborted;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return false;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Return the IP address
|
|
40
|
+
*
|
|
41
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
42
|
+
* @since 0.2.0
|
|
43
|
+
* @version 1.1.0
|
|
44
|
+
*/
|
|
45
|
+
HttpConduit.setProperty(function ip() {
|
|
46
|
+
|
|
47
|
+
var req = this.request;
|
|
48
|
+
|
|
49
|
+
if (!req) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let forwarded_for = req.headers['x-forwarded-for'] || req.headers['x-real-ip'];
|
|
54
|
+
|
|
55
|
+
if (forwarded_for) {
|
|
56
|
+
|
|
57
|
+
// Forwarded for can contain multiple ip addresses,
|
|
58
|
+
// return the first one
|
|
59
|
+
if (forwarded_for.indexOf(',') > -1) {
|
|
60
|
+
forwarded_for = forwarded_for.before(',');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return forwarded_for;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let remote_address;
|
|
67
|
+
|
|
68
|
+
if (req.connection) {
|
|
69
|
+
remote_address = req.connection.remoteAddress;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!remote_address && req.socket) {
|
|
73
|
+
remote_address = req.socket.remoteAddress;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!remote_address && req.connection && req.connection.socket) {
|
|
77
|
+
remote_address = req.connection.socket.remoteAddress;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return remote_address;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get a simple fingerprint of the client
|
|
85
|
+
* based on ip, accept-language & user-agent
|
|
86
|
+
*
|
|
87
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
88
|
+
* @since 1.1.0
|
|
89
|
+
* @version 1.1.0
|
|
90
|
+
*
|
|
91
|
+
* @type {String}
|
|
92
|
+
*/
|
|
93
|
+
HttpConduit.enforceProperty(function fingerprint() {
|
|
94
|
+
|
|
95
|
+
let result,
|
|
96
|
+
language = this.headers['accept-language'] || 'all',
|
|
97
|
+
ua = this.headers['user-agent'] || 'unknown',
|
|
98
|
+
ip = this.ip || '';
|
|
99
|
+
|
|
100
|
+
result = Object.checksum(ip + '_' + language + '_' + ua);
|
|
101
|
+
|
|
102
|
+
return result;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Init
|
|
107
|
+
*
|
|
108
|
+
* @author Jelle De Loecker <jelle@kipdola.be>
|
|
109
|
+
* @since 0.3.3
|
|
110
|
+
* @version 1.2.0
|
|
111
|
+
*
|
|
112
|
+
* @param {IncomingMessage} req
|
|
113
|
+
* @param {ServerResponse} res
|
|
114
|
+
* @param {Router} router
|
|
115
|
+
*/
|
|
116
|
+
HttpConduit.setMethod(async function initHttp(req, res, router) {
|
|
117
|
+
|
|
118
|
+
this.setReqRes(req, res);
|
|
119
|
+
|
|
120
|
+
if (router) {
|
|
121
|
+
this.router = router;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// The HTTP status
|
|
125
|
+
this.status = 200;
|
|
126
|
+
|
|
127
|
+
this.debugMark('Parse request');
|
|
128
|
+
|
|
129
|
+
// Parse the request, get the correct routes and such
|
|
130
|
+
await this.parseRequest();
|
|
131
|
+
|
|
132
|
+
if (this.halt_request) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (alchemy.settings.debug || alchemy.settings.environment != 'live') {
|
|
137
|
+
this.setHeader('X-Robots-Tag', 'none');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this.debugMark(false);
|
|
141
|
+
|
|
142
|
+
// Call the middleware, which will call the handler afterwards
|
|
143
|
+
this.callMiddleware();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get the original url path
|
|
148
|
+
*
|
|
149
|
+
* @author Jelle De Loecker <jelle@kipdola.be>
|
|
150
|
+
* @since 1.1.0
|
|
151
|
+
* @version 1.1.0
|
|
152
|
+
*
|
|
153
|
+
* @type {String}
|
|
154
|
+
*/
|
|
155
|
+
HttpConduit.setProperty(function original_path() {
|
|
156
|
+
return this.original_url.path;
|
|
157
|
+
}, function setPath(value) {
|
|
158
|
+
return this.original_url.path = value;
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get the original url pathname
|
|
163
|
+
*
|
|
164
|
+
* @author Jelle De Loecker <jelle@kipdola.be>
|
|
165
|
+
* @since 1.1.0
|
|
166
|
+
* @version 1.1.0
|
|
167
|
+
*
|
|
168
|
+
* @type {String}
|
|
169
|
+
*/
|
|
170
|
+
HttpConduit.setProperty(function original_pathname() {
|
|
171
|
+
return this.original_url.pathname;
|
|
172
|
+
}, function setPathname(value) {
|
|
173
|
+
return this.original_url.pathname = value;
|
|
193
174
|
});
|
|
@@ -76,9 +76,9 @@ LoopConduit.setMethod(function copyParentProperties(conduit) {
|
|
|
76
76
|
/**
|
|
77
77
|
* Set the loopback options
|
|
78
78
|
*
|
|
79
|
-
* @author Jelle De Loecker <jelle@
|
|
79
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
80
80
|
* @since 1.1.3
|
|
81
|
-
* @version 1.1.
|
|
81
|
+
* @version 1.1.7
|
|
82
82
|
*
|
|
83
83
|
* @param {Object} options
|
|
84
84
|
* @param {Function} callback
|
|
@@ -93,6 +93,9 @@ LoopConduit.setMethod(function setOptions(options, callback) {
|
|
|
93
93
|
info,
|
|
94
94
|
key;
|
|
95
95
|
|
|
96
|
+
// Always clone the options
|
|
97
|
+
options = JSON.clone(options);
|
|
98
|
+
|
|
96
99
|
for (key in options) {
|
|
97
100
|
let set_method = false;
|
|
98
101
|
|
|
@@ -113,17 +116,32 @@ LoopConduit.setMethod(function setOptions(options, callback) {
|
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
if (
|
|
117
|
-
this.method =
|
|
119
|
+
if (options.method) {
|
|
120
|
+
this.method = options.method;
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
if (options.name) {
|
|
121
124
|
// @TODO: what about path sections?
|
|
122
|
-
|
|
125
|
+
route = this.getRouteByName(options.name);
|
|
126
|
+
|
|
127
|
+
if (route && !this.method) {
|
|
128
|
+
if (route.methods.length == 1) {
|
|
129
|
+
this.method = route.methods[0];
|
|
130
|
+
} else if (options.body && route.methods.indexOf('post') > -1) {
|
|
131
|
+
this.method = 'post';
|
|
132
|
+
} else {
|
|
133
|
+
this.method = route.methods[0];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
123
136
|
|
|
124
137
|
// @WARNING: It's best to just generate the URL
|
|
125
138
|
// and let it parse all the information that way
|
|
126
139
|
options.href = alchemy.routeUrl(options.name, options.params, {extra_get_parameters: false});
|
|
140
|
+
// @TODO: alchemy.routeUrl will ignore the `keep_get_parameters` option
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!this.method) {
|
|
144
|
+
this.method = 'get';
|
|
127
145
|
}
|
|
128
146
|
|
|
129
147
|
if (options.href) {
|
|
@@ -83,18 +83,21 @@ TimeAgo.setMethod(function connected() {
|
|
|
83
83
|
*
|
|
84
84
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
85
85
|
* @since 0.1.0
|
|
86
|
-
* @version 0.1.
|
|
86
|
+
* @version 0.1.7
|
|
87
87
|
*
|
|
88
88
|
* @param {Boolean} reset_timer
|
|
89
89
|
*/
|
|
90
90
|
TimeAgo.setMethod(function refresh(reset_timer) {
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
let that = this,
|
|
93
93
|
counter,
|
|
94
94
|
timer,
|
|
95
|
+
text = this.value,
|
|
95
96
|
diff;
|
|
96
97
|
|
|
97
|
-
this.
|
|
98
|
+
if (this.textContent != text) {
|
|
99
|
+
this.textContent = text;
|
|
100
|
+
}
|
|
98
101
|
|
|
99
102
|
if (!reset_timer || Blast.isNode) {
|
|
100
103
|
return;
|
|
@@ -106,7 +109,7 @@ TimeAgo.setMethod(function refresh(reset_timer) {
|
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
if (this.date) {
|
|
109
|
-
diff = Date.now() - this.date;
|
|
112
|
+
diff = Math.abs(Date.now() - this.date);
|
|
110
113
|
counter = 0;
|
|
111
114
|
|
|
112
115
|
if (diff < 1000 * 29) {
|
|
@@ -15,7 +15,7 @@ var Remote = Function.inherits('Alchemy.Datasource', function Remote(name, optio
|
|
|
15
15
|
*
|
|
16
16
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
17
17
|
* @since 1.1.0
|
|
18
|
-
* @version 1.1.
|
|
18
|
+
* @version 1.1.7
|
|
19
19
|
*/
|
|
20
20
|
Remote.setMethod(async function doServerCommand(action, model, data, callback) {
|
|
21
21
|
|
|
@@ -55,7 +55,8 @@ Remote.setMethod(async function doServerCommand(action, model, data, callback) {
|
|
|
55
55
|
|
|
56
56
|
conduit.loopback({
|
|
57
57
|
name : route_name,
|
|
58
|
-
|
|
58
|
+
method : 'post',
|
|
59
|
+
body : data
|
|
59
60
|
}, function gotResult(err, result) {
|
|
60
61
|
|
|
61
62
|
if (err) {
|
|
@@ -20,6 +20,27 @@ var StringField = Function.inherits('Alchemy.Field', function String(schema, nam
|
|
|
20
20
|
*/
|
|
21
21
|
StringField.setDatatype('string');
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Cast the given value to this field's type for search in a db
|
|
25
|
+
*
|
|
26
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
27
|
+
* @since 1.1.7
|
|
28
|
+
* @version 1.1.7
|
|
29
|
+
*
|
|
30
|
+
* @param {Mixed} value
|
|
31
|
+
* @param {Array} field_paths The path to the field
|
|
32
|
+
*
|
|
33
|
+
* @return {Mixed}
|
|
34
|
+
*/
|
|
35
|
+
StringField.setMethod(function _castCondition(value, field_paths) {
|
|
36
|
+
|
|
37
|
+
if (typeof value == 'object' && RegExp.isRegExp(value)) {
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return this.cast(value, true);
|
|
42
|
+
});
|
|
43
|
+
|
|
23
44
|
/**
|
|
24
45
|
* Cast the given value to this field's type
|
|
25
46
|
*
|
|
@@ -277,7 +277,12 @@ SchemaField.setMethod(function _toApp(query, options, value, callback) {
|
|
|
277
277
|
|
|
278
278
|
name = this.name + 'FieldModel';
|
|
279
279
|
Dummy = alchemy.getModel('Model', false);
|
|
280
|
-
|
|
280
|
+
|
|
281
|
+
Dummy = new Dummy({
|
|
282
|
+
root_model : this.root_model,
|
|
283
|
+
name : name
|
|
284
|
+
});
|
|
285
|
+
|
|
281
286
|
item = {};
|
|
282
287
|
|
|
283
288
|
item[name] = value;
|
|
@@ -338,7 +343,7 @@ SchemaField.setMethod(function _toApp(query, options, value, callback) {
|
|
|
338
343
|
|
|
339
344
|
if (field != null) {
|
|
340
345
|
tasks[field_name] = function doToDatasource(next) {
|
|
341
|
-
field.toApp({}, {}, field_value, next);
|
|
346
|
+
field.toApp({}, {_root_data: options._root_data}, field_value, next);
|
|
342
347
|
};
|
|
343
348
|
}
|
|
344
349
|
});
|
|
@@ -510,6 +510,9 @@ Criteria.setMethod(function getCriteriaForAssociation(name, item) {
|
|
|
510
510
|
assoc_crit.where(assoc_key).equals(value);
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
+
assoc_crit.setOption('assoc_key', assoc_key);
|
|
514
|
+
assoc_crit.setOption('assoc_value', value);
|
|
515
|
+
|
|
513
516
|
// Take over the locale option
|
|
514
517
|
if (options.locale) {
|
|
515
518
|
assoc_crit.setOption('locale', options.locale);
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Alchemy.Criteria.FieldConfig:
|
|
3
|
+
* Configuration on what to do with a certain field during a database query
|
|
4
|
+
* or anywhere data is represented
|
|
3
5
|
*
|
|
4
6
|
* @constructor
|
|
5
7
|
*
|
|
6
8
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
7
9
|
* @since 1.1.3
|
|
8
|
-
* @version 1.1.
|
|
10
|
+
* @version 1.1.7
|
|
9
11
|
*
|
|
10
|
-
* @param {
|
|
12
|
+
* @param {string} path
|
|
11
13
|
* @param {Object} options
|
|
12
14
|
*/
|
|
13
15
|
const FieldConfig = Fn.inherits('Alchemy.Base', 'Alchemy.Criteria', function FieldConfig(path, options) {
|
|
@@ -54,7 +56,7 @@ FieldConfig.setStatic(function unDry(obj) {
|
|
|
54
56
|
* @since 1.1.3
|
|
55
57
|
* @version 1.1.3
|
|
56
58
|
*
|
|
57
|
-
* @type {
|
|
59
|
+
* @type {string}
|
|
58
60
|
*/
|
|
59
61
|
FieldConfig.setProperty(function title() {
|
|
60
62
|
|
|
@@ -107,7 +109,7 @@ FieldConfig.setMethod(function toJSON() {
|
|
|
107
109
|
* @since 1.1.3
|
|
108
110
|
* @version 1.1.3
|
|
109
111
|
*
|
|
110
|
-
* @param {
|
|
112
|
+
* @param {string} path
|
|
111
113
|
*/
|
|
112
114
|
FieldConfig.setMethod(function parsePath(path) {
|
|
113
115
|
|
|
@@ -160,4 +162,34 @@ FieldConfig.setMethod(function getValueIn(data) {
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
return Object.path(data, this.path);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get the display value for the value in the given object
|
|
169
|
+
*
|
|
170
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
171
|
+
* @since 1.1.7
|
|
172
|
+
* @version 1.1.7
|
|
173
|
+
*
|
|
174
|
+
* @param {Object} data
|
|
175
|
+
*
|
|
176
|
+
* @return {string}
|
|
177
|
+
*/
|
|
178
|
+
FieldConfig.setMethod(function getDisplayValueIn(data) {
|
|
179
|
+
|
|
180
|
+
let value = this.getValueIn(data);
|
|
181
|
+
|
|
182
|
+
if (value == null) {
|
|
183
|
+
return '';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (typeof value == 'object') {
|
|
187
|
+
if (Date.isDate(value)) {
|
|
188
|
+
value = value.format('y-m-d H:i:s');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return value;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return '' + value;
|
|
163
195
|
});
|
|
@@ -96,12 +96,18 @@ Model.setProperty(function table() {
|
|
|
96
96
|
*
|
|
97
97
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
98
98
|
* @since 1.0.0
|
|
99
|
-
* @version 1.1.
|
|
99
|
+
* @version 1.1.7
|
|
100
100
|
*
|
|
101
101
|
* @type {Datasource}
|
|
102
102
|
*/
|
|
103
103
|
Model.setProperty(function datasource() {
|
|
104
104
|
|
|
105
|
+
if (Blast.isNode) {
|
|
106
|
+
// We use the "remote" type datasource, which will make loopback
|
|
107
|
+
// requests on the server side
|
|
108
|
+
return Datasource.get({name: 'loopback', type: 'remote'});
|
|
109
|
+
}
|
|
110
|
+
|
|
105
111
|
if (!fallback_datasource) {
|
|
106
112
|
fallback_datasource = new Blast.Classes.Alchemy.Datasource.Fallback('default', {
|
|
107
113
|
upper: {
|
|
@@ -1052,6 +1058,26 @@ Model.setMethod(function addAssociatedDataToRecord(criteria, item, callback) {
|
|
|
1052
1058
|
return;
|
|
1053
1059
|
}
|
|
1054
1060
|
|
|
1061
|
+
// SchemaFields use a dummy Model name, so get the root_model in that case
|
|
1062
|
+
let root_model = (that.options && that.options.root_model) || that.name;
|
|
1063
|
+
|
|
1064
|
+
// Make sure references to the same model don't cause a deadlock
|
|
1065
|
+
// (Can happen when a model refers to itself)
|
|
1066
|
+
if (association.modelName == root_model && criteria.options._root_data) {
|
|
1067
|
+
let assoc_key = assoc_crit.options.assoc_key,
|
|
1068
|
+
assoc_value = assoc_crit.options.assoc_value,
|
|
1069
|
+
root = criteria.options._root_data[root_model];
|
|
1070
|
+
|
|
1071
|
+
if (root && root[assoc_key] && Object.alike(root[assoc_key], assoc_value)) {
|
|
1072
|
+
|
|
1073
|
+
aliases[alias] = nextAlias => {
|
|
1074
|
+
nextAlias(null, root[assoc_key]);
|
|
1075
|
+
};
|
|
1076
|
+
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1055
1081
|
aliases[alias] = function aliasRecordTask(nextAlias) {
|
|
1056
1082
|
|
|
1057
1083
|
var key;
|