alchemymvc 1.3.0 → 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/conduit/http_conduit.js +7 -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 +16 -7
- package/lib/app/helper_field/schema_field.js +44 -30
- package/lib/app/helper_model/document.js +40 -36
- package/lib/app/helper_model/model.js +72 -43
- 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/class/conduit.js +207 -46
- package/lib/class/controller.js +18 -15
- package/lib/class/datasource.js +14 -7
- package/lib/class/field.js +21 -3
- package/lib/class/migration.js +2 -1
- package/lib/class/model.js +12 -1
- package/lib/class/postponement.js +573 -0
- package/lib/class/route.js +18 -2
- package/lib/class/router.js +6 -2
- package/lib/class/schema.js +36 -0
- package/lib/class/schema_client.js +16 -19
- package/lib/class/session.js +138 -12
- package/lib/core/base.js +7 -1
- package/lib/core/client_alchemy.js +3 -1
- package/lib/init/alchemy.js +112 -2
- package/lib/init/functions.js +30 -4
- package/lib/stages.js +18 -3
- package/package.json +4 -4
|
@@ -60,13 +60,13 @@ Validator.setMethod(function toDry() {
|
|
|
60
60
|
*
|
|
61
61
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
62
62
|
* @since 1.1.0
|
|
63
|
-
* @version 1.1
|
|
63
|
+
* @version 1.3.1
|
|
64
64
|
*
|
|
65
65
|
* @param {FieldValue} fv The FieldValue instance
|
|
66
66
|
*
|
|
67
67
|
* @return {String}
|
|
68
68
|
*/
|
|
69
|
-
Validator.
|
|
69
|
+
Validator.setTypedMethod([Types.Alchemy.FieldValue], function getInvalidFieldMessage(fv) {
|
|
70
70
|
|
|
71
71
|
let field = fv.field,
|
|
72
72
|
value = fv.value;
|
|
@@ -105,20 +105,52 @@ Validator.setMethod(function createFieldViolation(fv) {
|
|
|
105
105
|
return result;
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Validate a value
|
|
110
|
+
*
|
|
111
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
112
|
+
* @since 1.3.1
|
|
113
|
+
* @version 1.3.1
|
|
114
|
+
*
|
|
115
|
+
* @param {Field} field
|
|
116
|
+
* @param {*} value
|
|
117
|
+
*
|
|
118
|
+
* @return {Promise<Violation|undefined>}
|
|
119
|
+
*/
|
|
120
|
+
Validator.setTypedMethod([Types.Alchemy.Field, Types.Any], function validateFieldValue(field, value) {
|
|
121
|
+
return this.validateFieldValue(field, field.path, value);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Validate a value
|
|
126
|
+
*
|
|
127
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
128
|
+
* @since 1.3.1
|
|
129
|
+
* @version 1.3.1
|
|
130
|
+
*
|
|
131
|
+
* @param {Field} field
|
|
132
|
+
* @param {String} path
|
|
133
|
+
* @param {*} value
|
|
134
|
+
*
|
|
135
|
+
* @return {Promise<Violation|undefined>}
|
|
136
|
+
*/
|
|
137
|
+
Validator.setTypedMethod([Types.Alchemy.Field, Types.String, Types.Any], function validateFieldValue(field, path, value) {
|
|
138
|
+
let fv = new Classes.Alchemy.FieldValue(field, path, value);
|
|
139
|
+
return this.validateFieldValue(fv);
|
|
140
|
+
});
|
|
141
|
+
|
|
108
142
|
/**
|
|
109
143
|
* Validate a value
|
|
110
144
|
*
|
|
111
145
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
112
146
|
* @since 1.1.0
|
|
113
|
-
* @version 1.1
|
|
147
|
+
* @version 1.3.1
|
|
114
148
|
*
|
|
115
149
|
* @param {FieldValue[]} field_values The FieldValue instance(s)
|
|
116
150
|
*
|
|
117
151
|
* @return {Promise<Violation|undefined>}
|
|
118
152
|
*/
|
|
119
|
-
Validator.
|
|
120
|
-
|
|
121
|
-
field_values = Array.cast(field_values);
|
|
153
|
+
Validator.setTypedMethod([Types.Alchemy.FieldValue.array()], async function validateFieldValue(field_values) {
|
|
122
154
|
|
|
123
155
|
let violation,
|
|
124
156
|
passes,
|
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @param {Object} options
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
NotEmpty.super.call(this, options);
|
|
15
|
-
});
|
|
13
|
+
const NotEmpty = Function.inherits('Alchemy.Validator', 'NotEmpty');
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
16
|
* The message to use inside errors
|
package/lib/app/routes.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
Router.add(['get', 'post'], 'APIResource', '/api/{action}', 'Api#{action}');
|
|
2
2
|
Router.get('AlchemyInfo', '/alchemy-info', 'AlchemyInfo#info');
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
Router.POSTPONED_ROUTE = Router.add({
|
|
5
|
+
name : 'AlchemyInfo#postponed',
|
|
6
|
+
paths : '/alchemy/postponed/{id}',
|
|
7
|
+
methods : ['get'],
|
|
8
|
+
can_be_postponed : false,
|
|
9
|
+
});
|
package/lib/class/conduit.js
CHANGED
|
@@ -1231,19 +1231,67 @@ Conduit.setMethod(function callHandler() {
|
|
|
1231
1231
|
this.route.callHandler(this);
|
|
1232
1232
|
});
|
|
1233
1233
|
|
|
1234
|
+
/**
|
|
1235
|
+
* Put this request in a queue
|
|
1236
|
+
*
|
|
1237
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1238
|
+
* @since 1.3.1
|
|
1239
|
+
* @version 1.3.1
|
|
1240
|
+
*
|
|
1241
|
+
* @param {Object} options Options or url
|
|
1242
|
+
*/
|
|
1243
|
+
Conduit.setMethod(function postponeAndQueue(options) {
|
|
1244
|
+
|
|
1245
|
+
if (!options) {
|
|
1246
|
+
options = {};
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
const postponement = this.postponeRequest({
|
|
1250
|
+
put_in_queue : true,
|
|
1251
|
+
});
|
|
1252
|
+
|
|
1253
|
+
return postponement;
|
|
1254
|
+
});
|
|
1255
|
+
|
|
1256
|
+
/**
|
|
1257
|
+
* Postpone the response and the request
|
|
1258
|
+
*
|
|
1259
|
+
* This does not stop the current request from processing.
|
|
1260
|
+
*
|
|
1261
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1262
|
+
* @since 1.3.1
|
|
1263
|
+
* @version 1.3.1
|
|
1264
|
+
*
|
|
1265
|
+
* @param {Number|Object} options Options or time to wait
|
|
1266
|
+
*
|
|
1267
|
+
* @return {Alchemy.Conduit.Postponement}
|
|
1268
|
+
*/
|
|
1269
|
+
Conduit.setMethod(function postponeRequest(options) {
|
|
1270
|
+
|
|
1271
|
+
let postponement = this.postponeResponse(options);
|
|
1272
|
+
|
|
1273
|
+
this.afterOnce('get-postponed-response', () => {
|
|
1274
|
+
this.callMiddleware();
|
|
1275
|
+
});
|
|
1276
|
+
|
|
1277
|
+
return postponement;
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1234
1280
|
/**
|
|
1235
1281
|
* End the current request with a 202 status
|
|
1236
|
-
* and tell the client to look at another url later
|
|
1282
|
+
* and tell the client to look at another url later.
|
|
1237
1283
|
*
|
|
1238
|
-
*
|
|
1284
|
+
* This does not stop the current request from processing.
|
|
1285
|
+
*
|
|
1286
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1239
1287
|
* @since 1.1.0
|
|
1240
|
-
* @version 1.
|
|
1288
|
+
* @version 1.3.1
|
|
1241
1289
|
*
|
|
1242
|
-
* @param {
|
|
1290
|
+
* @param {Number|Object} options Options or time to wait
|
|
1291
|
+
*
|
|
1292
|
+
* @return {Alchemy.Conduit.Postponement}
|
|
1243
1293
|
*/
|
|
1244
|
-
Conduit.setMethod(function
|
|
1245
|
-
|
|
1246
|
-
let session = this.getSession();
|
|
1294
|
+
Conduit.setMethod(function postponeResponse(options) {
|
|
1247
1295
|
|
|
1248
1296
|
if (typeof options == 'number') {
|
|
1249
1297
|
options = {
|
|
@@ -1253,36 +1301,55 @@ Conduit.setMethod(function postpone(options) {
|
|
|
1253
1301
|
options = {};
|
|
1254
1302
|
}
|
|
1255
1303
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1304
|
+
return this._postpone(options);
|
|
1305
|
+
});
|
|
1258
1306
|
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1307
|
+
/**
|
|
1308
|
+
* Handle the postponement
|
|
1309
|
+
*
|
|
1310
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1311
|
+
* @since 1.3.1
|
|
1312
|
+
* @version 1.3.1
|
|
1313
|
+
*
|
|
1314
|
+
* @param {Object} options
|
|
1315
|
+
*
|
|
1316
|
+
* @return {Alchemy.Conduit.Postponement}
|
|
1317
|
+
*/
|
|
1318
|
+
Conduit.setMethod(function _postpone(options) {
|
|
1263
1319
|
|
|
1264
|
-
let
|
|
1265
|
-
url = '/alchemy/postponed/' + postponed_id;
|
|
1320
|
+
let session = this.getSession();
|
|
1266
1321
|
|
|
1267
|
-
|
|
1268
|
-
this.response.setHeader('Location', url);
|
|
1269
|
-
this.response.setHeader('Content-Type', 'text/html');
|
|
1322
|
+
let postponement = session.getExistingPostponement(this);
|
|
1270
1323
|
|
|
1271
|
-
if (
|
|
1272
|
-
|
|
1324
|
+
if (postponement) {
|
|
1325
|
+
return postponement.showPostponementMessage(this);
|
|
1273
1326
|
}
|
|
1274
1327
|
|
|
1275
|
-
|
|
1276
|
-
this.response.writeHead(202);
|
|
1328
|
+
let response = this.response;
|
|
1277
1329
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1330
|
+
this.postponed_response = response;
|
|
1331
|
+
|
|
1332
|
+
// Make sure the scene id exists
|
|
1333
|
+
this.createScene();
|
|
1334
|
+
|
|
1335
|
+
postponement = session.postpone(this, options);
|
|
1336
|
+
|
|
1337
|
+
if (options.put_in_queue) {
|
|
1338
|
+
postponement.putInQueue();
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
if (options.show_postponement_message !== false) {
|
|
1342
|
+
postponement.showPostponementMessage();
|
|
1343
|
+
}
|
|
1280
1344
|
|
|
1281
1345
|
// Nullify the response
|
|
1282
1346
|
this.response = null;
|
|
1283
1347
|
|
|
1284
1348
|
// Set the original url
|
|
1285
|
-
this.overrideResponseUrl(this.url)
|
|
1349
|
+
this.overrideResponseUrl(this.url);
|
|
1350
|
+
|
|
1351
|
+
// Return the postponement
|
|
1352
|
+
return postponement;
|
|
1286
1353
|
});
|
|
1287
1354
|
|
|
1288
1355
|
/**
|
|
@@ -1436,15 +1503,17 @@ Conduit.setMethod(function redirect(status, options) {
|
|
|
1436
1503
|
/**
|
|
1437
1504
|
* Respond with an error
|
|
1438
1505
|
*
|
|
1439
|
-
* @author Jelle De Loecker <jelle@
|
|
1506
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1440
1507
|
* @since 0.2.0
|
|
1441
|
-
* @version 1.1
|
|
1508
|
+
* @version 1.3.1
|
|
1442
1509
|
*
|
|
1443
1510
|
* @param {Nulber} status Response statuscode
|
|
1444
1511
|
* @param {Error} message Optional error to send
|
|
1445
|
-
* @param {Boolean}
|
|
1512
|
+
* @param {Boolean} print_error Print the error, defaults to true
|
|
1446
1513
|
*/
|
|
1447
|
-
Conduit.setMethod(function error(status, message,
|
|
1514
|
+
Conduit.setMethod(function error(status, message, print_error) {
|
|
1515
|
+
|
|
1516
|
+
let print_dev = false;
|
|
1448
1517
|
|
|
1449
1518
|
if (status instanceof Classes.Alchemy.Error.HTTP) {
|
|
1450
1519
|
message = status;
|
|
@@ -1466,14 +1535,33 @@ Conduit.setMethod(function error(status, message, printError) {
|
|
|
1466
1535
|
message = error;
|
|
1467
1536
|
}
|
|
1468
1537
|
|
|
1469
|
-
let
|
|
1538
|
+
let is_400 = (status >= 400 && status <= 500);
|
|
1470
1539
|
|
|
1471
|
-
if (
|
|
1472
|
-
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1540
|
+
if (alchemy.settings.environment == 'dev') {
|
|
1541
|
+
print_dev = true;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
if (print_error == null) {
|
|
1545
|
+
if (is_400) {
|
|
1546
|
+
print_error = false;
|
|
1547
|
+
} else {
|
|
1548
|
+
print_error = true;
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
if (print_dev) {
|
|
1553
|
+
let subject = 'Error found on ' + this.original_path + '';
|
|
1554
|
+
log.error(subject + ':\n' + message, this);
|
|
1555
|
+
} else if (print_error) {
|
|
1556
|
+
let subject = 'Error found on ' + this.original_path + '';
|
|
1557
|
+
|
|
1558
|
+
if (is_400) {
|
|
1559
|
+
log.error(subject + ':\n' + message);
|
|
1560
|
+
} else if (message instanceof Error) {
|
|
1561
|
+
alchemy.printLog('error', [subject, String(message), message], {err: message, level: -2});
|
|
1562
|
+
} else {
|
|
1563
|
+
log.error(subject + ':\n' + message);
|
|
1564
|
+
}
|
|
1477
1565
|
}
|
|
1478
1566
|
|
|
1479
1567
|
// Make sure the client doesn't expect compression
|
|
@@ -1497,7 +1585,12 @@ Conduit.setMethod(function error(status, message, printError) {
|
|
|
1497
1585
|
} else {
|
|
1498
1586
|
this.set('status', status);
|
|
1499
1587
|
this.set('message', message);
|
|
1500
|
-
|
|
1588
|
+
|
|
1589
|
+
if (alchemy.isTooBusyForRequests()) {
|
|
1590
|
+
this._end(`Error ${status}:\n${message}`);
|
|
1591
|
+
} else {
|
|
1592
|
+
this.render(['error/' + status, 'error/unknown']);
|
|
1593
|
+
}
|
|
1501
1594
|
}
|
|
1502
1595
|
} else {
|
|
1503
1596
|
// Requests for images or scripts just get a non-expensive string response
|
|
@@ -1710,9 +1803,9 @@ Conduit.setMethod(function end(message) {
|
|
|
1710
1803
|
/**
|
|
1711
1804
|
* Call the actual end method
|
|
1712
1805
|
*
|
|
1713
|
-
* @author Jelle De Loecker <jelle@
|
|
1806
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1714
1807
|
* @since 0.2.0
|
|
1715
|
-
* @version 1.1
|
|
1808
|
+
* @version 1.3.1
|
|
1716
1809
|
*/
|
|
1717
1810
|
Conduit.setMethod(function _end(message, encoding = 'utf-8') {
|
|
1718
1811
|
|
|
@@ -1728,6 +1821,8 @@ Conduit.setMethod(function _end(message, encoding = 'utf-8') {
|
|
|
1728
1821
|
|
|
1729
1822
|
this._end_arguments = args;
|
|
1730
1823
|
|
|
1824
|
+
this.emit('after-postponed-end', args);
|
|
1825
|
+
|
|
1731
1826
|
return;
|
|
1732
1827
|
}
|
|
1733
1828
|
|
|
@@ -2120,9 +2215,9 @@ Conduit.setMethod(function _sendStream(stream, options) {
|
|
|
2120
2215
|
/**
|
|
2121
2216
|
* Create a session
|
|
2122
2217
|
*
|
|
2123
|
-
* @author Jelle De Loecker <jelle@
|
|
2218
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
2124
2219
|
* @since 0.2.0
|
|
2125
|
-
* @version 1.1
|
|
2220
|
+
* @version 1.3.1
|
|
2126
2221
|
*
|
|
2127
2222
|
* @param {Boolean} create Create a session if none exist
|
|
2128
2223
|
*
|
|
@@ -2130,16 +2225,16 @@ Conduit.setMethod(function _sendStream(stream, options) {
|
|
|
2130
2225
|
*/
|
|
2131
2226
|
Conduit.setMethod(function getSession(allow_create = true) {
|
|
2132
2227
|
|
|
2133
|
-
var cookie_name,
|
|
2134
|
-
fingerprint,
|
|
2135
|
-
session_id,
|
|
2136
|
-
session;
|
|
2137
|
-
|
|
2138
2228
|
// Only do this once per request
|
|
2139
2229
|
if (this.sessionData != null) {
|
|
2140
2230
|
return this.sessionData;
|
|
2141
2231
|
}
|
|
2142
2232
|
|
|
2233
|
+
let cookie_name,
|
|
2234
|
+
fingerprint,
|
|
2235
|
+
session_id,
|
|
2236
|
+
session;
|
|
2237
|
+
|
|
2143
2238
|
// Set the name of the cookie (could change in the future)
|
|
2144
2239
|
cookie_name = alchemy.settings.session_key || 'alchemy_sid';
|
|
2145
2240
|
|
|
@@ -2498,6 +2593,72 @@ Conduit.setMethod(function supports(feature) {
|
|
|
2498
2593
|
return null;
|
|
2499
2594
|
});
|
|
2500
2595
|
|
|
2596
|
+
/**
|
|
2597
|
+
* Should this request be delayed because the server is too busy?
|
|
2598
|
+
* This performs an early check, the controller might also check this later.
|
|
2599
|
+
* This is mainly so we can prevent Server-Side-Renders from happening
|
|
2600
|
+
* when the system is already overloaded.
|
|
2601
|
+
*
|
|
2602
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
2603
|
+
* @since 1.3.1
|
|
2604
|
+
* @version 1.3.1
|
|
2605
|
+
*
|
|
2606
|
+
* @return {Boolean}
|
|
2607
|
+
*/
|
|
2608
|
+
Conduit.setMethod(function shouldBePostponed() {
|
|
2609
|
+
|
|
2610
|
+
if (!alchemy.settings.postpone_requests_on_overload) {
|
|
2611
|
+
return false;
|
|
2612
|
+
}
|
|
2613
|
+
|
|
2614
|
+
const route = this.route;
|
|
2615
|
+
|
|
2616
|
+
// If no route is found, it can be allowed.
|
|
2617
|
+
// Most of the time this means it's a middleware-request
|
|
2618
|
+
// (like stylesheets, images, scripts, ...)
|
|
2619
|
+
// But also 404s (This can be delayed later by the controller)
|
|
2620
|
+
if (route == null) {
|
|
2621
|
+
return false;
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2624
|
+
// Some routes can't even be postponed
|
|
2625
|
+
if (!route.can_be_postponed) {
|
|
2626
|
+
return false;
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
// If alchemy isn't even too busy, it's obviously allowed
|
|
2630
|
+
if (!alchemy.isTooBusyForRequests()) {
|
|
2631
|
+
return false;
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
// Some users have the permission to skip postponements
|
|
2635
|
+
if (this.hasPermission('alchemy.queue.skip')) {
|
|
2636
|
+
return false;
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
let session = this.getSession(false);
|
|
2640
|
+
|
|
2641
|
+
if (session) {
|
|
2642
|
+
|
|
2643
|
+
// Do not postpone clients that have already been in the queue
|
|
2644
|
+
if (session.hasAlreadyQueued()) {
|
|
2645
|
+
return false;
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2648
|
+
// Do not postpone clients that have already rendered something
|
|
2649
|
+
if (session.render_counter > 0 && session.is_active) {
|
|
2650
|
+
return false;
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
// AJAX requests are allowed a bit more
|
|
2655
|
+
if (this.ajax) {
|
|
2656
|
+
return alchemy.isTooBusyForAjax();
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
return true;
|
|
2660
|
+
});
|
|
2661
|
+
|
|
2501
2662
|
/**
|
|
2502
2663
|
* Broadcast data to every connected user
|
|
2503
2664
|
*
|
package/lib/class/controller.js
CHANGED
|
@@ -225,9 +225,9 @@ Controller.setMethod(function renderDialogIn(config, template) {
|
|
|
225
225
|
/**
|
|
226
226
|
* Render the given template and send it to the client
|
|
227
227
|
*
|
|
228
|
-
* @author Jelle De Loecker <jelle@
|
|
228
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
229
229
|
* @since 0.2.0
|
|
230
|
-
* @version 1.1
|
|
230
|
+
* @version 1.3.1
|
|
231
231
|
*
|
|
232
232
|
* @param {Number} status
|
|
233
233
|
* @param {Array} template
|
|
@@ -236,17 +236,24 @@ Controller.setMethod(function renderDialogIn(config, template) {
|
|
|
236
236
|
*/
|
|
237
237
|
Controller.setMethod(function render(status, template) {
|
|
238
238
|
|
|
239
|
-
|
|
240
|
-
pledge = new Classes.Pledge();
|
|
239
|
+
const conduit = this.conduit;
|
|
241
240
|
|
|
242
|
-
|
|
241
|
+
const session = conduit.getSession(false);
|
|
242
|
+
|
|
243
|
+
if (session) {
|
|
244
|
+
session.incrementRenderCount();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
let pledge = new Classes.Pledge();
|
|
248
|
+
|
|
249
|
+
this.renderHTML(status, template).done(async (err, output) => {
|
|
243
250
|
|
|
244
251
|
if (err) {
|
|
245
|
-
|
|
252
|
+
conduit.error(err);
|
|
246
253
|
return pledge.resolve(false);
|
|
247
254
|
}
|
|
248
255
|
|
|
249
|
-
|
|
256
|
+
conduit.end(output);
|
|
250
257
|
pledge.resolve(true);
|
|
251
258
|
});
|
|
252
259
|
|
|
@@ -466,7 +473,7 @@ Controller.setAction(async function readDatasource(conduit) {
|
|
|
466
473
|
*
|
|
467
474
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
468
475
|
* @since 1.0.4
|
|
469
|
-
* @version 1.
|
|
476
|
+
* @version 1.3.1
|
|
470
477
|
*/
|
|
471
478
|
Controller.setAction(async function saveRecord(conduit) {
|
|
472
479
|
|
|
@@ -488,14 +495,10 @@ Controller.setAction(async function saveRecord(conduit) {
|
|
|
488
495
|
return;
|
|
489
496
|
}
|
|
490
497
|
|
|
491
|
-
let
|
|
492
|
-
data = conduit.param('data'),
|
|
493
|
-
options = conduit.param('options');
|
|
498
|
+
let body = JSON.undry(conduit.body);
|
|
494
499
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
data = JSON.undry({data: data}).data;
|
|
498
|
-
}
|
|
500
|
+
let options = body.options,
|
|
501
|
+
data = body.data;
|
|
499
502
|
|
|
500
503
|
if (Object.isPlainObject(data)) {
|
|
501
504
|
data = model.createDocument(data);
|
package/lib/class/datasource.js
CHANGED
|
@@ -189,7 +189,7 @@ Datasource.setMethod(function toDatasource(schema, data, callback) {
|
|
|
189
189
|
if (!schema) {
|
|
190
190
|
|
|
191
191
|
if (alchemy.settings.debug) {
|
|
192
|
-
|
|
192
|
+
alchemy.distinctProblem('schema-not-found', 'Schema not found: not normalizing data');
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
pledge = Pledge.resolve(data);
|
|
@@ -256,7 +256,7 @@ Datasource.setMethod(function toDatasource(schema, data, callback) {
|
|
|
256
256
|
*
|
|
257
257
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
258
258
|
* @since 0.2.0
|
|
259
|
-
* @version 1.1
|
|
259
|
+
* @version 1.3.1
|
|
260
260
|
*
|
|
261
261
|
* @param {Schema|Model} schema
|
|
262
262
|
* @param {Object} query
|
|
@@ -281,7 +281,7 @@ Datasource.setMethod(function toApp(schema, query, options, data, callback) {
|
|
|
281
281
|
schema = this.getSchema(schema);
|
|
282
282
|
|
|
283
283
|
if (schema == null) {
|
|
284
|
-
|
|
284
|
+
alchemy.distinctProblem('schema-not-found-unnormalize', 'Schema not found: not un-normalizing data');
|
|
285
285
|
|
|
286
286
|
let pledge = Pledge.resolve(data);
|
|
287
287
|
pledge.done(callback);
|
|
@@ -519,13 +519,22 @@ Datasource.setMethod(function read(model, criteria, callback) {
|
|
|
519
519
|
return pledge.reject(err);
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
if (criteria.options.return_raw_data) {
|
|
523
|
+
criteria.setOption('document', false);
|
|
524
|
+
return handleResults(null, results);
|
|
525
|
+
}
|
|
526
|
+
|
|
522
527
|
tasks = results.map(function eachEntry(entry) {
|
|
523
528
|
return function entryToApp(next) {
|
|
524
529
|
that.toApp(model, criteria, {}, entry, next);
|
|
525
530
|
};
|
|
526
531
|
});
|
|
527
532
|
|
|
528
|
-
sub_pledge = Function.parallel(tasks,
|
|
533
|
+
sub_pledge = Function.parallel(tasks, handleResults);
|
|
534
|
+
|
|
535
|
+
pledge._addProgressPledge(sub_pledge);
|
|
536
|
+
|
|
537
|
+
function handleResults(err, app_results) {
|
|
529
538
|
|
|
530
539
|
if (err) {
|
|
531
540
|
return pledge.reject(err);
|
|
@@ -549,9 +558,7 @@ Datasource.setMethod(function read(model, criteria, callback) {
|
|
|
549
558
|
}
|
|
550
559
|
|
|
551
560
|
pledge.resolve(result);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
pledge._addProgressPledge(sub_pledge);
|
|
561
|
+
}
|
|
555
562
|
});
|
|
556
563
|
|
|
557
564
|
if (this.queryCache && model.cache && cache_pledge) {
|
package/lib/class/field.js
CHANGED
|
@@ -301,16 +301,17 @@ Field.setStatic(function unDry(value) {
|
|
|
301
301
|
*
|
|
302
302
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
303
303
|
* @since 0.2.0
|
|
304
|
-
* @version 1.1
|
|
304
|
+
* @version 1.3.1
|
|
305
305
|
*
|
|
306
306
|
* @return {Object}
|
|
307
307
|
*/
|
|
308
308
|
Field.setMethod(function toDry() {
|
|
309
309
|
return {
|
|
310
310
|
value: {
|
|
311
|
+
bla: 1,
|
|
311
312
|
schema : this.schema,
|
|
312
313
|
name : this.name,
|
|
313
|
-
options : this.
|
|
314
|
+
options : this.getOptionsForDrying(),
|
|
314
315
|
}
|
|
315
316
|
};
|
|
316
317
|
});
|
|
@@ -684,7 +685,7 @@ Field.setMethod(function _toDatasource(value, data, datasource, callback) {
|
|
|
684
685
|
*
|
|
685
686
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
686
687
|
* @since 0.2.0
|
|
687
|
-
* @version 1.1
|
|
688
|
+
* @version 1.3.1
|
|
688
689
|
*
|
|
689
690
|
* @param {Object} values
|
|
690
691
|
*/
|
|
@@ -698,6 +699,10 @@ Field.setMethod(function regularToDatasource(value, data, datasource, callback)
|
|
|
698
699
|
return this._toDatasource(value, data, datasource, callback);
|
|
699
700
|
}
|
|
700
701
|
|
|
702
|
+
if (!value) {
|
|
703
|
+
return callback();
|
|
704
|
+
}
|
|
705
|
+
|
|
701
706
|
// Arrayable fields need to process every value inside the array
|
|
702
707
|
tasks = value.map(function eachValue(entry) {
|
|
703
708
|
return function eachValueToDs(next) {
|
|
@@ -1033,6 +1038,19 @@ Field.setMethod(function getClientConfigOptions(wm) {
|
|
|
1033
1038
|
return JSON.clone(this.options, 'toHawkejs', wm);
|
|
1034
1039
|
});
|
|
1035
1040
|
|
|
1041
|
+
/**
|
|
1042
|
+
* Get the options that can be used for drying
|
|
1043
|
+
*
|
|
1044
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1045
|
+
* @since 1.3.1
|
|
1046
|
+
* @version 1.3.1
|
|
1047
|
+
*
|
|
1048
|
+
* @return {Object}
|
|
1049
|
+
*/
|
|
1050
|
+
Field.setMethod(function getOptionsForDrying() {
|
|
1051
|
+
return this.options;
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1036
1054
|
/**
|
|
1037
1055
|
* Get all the rules for this field
|
|
1038
1056
|
*
|
package/lib/class/migration.js
CHANGED
|
@@ -118,7 +118,7 @@ Migration.setStatic(async function start() {
|
|
|
118
118
|
*
|
|
119
119
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
120
120
|
* @since 1.2.0
|
|
121
|
-
* @version 1.
|
|
121
|
+
* @version 1.3.1
|
|
122
122
|
*/
|
|
123
123
|
Migration.setMethod(function processRecords(model_name, fnc) {
|
|
124
124
|
|
|
@@ -127,6 +127,7 @@ Migration.setMethod(function processRecords(model_name, fnc) {
|
|
|
127
127
|
let options = {
|
|
128
128
|
document : false,
|
|
129
129
|
parallel_limit : 1,
|
|
130
|
+
return_raw_data: true,
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
return model.eachRecord(options, async (record, index, next) => {
|
package/lib/class/model.js
CHANGED
|
@@ -509,7 +509,7 @@ Model.setStatic(function getField(name) {
|
|
|
509
509
|
*
|
|
510
510
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
511
511
|
* @since 1.0.0
|
|
512
|
-
* @version 1.
|
|
512
|
+
* @version 1.3.1
|
|
513
513
|
*/
|
|
514
514
|
Model.setStatic(function getClientConfig() {
|
|
515
515
|
|
|
@@ -518,10 +518,21 @@ Model.setStatic(function getClientConfig() {
|
|
|
518
518
|
schema : this.schema,
|
|
519
519
|
primary_key : this.prototype.primary_key,
|
|
520
520
|
display_field : this.prototype.display_field,
|
|
521
|
+
ancestors : 0,
|
|
521
522
|
};
|
|
522
523
|
|
|
523
524
|
if (this.super.name != 'Model') {
|
|
524
525
|
result.parent = this.super.name;
|
|
526
|
+
|
|
527
|
+
let ancestors = 0,
|
|
528
|
+
ancestor = this.super;
|
|
529
|
+
|
|
530
|
+
while (ancestor && ancestor.name != 'Model') {
|
|
531
|
+
ancestors++;
|
|
532
|
+
ancestor = ancestor.super;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
result.ancestors = ancestors;
|
|
525
536
|
}
|
|
526
537
|
|
|
527
538
|
return result;
|