alchemymvc 1.3.19 → 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.
Files changed (42) hide show
  1. package/lib/app/behaviour/sluggable_behaviour.js +0 -0
  2. package/lib/app/datasource/mongo_datasource.js +94 -1
  3. package/lib/app/element/time_ago.js +0 -0
  4. package/lib/app/helper/alchemy_helper.js +8 -4
  5. package/lib/app/helper_controller/controller.js +1 -0
  6. package/lib/app/helper_datasource/00-nosql_datasource.js +0 -0
  7. package/lib/app/helper_field/{date_field.js → 11-date_field.js} +1 -3
  8. package/lib/app/helper_field/15-local_temporal_field.js +100 -0
  9. package/lib/app/helper_field/20-decimal_field.js +105 -0
  10. package/lib/app/helper_field/big_int_field.js +7 -13
  11. package/lib/app/helper_field/fixed_decimal_field.js +44 -0
  12. package/lib/app/helper_field/local_date_field.js +39 -0
  13. package/lib/app/helper_field/local_date_time_field.js +39 -0
  14. package/lib/app/helper_field/local_time_field.js +39 -0
  15. package/lib/app/helper_field/mixed_field.js +73 -0
  16. package/lib/app/helper_field/schema_field.js +121 -35
  17. package/lib/app/helper_model/criteria.js +13 -0
  18. package/lib/app/helper_model/document.js +229 -0
  19. package/lib/app/helper_model/field_set.js +0 -0
  20. package/lib/app/helper_model/model.js +91 -18
  21. package/lib/app/model/alchemy_task_history_model.js +0 -0
  22. package/lib/bootstrap.js +0 -0
  23. package/lib/class/conduit.js +2 -2
  24. package/lib/class/datasource.js +80 -0
  25. package/lib/class/document.js +27 -0
  26. package/lib/class/field.js +110 -0
  27. package/lib/class/inode_file.js +0 -0
  28. package/lib/class/model.js +50 -28
  29. package/lib/class/path_evaluator.js +16 -9
  30. package/lib/class/route.js +4 -1
  31. package/lib/class/router.js +4 -2
  32. package/lib/class/schema_client.js +163 -20
  33. package/lib/class/session.js +0 -0
  34. package/lib/class/task.js +48 -2
  35. package/lib/class/task_service.js +37 -8
  36. package/lib/core/base.js +19 -4
  37. package/lib/core/client_alchemy.js +84 -1
  38. package/lib/core/middleware.js +27 -7
  39. package/lib/init/alchemy.js +4 -1
  40. package/lib/init/constants.js +23 -0
  41. package/lib/init/requirements.js +0 -0
  42. package/package.json +3 -3
@@ -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.4
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.4
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
- return {
299
- alias : alias,
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 : model_name,
302
- options : 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.0
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 0.2.0
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.0
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 {FieldType}
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.1.0
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.5
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 (name.indexOf('.') > -1) {
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
 
File without changes
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.17
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
- return this[PAUSE_PLEDGE];
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
  *
@@ -105,7 +105,7 @@ Service.setMethod(function checksumSystemSchedule(type_path, cron, settings) {
105
105
  *
106
106
  * @author Jelle De Loecker <jelle@elevenways.be>
107
107
  * @since 1.3.17
108
- * @version 1.3.17
108
+ * @version 1.3.20
109
109
  */
110
110
  Service.setMethod(async function initSchedules() {
111
111
 
@@ -179,6 +179,7 @@ Service.setMethod(async function initSchedules() {
179
179
  // If this checksum has already been seen, also remove it
180
180
  if (existing_system_records.has(checksum)) {
181
181
  await record.remove();
182
+ continue;
182
183
  }
183
184
 
184
185
  // Update the record
@@ -188,6 +189,8 @@ Service.setMethod(async function initSchedules() {
188
189
 
189
190
  await record.save();
190
191
 
192
+ existing_system_records.set(checksum, record);
193
+
191
194
  } catch (err) {
192
195
  alchemy.registerError(err);
193
196
  }
@@ -230,7 +233,7 @@ Service.setMethod(async function initSchedules() {
230
233
  *
231
234
  * @author Jelle De Loecker <jelle@elevenways.be>
232
235
  * @since 1.3.17
233
- * @version 1.3.17
236
+ * @version 1.3.21
234
237
  */
235
238
  Service.setMethod(function createJanewayTaskMenu() {
236
239
 
@@ -266,6 +269,10 @@ Service.setMethod(function createJanewayTaskMenu() {
266
269
  }
267
270
  });
268
271
 
272
+ if (!running_task_menu) {
273
+ return;
274
+ }
275
+
269
276
  if (!running_task_menu.addItem) {
270
277
  return running_task_menu.remove();
271
278
  }
@@ -526,12 +533,15 @@ class TaskSchedules {
526
533
  *
527
534
  * @author Jelle De Loecker <jelle@elevenways.be>
528
535
  * @since 1.3.17
529
- * @version 1.3.17
536
+ * @version 1.3.20
530
537
  */
531
- #startFromMenu(task_record) {
538
+ async #startFromMenu(task_record) {
532
539
  console.log('Manually starting', task_record.type, 'task:', task_record);
533
540
  let schedule = new TaskSchedule(this, null, task_record.settings, task_record);
534
- schedule.startManually();
541
+ let task_instance = await schedule.startManually();
542
+ console.log(' -- Started:', task_instance);
543
+
544
+ return task_instance;
535
545
  }
536
546
 
537
547
  /**
@@ -579,6 +589,7 @@ class TaskSchedule {
579
589
  janeway_menu_item = null;
580
590
 
581
591
  #change_counter = 0;
592
+ #instance_pledge = null;
582
593
 
583
594
  /**
584
595
  * Initialize the instance
@@ -845,10 +856,22 @@ class TaskSchedule {
845
856
  *
846
857
  * @author Jelle De Loecker <jelle@elevenways.be>
847
858
  * @since 1.3.17
848
- * @version 1.3.17
859
+ * @version 1.3.20
860
+ *
861
+ * @return {Task}
849
862
  */
850
863
  async startManually() {
851
- return this.#run(true);
864
+
865
+ if (this.is_running) {
866
+ return false;
867
+ }
868
+
869
+ let pledge = new Pledge();
870
+ this.#instance_pledge = pledge;
871
+
872
+ this.#run(true);
873
+
874
+ return pledge;
852
875
  }
853
876
 
854
877
  /**
@@ -856,7 +879,7 @@ class TaskSchedule {
856
879
  *
857
880
  * @author Jelle De Loecker <jelle@elevenways.be>
858
881
  * @since 1.3.17
859
- * @version 1.3.17
882
+ * @version 1.3.20
860
883
  */
861
884
  async #run(started_manually = false) {
862
885
 
@@ -889,6 +912,12 @@ class TaskSchedule {
889
912
  if (started_manually || await this.ownsScheduledTask()) {
890
913
  let instance = this.createInstance();
891
914
  this.task_instance = instance;
915
+
916
+ if (this.#instance_pledge) {
917
+ this.#instance_pledge.resolve(instance);
918
+ this.#instance_pledge = null;
919
+ }
920
+
892
921
  await instance.start();
893
922
  }
894
923
  } catch (err) {
package/lib/core/base.js CHANGED
@@ -471,7 +471,11 @@ Base.setMethod(function getClassPathAfter(after) {
471
471
  *
472
472
  * @author Jelle De Loecker <jelle@elevenways.be>
473
473
  * @since 1.0.0
474
- * @version 1.2.2
474
+ * @version 1.3.20
475
+ *
476
+ * @param {String} name The name of the method to call
477
+ * @param {Array} args The arguments to pass
478
+ * @param {Function} next The callback to call afterwards
475
479
  */
476
480
  Base.setMethod(function callOrNext(name, args, next) {
477
481
 
@@ -480,14 +484,25 @@ Base.setMethod(function callOrNext(name, args, next) {
480
484
  args = [];
481
485
  }
482
486
 
483
- if (typeof this[name] == 'function') {
487
+ const fnc = this[name];
488
+
489
+ if (typeof fnc == 'function') {
490
+
491
+ let has_callback = false,
492
+ promise;
484
493
 
485
- if (next) {
494
+ if (next && fnc.length > args.length) {
495
+ has_callback = true;
486
496
  args.push(next);
487
497
  }
488
498
 
489
499
  try {
490
- this[name].apply(this, args);
500
+ promise = this[name].apply(this, args);
501
+
502
+ if (!has_callback) {
503
+ Pledge.done(promise, next);
504
+ }
505
+
491
506
  } catch (err) {
492
507
  next(err);
493
508
  }
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @author Jelle De Loecker <jelle@develry.be>
7
7
  * @since 0.1.0
8
- * @version 1.3.0
8
+ * @version 1.3.21
9
9
  */
10
10
  var Alchemy = Function.inherits('Alchemy.Client.Base', function Alchemy() {
11
11
 
@@ -24,6 +24,9 @@ var Alchemy = Function.inherits('Alchemy.Client.Base', function Alchemy() {
24
24
  this.sent_subscriptions = [];
25
25
 
26
26
  this.distinct_problems = new Map();
27
+
28
+ // Custom handlers
29
+ this.custom_handlers = new Map();
27
30
  });
28
31
 
29
32
  /**
@@ -196,6 +199,79 @@ Alchemy.setMethod(function distinctProblem(id, message, options = {}) {
196
199
  return entry;
197
200
  });
198
201
 
202
+ /**
203
+ * Register a custom handler
204
+ *
205
+ * @author Jelle De Loecker <jelle@elevenways.be>
206
+ * @since 1.3.21
207
+ * @version 1.3.21
208
+ *
209
+ * @param {string|symbol} type
210
+ * @param {Function} callback
211
+ * @param {Number} weight
212
+ */
213
+ Alchemy.setMethod(function registerCustomHandler(type, callback, weight) {
214
+
215
+ if (typeof callback != 'function') {
216
+ throw new Error('Custom handler needs to be a function');
217
+ }
218
+
219
+ let handlers = this.custom_handlers.get(type);
220
+
221
+ if (!handlers) {
222
+ handlers = new Deck();
223
+ this.custom_handlers.set(type, handlers);
224
+ }
225
+
226
+ if (weight == null) {
227
+ weight = 10;
228
+ }
229
+
230
+ handlers.push(callback, weight);
231
+ });
232
+
233
+ /**
234
+ * Get the highest priority custom handler of the given type
235
+ *
236
+ * @author Jelle De Loecker <jelle@elevenways.be>
237
+ * @since 1.3.21
238
+ * @version 1.3.21
239
+ *
240
+ * @param {string|symbol} type
241
+ *
242
+ * @return {Function}
243
+ */
244
+ Alchemy.setMethod(function getCustomHandler(type) {
245
+
246
+ let handlers = this.custom_handlers.get(type);
247
+
248
+ if (handlers) {
249
+ return handlers.first();
250
+ }
251
+ });
252
+
253
+ /**
254
+ * Get all the custom handlers of the given type
255
+ *
256
+ * @author Jelle De Loecker <jelle@elevenways.be>
257
+ * @since 1.3.21
258
+ * @version 1.3.21
259
+ *
260
+ * @param {string|symbol} type
261
+ *
262
+ * @return {Function[]}
263
+ */
264
+ Alchemy.setMethod(function getAllCustomHandlers(type) {
265
+
266
+ let handlers = this.custom_handlers.get(type);
267
+
268
+ if (handlers) {
269
+ return [...handlers];
270
+ }
271
+
272
+ return [];
273
+ });
274
+
199
275
  /**
200
276
  * Actually print a log message
201
277
  *
@@ -635,6 +711,13 @@ function getRoutesDict() {
635
711
 
636
712
  // From here on, only client-side code is added
637
713
  if (Blast.isBrowser) {
714
+ window.LocalDateTime = Blast.Classes.Develry.LocalDateTime;
715
+ window.LocalDate = Blast.Classes.Develry.LocalDate;
716
+ window.LocalTime = Blast.Classes.Develry.LocalTime;
717
+ window.Decimal = Blast.Classes.Develry.Decimal;
718
+ window.MutableDecimal = Blast.Classes.Develry.MutableDecimal;
719
+ window.FixedDecimal = Blast.Classes.Develry.FixedDecimal;
720
+ window.MutableFixedDecimal = Blast.Classes.Develry.MutableFixedDecimal;
638
721
  window.alchemy = new Alchemy();
639
722
  } else {
640
723
  return;
@@ -426,13 +426,29 @@ Alchemy.setMethod(function minifyScript(path, options, callback) {
426
426
 
427
427
  let minify_options = {
428
428
  compress: {
429
- keep_fargs : true,
430
- keep_fnames : true,
429
+ // Keep all function arguments
430
+ keep_fargs : true,
431
+
432
+ // Keep function names
433
+ keep_fnames : true,
434
+
435
+ // Keep classnames
431
436
  keep_classnames : true,
432
- hoist_funs : false,
433
- drop_console : !alchemy.settings.debug,
434
- dead_code : true,
435
- global_defs : {
437
+
438
+ // Do not hoist function declarations
439
+ hoist_funs : false,
440
+
441
+ // Only drop console calls when not debugging
442
+ drop_console : !alchemy.settings.debug,
443
+
444
+ // Remove dead code
445
+ dead_code : true,
446
+
447
+ // Remove symbol names
448
+ unsafe_symbols : true,
449
+
450
+ // Provide it some info on global definitions
451
+ global_defs : {
436
452
  '__BLAST_IS_NODE' : false,
437
453
  '__BLAST_IS_BROWSER' : true
438
454
  }
@@ -440,7 +456,11 @@ Alchemy.setMethod(function minifyScript(path, options, callback) {
440
456
  mangle: {
441
457
  keep_fnames : true,
442
458
  keep_classnames : true,
443
- }
459
+ },
460
+ output: {
461
+ // Do not wrap functions that are arguments in parenthesis
462
+ wrap_func_args : false,
463
+ },
444
464
  };
445
465
 
446
466
  if (alchemy.settings.debug && alchemy.settings.source_map) {
@@ -19,7 +19,7 @@ var shared_objects = {},
19
19
  *
20
20
  * @author Jelle De Loecker <jelle@elevenways.be>
21
21
  * @since 0.0.1
22
- * @version 1.3.11
22
+ * @version 1.3.21
23
23
  */
24
24
  global.Alchemy = Function.inherits('Informer', 'Alchemy', function Alchemy() {
25
25
 
@@ -105,6 +105,9 @@ global.Alchemy = Function.inherits('Informer', 'Alchemy', function Alchemy() {
105
105
  // Distinct problems
106
106
  this.distinct_problems = new Map();
107
107
 
108
+ // Custom handlers
109
+ this.custom_handlers = new Map();
110
+
108
111
  // Load the settings
109
112
  this.loadSettings();
110
113