@reldens/utils 0.49.0 → 0.51.0
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/events-manager.js +324 -64
- package/lib/logger.js +13 -8
- package/lib/shortcuts.js +10 -0
- package/package.json +5 -4
- package/tests/events-manager-test.js +1084 -0
- package/tests/run.js +13 -0
package/lib/events-manager.js
CHANGED
|
@@ -2,55 +2,336 @@
|
|
|
2
2
|
*
|
|
3
3
|
* Reldens - EventsManager
|
|
4
4
|
*
|
|
5
|
-
* This extension includes a few new features:
|
|
6
|
-
*
|
|
7
|
-
* - The onWithKey and offWithKey methods will allow you to specify a "group" key for the event listener, the related
|
|
8
|
-
* event will be referenced in a new property called "eventsByRemoveKey" so you can detach multiple listeners at the
|
|
9
|
-
* time.
|
|
10
|
-
*
|
|
11
|
-
* - We override the "on" and "off" aliases override to include a debug check with a log. Using the debug property,
|
|
12
|
-
* you can specify to log "all" the fire and listeners, or just by key. Note the key search will be applied in both
|
|
13
|
-
* directions, it will check if the debug value exists in the event key or if the event key exists in the debug value.
|
|
14
|
-
*
|
|
15
5
|
*/
|
|
16
6
|
|
|
17
|
-
const AwaitEventEmitter = require('await-event-emitter').default;
|
|
18
7
|
const Logger = require('./logger');
|
|
19
8
|
const sc = require('./shortcuts');
|
|
20
9
|
|
|
21
|
-
class
|
|
10
|
+
class EventsManager
|
|
22
11
|
{
|
|
23
12
|
|
|
24
13
|
constructor()
|
|
25
14
|
{
|
|
26
|
-
|
|
15
|
+
this._events = {};
|
|
27
16
|
this.eventsByRemoveKeys = {};
|
|
28
17
|
this.debug = false;
|
|
18
|
+
this._listenersCache = {};
|
|
19
|
+
this._validationCache = new Map();
|
|
20
|
+
this._debugPatterns = null;
|
|
21
|
+
this.maxEventKeyLength = 1000;
|
|
22
|
+
this.maxListeners = 10000;
|
|
23
|
+
this.maxEventArgs = 50;
|
|
24
|
+
this.sensitiveFields = ['password', 'token', 'secret', 'key', 'auth', 'credential'];
|
|
25
|
+
this.hasLoggedMaxListeners = false;
|
|
26
|
+
this.symbolString = '--[[await-event-emitter]]--';
|
|
27
|
+
this.typeKeyName = sc.isFunction(Symbol) ? Symbol.for(this.symbolString) : this.symbolString;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
assertType(type)
|
|
31
|
+
{
|
|
32
|
+
if(!sc.isString(type) && !sc.isSymbol(type)){
|
|
33
|
+
throw new TypeError('type is not type of string or symbol!');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
assertFn(fn)
|
|
38
|
+
{
|
|
39
|
+
if(!sc.isFunction(fn)){
|
|
40
|
+
throw new TypeError('fn is not type of Function!');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
alwaysListener(fn)
|
|
45
|
+
{
|
|
46
|
+
return {
|
|
47
|
+
[this.typeKeyName]: 'always',
|
|
48
|
+
fn
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onceListener(fn)
|
|
53
|
+
{
|
|
54
|
+
return {
|
|
55
|
+
[this.typeKeyName]: 'once',
|
|
56
|
+
fn
|
|
57
|
+
};
|
|
29
58
|
}
|
|
30
59
|
|
|
31
60
|
validateEventKey(eventKey)
|
|
32
61
|
{
|
|
33
|
-
|
|
62
|
+
if(this._validationCache.has(eventKey)){
|
|
63
|
+
return this._validationCache.get(eventKey);
|
|
64
|
+
}
|
|
65
|
+
if(sc.isString(eventKey) && eventKey.length > this.maxEventKeyLength){
|
|
66
|
+
Logger.critical('Event key exceeds maximum length: '+eventKey.length);
|
|
67
|
+
this._validationCache.set(eventKey, false);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
let isValid = !sc.hasDangerousKeys(null, eventKey);
|
|
71
|
+
this._validationCache.set(eventKey, isValid);
|
|
72
|
+
return isValid;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
sanitizeEventArgs(args)
|
|
76
|
+
{
|
|
77
|
+
if(!sc.isArray(args)){
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
if(args.length > this.maxEventArgs){
|
|
81
|
+
Logger.warning('Event arguments exceed maximum: '+args.length);
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
return args.map(arg => {
|
|
85
|
+
if(sc.isObject(arg)){
|
|
86
|
+
return this.filterSensitiveData(arg);
|
|
87
|
+
}
|
|
88
|
+
return arg;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
filterSensitiveData(obj)
|
|
93
|
+
{
|
|
94
|
+
if(!sc.isObject(obj)){
|
|
95
|
+
return obj;
|
|
96
|
+
}
|
|
97
|
+
let filtered = {};
|
|
98
|
+
for(let key of Object.keys(obj)){
|
|
99
|
+
if(sc.hasDangerousKeys(null, key)){
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
let isKeywordSensitive = this.sensitiveFields.some(sensitive =>
|
|
103
|
+
key.toLowerCase().includes(sensitive.toLowerCase())
|
|
104
|
+
);
|
|
105
|
+
if(isKeywordSensitive){
|
|
106
|
+
filtered[key] = '[FILTERED]';
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if(sc.isObject(obj[key])){
|
|
110
|
+
filtered[key] = this.filterSensitiveData(obj[key]);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
filtered[key] = obj[key];
|
|
114
|
+
}
|
|
115
|
+
return filtered;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
checkMemoryLeaks()
|
|
119
|
+
{
|
|
120
|
+
if(this.hasLoggedMaxListeners){
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
let totalListeners = 0;
|
|
124
|
+
for(let eventType of Object.keys(this._events)){
|
|
125
|
+
totalListeners += this._events[eventType].length;
|
|
126
|
+
}
|
|
127
|
+
if(totalListeners > this.maxListeners){
|
|
128
|
+
Logger.debug('High listener count detected: '+totalListeners+' total listeners');
|
|
129
|
+
this.hasLoggedMaxListeners = true;
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
addListener(type, fn)
|
|
135
|
+
{
|
|
136
|
+
return this.on(type, fn);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
on(type, fn)
|
|
140
|
+
{
|
|
141
|
+
this.assertType(type);
|
|
142
|
+
this.assertFn(fn);
|
|
143
|
+
if(!this.validateEventKey(type)){
|
|
144
|
+
Logger.critical('Invalid event key detected: '+type);
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if(false !== this.debug){
|
|
148
|
+
this.logDebugEvent(type, 'Listen');
|
|
149
|
+
}
|
|
150
|
+
this._events[type] = this._events[type] || [];
|
|
151
|
+
this._events[type].push(this.alwaysListener(fn));
|
|
152
|
+
delete this._listenersCache[type];
|
|
153
|
+
this.checkMemoryLeaks();
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
prependListener(type, fn)
|
|
158
|
+
{
|
|
159
|
+
return this.prepend(type, fn);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
prepend(type, fn)
|
|
163
|
+
{
|
|
164
|
+
this.assertType(type);
|
|
165
|
+
this.assertFn(fn);
|
|
166
|
+
if(!this.validateEventKey(type)){
|
|
167
|
+
Logger.critical('Invalid event key detected: '+type);
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
this._events[type] = this._events[type] || [];
|
|
171
|
+
this._events[type].unshift(this.alwaysListener(fn));
|
|
172
|
+
delete this._listenersCache[type];
|
|
173
|
+
this.checkMemoryLeaks();
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
prependOnceListener(type, fn)
|
|
178
|
+
{
|
|
179
|
+
return this.prependOnce(type, fn);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
prependOnce(type, fn)
|
|
183
|
+
{
|
|
184
|
+
this.assertType(type);
|
|
185
|
+
this.assertFn(fn);
|
|
186
|
+
if(!this.validateEventKey(type)){
|
|
187
|
+
Logger.critical('Invalid event key detected: '+type);
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
this._events[type] = this._events[type] || [];
|
|
191
|
+
this._events[type].unshift(this.onceListener(fn));
|
|
192
|
+
delete this._listenersCache[type];
|
|
193
|
+
this.checkMemoryLeaks();
|
|
194
|
+
return this;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
listeners(type)
|
|
198
|
+
{
|
|
199
|
+
if(this._listenersCache[type]){
|
|
200
|
+
return this._listenersCache[type];
|
|
201
|
+
}
|
|
202
|
+
let result = (this._events[type] || []).map((x) => x.fn);
|
|
203
|
+
this._listenersCache[type] = result;
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
once(type, fn)
|
|
208
|
+
{
|
|
209
|
+
this.assertType(type);
|
|
210
|
+
this.assertFn(fn);
|
|
211
|
+
if(!this.validateEventKey(type)){
|
|
212
|
+
Logger.critical('Invalid event key detected: '+type);
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
this._events[type] = this._events[type] || [];
|
|
216
|
+
this._events[type].push(this.onceListener(fn));
|
|
217
|
+
delete this._listenersCache[type];
|
|
218
|
+
this.checkMemoryLeaks();
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
removeAllListeners()
|
|
223
|
+
{
|
|
224
|
+
this._events = {};
|
|
225
|
+
this._listenersCache = {};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
off(type, nullOrFn)
|
|
229
|
+
{
|
|
230
|
+
return this.removeListener(type, nullOrFn);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
removeListener(type, nullOrFn)
|
|
234
|
+
{
|
|
235
|
+
this.assertType(type);
|
|
236
|
+
if(!this.validateEventKey(type)){
|
|
237
|
+
Logger.critical('Invalid event key detected: '+type);
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
let listeners = this.listeners(type);
|
|
241
|
+
if(sc.isFunction(nullOrFn)){
|
|
242
|
+
let index = -1;
|
|
243
|
+
let found = false;
|
|
244
|
+
while(-1 < (index = listeners.indexOf(nullOrFn))){
|
|
245
|
+
listeners.splice(index, 1);
|
|
246
|
+
this._events[type].splice(index, 1);
|
|
247
|
+
found = true;
|
|
248
|
+
}
|
|
249
|
+
delete this._listenersCache[type];
|
|
250
|
+
return found;
|
|
251
|
+
}
|
|
252
|
+
delete this._events[type];
|
|
253
|
+
delete this._listenersCache[type];
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async emit(type, ...args)
|
|
258
|
+
{
|
|
259
|
+
this.assertType(type);
|
|
260
|
+
if(!this.validateEventKey(type)){
|
|
261
|
+
Logger.critical('Invalid event key detected: '+type);
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
let sanitizedArgs = this.sanitizeEventArgs(args);
|
|
265
|
+
if(false !== this.debug){
|
|
266
|
+
this.logDebugEvent(type, 'Fire', sanitizedArgs);
|
|
267
|
+
}
|
|
268
|
+
this.checkMemoryLeaks();
|
|
269
|
+
let listeners = this.listeners(type);
|
|
270
|
+
let onceListeners = [];
|
|
271
|
+
if(listeners && listeners.length){
|
|
272
|
+
for(let i = 0; i < listeners.length; i++){
|
|
273
|
+
let event = listeners[i];
|
|
274
|
+
let rlt = event.apply(this, sanitizedArgs);
|
|
275
|
+
if(sc.isPromise(rlt)){
|
|
276
|
+
await rlt;
|
|
277
|
+
}
|
|
278
|
+
if(this._events[type] && this._events[type][i] && 'once' === this._events[type][i][this.typeKeyName]){
|
|
279
|
+
onceListeners.push(event);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
for(let event of onceListeners){
|
|
283
|
+
this.removeListener(type, event);
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
emitSync(type, ...args)
|
|
291
|
+
{
|
|
292
|
+
this.assertType(type);
|
|
293
|
+
if(!this.validateEventKey(type)){
|
|
294
|
+
Logger.critical('Invalid event key detected: '+type);
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
let sanitizedArgs = this.sanitizeEventArgs(args);
|
|
298
|
+
let listeners = this.listeners(type);
|
|
299
|
+
let onceListeners = [];
|
|
300
|
+
if(listeners && listeners.length){
|
|
301
|
+
for(let i = 0; i < listeners.length; i++){
|
|
302
|
+
let event = listeners[i];
|
|
303
|
+
event.apply(this, sanitizedArgs);
|
|
304
|
+
if(this._events[type] && this._events[type][i] && 'once' === this._events[type][i][this.typeKeyName]){
|
|
305
|
+
onceListeners.push(event);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
for(let event of onceListeners){
|
|
309
|
+
this.removeListener(type, event);
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
return false;
|
|
34
314
|
}
|
|
35
315
|
|
|
36
316
|
onWithKey(eventName, callback, uniqueRemoveKey, masterKey)
|
|
37
317
|
{
|
|
38
|
-
if(!this.validateEventKey(eventName)
|
|
39
|
-
Logger.critical('Invalid event key detected: '+eventName
|
|
318
|
+
if(!this.validateEventKey(eventName)){
|
|
319
|
+
Logger.critical('Invalid event key detected: '+eventName);
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
if(!this.validateEventKey(uniqueRemoveKey)){
|
|
323
|
+
Logger.critical('Invalid remove key detected: '+uniqueRemoveKey);
|
|
40
324
|
return false;
|
|
41
325
|
}
|
|
42
326
|
if(masterKey && !this.validateEventKey(masterKey)){
|
|
43
327
|
Logger.critical('Invalid master key detected: '+masterKey);
|
|
44
328
|
return false;
|
|
45
329
|
}
|
|
46
|
-
if(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
&& sc.hasOwn(this.eventsByRemoveKeys[masterKey], uniqueRemoveKey)
|
|
52
|
-
)
|
|
53
|
-
){
|
|
330
|
+
if(sc.hasOwn(this.eventsByRemoveKeys, uniqueRemoveKey)){
|
|
331
|
+
Logger.debug('Event "'+eventName+'" exists with key "'+uniqueRemoveKey+'".');
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
if(masterKey && sc.hasOwn(this.eventsByRemoveKeys, masterKey) && sc.hasOwn(this.eventsByRemoveKeys[masterKey], uniqueRemoveKey)){
|
|
54
335
|
Logger.debug('Event "'+eventName+'" exists with key "'+uniqueRemoveKey+'" and masterKey "'+masterKey+'".');
|
|
55
336
|
return false;
|
|
56
337
|
}
|
|
@@ -69,10 +350,6 @@ class AwaitEventEmitterExtended extends AwaitEventEmitter
|
|
|
69
350
|
return currentListener;
|
|
70
351
|
}
|
|
71
352
|
|
|
72
|
-
/**
|
|
73
|
-
* This method will remove a SINGLE event using the unique remove key.
|
|
74
|
-
* If the event listener was assigned using a masterKey then we need to pass it as well to find the event.
|
|
75
|
-
*/
|
|
76
353
|
offWithKey(uniqueRemoveKey, masterKey)
|
|
77
354
|
{
|
|
78
355
|
if(!this.validateEventKey(uniqueRemoveKey)){
|
|
@@ -109,6 +386,7 @@ class AwaitEventEmitterExtended extends AwaitEventEmitter
|
|
|
109
386
|
if(0 === this._events[eventToRemove.eventName].length){
|
|
110
387
|
delete this._events[eventToRemove.eventName];
|
|
111
388
|
}
|
|
389
|
+
delete this._listenersCache[eventToRemove.eventName];
|
|
112
390
|
if(masterKey){
|
|
113
391
|
delete this.eventsByRemoveKeys[masterKey][uniqueRemoveKey];
|
|
114
392
|
Logger.debug('Deleted event by removeKey "'+uniqueRemoveKey+'" and masterKey "'+masterKey+'".');
|
|
@@ -119,9 +397,6 @@ class AwaitEventEmitterExtended extends AwaitEventEmitter
|
|
|
119
397
|
return true;
|
|
120
398
|
}
|
|
121
399
|
|
|
122
|
-
/**
|
|
123
|
-
* This method will remove ALL the events below the specified masterKey.
|
|
124
|
-
*/
|
|
125
400
|
offByMasterKey(masterKey)
|
|
126
401
|
{
|
|
127
402
|
if(!this.validateEventKey(masterKey)){
|
|
@@ -132,14 +407,15 @@ class AwaitEventEmitterExtended extends AwaitEventEmitter
|
|
|
132
407
|
Logger.debug('Events not found by masterKey "'+masterKey+'".');
|
|
133
408
|
return false;
|
|
134
409
|
}
|
|
135
|
-
// @NOTE: we loop all the events related to the masterKey and remove them one by one since the _events property
|
|
136
|
-
// is an object with multiple listeners attached.
|
|
137
410
|
Logger.debug('Removing events by masterKey: '+masterKey, Object.keys(this.eventsByRemoveKeys[masterKey]));
|
|
138
|
-
|
|
411
|
+
let eventsToRemove = Object.keys(this.eventsByRemoveKeys[masterKey]);
|
|
412
|
+
let affectedEvents = new Set();
|
|
413
|
+
for(let uniqueRemoveKey of eventsToRemove){
|
|
139
414
|
let eventToRemove = this.eventsByRemoveKeys[masterKey][uniqueRemoveKey];
|
|
140
415
|
if(!this.validateEventKey(eventToRemove.eventName)){
|
|
141
416
|
continue;
|
|
142
417
|
}
|
|
418
|
+
affectedEvents.add(eventToRemove.eventName);
|
|
143
419
|
let dataArr = this.listeners(eventToRemove.eventName);
|
|
144
420
|
let currentListenerIndex = dataArr.indexOf(eventToRemove.callback);
|
|
145
421
|
if(-1 === currentListenerIndex){
|
|
@@ -150,44 +426,28 @@ class AwaitEventEmitterExtended extends AwaitEventEmitter
|
|
|
150
426
|
delete this._events[eventToRemove.eventName];
|
|
151
427
|
}
|
|
152
428
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
on(key, callback)
|
|
157
|
-
{
|
|
158
|
-
if(!this.validateEventKey(key)){
|
|
159
|
-
Logger.critical('Invalid event key detected: '+key);
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
162
|
-
if(false !== this.debug){
|
|
163
|
-
this.logDebugEvent(key, 'Listen');
|
|
429
|
+
for(let eventName of affectedEvents){
|
|
430
|
+
delete this._listenersCache[eventName];
|
|
164
431
|
}
|
|
165
|
-
|
|
432
|
+
delete this.eventsByRemoveKeys[masterKey];
|
|
166
433
|
}
|
|
167
434
|
|
|
168
|
-
|
|
435
|
+
logDebugEvent(key, type, args = null)
|
|
169
436
|
{
|
|
170
|
-
if(!this.
|
|
171
|
-
|
|
172
|
-
return false;
|
|
437
|
+
if(!this._debugPatterns){
|
|
438
|
+
this._debugPatterns = new Set(this.debug.split(','));
|
|
173
439
|
}
|
|
174
|
-
if(
|
|
175
|
-
|
|
440
|
+
if(!this._debugPatterns.has('all') && !this._debugPatterns.has(key) && -1 === key.indexOf(this.debug)){
|
|
441
|
+
return;
|
|
176
442
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
{
|
|
182
|
-
if(
|
|
183
|
-
-1 !== this.debug.indexOf('all')
|
|
184
|
-
|| -1 !== this.debug.indexOf(key)
|
|
185
|
-
|| -1 !== key.indexOf(this.debug)
|
|
186
|
-
){
|
|
187
|
-
Logger.debug(type+' Event:', key);
|
|
443
|
+
let logMessage = type+' Event: '+key;
|
|
444
|
+
if(args && 0 < args.length){
|
|
445
|
+
let filteredArgs = args.map(arg => this.filterSensitiveData(arg));
|
|
446
|
+
logMessage += ' with '+filteredArgs.length+' arguments';
|
|
188
447
|
}
|
|
448
|
+
Logger.debug(logMessage);
|
|
189
449
|
}
|
|
190
450
|
|
|
191
451
|
}
|
|
192
452
|
|
|
193
|
-
module.exports =
|
|
453
|
+
module.exports = EventsManager;
|
package/lib/logger.js
CHANGED
|
@@ -29,14 +29,13 @@ class Logger
|
|
|
29
29
|
this.callback = false;
|
|
30
30
|
this.forcedDisabled = Boolean(sc.get(context, 'RELDENS_LOGS_FORCED_DISABLED', false));
|
|
31
31
|
this.addTimeStamp = Boolean(sc.get(context, 'RELDENS_LOGS_INCLUDE_TIMESTAMP', true));
|
|
32
|
-
this.maxLogArgLength = sc.get(context, 'RELDENS_LOGS_MAX_ARGUMENT_LENGTH',
|
|
33
|
-
this.maxStackTraceLength = sc.get(context, 'RELDENS_LOGS_MAX_STACK_TRACE_LENGTH',
|
|
32
|
+
this.maxLogArgLength = sc.get(context, 'RELDENS_LOGS_MAX_ARGUMENT_LENGTH', 0);
|
|
33
|
+
this.maxStackTraceLength = sc.get(context, 'RELDENS_LOGS_MAX_STACK_TRACE_LENGTH', 0);
|
|
34
|
+
this.applySanitizer = Boolean(sc.get(context, 'RELDENS_LOGS_APPLY_SANITIZER', false));
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
context()
|
|
37
38
|
{
|
|
38
|
-
// @NOTE: any change on this method could break Parcel and you will end up with the following error.
|
|
39
|
-
// Failed to resolve module specifier "process"
|
|
40
39
|
let context = process.env;
|
|
41
40
|
if('undefined' !== typeof window){
|
|
42
41
|
return window;
|
|
@@ -95,8 +94,11 @@ class Logger
|
|
|
95
94
|
log(levelLabel, ...args)
|
|
96
95
|
{
|
|
97
96
|
let date = !this.addTimeStamp ? '' : (new Date()).toISOString().slice(0, 19).replace('T', ' ')+' - ';
|
|
98
|
-
let
|
|
99
|
-
this.
|
|
97
|
+
let processedArgs = args;
|
|
98
|
+
if(this.applySanitizer){
|
|
99
|
+
processedArgs = args.map(arg => sc.isString(arg) ? sc.cleanMessage(arg, this.maxLogArgLength) : arg);
|
|
100
|
+
}
|
|
101
|
+
this.logWithCallback(date+levelLabel.toUpperCase()+' -', ...processedArgs);
|
|
100
102
|
if(-1 !== this.enableTraceFor().indexOf('all') || -1 !== this.enableTraceFor().indexOf(levelLabel)){
|
|
101
103
|
if('function' !== typeof Error?.captureStackTrace){
|
|
102
104
|
this.logWithCallback('Error.captureStackTrace is not available.', typeof Error?.captureStackTrace);
|
|
@@ -104,8 +106,11 @@ class Logger
|
|
|
104
106
|
}
|
|
105
107
|
let stackHolder = {};
|
|
106
108
|
Error.captureStackTrace(stackHolder, levelLabel);
|
|
107
|
-
let
|
|
108
|
-
this.
|
|
109
|
+
let processedStack = stackHolder.stack;
|
|
110
|
+
if(this.applySanitizer){
|
|
111
|
+
processedStack = sc.cleanMessage(stackHolder.stack, this.maxStackTraceLength);
|
|
112
|
+
}
|
|
113
|
+
this.logWithCallback(processedStack);
|
|
109
114
|
}
|
|
110
115
|
return this;
|
|
111
116
|
}
|
package/lib/shortcuts.js
CHANGED
|
@@ -62,6 +62,11 @@ class Shortcuts
|
|
|
62
62
|
return this.isObject(obj) && property && 'function' === typeof obj[property];
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
isSymbol(value)
|
|
66
|
+
{
|
|
67
|
+
return 'symbol' === typeof value;
|
|
68
|
+
}
|
|
69
|
+
|
|
65
70
|
isString(value)
|
|
66
71
|
{
|
|
67
72
|
return 'string' === typeof value;
|
|
@@ -93,6 +98,11 @@ class Shortcuts
|
|
|
93
98
|
return 'boolean' === typeof value;
|
|
94
99
|
}
|
|
95
100
|
|
|
101
|
+
isPromise(value)
|
|
102
|
+
{
|
|
103
|
+
return value && 'function' === typeof value.then;
|
|
104
|
+
}
|
|
105
|
+
|
|
96
106
|
hasDangerousKeys(obj, key = null)
|
|
97
107
|
{
|
|
98
108
|
let dangerousKeys = ['__proto__', 'constructor', 'prototype'];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reldens/utils",
|
|
3
3
|
"scope": "@reldens",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.51.0",
|
|
5
5
|
"description": "Reldens - Utils",
|
|
6
6
|
"author": "Damian A. Pastorini",
|
|
7
7
|
"license": "MIT",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/damian-pastorini/reldens-utils/issues"
|
|
36
36
|
},
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
}
|
|
37
|
+
"scripts": {
|
|
38
|
+
"test": "node tests/run.js"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {}
|
|
40
41
|
}
|