alchemymvc 1.3.16 → 1.3.18

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/core/base.js CHANGED
@@ -35,7 +35,7 @@ __Protoblast.getGroup = function getGroup(name) {
35
35
  *
36
36
  * @author Jelle De Loecker <jelle@develry.be>
37
37
  * @since 0.3.0
38
- * @version 1.2.6
38
+ * @version 1.3.17
39
39
  */
40
40
  Base.constitute(function setBasicBehaviour() {
41
41
 
@@ -134,6 +134,28 @@ Base.constitute(function setBasicBehaviour() {
134
134
  this.setStatic('title', this.createClassTitle(name), false);
135
135
  }
136
136
 
137
+ // And also set the type path
138
+ if (!this.hasOwnProperty('type_path')) {
139
+ let namespace = this.namespace;
140
+ let parent_namespace = this.super?.namespace;
141
+ let type_path = this.type_name;
142
+
143
+ // Add extra identifier info if this child comes from another namespace
144
+ if (namespace && namespace != parent_namespace) {
145
+ if (parent_namespace && namespace.startsWith(parent_namespace)) {
146
+ namespace = namespace.after(parent_namespace);
147
+
148
+ if (namespace[0] == '.') {
149
+ namespace = namespace.slice(1);
150
+ }
151
+ }
152
+
153
+ type_path = Blast.Bound.String.underscore(Blast.Bound.String.slug(namespace)) + '.' + type_path;
154
+ }
155
+
156
+ this.setStatic('type_path', type_path, false);
157
+ }
158
+
137
159
  // Add this class to the shared group
138
160
  shared_group[this.type_name] = this;
139
161
  });
@@ -311,7 +311,7 @@ Alchemy.setMethod(function sourcemapMiddleware(req, res, nextMiddleware) {
311
311
  *
312
312
  * @author Jelle De Loecker <jelle@develry.be>
313
313
  * @since 0.2.0
314
- * @version 1.3.4
314
+ * @version 1.3.17
315
315
  *
316
316
  * @param {String} path
317
317
  * @param {Object} options
@@ -418,7 +418,7 @@ Alchemy.setMethod(function minifyScript(path, options, callback) {
418
418
  }
419
419
  }
420
420
 
421
- if (should_minify) {
421
+ if (should_minify && typeof Terser?.minify == 'function') {
422
422
 
423
423
  // Force Blast.isNode & Blast.isBrowser to be replaced later
424
424
  data = data.replaceAll('Blast.isNode', '__BLAST_IS_NODE');
@@ -135,7 +135,11 @@ global.Alchemy = Function.inherits('Informer', 'Alchemy', function Alchemy() {
135
135
  this.startJaneway();
136
136
  }
137
137
  } catch (err) {
138
- log.warn('Failed to start Janeway:', err);
138
+ if (typeof log != 'undefined') {
139
+ log.warn('Failed to start Janeway:', err);
140
+ } else {
141
+ console.warn('Failed to start Janeway:', err);
142
+ }
139
143
  }
140
144
  });
141
145
 
@@ -334,7 +338,7 @@ Alchemy.setMethod(function isTooBusyForRequests() {
334
338
  *
335
339
  * @author Jelle De Loecker <jelle@elevenways.be>
336
340
  * @since 1.3.1
337
- * @version 1.3.2
341
+ * @version 1.3.18
338
342
  *
339
343
  * @return {Boolean}
340
344
  */
@@ -344,11 +348,11 @@ Alchemy.setMethod(function isTooBusyForAjax() {
344
348
  return false;
345
349
  }
346
350
 
347
- let lag = this.lagInMs();
348
-
349
- let max_event_loop_lag = alchemy.settings.max_event_loop_lag || alchemy.settings.toobusy;
351
+ let max_event_loop_lag = alchemy.settings.max_event_loop_lag ?? alchemy.settings.toobusy;
350
352
 
351
353
  if (max_event_loop_lag) {
354
+ let lag = this.lagInMs();
355
+
352
356
  if (lag > (max_event_loop_lag * 3)) {
353
357
  return true;
354
358
  }
@@ -357,6 +361,83 @@ Alchemy.setMethod(function isTooBusyForAjax() {
357
361
  return false;
358
362
  });
359
363
 
364
+ /**
365
+ * Set the maximum event loop lag before the server is considered overloaded
366
+ *
367
+ * @author Jelle De Loecker <jelle@elevenways.be>
368
+ * @since 1.3.18
369
+ * @version 1.3.18
370
+ *
371
+ * @param {Number} max_lag
372
+ */
373
+ Alchemy.setMethod(function setMaxEventLoopLag(max_lag) {
374
+
375
+ if (typeof max_lag != 'number' || !isFinite(max_lag)) {
376
+ max_lag = null;
377
+ }
378
+
379
+ if (max_lag == null) {
380
+ max_lag = 70;
381
+ }
382
+
383
+ this.settings.max_event_loop_lag = max_lag;
384
+ });
385
+
386
+ /**
387
+ * Called after the server has started
388
+ *
389
+ * @author Jelle De Loecker <jelle@elevenways.be>
390
+ * @since 1.3.17
391
+ * @version 1.3.17
392
+ */
393
+ Alchemy.setMethod(function afterStart() {
394
+ this.startTaskService();
395
+ });
396
+
397
+ let task_service_has_started = false;
398
+
399
+ /**
400
+ * Start the task service
401
+ *
402
+ * @author Jelle De Loecker <jelle@elevenways.be>
403
+ * @since 1.3.17
404
+ * @version 1.3.17
405
+ */
406
+ Alchemy.setMethod(function startTaskService() {
407
+
408
+ if (task_service_has_started) {
409
+ return;
410
+ }
411
+
412
+ task_service_has_started = true;
413
+
414
+ this.task_service = new Classes.Alchemy.Task.TaskService();
415
+ });
416
+
417
+ /**
418
+ * Is the given PID running?
419
+ *
420
+ * @author Jelle De Loecker <jelle@elevenways.be>
421
+ * @since 1.3.17
422
+ * @version 1.3.17
423
+ *
424
+ * @param {Number} pid
425
+ *
426
+ * @return {Boolean}
427
+ */
428
+ Alchemy.setMethod(function isProcessRunning(pid) {
429
+
430
+ if (!pid) {
431
+ return false;
432
+ }
433
+
434
+ try {
435
+ return process.kill(pid, 0);
436
+ } catch (e) {
437
+ return e.code === 'EPERM'
438
+ }
439
+ });
440
+
360
441
  /**
361
442
  * Start janeway
362
443
  *
@@ -441,6 +522,13 @@ Alchemy.setMethod(function startJaneway(options) {
441
522
  return session_menu.remove();
442
523
  }
443
524
 
525
+ session_menu.addItem({
526
+ title : 'Current active browser sessions:',
527
+ weight : Infinity,
528
+ }, () => {
529
+ console.log('All sessions:', alchemy.sessions);
530
+ });
531
+
444
532
  this.Janeway.session_menu = session_menu;
445
533
  }
446
534
 
@@ -522,7 +610,7 @@ Alchemy.setMethod(function printLog(level, args, options) {
522
610
  *
523
611
  * @author Jelle De Loecker <jelle@develry.be>
524
612
  * @since 0.4.0
525
- * @version 1.3.3
613
+ * @version 1.3.18
526
614
  */
527
615
  Alchemy.setMethod(function loadSettings() {
528
616
 
@@ -660,8 +748,10 @@ Alchemy.setMethod(function loadSettings() {
660
748
  settings.url = this.argv.url;
661
749
  }
662
750
 
663
- if (settings.url && settings.url.indexOf('{') > -1) {
664
- settings.url = settings.url.assign(settings);
751
+ this.setUrl(settings.url);
752
+
753
+ if (settings.cookie_domain) {
754
+ this.setCookieDomain(settings.cookie_domain);
665
755
  }
666
756
 
667
757
  if (this.argv.preload) {
@@ -714,10 +804,76 @@ Alchemy.setMethod(function loadSettings() {
714
804
  this.doPreload();
715
805
  }
716
806
 
807
+ this.setMaxEventLoopLag(settings.max_event_loop_lag);
808
+
717
809
  // Set the debug value
718
810
  global.DEBUG = settings.debug;
719
811
  });
720
812
 
813
+ /**
814
+ * Set the main url
815
+ *
816
+ * @author Jelle De Loecker <jelle@elevenways.be>
817
+ * @since 1.3.18
818
+ * @version 1.3.18
819
+ *
820
+ * @param {RURL|String} value
821
+ */
822
+ Alchemy.setMethod(function setUrl(value) {
823
+
824
+ if (value) {
825
+ value = ''+value;
826
+
827
+ if (value.indexOf('{') > -1) {
828
+ value = value.assign(this.settings);
829
+ }
830
+ }
831
+
832
+ this.settings.url = value;
833
+
834
+ if (this.settings.cookie_domain === true || this.settings.cookie_domain == null) {
835
+ this.setCookieDomain(value);
836
+ }
837
+ });
838
+
839
+ /**
840
+ * Set the cookie domain
841
+ *
842
+ * @author Jelle De Loecker <jelle@elevenways.be>
843
+ * @since 1.3.18
844
+ * @version 1.3.18
845
+ *
846
+ * @param {RURL|String} value
847
+ */
848
+ Alchemy.setMethod(function setCookieDomain(value) {
849
+
850
+ if (value === false) {
851
+ this.settings.cookie_domain = false;
852
+ return;
853
+ }
854
+
855
+ if (!value) {
856
+ value = this.settings.url;
857
+ }
858
+
859
+ if (!value) {
860
+ return;
861
+ }
862
+
863
+ value = ''+value;
864
+
865
+ if (value.indexOf('{') > -1) {
866
+ value = value.assign(this.settings);
867
+ }
868
+
869
+ if (value.indexOf('/') > -1) {
870
+ let url = RURL.parse(value);
871
+ value = url.hostname;
872
+ }
873
+
874
+ this.settings.cookie_domain = value;
875
+ });
876
+
721
877
  /**
722
878
  * Set status
723
879
  *
@@ -1051,7 +1207,7 @@ Alchemy.setMethod(function searchModule(startPath, moduleName, recurse) {
1051
1207
  *
1052
1208
  * @author Jelle De Loecker <jelle@develry.be>
1053
1209
  * @since 0.0.1
1054
- * @version 1.3.16
1210
+ * @version 1.3.17
1055
1211
  *
1056
1212
  * @param {String} moduleName
1057
1213
  * @param {Object} options
@@ -1183,10 +1339,22 @@ Alchemy.setMethod(function findModule(moduleName, options) {
1183
1339
  // Make sure this does not support CJS.
1184
1340
  // Some packages have the `module` type, but do have CJS exports too
1185
1341
  if (!supports_cjs) {
1186
- let exports = package_json.exports?.['.'];
1187
1342
 
1188
- if (exports?.require) {
1343
+ if (package_json.module && package_json.main) {
1189
1344
  supports_cjs = true;
1345
+ } else {
1346
+
1347
+ let exports = package_json.exports?.['.'];
1348
+
1349
+ if (Array.isArray(exports)) {
1350
+ for (let entry of exports) {
1351
+ if (entry && typeof entry == 'object' && entry.require) {
1352
+ supports_cjs = true;
1353
+ }
1354
+ }
1355
+ } else if (exports?.require) {
1356
+ supports_cjs = true;
1357
+ }
1190
1358
  }
1191
1359
  }
1192
1360
 
@@ -1573,7 +1741,7 @@ Alchemy.setMethod(function addAppcacheEntry(entry) {
1573
1741
  *
1574
1742
  * @author Jelle De Loecker <jelle@develry.be>
1575
1743
  * @since 1.1.0
1576
- * @version 1.3.0
1744
+ * @version 1.3.18
1577
1745
  *
1578
1746
  * @param {IncomingMessage} req
1579
1747
  * @param {OutgoingMessage} res Optional
@@ -1596,8 +1764,10 @@ Alchemy.setMethod(function parseRequestBody(req, res, callback) {
1596
1764
  return callback(null, req.body);
1597
1765
  }
1598
1766
 
1767
+ let content_type = req.headers['content-type'];
1768
+
1599
1769
  // Multipart data is handled by "formidable"
1600
- if (req.headers['content-type'] && req.headers['content-type'].startsWith('multipart/form-data')) {
1770
+ if (content_type && content_type.startsWith('multipart/form-data')) {
1601
1771
 
1602
1772
  let form = new formidable.IncomingForm({
1603
1773
  multiples : true,
@@ -1651,7 +1821,7 @@ Alchemy.setMethod(function parseRequestBody(req, res, callback) {
1651
1821
  }
1652
1822
 
1653
1823
  // Regular form-encoded data
1654
- if (req.headers['content-type'] && req.headers['content-type'].indexOf('form-urlencoded') > -1) {
1824
+ if (content_type && content_type.indexOf('form-urlencoded') > -1) {
1655
1825
 
1656
1826
  urlFormBody(req, res, function parsedBody(err) {
1657
1827
 
@@ -1682,25 +1852,36 @@ Alchemy.setMethod(function parseRequestBody(req, res, callback) {
1682
1852
  // Any other encoded data (like JSON)
1683
1853
  anyBody(req, function parsedBody(err, body) {
1684
1854
 
1685
- if (err && req.conduit && req.conduit.aborted) {
1686
- return callback(null);
1855
+ function handleResponse(err, body) {
1856
+ if (err && req.conduit && req.conduit.aborted) {
1857
+ return callback(null);
1858
+ }
1859
+
1860
+ // You can't send files using a regular post
1861
+ req.files = {};
1862
+
1863
+ if (err) {
1864
+ log.error('Error parsing body data', {err: err});
1865
+ req.body = {};
1866
+ } else {
1867
+ req.body = body;
1868
+
1869
+ if (conduit) {
1870
+ conduit.setRequestBody(body);
1871
+ }
1872
+ }
1873
+
1874
+ callback(null, req.body);
1687
1875
  }
1688
1876
 
1689
- // You can't send files using a regular post
1690
- req.files = {};
1691
-
1692
- if (err) {
1693
- log.error('Error parsing body data', {err: err});
1694
- req.body = {};
1695
- } else {
1696
- req.body = body;
1697
-
1698
- if (conduit) {
1699
- conduit.setRequestBody(body);
1877
+ if (err?.type == 'invalid.content.type') {
1878
+ if (!content_type || content_type.startsWith('text/')) {
1879
+ textBody(req, handleResponse);
1880
+ return;
1700
1881
  }
1701
1882
  }
1702
1883
 
1703
- callback(null, req.body);
1884
+ handleResponse(err, body);
1704
1885
  });
1705
1886
  });
1706
1887
 
@@ -2180,6 +2361,7 @@ log.todo = function todo(...args) {
2180
2361
 
2181
2362
  const anyBody = alchemy.use('body/any'),
2182
2363
  formBody = alchemy.use('body/form'),
2364
+ textBody = alchemy.use('body'),
2183
2365
  formidable = alchemy.use('formidable'),
2184
2366
  bodyParser = alchemy.use('body-parser'),
2185
2367
  urlFormBody = bodyParser.urlencoded({extended: true});
@@ -57,13 +57,6 @@ alchemy.hawkejs = Classes.Hawkejs.Hawkejs.getInstance();
57
57
  */
58
58
  alchemy.toobusy = alchemy.use('toobusy-js', 'toobusy');
59
59
 
60
- let max_event_loop_lag = alchemy.settings.max_event_loop_lag || alchemy.settings.toobusy;
61
-
62
- // If the config is a number, use that as the lag threshold
63
- if (typeof max_event_loop_lag === 'number') {
64
- alchemy.toobusy.maxLag(max_event_loop_lag);
65
- }
66
-
67
60
  /**
68
61
  * Load Sputnik, the stage-based launcher
69
62
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemymvc",
3
3
  "description": "MVC framework for Node.js",
4
- "version": "1.3.16",
4
+ "version": "1.3.18",
5
5
  "author": "Jelle De Loecker <jelle@elevenways.be>",
6
6
  "keywords": [
7
7
  "alchemy",
@@ -45,7 +45,7 @@
45
45
  "index.js"
46
46
  ],
47
47
  "optionalDependencies": {
48
- "janeway" : "~0.4.0",
48
+ "janeway" : "~0.4.2",
49
49
  "less" : "~4.2.0",
50
50
  "sass" : "~1.68.0",
51
51
  "sass-embedded" : "~1.67.0",