alchemymvc 1.3.20 → 1.3.21
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/helper/alchemy_helper.js +8 -4
- package/lib/app/helper_controller/controller.js +1 -0
- package/lib/app/helper_field/big_int_field.js +2 -2
- package/lib/app/helper_field/mixed_field.js +73 -0
- package/lib/app/helper_field/schema_field.js +110 -35
- package/lib/app/helper_model/criteria.js +13 -0
- package/lib/app/helper_model/document.js +229 -0
- package/lib/app/helper_model/model.js +67 -8
- package/lib/class/conduit.js +2 -2
- package/lib/class/document.js +27 -0
- package/lib/class/field.js +110 -0
- package/lib/class/model.js +47 -12
- package/lib/class/route.js +4 -1
- package/lib/class/router.js +4 -2
- package/lib/class/schema_client.js +163 -20
- package/lib/class/task.js +48 -2
- package/lib/class/task_service.js +5 -1
- package/lib/core/client_alchemy.js +77 -1
- package/lib/core/middleware.js +27 -7
- package/lib/init/alchemy.js +4 -1
- package/package.json +3 -3
package/lib/class/conduit.js
CHANGED
|
@@ -1578,7 +1578,7 @@ Conduit.setMethod(function redirect(status, options) {
|
|
|
1578
1578
|
*
|
|
1579
1579
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1580
1580
|
* @since 0.2.0
|
|
1581
|
-
* @version 1.3.
|
|
1581
|
+
* @version 1.3.21
|
|
1582
1582
|
*
|
|
1583
1583
|
* @param {Nulber} status Response statuscode
|
|
1584
1584
|
* @param {Error} message Optional error to send
|
|
@@ -1613,7 +1613,7 @@ Conduit.setMethod(function error(status, message, print_error) {
|
|
|
1613
1613
|
if (alchemy.settings.environment == 'dev') {
|
|
1614
1614
|
print_dev = true;
|
|
1615
1615
|
|
|
1616
|
-
if (is_400 && this.original_path.indexOf('.js.map') > -1) {
|
|
1616
|
+
if (is_400 && this.original_path && this.original_path.indexOf('.js.map') > -1) {
|
|
1617
1617
|
print_dev = false;
|
|
1618
1618
|
print_error = false;
|
|
1619
1619
|
}
|
package/lib/class/document.js
CHANGED
|
@@ -178,6 +178,33 @@ Document.setStatic(function unDry(obj, cloned) {
|
|
|
178
178
|
return result;
|
|
179
179
|
});
|
|
180
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Set the getter for this computed field
|
|
183
|
+
*
|
|
184
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
185
|
+
* @since 1.3.21
|
|
186
|
+
* @version 1.3.21
|
|
187
|
+
*
|
|
188
|
+
* @param {String} name Name of the property
|
|
189
|
+
* @param {Function} getter Optional getter function
|
|
190
|
+
* @param {Function} setter Optional setter function
|
|
191
|
+
*/
|
|
192
|
+
Document.setStatic(function setComputedFieldGetter(name) {
|
|
193
|
+
this.setProperty(name, function getComputedFieldValue() {
|
|
194
|
+
this.recomputeFieldIfNecessary(name);
|
|
195
|
+
return this.$main[name];
|
|
196
|
+
}, function setComputedFieldValue(value) {
|
|
197
|
+
|
|
198
|
+
const field = this.$model.schema.getField(name);
|
|
199
|
+
|
|
200
|
+
if (field?.options?.allow_manual_set) {
|
|
201
|
+
return this.$main[name] = value;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
console.error('Can not set computed field "' + name + '" to', value);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
181
208
|
/**
|
|
182
209
|
* Set the getter for this field
|
|
183
210
|
*
|
package/lib/class/field.js
CHANGED
|
@@ -207,6 +207,116 @@ Field.setProperty(function is_array() {
|
|
|
207
207
|
return !!result;
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Does this field have a computed value?
|
|
212
|
+
*
|
|
213
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
214
|
+
* @since 1.3.21
|
|
215
|
+
* @version 1.3.21
|
|
216
|
+
*
|
|
217
|
+
* @type {Boolean}
|
|
218
|
+
*/
|
|
219
|
+
Field.setProperty(function is_computed() {
|
|
220
|
+
return !!this.options.is_computed;
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get the required related fields
|
|
225
|
+
*
|
|
226
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
227
|
+
* @since 1.3.21
|
|
228
|
+
* @version 1.3.21
|
|
229
|
+
*
|
|
230
|
+
* @type {Field[]}
|
|
231
|
+
*/
|
|
232
|
+
Field.enforceProperty(function required_fields(new_value) {
|
|
233
|
+
|
|
234
|
+
if (!new_value) {
|
|
235
|
+
new_value = resolveFieldPaths(this, this.options.required_fields);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return new_value;
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Get the optional related fields
|
|
243
|
+
*
|
|
244
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
245
|
+
* @since 1.3.21
|
|
246
|
+
* @version 1.3.21
|
|
247
|
+
*
|
|
248
|
+
* @type {Field[]}
|
|
249
|
+
*/
|
|
250
|
+
Field.enforceProperty(function optional_fields(new_value) {
|
|
251
|
+
|
|
252
|
+
if (!new_value) {
|
|
253
|
+
new_value = resolveFieldPaths(this, this.options.optional_fields);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return new_value;
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get all the dependency fields
|
|
261
|
+
*
|
|
262
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
263
|
+
* @since 1.3.21
|
|
264
|
+
* @version 1.3.21
|
|
265
|
+
*
|
|
266
|
+
* @type {Field[]}
|
|
267
|
+
*/
|
|
268
|
+
Field.enforceProperty(function dependency_fields(new_value) {
|
|
269
|
+
|
|
270
|
+
if (!new_value) {
|
|
271
|
+
let required_fields = this.required_fields,
|
|
272
|
+
optional_fields = this.optional_fields;
|
|
273
|
+
|
|
274
|
+
new_value = [];
|
|
275
|
+
|
|
276
|
+
if (required_fields) {
|
|
277
|
+
new_value = new_value.concat(required_fields);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (optional_fields) {
|
|
281
|
+
new_value = new_value.concat(optional_fields);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return new_value;
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Resolve a field path to a field instance
|
|
290
|
+
*
|
|
291
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
292
|
+
* @since 1.3.21
|
|
293
|
+
* @version 1.3.21
|
|
294
|
+
*/
|
|
295
|
+
function resolveFieldPaths(field, field_paths) {
|
|
296
|
+
|
|
297
|
+
let result = [],
|
|
298
|
+
i;
|
|
299
|
+
|
|
300
|
+
if (!field_paths) {
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
for (i = 0; i < field_paths.length; i++) {
|
|
305
|
+
|
|
306
|
+
if (!field.parent_schema) {
|
|
307
|
+
continue
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
let other_field = field.parent_schema.getField(field_paths[i]);
|
|
311
|
+
|
|
312
|
+
if (other_field && result.indexOf(other_field) == -1) {
|
|
313
|
+
result.push(other_field);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
|
|
210
320
|
/**
|
|
211
321
|
* The datasource this field is used in
|
|
212
322
|
*
|
package/lib/class/model.js
CHANGED
|
@@ -366,24 +366,49 @@ Model.setStatic(async function checkPathValue(value, name, field_name, conduit)
|
|
|
366
366
|
return result;
|
|
367
367
|
});
|
|
368
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Add a computed field to this model's schema
|
|
371
|
+
*
|
|
372
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
373
|
+
* @since 1.3.21
|
|
374
|
+
* @version 1.3.21
|
|
375
|
+
*
|
|
376
|
+
* @return {Alchemy.Field}
|
|
377
|
+
*/
|
|
378
|
+
Model.setStatic(function addComputedField(name, type, options) {
|
|
379
|
+
let is_new = !this.schema.has(name);
|
|
380
|
+
|
|
381
|
+
// Add it to the schema
|
|
382
|
+
let field = this.schema.addComputedField(name, type, options);
|
|
383
|
+
|
|
384
|
+
if (is_new) {
|
|
385
|
+
// Add it to the Document class
|
|
386
|
+
this.Document.setComputedFieldGetter(name);
|
|
387
|
+
|
|
388
|
+
// False means it should not be set on the server implementation
|
|
389
|
+
// (because that's where it's coming from)
|
|
390
|
+
// Yes, this also sets private fields on the server-side client document.
|
|
391
|
+
this.ClientDocument.setComputedFieldGetter(name, null, null, false);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return field;
|
|
395
|
+
});
|
|
396
|
+
|
|
369
397
|
/**
|
|
370
398
|
* Add a field to this model's schema
|
|
371
399
|
*
|
|
372
400
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
373
401
|
* @since 0.2.0
|
|
374
|
-
* @version 1.2.
|
|
402
|
+
* @version 1.2.21
|
|
375
403
|
*
|
|
376
404
|
* @return {Alchemy.Field}
|
|
377
405
|
*/
|
|
378
406
|
Model.setStatic(function addField(name, type, options) {
|
|
379
407
|
|
|
380
|
-
|
|
381
|
-
is_new;
|
|
382
|
-
|
|
383
|
-
is_new = !this.schema.has(name);
|
|
408
|
+
let is_new = !this.schema.has(name);
|
|
384
409
|
|
|
385
410
|
// Add it to the schema
|
|
386
|
-
field = this.schema.addField(name, type, options);
|
|
411
|
+
let field = this.schema.addField(name, type, options);
|
|
387
412
|
|
|
388
413
|
if (is_new) {
|
|
389
414
|
// Add it to the Document class
|
|
@@ -1262,7 +1287,7 @@ Model.setMethod(async function executeMongoPipeline(pipeline) {
|
|
|
1262
1287
|
*
|
|
1263
1288
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
1264
1289
|
* @since 0.0.1
|
|
1265
|
-
* @version 1.
|
|
1290
|
+
* @version 1.3.21
|
|
1266
1291
|
*
|
|
1267
1292
|
* @param {String} id The object id
|
|
1268
1293
|
* @param {Function} callback
|
|
@@ -1291,14 +1316,24 @@ Model.setMethod(function remove(id, callback) {
|
|
|
1291
1316
|
let query = {};
|
|
1292
1317
|
query[this.primary_key] = id;
|
|
1293
1318
|
|
|
1294
|
-
|
|
1319
|
+
Function.series(function recompute(next) {
|
|
1320
|
+
that.callOrNext('beforeRemove', [id], next);
|
|
1321
|
+
}, function done(err) {
|
|
1295
1322
|
|
|
1296
|
-
if (err
|
|
1297
|
-
|
|
1323
|
+
if (err) {
|
|
1324
|
+
pledge.reject(err);
|
|
1325
|
+
return;
|
|
1298
1326
|
}
|
|
1299
1327
|
|
|
1300
|
-
that.
|
|
1301
|
-
|
|
1328
|
+
that.datasource.remove(that, query, {}, function afterRemove(err, result) {
|
|
1329
|
+
|
|
1330
|
+
if (err != null) {
|
|
1331
|
+
return pledge.reject(err);
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
that.emit('removed', result, {}, false, function afterRemovedEvent() {
|
|
1335
|
+
pledge.resolve(result);
|
|
1336
|
+
});
|
|
1302
1337
|
});
|
|
1303
1338
|
});
|
|
1304
1339
|
|
package/lib/class/route.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
5
5
|
* @since 0.2.0
|
|
6
|
-
* @version 1.3.
|
|
6
|
+
* @version 1.3.21
|
|
7
7
|
*/
|
|
8
8
|
const Route = Function.inherits('Alchemy.Base', function Route(router, paths, options) {
|
|
9
9
|
|
|
@@ -62,6 +62,9 @@ const Route = Function.inherits('Alchemy.Base', function Route(router, paths, op
|
|
|
62
62
|
// All routes can be postponed by default
|
|
63
63
|
this.can_be_postponed = true;
|
|
64
64
|
|
|
65
|
+
// Possible cache instructions
|
|
66
|
+
this.cache = null;
|
|
67
|
+
|
|
65
68
|
this.setPaths(paths);
|
|
66
69
|
});
|
|
67
70
|
|
package/lib/class/router.js
CHANGED
|
@@ -767,7 +767,7 @@ RouterClass.setMethod(function setOption(name, value) {
|
|
|
767
767
|
*
|
|
768
768
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
769
769
|
* @since 0.2.0
|
|
770
|
-
* @version 1.3.
|
|
770
|
+
* @version 1.3.21
|
|
771
771
|
*
|
|
772
772
|
* @param {Object} args
|
|
773
773
|
* @param {String} args.name Optional route name
|
|
@@ -819,6 +819,7 @@ RouterClass.setMethod(function add(args) {
|
|
|
819
819
|
route.setBreadcrumb(args.breadcrumb);
|
|
820
820
|
route.sitemap = args.sitemap;
|
|
821
821
|
route.title = args.title;
|
|
822
|
+
route.cache = args.cache;
|
|
822
823
|
|
|
823
824
|
if (args.visible_location != null) {
|
|
824
825
|
route.visible_location = args.visible_location;
|
|
@@ -1167,7 +1168,7 @@ RouterClass.setMethod(function getOptions(result) {
|
|
|
1167
1168
|
*
|
|
1168
1169
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1169
1170
|
* @since 0.2.0
|
|
1170
|
-
* @version 1.3.
|
|
1171
|
+
* @version 1.3.21
|
|
1171
1172
|
*
|
|
1172
1173
|
* @param {Object} result Optional object to store sectioned results in
|
|
1173
1174
|
*
|
|
@@ -1219,6 +1220,7 @@ RouterClass.setMethod(function getRoutes(result) {
|
|
|
1219
1220
|
is_system_route : route.is_system_route,
|
|
1220
1221
|
schema : route.schema,
|
|
1221
1222
|
param_definitions : route.param_definitions,
|
|
1223
|
+
cache : route.cache,
|
|
1222
1224
|
};
|
|
1223
1225
|
}
|
|
1224
1226
|
|
|
@@ -183,7 +183,7 @@ Schema.addRelationCreator('HasOneChild', {internal: false, singular: tru
|
|
|
183
183
|
*
|
|
184
184
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
185
185
|
* @since 1.3.4
|
|
186
|
-
* @version 1.3.
|
|
186
|
+
* @version 1.3.21
|
|
187
187
|
*
|
|
188
188
|
* @param {String} alias
|
|
189
189
|
* @param {String} modelname
|
|
@@ -239,7 +239,7 @@ Schema.setMethod(function addAssociation(relation_type, relation_config, alias,
|
|
|
239
239
|
*
|
|
240
240
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
241
241
|
* @since 0.2.0
|
|
242
|
-
* @version 1.3.
|
|
242
|
+
* @version 1.3.21
|
|
243
243
|
*
|
|
244
244
|
* @param {Boolean} is_internal Is this internal (A remote record's id is stored inside this record)
|
|
245
245
|
* @param {String} alias
|
|
@@ -295,12 +295,25 @@ Schema.setMethod(function getAssociationArguments(is_internal, alias, model_name
|
|
|
295
295
|
options.local_key = options.localKey = local_key;
|
|
296
296
|
options.foreign_key = options.foreignKey = foreign_key;
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
298
|
+
let field_options = options.field_options;
|
|
299
|
+
|
|
300
|
+
if (!field_options) {
|
|
301
|
+
options.field_options = field_options = {};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (options.required != null) {
|
|
305
|
+
field_options.required = options.required;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
let result = {
|
|
309
|
+
alias : alias,
|
|
300
310
|
model_name,
|
|
301
|
-
modelName
|
|
302
|
-
options
|
|
311
|
+
modelName : model_name,
|
|
312
|
+
options : options,
|
|
313
|
+
constraints : options?.constraints,
|
|
303
314
|
};
|
|
315
|
+
|
|
316
|
+
return result;
|
|
304
317
|
});
|
|
305
318
|
|
|
306
319
|
/**
|
|
@@ -402,7 +415,7 @@ Schema.setMethod(function toDry() {
|
|
|
402
415
|
*
|
|
403
416
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
404
417
|
* @since 1.1.0
|
|
405
|
-
* @version 1.3.
|
|
418
|
+
* @version 1.3.21
|
|
406
419
|
*/
|
|
407
420
|
Schema.setMethod(function init() {
|
|
408
421
|
this.associations = {};
|
|
@@ -434,6 +447,15 @@ Schema.setMethod(function init() {
|
|
|
434
447
|
// Validation rules
|
|
435
448
|
this.rules = new Deck();
|
|
436
449
|
|
|
450
|
+
// Computed fields
|
|
451
|
+
this.computed_fields = {};
|
|
452
|
+
|
|
453
|
+
// How many computed fields there are
|
|
454
|
+
this.has_computed_fields = 0;
|
|
455
|
+
|
|
456
|
+
// How many computed fields require a recompute after find
|
|
457
|
+
this.has_recompute_after_find = 0;
|
|
458
|
+
|
|
437
459
|
// Behaviour count
|
|
438
460
|
this.has_behaviours = 0;
|
|
439
461
|
});
|
|
@@ -456,11 +478,17 @@ Schema.setMethod(function setName(name) {
|
|
|
456
478
|
*
|
|
457
479
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
458
480
|
* @since 0.2.0
|
|
459
|
-
* @version
|
|
481
|
+
* @version 1.3.21
|
|
460
482
|
*
|
|
461
483
|
* @param {Schema} schema
|
|
462
484
|
*/
|
|
463
485
|
Schema.setMethod(function setParent(schema) {
|
|
486
|
+
|
|
487
|
+
if (schema != this.parent) {
|
|
488
|
+
schema.has_computed_fields += this.has_computed_fields;
|
|
489
|
+
schema.has_recompute_after_find += this.has_recompute_after_find;
|
|
490
|
+
}
|
|
491
|
+
|
|
464
492
|
this.parent = schema;
|
|
465
493
|
});
|
|
466
494
|
|
|
@@ -631,18 +659,69 @@ Schema.setMethod(function getPrivateFields() {
|
|
|
631
659
|
return result;
|
|
632
660
|
});
|
|
633
661
|
|
|
662
|
+
/**
|
|
663
|
+
* Add a computed field to this schema:
|
|
664
|
+
* The value of these fields will be computed
|
|
665
|
+
* when the document is saved or loaded.
|
|
666
|
+
*
|
|
667
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
668
|
+
* @since 1.3.21
|
|
669
|
+
* @version 1.3.21
|
|
670
|
+
*
|
|
671
|
+
* @param {String} name
|
|
672
|
+
* @param {String} type
|
|
673
|
+
* @param {Object} options
|
|
674
|
+
*
|
|
675
|
+
* @return {Alchemy.Field.Field}
|
|
676
|
+
*/
|
|
677
|
+
Schema.setMethod(function addComputedField(name, type, options) {
|
|
678
|
+
|
|
679
|
+
if (arguments.length < 3 || !type || !options) {
|
|
680
|
+
throw new Error('Schema#addComputedField expects at least 3 arguments');
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (!options.compute_method) {
|
|
684
|
+
throw new Error('Schema#addComputedField expects a compute_method option');
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
if (!this.name || this.model_name != this.name) {
|
|
688
|
+
throw new Error('Computed fields can only be added to the root schema');
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
options.is_computed = true;
|
|
692
|
+
|
|
693
|
+
let result = this.addField(name, type, options);
|
|
694
|
+
|
|
695
|
+
this.computed_fields[name] = result;
|
|
696
|
+
this.has_computed_fields++;
|
|
697
|
+
|
|
698
|
+
if (this.parent) {
|
|
699
|
+
this.parent.has_computed_fields++;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if (options.compute_after_find) {
|
|
703
|
+
this.has_recompute_after_find++;
|
|
704
|
+
|
|
705
|
+
if (this.parent) {
|
|
706
|
+
this.parent.has_recompute_after_find++;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
return result;
|
|
711
|
+
});
|
|
712
|
+
|
|
634
713
|
/**
|
|
635
714
|
* Add a field to this schema
|
|
636
715
|
*
|
|
637
716
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
638
717
|
* @since 0.2.0
|
|
639
|
-
* @version 1.3.
|
|
718
|
+
* @version 1.3.21
|
|
640
719
|
*
|
|
641
720
|
* @param {String} name
|
|
642
721
|
* @param {String} type
|
|
643
722
|
* @param {Object} options
|
|
644
723
|
*
|
|
645
|
-
* @return {
|
|
724
|
+
* @return {Alchemy.Field.Field}
|
|
646
725
|
*/
|
|
647
726
|
Schema.setMethod(function addField(name, type, options) {
|
|
648
727
|
|
|
@@ -693,6 +772,43 @@ Schema.setMethod(function addField(name, type, options) {
|
|
|
693
772
|
}
|
|
694
773
|
}
|
|
695
774
|
|
|
775
|
+
if (options.constraints) {
|
|
776
|
+
let required_fields = options.required_fields,
|
|
777
|
+
optional_fields = options.optional_fields,
|
|
778
|
+
value,
|
|
779
|
+
key;
|
|
780
|
+
|
|
781
|
+
if (!required_fields) {
|
|
782
|
+
required_fields = [];
|
|
783
|
+
} else {
|
|
784
|
+
required_fields = required_fields.slice(0);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
if (!optional_fields) {
|
|
788
|
+
optional_fields = [];
|
|
789
|
+
} else {
|
|
790
|
+
optional_fields = optional_fields.slice(0);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
for (key in options.constraints) {
|
|
794
|
+
value = options.constraints[key];
|
|
795
|
+
|
|
796
|
+
if (value && typeof value == 'object') {
|
|
797
|
+
if (value instanceof Classes.Alchemy.PathEvaluator) {
|
|
798
|
+
required_fields.push(value);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (required_fields.length) {
|
|
804
|
+
options.required_fields = required_fields;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if (optional_fields.length) {
|
|
808
|
+
options.optional_fields = optional_fields;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
696
812
|
field = new FieldClass(this, name, options);
|
|
697
813
|
|
|
698
814
|
if (field.requires_translating) {
|
|
@@ -723,7 +839,7 @@ Schema.setMethod(function addField(name, type, options) {
|
|
|
723
839
|
*
|
|
724
840
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
725
841
|
* @since 0.2.0
|
|
726
|
-
* @version 1.
|
|
842
|
+
* @version 1.3.21
|
|
727
843
|
*
|
|
728
844
|
* @param {String} rule_name
|
|
729
845
|
* @param {Object} options
|
|
@@ -738,10 +854,6 @@ Schema.setMethod(function addRule(rule_name, options) {
|
|
|
738
854
|
throw new Error('Custom function validators not yet implemented');
|
|
739
855
|
}
|
|
740
856
|
|
|
741
|
-
if (!options) {
|
|
742
|
-
throw new Error('No valid options were found for the ' + rule_name + ' validator');
|
|
743
|
-
}
|
|
744
|
-
|
|
745
857
|
let constructor = alchemy.getValidatorClass(rule_name);
|
|
746
858
|
|
|
747
859
|
if (!constructor) {
|
|
@@ -818,26 +930,57 @@ Schema.setMethod(function getField(name) {
|
|
|
818
930
|
return this.getFieldChain(name).last();
|
|
819
931
|
});
|
|
820
932
|
|
|
933
|
+
/**
|
|
934
|
+
* Get an association by name
|
|
935
|
+
*
|
|
936
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
937
|
+
* @since 1.3.21
|
|
938
|
+
* @version 1.3.21
|
|
939
|
+
*
|
|
940
|
+
* @param {String} name
|
|
941
|
+
*
|
|
942
|
+
* @return {Object}
|
|
943
|
+
*/
|
|
944
|
+
Schema.setMethod(function getAssociation(name) {
|
|
945
|
+
return this.associations[name];
|
|
946
|
+
});
|
|
947
|
+
|
|
821
948
|
/**
|
|
822
949
|
* Get a field
|
|
823
950
|
*
|
|
824
951
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
825
952
|
* @since 0.2.0
|
|
826
|
-
* @version 1.2.
|
|
953
|
+
* @version 1.2.21
|
|
827
954
|
*
|
|
828
|
-
* @param {String} name
|
|
955
|
+
* @param {String|PathEvaluator} name
|
|
829
956
|
*
|
|
830
957
|
* @return {FieldType[]}
|
|
831
958
|
*/
|
|
832
959
|
Schema.setMethod(function getFieldChain(name) {
|
|
833
960
|
|
|
834
|
-
let result
|
|
961
|
+
let result,
|
|
962
|
+
pieces;
|
|
963
|
+
|
|
964
|
+
if (typeof name == 'object') {
|
|
965
|
+
|
|
966
|
+
if (name instanceof Classes.Alchemy.PathEvaluator) {
|
|
967
|
+
pieces = name.path;
|
|
968
|
+
|
|
969
|
+
if (pieces[0] == '$0') {
|
|
970
|
+
pieces = pieces.slice(1);
|
|
971
|
+
return this.root_schema.getFieldChain(pieces);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
} else if (Array.isArray(name)) {
|
|
975
|
+
pieces = name;
|
|
976
|
+
} else if (typeof name == 'string' && name.indexOf('.') > -1) {
|
|
977
|
+
pieces = name.split('.');
|
|
978
|
+
}
|
|
835
979
|
|
|
836
980
|
// Allow getting a nested field by a path
|
|
837
|
-
if (
|
|
981
|
+
if (pieces) {
|
|
838
982
|
|
|
839
983
|
let current = this,
|
|
840
|
-
pieces = name.split('.'),
|
|
841
984
|
max = pieces.length - 1,
|
|
842
985
|
i;
|
|
843
986
|
|
package/lib/class/task.js
CHANGED
|
@@ -489,7 +489,7 @@ Task.setMethod(function getParam(name) {
|
|
|
489
489
|
*
|
|
490
490
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
491
491
|
* @since 1.3.17
|
|
492
|
-
* @version 1.3.
|
|
492
|
+
* @version 1.3.21
|
|
493
493
|
*/
|
|
494
494
|
Task.setMethod(function waitUntilResumed() {
|
|
495
495
|
|
|
@@ -497,9 +497,55 @@ Task.setMethod(function waitUntilResumed() {
|
|
|
497
497
|
return false;
|
|
498
498
|
}
|
|
499
499
|
|
|
500
|
-
|
|
500
|
+
let paused = this[PAUSE_PLEDGE];
|
|
501
|
+
|
|
502
|
+
if (paused) {
|
|
503
|
+
return paused;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
return this.waitIfTooBusy();
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Wait if the system is too busy
|
|
511
|
+
*
|
|
512
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
513
|
+
* @since 1.3.21
|
|
514
|
+
* @version 1.3.21
|
|
515
|
+
*/
|
|
516
|
+
Task.setMethod(function waitIfTooBusy() {
|
|
517
|
+
|
|
518
|
+
if (!alchemy.isTooBusy()) {
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return doAsyncLoopUntilNotBusy(10);
|
|
501
523
|
});
|
|
502
524
|
|
|
525
|
+
/**
|
|
526
|
+
* Do a loop until the system is no longer busy
|
|
527
|
+
*
|
|
528
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
529
|
+
* @since 1.3.21
|
|
530
|
+
* @version 1.3.21
|
|
531
|
+
*/
|
|
532
|
+
async function doAsyncLoopUntilNotBusy(max_tries) {
|
|
533
|
+
|
|
534
|
+
let tries = 0;
|
|
535
|
+
|
|
536
|
+
if (!max_tries || max_tries < 1) {
|
|
537
|
+
max_tries = 5;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
do {
|
|
541
|
+
console.log('Waiting for system to be less busy', tries)
|
|
542
|
+
await Pledge.after(500);
|
|
543
|
+
tries++;
|
|
544
|
+
} while (tries < max_tries && alchemy.isTooBusy());
|
|
545
|
+
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
548
|
+
|
|
503
549
|
/**
|
|
504
550
|
* Report command progress
|
|
505
551
|
*
|
|
@@ -233,7 +233,7 @@ Service.setMethod(async function initSchedules() {
|
|
|
233
233
|
*
|
|
234
234
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
235
235
|
* @since 1.3.17
|
|
236
|
-
* @version 1.3.
|
|
236
|
+
* @version 1.3.21
|
|
237
237
|
*/
|
|
238
238
|
Service.setMethod(function createJanewayTaskMenu() {
|
|
239
239
|
|
|
@@ -269,6 +269,10 @@ Service.setMethod(function createJanewayTaskMenu() {
|
|
|
269
269
|
}
|
|
270
270
|
});
|
|
271
271
|
|
|
272
|
+
if (!running_task_menu) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
272
276
|
if (!running_task_menu.addItem) {
|
|
273
277
|
return running_task_menu.remove();
|
|
274
278
|
}
|