alchemymvc 1.4.0-alpha.10 → 1.4.0-alpha.12
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/socket_conduit.js +21 -1
- package/lib/app/element/al_time.js +126 -0
- package/lib/class/conduit.js +79 -1
- package/lib/core/alchemy.js +50 -0
- package/lib/scripts/create_settings.js +33 -0
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ var iostream = alchemy.use('socket.io-stream'),
|
|
|
6
6
|
*
|
|
7
7
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
8
8
|
* @since 0.2.0
|
|
9
|
-
* @version 1.
|
|
9
|
+
* @version 1.4.0
|
|
10
10
|
*
|
|
11
11
|
* @param {Socker} socket
|
|
12
12
|
* @param {Object} announcement
|
|
@@ -25,6 +25,10 @@ var SocketConduit = Function.inherits('Alchemy.Conduit', function Socket(socket,
|
|
|
25
25
|
// Store the announcement data
|
|
26
26
|
this.announcement = announcement;
|
|
27
27
|
|
|
28
|
+
if (!this.canCreateSocketConnection()) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
// Detect node clients
|
|
29
33
|
if (this.headers['user-agent'] == 'node-XMLHttpRequest') {
|
|
30
34
|
this.isNodeClient = true;
|
|
@@ -145,6 +149,22 @@ SocketConduit.setProperty(function is_connected() {
|
|
|
145
149
|
return this.socket?.connected || false;
|
|
146
150
|
});
|
|
147
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Is this client allowed to create a socket connection?
|
|
154
|
+
*
|
|
155
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
156
|
+
* @since 1.4.0
|
|
157
|
+
* @version 1.4.0
|
|
158
|
+
*/
|
|
159
|
+
SocketConduit.setMethod(function canCreateSocketConnection() {
|
|
160
|
+
|
|
161
|
+
if (this.isCrawler()) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return true;
|
|
166
|
+
});
|
|
167
|
+
|
|
148
168
|
/**
|
|
149
169
|
* Parse the request, get information from the url
|
|
150
170
|
*
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const DATETIME = Symbol('datetime');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The custom al-time element
|
|
5
|
+
*
|
|
6
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
7
|
+
* @since 1.4.0
|
|
8
|
+
* @version 1.4.0
|
|
9
|
+
*/
|
|
10
|
+
const AlTime = Function.inherits('Alchemy.Element', 'AlTime');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The preferred format
|
|
14
|
+
*
|
|
15
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
16
|
+
* @since 0.3.0
|
|
17
|
+
* @version 0.3.0
|
|
18
|
+
*/
|
|
19
|
+
AlTime.setAttribute('format', null, function setFormat(format) {
|
|
20
|
+
this._populate({value: this.datetime, format: format});
|
|
21
|
+
return format;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get/set the datetime value
|
|
26
|
+
*
|
|
27
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
28
|
+
* @since 0.3.0
|
|
29
|
+
* @version 0.3.0
|
|
30
|
+
*/
|
|
31
|
+
AlTime.setAttribute('datetime', null, function setDatetime(value) {
|
|
32
|
+
this._populate({value: value});
|
|
33
|
+
return this[DATETIME];
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Set the value with a function call
|
|
38
|
+
*
|
|
39
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
40
|
+
* @since 0.3.0
|
|
41
|
+
* @version 0.3.0
|
|
42
|
+
*/
|
|
43
|
+
AlTime.setMethod(function setDatetime(value) {
|
|
44
|
+
this.datetime = value;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Populate the element
|
|
49
|
+
*
|
|
50
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
51
|
+
* @since 0.3.0
|
|
52
|
+
* @version 0.3.0
|
|
53
|
+
*
|
|
54
|
+
* @return {Object[]}
|
|
55
|
+
*/
|
|
56
|
+
AlTime.setMethod(function populate() {
|
|
57
|
+
let iso_string = this._populate({value: this.value, format: this.format});
|
|
58
|
+
this[DATETIME] = iso_string;
|
|
59
|
+
return iso_string;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Populate the element
|
|
64
|
+
*
|
|
65
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
66
|
+
* @since 0.3.0
|
|
67
|
+
* @version 0.3.0
|
|
68
|
+
*/
|
|
69
|
+
AlTime.setMethod(function _populate(input) {
|
|
70
|
+
|
|
71
|
+
if (!input) {
|
|
72
|
+
input = {};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let {value, format} = input;
|
|
76
|
+
|
|
77
|
+
if (value == null) {
|
|
78
|
+
value = this[DATETIME];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (format == null) {
|
|
82
|
+
format = this.format;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let iso_date,
|
|
86
|
+
date;
|
|
87
|
+
|
|
88
|
+
if (value) {
|
|
89
|
+
date = Date.create(value);
|
|
90
|
+
iso_date = date.toISOString();
|
|
91
|
+
} else {
|
|
92
|
+
iso_date = '';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
value = iso_date;
|
|
96
|
+
|
|
97
|
+
if (Blast.isServer) {
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let target_element = this.children?.[0];
|
|
102
|
+
|
|
103
|
+
if (!target_element) {
|
|
104
|
+
target_element = this.createElement('time');
|
|
105
|
+
this.append(target_element);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let tag_name = target_element.tagName;
|
|
109
|
+
let formatted;
|
|
110
|
+
|
|
111
|
+
if (format) {
|
|
112
|
+
formatted = date.format(format);
|
|
113
|
+
} else {
|
|
114
|
+
formatted = date + '';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (tag_name == 'INPUT') {
|
|
118
|
+
target_element.value = formatted;
|
|
119
|
+
} else {
|
|
120
|
+
if (tag_name == 'TIME') {
|
|
121
|
+
target_element.setAttribute('datetime', iso_date);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
target_element.textContent = formatted;
|
|
125
|
+
}
|
|
126
|
+
});
|
package/lib/class/conduit.js
CHANGED
|
@@ -447,7 +447,7 @@ Conduit.setMethod(function setReqRes(req, res) {
|
|
|
447
447
|
*
|
|
448
448
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
449
449
|
* @since 0.3.3
|
|
450
|
-
* @version 1.
|
|
450
|
+
* @version 1.4.0
|
|
451
451
|
*/
|
|
452
452
|
Conduit.setMethod(function initValues() {
|
|
453
453
|
|
|
@@ -493,6 +493,9 @@ Conduit.setMethod(function initValues() {
|
|
|
493
493
|
|
|
494
494
|
// Make sure the tested routes are reset
|
|
495
495
|
this[TESTED_ROUTES] = null;
|
|
496
|
+
|
|
497
|
+
// Is this a crawler?
|
|
498
|
+
this.is_crawler = null;
|
|
496
499
|
});
|
|
497
500
|
|
|
498
501
|
/**
|
|
@@ -2383,6 +2386,13 @@ Conduit.setMethod(function getSession(allow_create = true) {
|
|
|
2383
2386
|
return this.session_instance;
|
|
2384
2387
|
}
|
|
2385
2388
|
|
|
2389
|
+
if (this.isCrawler()) {
|
|
2390
|
+
// Create a dummy non-persistent session for crawlers
|
|
2391
|
+
let session = new Classes.Alchemy.ClientSession(this);
|
|
2392
|
+
this.session_instance = session;
|
|
2393
|
+
return session;
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2386
2396
|
let cookie_name = this.session_cookie_name,
|
|
2387
2397
|
session_id,
|
|
2388
2398
|
session;
|
|
@@ -2771,6 +2781,74 @@ Conduit.setMethod(function supports(feature) {
|
|
|
2771
2781
|
return null;
|
|
2772
2782
|
});
|
|
2773
2783
|
|
|
2784
|
+
/**
|
|
2785
|
+
* Is the connecting client a crawler?
|
|
2786
|
+
*
|
|
2787
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
2788
|
+
* @since 1.4.0
|
|
2789
|
+
* @version 1.4.0
|
|
2790
|
+
*
|
|
2791
|
+
* @return {boolean}
|
|
2792
|
+
*/
|
|
2793
|
+
Conduit.setMethod(function isCrawler() {
|
|
2794
|
+
|
|
2795
|
+
if (this.is_crawler == null) {
|
|
2796
|
+
let ua = this.useragent;
|
|
2797
|
+
let is_crawler = false;
|
|
2798
|
+
|
|
2799
|
+
if (ua) {
|
|
2800
|
+
let device = ua.device?.family;
|
|
2801
|
+
|
|
2802
|
+
// The Useragent parser already detects a lot of spiders/crawlers
|
|
2803
|
+
if (device == 'Spider') {
|
|
2804
|
+
is_crawler = true;
|
|
2805
|
+
} else {
|
|
2806
|
+
let family = String(ua.family);
|
|
2807
|
+
|
|
2808
|
+
if (family == 'Chrome'
|
|
2809
|
+
|| family == 'Firefox'
|
|
2810
|
+
|| family == 'Safari'
|
|
2811
|
+
|| family == 'Mobile Safari'
|
|
2812
|
+
|| family == 'Chrome Mobile'
|
|
2813
|
+
) {
|
|
2814
|
+
// Ignore
|
|
2815
|
+
} else {
|
|
2816
|
+
family = family.toLowerCase();
|
|
2817
|
+
|
|
2818
|
+
if (family == 'other') {
|
|
2819
|
+
let source = ua.source.toLowerCase();
|
|
2820
|
+
|
|
2821
|
+
if (
|
|
2822
|
+
source.includes('perplexity')
|
|
2823
|
+
|| source.includes('www.you.com')
|
|
2824
|
+
|| source.includes(' youbot ')
|
|
2825
|
+
|| source.includes('google')
|
|
2826
|
+
|| source.includes('python')
|
|
2827
|
+
|| source.includes('httpunit')
|
|
2828
|
+
|| source.includes('go-http')
|
|
2829
|
+
) {
|
|
2830
|
+
is_crawler = true;
|
|
2831
|
+
}
|
|
2832
|
+
} else if (family == 'gptbot'
|
|
2833
|
+
|| family == 'linkedinbot'
|
|
2834
|
+
|| family == 'wget'
|
|
2835
|
+
|| family == 'libwww-perl'
|
|
2836
|
+
|| family.includes('google')
|
|
2837
|
+
|| family.includes('python')
|
|
2838
|
+
|| family.includes('yandex')
|
|
2839
|
+
) {
|
|
2840
|
+
is_crawler = true;
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2846
|
+
this.is_crawler = is_crawler;
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2849
|
+
return this.is_crawler;
|
|
2850
|
+
});
|
|
2851
|
+
|
|
2774
2852
|
/**
|
|
2775
2853
|
* Should this request be delayed because the server is too busy?
|
|
2776
2854
|
* This performs an early check, the controller might also check this later.
|
package/lib/core/alchemy.js
CHANGED
|
@@ -1549,6 +1549,56 @@ Alchemy.setMethod(function getCache(name, options) {
|
|
|
1549
1549
|
return instance;
|
|
1550
1550
|
});
|
|
1551
1551
|
|
|
1552
|
+
/**
|
|
1553
|
+
* Prune all the caches
|
|
1554
|
+
*
|
|
1555
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1556
|
+
* @since 1.4.0
|
|
1557
|
+
* @version 1.4.0
|
|
1558
|
+
*/
|
|
1559
|
+
Alchemy.setMethod(function pruneCaches(force_log = true) {
|
|
1560
|
+
|
|
1561
|
+
let checked = 0,
|
|
1562
|
+
pruned = 0;
|
|
1563
|
+
|
|
1564
|
+
let do_log;
|
|
1565
|
+
|
|
1566
|
+
if (force_log === 'auto') {
|
|
1567
|
+
do_log = alchemy.settings.debugging.debug;
|
|
1568
|
+
} else {
|
|
1569
|
+
do_log = force_log;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
for (let key in this.caches) {
|
|
1573
|
+
let cache = this.caches[key];
|
|
1574
|
+
|
|
1575
|
+
if (!cache) {
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
checked++;
|
|
1580
|
+
let old_length = cache.length;
|
|
1581
|
+
|
|
1582
|
+
for (let entry of cache) {
|
|
1583
|
+
// This triggers a check of all the entries
|
|
1584
|
+
// @TODO: Use cache.prune() instead, which will be fixed in next Protoblast version
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
let new_length = cache.length;
|
|
1588
|
+
|
|
1589
|
+
if (new_length != old_length) {
|
|
1590
|
+
pruned++;
|
|
1591
|
+
if (do_log) {
|
|
1592
|
+
console.log('Pruned cache', cache, 'from', old_length, 'to', new_length);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
if (do_log) {
|
|
1598
|
+
console.log('Checked', checked, 'caches and pruned', pruned, 'of them');
|
|
1599
|
+
}
|
|
1600
|
+
});
|
|
1601
|
+
|
|
1552
1602
|
/**
|
|
1553
1603
|
* Get a route
|
|
1554
1604
|
*
|
|
@@ -186,6 +186,39 @@ performance.addSetting('janeway_lag_menu', {
|
|
|
186
186
|
},
|
|
187
187
|
});
|
|
188
188
|
|
|
189
|
+
let prune_cache_interval_id = null;
|
|
190
|
+
|
|
191
|
+
performance.addSetting('prune_cache', {
|
|
192
|
+
type : 'string',
|
|
193
|
+
default : '20 minutes',
|
|
194
|
+
description : 'Prune all the caches at a regular interval',
|
|
195
|
+
action : (value, value_instance) => {
|
|
196
|
+
|
|
197
|
+
if (prune_cache_interval_id != null) {
|
|
198
|
+
clearInterval(prune_cache_interval_id);
|
|
199
|
+
prune_cache_interval_id = null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!value) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let duration_in_ms = Date.parseDuration(value);
|
|
207
|
+
|
|
208
|
+
if (!duration_in_ms) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (duration_in_ms < 5000) {
|
|
213
|
+
duration_in_ms = 5000;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
prune_cache_interval_id = setInterval(() => {
|
|
217
|
+
alchemy.pruneCaches('auto');
|
|
218
|
+
}, duration_in_ms);
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
189
222
|
const debugging = system.createGroup('debugging');
|
|
190
223
|
|
|
191
224
|
debugging.addSetting('debug', {
|