@pryv/boiler 1.2.3 → 1.2.5
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/LICENSE +1 -1
- package/examples/customLogger/src/index.js +14 -10
- package/package.json +2 -2
- package/src/config.js +58 -70
- package/src/index.d.ts +210 -0
- package/src/index.js +3 -3
- package/src/logging.js +78 -75
package/LICENSE
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* [BSD-3-Clause](https://github.com/pryv/pryv-boiler/blob/master/LICENSE)
|
|
4
|
+
*/
|
|
1
5
|
|
|
2
|
-
module.exports = {
|
|
3
|
-
init,
|
|
6
|
+
module.exports = {
|
|
7
|
+
init,
|
|
4
8
|
log
|
|
5
|
-
}
|
|
9
|
+
};
|
|
6
10
|
|
|
7
|
-
async function init(settings) {
|
|
11
|
+
async function init (settings) {
|
|
8
12
|
console.log('CUSTOM LOGGER initilaized with', settings);
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
16
|
+
*
|
|
13
17
|
* @param {string} level one of 'debug', 'info', 'warn', 'error'
|
|
14
18
|
* @param {string} key ':' namespaced keys
|
|
15
|
-
* @param {message} message
|
|
16
|
-
* @param {object} meta
|
|
19
|
+
* @param {message} message
|
|
20
|
+
* @param {object} meta
|
|
17
21
|
*/
|
|
18
|
-
function log(level, key, text, meta) {
|
|
19
|
-
console.log('Custom: ' + JSON.stringify({level, key, text, meta}));
|
|
20
|
-
}
|
|
22
|
+
function log (level, key, text, meta) {
|
|
23
|
+
console.log('Custom: ' + JSON.stringify({ level, key, text, meta }));
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pryv/boiler",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Logging and config boilerplate library for Node.js apps and services at Pryv",
|
|
6
6
|
"keywords": [
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"license": "BSD-3-Clause",
|
|
20
20
|
"author": "Pryv S.A <info@pryv.com> (https://pryv.com)",
|
|
21
21
|
"main": "src/index",
|
|
22
|
+
"types": "src/index.d.ts",
|
|
22
23
|
"scripts": {
|
|
23
24
|
"license": "source-licenser -c .licenser.yml .",
|
|
24
25
|
"lint": "semistandard"
|
|
@@ -27,7 +28,6 @@
|
|
|
27
28
|
"debug": "^4.3.4",
|
|
28
29
|
"js-yaml": "^4.1.0",
|
|
29
30
|
"nconf": "^0.12.0",
|
|
30
|
-
"superagent": "^8.0.9",
|
|
31
31
|
"winston": "^3.9.0",
|
|
32
32
|
"winston-daily-rotate-file": "^4.7.1"
|
|
33
33
|
},
|
package/src/config.js
CHANGED
|
@@ -24,8 +24,6 @@ const path = require('path');
|
|
|
24
24
|
const nconf = require('nconf');
|
|
25
25
|
nconf.formats.yaml = require('./lib/nconf-yaml');
|
|
26
26
|
|
|
27
|
-
const superagent = require('superagent');
|
|
28
|
-
|
|
29
27
|
/**
|
|
30
28
|
* Default values for Logger
|
|
31
29
|
*/
|
|
@@ -50,8 +48,6 @@ const defaults = {
|
|
|
50
48
|
}
|
|
51
49
|
};
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
51
|
/**
|
|
56
52
|
* Config manager
|
|
57
53
|
*/
|
|
@@ -62,7 +58,7 @@ class Config {
|
|
|
62
58
|
baseConfigDir;
|
|
63
59
|
learnDirectoryAndFilename;
|
|
64
60
|
|
|
65
|
-
constructor() {
|
|
61
|
+
constructor () {
|
|
66
62
|
this.extraAsync = [];
|
|
67
63
|
}
|
|
68
64
|
|
|
@@ -78,7 +74,7 @@ class Config {
|
|
|
78
74
|
* @param {Object} logging
|
|
79
75
|
* @returns {Config} this
|
|
80
76
|
*/
|
|
81
|
-
initSync(options, logging) {
|
|
77
|
+
initSync (options, logging) {
|
|
82
78
|
this.appName = options.appName;
|
|
83
79
|
this.learnDirectoryAndFilename = getLearnFilename(options.appName, options.learnDirectory);
|
|
84
80
|
this.baseFilesDir = options.baseFilesDir || process.cwd();
|
|
@@ -103,12 +99,12 @@ class Config {
|
|
|
103
99
|
// memory must come first for config.set() to work without loading config files
|
|
104
100
|
// 3. `process.env`
|
|
105
101
|
// 4. `process.argv`
|
|
106
|
-
store.argv({parseValues: true}).env({parseValues: true, separator: '__'});
|
|
102
|
+
store.argv({ parseValues: true }).env({ parseValues: true, separator: '__' });
|
|
107
103
|
|
|
108
104
|
// 5. Values in `${NODE_ENV}-config.yml` or from --config parameter
|
|
109
105
|
let configFile;
|
|
110
106
|
if (store.get('config')) {
|
|
111
|
-
configFile = store.get('config')
|
|
107
|
+
configFile = store.get('config');
|
|
112
108
|
} else if (store.get('NODE_ENV')) {
|
|
113
109
|
configFile = path.resolve(baseConfigDir, store.get('NODE_ENV') + '-config.yml');
|
|
114
110
|
}
|
|
@@ -122,7 +118,7 @@ class Config {
|
|
|
122
118
|
|
|
123
119
|
// load extra config files & plugins
|
|
124
120
|
if (options.extras) {
|
|
125
|
-
for (
|
|
121
|
+
for (const extra of options.extras) {
|
|
126
122
|
if (extra.file) {
|
|
127
123
|
loadFile(extra.scope, extra.file);
|
|
128
124
|
continue;
|
|
@@ -133,7 +129,7 @@ class Config {
|
|
|
133
129
|
continue;
|
|
134
130
|
}
|
|
135
131
|
if (extra.data) {
|
|
136
|
-
const conf = extra.key ? {[extra.key]: extra.data} : extra.data;
|
|
132
|
+
const conf = extra.key ? { [extra.key]: extra.data } : extra.data;
|
|
137
133
|
store.use(extra.scope, { type: 'literal', store: conf });
|
|
138
134
|
logger.debug('Loaded [' + extra.scope + '] from DATA: ' + (extra.key ? ' under [' + extra.key + ']' : ''));
|
|
139
135
|
continue;
|
|
@@ -141,7 +137,7 @@ class Config {
|
|
|
141
137
|
if (extra.url || extra.urlFromKey || extra.fileAsync) {
|
|
142
138
|
// register scope in the chain to keep order of configs
|
|
143
139
|
store.use(extra.scope, { type: 'literal', store: {} });
|
|
144
|
-
logger.debug('Booked [' + extra.scope +'] for async Loading ');
|
|
140
|
+
logger.debug('Booked [' + extra.scope + '] for async Loading ');
|
|
145
141
|
this.extraAsync.push(extra);
|
|
146
142
|
continue;
|
|
147
143
|
}
|
|
@@ -154,7 +150,6 @@ class Config {
|
|
|
154
150
|
}
|
|
155
151
|
}
|
|
156
152
|
|
|
157
|
-
|
|
158
153
|
// .end-1 load default and custom config from configs/default-config.json
|
|
159
154
|
loadFile('default-file', path.resolve(baseConfigDir, 'default-config.yml'));
|
|
160
155
|
|
|
@@ -167,36 +162,34 @@ class Config {
|
|
|
167
162
|
|
|
168
163
|
// --- helpers --/
|
|
169
164
|
|
|
170
|
-
function loadFile(scope, filePath) {
|
|
171
|
-
|
|
165
|
+
function loadFile (scope, filePath) {
|
|
172
166
|
if (fs.existsSync(filePath)) {
|
|
173
|
-
|
|
174
|
-
if (filePath.endsWith('.js')) { // JS file
|
|
167
|
+
if (filePath.endsWith('.js')) { // JS file
|
|
175
168
|
const conf = require(filePath);
|
|
176
169
|
store.use(scope, { type: 'literal', store: conf });
|
|
177
|
-
} else {
|
|
178
|
-
const options = { file: filePath }
|
|
179
|
-
if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) { options.format = nconf.formats.yaml }
|
|
170
|
+
} else { // JSON or YAML
|
|
171
|
+
const options = { file: filePath };
|
|
172
|
+
if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) { options.format = nconf.formats.yaml; }
|
|
180
173
|
store.file(scope, options);
|
|
181
174
|
}
|
|
182
175
|
|
|
183
|
-
logger.debug('Loaded [' + scope + '] from file: ' + filePath)
|
|
176
|
+
logger.debug('Loaded [' + scope + '] from file: ' + filePath);
|
|
184
177
|
} else {
|
|
185
178
|
logger.debug('Cannot find file: ' + filePath + ' for scope [' + scope + ']');
|
|
186
179
|
}
|
|
187
180
|
}
|
|
188
181
|
}
|
|
189
182
|
|
|
190
|
-
async initASync() {
|
|
183
|
+
async initASync () {
|
|
191
184
|
const store = this.store;
|
|
192
185
|
const logger = this.logger;
|
|
193
186
|
const baseConfigDir = this.baseConfigDir;
|
|
194
187
|
const baseFilesDir = this.baseFilesDir;
|
|
195
188
|
|
|
196
|
-
async function loadUrl(scope, key, url) {
|
|
189
|
+
async function loadUrl (scope, key, url) {
|
|
197
190
|
if (typeof url === 'undefined' || url === null) {
|
|
198
|
-
|
|
199
|
-
|
|
191
|
+
logger.warn('Null or Undefined Url for [' + scope + ']');
|
|
192
|
+
return;
|
|
200
193
|
}
|
|
201
194
|
|
|
202
195
|
let res = null;
|
|
@@ -205,13 +198,13 @@ class Config {
|
|
|
205
198
|
} else {
|
|
206
199
|
res = await loadFromUrl(url);
|
|
207
200
|
}
|
|
208
|
-
const conf = key ? {[key]: res} : res;
|
|
201
|
+
const conf = key ? { [key]: res } : res;
|
|
209
202
|
store.add(scope, { type: 'literal', store: conf });
|
|
210
203
|
logger.debug('Loaded [' + scope + '] from URL: ' + url + (key ? ' under [' + key + ']' : ''));
|
|
211
204
|
}
|
|
212
205
|
|
|
213
206
|
// load remote config files
|
|
214
|
-
for (
|
|
207
|
+
for (const extra of this.extraAsync) {
|
|
215
208
|
if (extra.url) {
|
|
216
209
|
await loadUrl(extra.scope, extra.key, extra.url);
|
|
217
210
|
continue;
|
|
@@ -231,11 +224,11 @@ class Config {
|
|
|
231
224
|
if (extra.fileAsync) {
|
|
232
225
|
const filePath = path.resolve(baseConfigDir, extra.fileAsync);
|
|
233
226
|
|
|
234
|
-
if (!
|
|
227
|
+
if (!fs.existsSync(filePath)) {
|
|
235
228
|
logger.warn('Cannot find file: ' + filePath + ' for scope [' + extra.scope + ']');
|
|
236
229
|
continue;
|
|
237
230
|
}
|
|
238
|
-
if (!
|
|
231
|
+
if (!filePath.endsWith('.js')) {
|
|
239
232
|
logger.warn('Cannot only load .js file: ' + filePath + ' for scope [' + extra.scope + ']');
|
|
240
233
|
continue;
|
|
241
234
|
}
|
|
@@ -257,8 +250,8 @@ class Config {
|
|
|
257
250
|
* @param {string} key
|
|
258
251
|
* @returns {boolean}
|
|
259
252
|
*/
|
|
260
|
-
has(key) {
|
|
261
|
-
if (!
|
|
253
|
+
has (key) {
|
|
254
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
262
255
|
const value = this.store.get(key);
|
|
263
256
|
return (typeof value !== 'undefined');
|
|
264
257
|
}
|
|
@@ -267,10 +260,10 @@ class Config {
|
|
|
267
260
|
* Retreive value
|
|
268
261
|
* @param {string} [key] if no key is provided all the config is returned
|
|
269
262
|
*/
|
|
270
|
-
get(key) {
|
|
271
|
-
if (!
|
|
263
|
+
get (key) {
|
|
264
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
272
265
|
const value = this.store.get(key);
|
|
273
|
-
if (typeof value === 'undefined') this.logger.debug('get: [' + key +'] is undefined');
|
|
266
|
+
if (typeof value === 'undefined') this.logger.debug('get: [' + key + '] is undefined');
|
|
274
267
|
learn(this.learnDirectoryAndFilename, key);
|
|
275
268
|
return value;
|
|
276
269
|
}
|
|
@@ -279,20 +272,20 @@ class Config {
|
|
|
279
272
|
* Retreive value and store info that applies
|
|
280
273
|
* @param {string} key
|
|
281
274
|
*/
|
|
282
|
-
getScopeAndValue(key) {
|
|
283
|
-
if (!
|
|
284
|
-
for (
|
|
275
|
+
getScopeAndValue (key) {
|
|
276
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
277
|
+
for (const scopeName of Object.keys(this.store.stores)) {
|
|
285
278
|
const store = this.store.stores[scopeName];
|
|
286
279
|
const value = store.get(key);
|
|
287
280
|
if (typeof value !== 'undefined') {
|
|
288
281
|
const res = {
|
|
289
|
-
value
|
|
282
|
+
value,
|
|
290
283
|
scope: scopeName
|
|
291
|
-
}
|
|
284
|
+
};
|
|
292
285
|
if (store.type === 'file') {
|
|
293
|
-
res.info = 'From file: ' + store.file
|
|
286
|
+
res.info = 'From file: ' + store.file;
|
|
294
287
|
} else {
|
|
295
|
-
info = 'Type: ' + store.type
|
|
288
|
+
res.info = 'Type: ' + store.type;
|
|
296
289
|
}
|
|
297
290
|
return res;
|
|
298
291
|
}
|
|
@@ -305,8 +298,8 @@ class Config {
|
|
|
305
298
|
* @param {string} key
|
|
306
299
|
* @param {Object} value
|
|
307
300
|
*/
|
|
308
|
-
set(key, value) {
|
|
309
|
-
if (!
|
|
301
|
+
set (key, value) {
|
|
302
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
310
303
|
this.store.set(key, value);
|
|
311
304
|
}
|
|
312
305
|
|
|
@@ -314,7 +307,7 @@ class Config {
|
|
|
314
307
|
* Inject Test Config and override any other option
|
|
315
308
|
* @param {Object} configObject;
|
|
316
309
|
*/
|
|
317
|
-
injectTestConfig(configObject) {
|
|
310
|
+
injectTestConfig (configObject) {
|
|
318
311
|
this.replaceScopeConfig('test', configObject);
|
|
319
312
|
}
|
|
320
313
|
|
|
@@ -323,12 +316,11 @@ class Config {
|
|
|
323
316
|
* @param {string} scope;
|
|
324
317
|
* @param {Object} configObject;
|
|
325
318
|
*/
|
|
326
|
-
replaceScopeConfig(scope, configObject) {
|
|
327
|
-
if (!
|
|
328
|
-
this.logger.debug('Replace ['+ scope + '] with: ', configObject);
|
|
329
|
-
this.store.add(scope, {type: 'literal', store: configObject});
|
|
319
|
+
replaceScopeConfig (scope, configObject) {
|
|
320
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
321
|
+
this.logger.debug('Replace [' + scope + '] with: ', configObject);
|
|
322
|
+
this.store.add(scope, { type: 'literal', store: configObject });
|
|
330
323
|
}
|
|
331
|
-
|
|
332
324
|
}
|
|
333
325
|
|
|
334
326
|
module.exports = Config;
|
|
@@ -338,12 +330,12 @@ module.exports = Config;
|
|
|
338
330
|
const FILE_PROTOCOL = 'file://';
|
|
339
331
|
const FILE_PROTOCOL_LENGTH = FILE_PROTOCOL.length;
|
|
340
332
|
|
|
341
|
-
async function loadFromUrl(url) {
|
|
342
|
-
const res = await
|
|
343
|
-
return res.
|
|
333
|
+
async function loadFromUrl (url) {
|
|
334
|
+
const res = await fetch(url);
|
|
335
|
+
return res.json();
|
|
344
336
|
}
|
|
345
337
|
|
|
346
|
-
function loadFromFile(fileUrl, baseFilesDir) {
|
|
338
|
+
function loadFromFile (fileUrl, baseFilesDir) {
|
|
347
339
|
const filePath = stripFileProtocol(fileUrl);
|
|
348
340
|
|
|
349
341
|
if (isRelativePath(filePath)) {
|
|
@@ -358,69 +350,65 @@ function loadFromFile(fileUrl, baseFilesDir) {
|
|
|
358
350
|
return res;
|
|
359
351
|
}
|
|
360
352
|
|
|
361
|
-
|
|
362
|
-
function isFileUrl(filePath) {
|
|
353
|
+
function isFileUrl (filePath) {
|
|
363
354
|
return filePath.startsWith(FILE_PROTOCOL);
|
|
364
355
|
}
|
|
365
356
|
|
|
366
|
-
function isRelativePath(filePath) {
|
|
357
|
+
function isRelativePath (filePath) {
|
|
367
358
|
return !path.isAbsolute(filePath);
|
|
368
359
|
}
|
|
369
360
|
|
|
370
|
-
function stripFileProtocol(filePath) {
|
|
361
|
+
function stripFileProtocol (filePath) {
|
|
371
362
|
return filePath.substring(FILE_PROTOCOL_LENGTH);
|
|
372
363
|
}
|
|
373
364
|
|
|
374
|
-
|
|
375
365
|
// -------- learning mode ------- //
|
|
376
366
|
|
|
377
|
-
function getLearnFilename(appName, learnDirectory) {
|
|
378
|
-
if (!
|
|
367
|
+
function getLearnFilename (appName, learnDirectory) {
|
|
368
|
+
if (!learnDirectory) return;
|
|
379
369
|
let i = 0;
|
|
380
370
|
let res;
|
|
381
371
|
do {
|
|
382
|
-
res = path.join(learnDirectory, appName + i
|
|
372
|
+
res = path.join(learnDirectory, appName + i);
|
|
383
373
|
i++;
|
|
384
|
-
} while(fs.existsSync(res + '-config.json'));
|
|
374
|
+
} while (fs.existsSync(res + '-config.json'));
|
|
385
375
|
return res;
|
|
386
376
|
}
|
|
387
377
|
|
|
388
|
-
function learn(learnDirectoryAndFilename, key) {
|
|
378
|
+
function learn (learnDirectoryAndFilename, key) {
|
|
389
379
|
if (learnDirectoryAndFilename) {
|
|
390
380
|
const caller_line = (new Error()).stack.split('\n')[3]; // get callee name and line
|
|
391
|
-
const index = caller_line.indexOf(
|
|
392
|
-
const str = key + ';' + caller_line.slice(index+3, caller_line.length) + '\n';
|
|
381
|
+
const index = caller_line.indexOf('at ');
|
|
382
|
+
const str = key + ';' + caller_line.slice(index + 3, caller_line.length) + '\n';
|
|
393
383
|
fs.appendFileSync(learnDirectoryAndFilename + '-calls.csv', str);
|
|
394
384
|
}
|
|
395
385
|
}
|
|
396
386
|
|
|
397
|
-
function saveConfig(learnDirectoryAndFilename, store) {
|
|
387
|
+
function saveConfig (learnDirectoryAndFilename, store) {
|
|
398
388
|
if (learnDirectoryAndFilename) {
|
|
399
389
|
const filename = learnDirectoryAndFilename + '-config.json';
|
|
400
|
-
fs.writeFileSync(filename, JSON.stringify({stores: store.stores, config: store.get()}, null, 2));
|
|
390
|
+
fs.writeFileSync(filename, JSON.stringify({ stores: store.stores, config: store.get() }, null, 2));
|
|
401
391
|
}
|
|
402
392
|
}
|
|
403
393
|
|
|
404
|
-
|
|
405
394
|
/**
|
|
406
395
|
* @typedef ConfigFile
|
|
407
396
|
* @property {string} scope - scope for nconf hierachical load
|
|
408
397
|
* @property {string} file - the config file (.yml, .json, .js)
|
|
409
398
|
*/
|
|
410
399
|
|
|
411
|
-
|
|
400
|
+
/**
|
|
412
401
|
* @typedef ConfigPlugin
|
|
413
402
|
* @property {Object} plugin
|
|
414
403
|
* @property {Function} plugin.load - a function that takes the "nconf store" as argument and returns the "name" of the plugin
|
|
415
404
|
*/
|
|
416
405
|
|
|
417
|
-
|
|
406
|
+
/**
|
|
418
407
|
* @typedef ConfigData
|
|
419
408
|
* @property {string} scope - scope for nconf hierachical load
|
|
420
409
|
* @property {string} [key] - (optional) key to load result of url. If null loaded at root of the config
|
|
421
410
|
* @property {object} data - the data to load
|
|
422
411
|
|
|
423
|
-
|
|
424
412
|
/**
|
|
425
413
|
* @typedef ConfigRemoteURL
|
|
426
414
|
* @property {string} scope - scope for nconf hierachical load
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* [BSD-3-Clause](https://github.com/pryv/pryv-boiler/blob/master/LICENSE)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export = boiler;
|
|
7
|
+
|
|
8
|
+
declare const boiler: {
|
|
9
|
+
/**
|
|
10
|
+
* Get a Logger
|
|
11
|
+
* @param name - The name of the logger
|
|
12
|
+
*/
|
|
13
|
+
getLogger: (name?: string) => boiler.Logger;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Preferred way to get the configuration.
|
|
17
|
+
* Waits until the configuration is fully initialized.
|
|
18
|
+
*/
|
|
19
|
+
getConfig: () => Promise<boiler.Config>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get the configuration.
|
|
23
|
+
* If the configuration is not fully initialized, throws an error (or warns if warnOnly is true).
|
|
24
|
+
* @param warnOnly - Only warns about potential misuse of config instead of throwing
|
|
25
|
+
*/
|
|
26
|
+
getConfigUnsafe: (warnOnly?: boolean) => boiler.Config;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Initialize Boiler. Should be called just once when starting an app.
|
|
30
|
+
* @param options - Initialization options
|
|
31
|
+
* @param fullyLoadedCallback - Called when the config is fully loaded
|
|
32
|
+
*/
|
|
33
|
+
init: (options: boiler.InitOptions, fullyLoadedCallback?: (config: boiler.Config) => void) => typeof boiler;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
declare namespace boiler {
|
|
37
|
+
interface InitOptions {
|
|
38
|
+
/** The name of the application, used by Logger and debug */
|
|
39
|
+
appName: string;
|
|
40
|
+
/** Directory to use to look for configs (default, env) */
|
|
41
|
+
baseConfigDir?: string;
|
|
42
|
+
/** Directory to use for `file://` relative paths */
|
|
43
|
+
baseFilesDir?: string;
|
|
44
|
+
/** Array of extra config sources to load */
|
|
45
|
+
extraConfigs?: Array<ConfigFile | ConfigPlugin | ConfigPluginAsync | ConfigData | ConfigRemoteURL | ConfigRemoteURLFromKey | ConfigFileAsync>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface ConfigFile {
|
|
49
|
+
/** Scope for nconf hierarchical load */
|
|
50
|
+
scope: string;
|
|
51
|
+
/** The config file path (.yml, .json, .js) */
|
|
52
|
+
file: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface ConfigFileAsync {
|
|
56
|
+
/** Scope for nconf hierarchical load */
|
|
57
|
+
scope: string;
|
|
58
|
+
/** The async config file path (.js that exports an async function) */
|
|
59
|
+
fileAsync: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface ConfigPlugin {
|
|
63
|
+
plugin: {
|
|
64
|
+
/** Function that takes the Config instance and returns the plugin name */
|
|
65
|
+
load: (config: Config) => string;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface ConfigPluginAsync {
|
|
70
|
+
pluginAsync: {
|
|
71
|
+
/** Async function that takes the Config instance and returns the plugin name */
|
|
72
|
+
load: (config: Config) => Promise<string>;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface ConfigData {
|
|
77
|
+
/** Scope for nconf hierarchical load */
|
|
78
|
+
scope: string;
|
|
79
|
+
/** Key to load data under. If null, loaded at root of the config */
|
|
80
|
+
key?: string;
|
|
81
|
+
/** The data to load */
|
|
82
|
+
data: object;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface ConfigRemoteURL {
|
|
86
|
+
/** Scope for nconf hierarchical load */
|
|
87
|
+
scope: string;
|
|
88
|
+
/** Key to load result of URL under. If null, loaded at root of the config */
|
|
89
|
+
key?: string;
|
|
90
|
+
/** The URL to the config definition */
|
|
91
|
+
url: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface ConfigRemoteURLFromKey {
|
|
95
|
+
/** Scope for nconf hierarchical load */
|
|
96
|
+
scope: string;
|
|
97
|
+
/** Key to load result of URL under. If null, override */
|
|
98
|
+
key?: string;
|
|
99
|
+
/** Retrieve URL from config matching this key */
|
|
100
|
+
urlFromKey: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
interface ScopeAndValue {
|
|
104
|
+
value: unknown;
|
|
105
|
+
scope: string;
|
|
106
|
+
info: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class Config {
|
|
110
|
+
/** The nconf store instance */
|
|
111
|
+
store: unknown;
|
|
112
|
+
/** The logger instance for config */
|
|
113
|
+
logger: Logger;
|
|
114
|
+
/** Base directory for config files */
|
|
115
|
+
baseConfigDir: string;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Return true if key has a value
|
|
119
|
+
* @param key - The config key to check
|
|
120
|
+
*/
|
|
121
|
+
has(key: string): boolean;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Retrieve value
|
|
125
|
+
* @param key - The config key. If no key is provided, all the config is returned
|
|
126
|
+
*/
|
|
127
|
+
get(key?: string): unknown;
|
|
128
|
+
get<T>(key: string): T | undefined;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Retrieve value and store info that applies
|
|
132
|
+
* @param key - The config key
|
|
133
|
+
*/
|
|
134
|
+
getScopeAndValue(key: string): ScopeAndValue | null;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Set value
|
|
138
|
+
* @param key - The config key
|
|
139
|
+
* @param value - The value to set
|
|
140
|
+
*/
|
|
141
|
+
set(key: string, value: unknown): void;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Inject test config and override any other option
|
|
145
|
+
* @param configObject - The config object to inject for testing
|
|
146
|
+
*/
|
|
147
|
+
injectTestConfig(configObject: object): void;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Replace a scope config set
|
|
151
|
+
* @param scope - The scope to replace
|
|
152
|
+
* @param configObject - The new config object for the scope
|
|
153
|
+
*/
|
|
154
|
+
replaceScopeConfig(scope: string, configObject: object): void;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
class Logger {
|
|
158
|
+
/** The name of this logger */
|
|
159
|
+
name: string;
|
|
160
|
+
/** The parent logger, if any */
|
|
161
|
+
parent: Logger | null;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Log a message at the specified level
|
|
165
|
+
* @param level - The log level
|
|
166
|
+
* @param message - The log message
|
|
167
|
+
* @param context - Additional context
|
|
168
|
+
*/
|
|
169
|
+
log(level: string, message: string, ...context: unknown[]): void;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Log an info message
|
|
173
|
+
* @param message - The log message
|
|
174
|
+
* @param context - Additional context
|
|
175
|
+
*/
|
|
176
|
+
info(message: string, ...context: unknown[]): void;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Log a warning message
|
|
180
|
+
* @param message - The log message
|
|
181
|
+
* @param context - Additional context
|
|
182
|
+
*/
|
|
183
|
+
warn(message: string, ...context: unknown[]): void;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Log an error message
|
|
187
|
+
* @param message - The log message
|
|
188
|
+
* @param context - Additional context
|
|
189
|
+
*/
|
|
190
|
+
error(message: string, ...context: unknown[]): void;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Log a debug message
|
|
194
|
+
* @param message - The log message
|
|
195
|
+
* @param context - Additional context
|
|
196
|
+
*/
|
|
197
|
+
debug(message: string, ...context: unknown[]): void;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get a "sub" Logger
|
|
201
|
+
* @param name - The name of the child logger
|
|
202
|
+
*/
|
|
203
|
+
getLogger(name: string): Logger;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Dump objects with file and line for debugging
|
|
207
|
+
*/
|
|
208
|
+
inspect(...args: unknown[]): void;
|
|
209
|
+
}
|
|
210
|
+
}
|
package/src/index.js
CHANGED
|
@@ -25,14 +25,14 @@ const boiler = {
|
|
|
25
25
|
* Prefered way to get the configuration
|
|
26
26
|
* @returns {Promise<Config>}
|
|
27
27
|
*/
|
|
28
|
-
getConfig
|
|
28
|
+
getConfig,
|
|
29
29
|
/**
|
|
30
30
|
* get the configuration.
|
|
31
31
|
* If the configuration is not fully initialized throw an error
|
|
32
32
|
* @param {boolean} warnOnly - Only warns about potential misuse of config
|
|
33
33
|
* @returns {Config}
|
|
34
34
|
*/
|
|
35
|
-
getConfigUnsafe
|
|
35
|
+
getConfigUnsafe,
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Init Boiler, should be called just once when starting an APP
|
|
@@ -42,7 +42,7 @@ const boiler = {
|
|
|
42
42
|
* @param {Array<ConfigFile|ConfigRemoteURL|ConfigRemoteURLFromKey|ConfigPlugin>} [options.extraConfigs] - (optional) and array of extra files to load
|
|
43
43
|
* @param {Function} [fullyLoadedCallback] - (optional) called when the config is fully loaded
|
|
44
44
|
*/
|
|
45
|
-
init
|
|
45
|
+
init
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
let logger;
|
package/src/logging.js
CHANGED
|
@@ -13,17 +13,17 @@ let customLoggerInstance = null;
|
|
|
13
13
|
// ------ winston formating
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @param {Object} options
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} options
|
|
18
18
|
* @param {boolean} options.color - set to true to have colors
|
|
19
19
|
* @param {boolean} options.time - set to true to for timestamp
|
|
20
20
|
* @param {boolean} options.align - set to true to allign logs items
|
|
21
21
|
*/
|
|
22
|
-
function generateFormat(options) {
|
|
22
|
+
function generateFormat (options) {
|
|
23
23
|
const formats = [];
|
|
24
24
|
if (options.color) {
|
|
25
25
|
formats.push(winston.format.colorize());
|
|
26
|
-
}
|
|
26
|
+
}
|
|
27
27
|
if (options.time) {
|
|
28
28
|
formats.push(winston.format.timestamp());
|
|
29
29
|
}
|
|
@@ -31,13 +31,13 @@ function generateFormat(options) {
|
|
|
31
31
|
formats.push(winston.format.align());
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function printf(info) {
|
|
34
|
+
function printf (info) {
|
|
35
35
|
const {
|
|
36
36
|
timestamp, level, message, ...args
|
|
37
37
|
} = info;
|
|
38
|
-
|
|
39
|
-
let items = info[Symbol.for('splat')] ||
|
|
40
|
-
|
|
38
|
+
|
|
39
|
+
let items = info[Symbol.for('splat')] || {};
|
|
40
|
+
|
|
41
41
|
let itemStr = '';
|
|
42
42
|
if (items.length > 0) {
|
|
43
43
|
let skip = false;
|
|
@@ -45,17 +45,14 @@ function generateFormat(options) {
|
|
|
45
45
|
if (typeof items[0] === 'undefined') {
|
|
46
46
|
skip = true;
|
|
47
47
|
} else {
|
|
48
|
-
if (items[0] && items[0].context) {
|
|
48
|
+
if (items[0] && items[0].context) {
|
|
49
49
|
items = items[0].context;
|
|
50
|
-
}
|
|
50
|
+
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
if (!
|
|
54
|
-
itemStr = util.inspect(items, {depth: 10, colors: true});
|
|
53
|
+
if (!skip) { itemStr = util.inspect(items, { depth: 10, colors: true }); }
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
56
|
const line = `[${level}]: ${message} ${itemStr}`;
|
|
60
57
|
|
|
61
58
|
if (options.time) {
|
|
@@ -69,12 +66,10 @@ function generateFormat(options) {
|
|
|
69
66
|
return winston.format.combine(...formats);
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
74
69
|
/**
|
|
75
70
|
* Helper to pass log instructions to winston
|
|
76
71
|
*/
|
|
77
|
-
function globalLog(level, key, message, context) {
|
|
72
|
+
function globalLog (level, key, message, context) {
|
|
78
73
|
const text = `[${key}] ${message}`;
|
|
79
74
|
if (winstonInstance) {
|
|
80
75
|
winstonInstance[level](text, context);
|
|
@@ -86,56 +81,60 @@ function globalLog(level, key, message, context) {
|
|
|
86
81
|
}
|
|
87
82
|
}
|
|
88
83
|
|
|
89
|
-
|
|
90
84
|
/**
|
|
91
85
|
* Config initialize Logger right after beeing loaded
|
|
92
86
|
* This is done by config Only
|
|
93
|
-
*/
|
|
94
|
-
async function initLoggerWithConfig(config) {
|
|
87
|
+
*/
|
|
88
|
+
async function initLoggerWithConfig (config) {
|
|
95
89
|
if (winstonInstance) {
|
|
96
|
-
throw new Error(
|
|
90
|
+
throw new Error('Logger was already initialized');
|
|
97
91
|
}
|
|
98
92
|
// console
|
|
99
93
|
winstonInstance = winston.createLogger({ });
|
|
100
94
|
const logConsole = config.get('logs:console');
|
|
101
|
-
let isSilent = !
|
|
95
|
+
let isSilent = !config.get('logs:console:active');
|
|
102
96
|
|
|
103
97
|
// LOGS env var can override settings
|
|
104
98
|
if (process.env.LOGS) {
|
|
105
99
|
logConsole.level = process.env.LOGS;
|
|
106
100
|
isSilent = false;
|
|
107
|
-
}
|
|
108
|
-
|
|
101
|
+
}
|
|
109
102
|
|
|
110
|
-
const
|
|
111
|
-
const myconsole = new winston.transports.Console({ format:
|
|
103
|
+
const consoleFormat = generateFormat(logConsole.format);
|
|
104
|
+
const myconsole = new winston.transports.Console({ format: consoleFormat, level: logConsole.level, silent: isSilent });
|
|
112
105
|
winstonInstance.add(myconsole);
|
|
113
|
-
|
|
114
|
-
rootLogger.debug((isSilent ?
|
|
106
|
+
|
|
107
|
+
rootLogger.debug((isSilent ? '** silent ** ' : '') + 'Console with level: ', logConsole.level);
|
|
115
108
|
|
|
116
109
|
// file
|
|
117
110
|
const logFile = config.get('logs:file');
|
|
118
111
|
if (config.get('logs:file:active')) {
|
|
112
|
+
const fileFormat = winston.format.combine(
|
|
113
|
+
winston.format.timestamp(),
|
|
114
|
+
winston.format.json()
|
|
115
|
+
);
|
|
116
|
+
|
|
119
117
|
rootLogger.debug('File active: ' + logFile.path);
|
|
120
118
|
if (logFile.rotation.isActive) {
|
|
121
|
-
const
|
|
119
|
+
const rotatedFiles = new winston.transports.DailyRotateFile({
|
|
122
120
|
filename: logFile.path + '.%DATE%',
|
|
123
121
|
datePattern: 'YYYY-MM-DD',
|
|
124
122
|
zippedArchive: true,
|
|
123
|
+
level: logFile.level,
|
|
125
124
|
maxFiles: logFile.rotation.days ? logFile.rotation.days + 'd' : null,
|
|
125
|
+
format: fileFormat
|
|
126
126
|
});
|
|
127
|
+
winstonInstance.add(rotatedFiles);
|
|
127
128
|
} else {
|
|
128
|
-
const files = new winston.transports.File({
|
|
129
|
+
const files = new winston.transports.File({
|
|
129
130
|
filename: logFile.path,
|
|
130
131
|
level: logFile.level,
|
|
131
|
-
|
|
132
|
-
maxFiles: logFile.maxNbFiles,
|
|
133
|
-
|
|
134
|
-
json: false
|
|
132
|
+
maxSize: logFile.maxFileBytes || '10m',
|
|
133
|
+
maxFiles: logFile.maxNbFiles || '14d',
|
|
134
|
+
format: fileFormat
|
|
135
135
|
});
|
|
136
136
|
winstonInstance.add(files);
|
|
137
137
|
}
|
|
138
|
-
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
// custom
|
|
@@ -144,17 +143,23 @@ async function initLoggerWithConfig(config) {
|
|
|
144
143
|
await customLoggerInstance.init(config.get('logs:custom:settings'));
|
|
145
144
|
}
|
|
146
145
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
// catch all errors.
|
|
147
|
+
if (!config.get('logs:skipUncaughtException')) {
|
|
148
|
+
process.on('uncaughtException', function (err) {
|
|
149
|
+
rootLogger.error('UncaughtException', { message: err.message, name: err.name, stack: err.stack });
|
|
150
|
+
throw err;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
150
153
|
|
|
154
|
+
rootLogger.debug('Logger Initialized');
|
|
155
|
+
}
|
|
151
156
|
|
|
152
|
-
// --------------- debug utils
|
|
157
|
+
// --------------- debug utils
|
|
153
158
|
|
|
154
159
|
/**
|
|
155
160
|
* Dump objects with file and line
|
|
156
161
|
*/
|
|
157
|
-
function inspect() {
|
|
162
|
+
function inspect () {
|
|
158
163
|
let line = '';
|
|
159
164
|
try {
|
|
160
165
|
throw new Error();
|
|
@@ -162,38 +167,37 @@ function inspect() {
|
|
|
162
167
|
line = e.stack.split(' at ')[2].trim();
|
|
163
168
|
}
|
|
164
169
|
let res = '\n * dump at: ' + line;
|
|
165
|
-
for (
|
|
170
|
+
for (let i = 0; i < arguments.length; i++) {
|
|
166
171
|
res += '\n' + i + ' ' + util.inspect(arguments[i], true, 10, true) + '\n';
|
|
167
172
|
}
|
|
168
173
|
return res;
|
|
169
|
-
}
|
|
170
|
-
|
|
174
|
+
}
|
|
171
175
|
|
|
172
|
-
function setGlobalName(name) {
|
|
176
|
+
function setGlobalName (name) {
|
|
173
177
|
// create root logger
|
|
174
178
|
rootLogger = new Logger(name, null);
|
|
175
179
|
rootLogger.debug('setGlobalName: ' + name);
|
|
176
180
|
}
|
|
177
181
|
|
|
178
|
-
|
|
179
182
|
class Logger {
|
|
180
183
|
parent; // eventual parent
|
|
181
184
|
debugInstance; // debug instance
|
|
182
185
|
|
|
183
|
-
constructor(name, parent) {
|
|
186
|
+
constructor (name, parent) {
|
|
184
187
|
this.name = name;
|
|
185
188
|
this.parent = parent;
|
|
186
|
-
this.debugInstance =
|
|
189
|
+
this.debugInstance = debugModule('pryv:' + this._name());
|
|
187
190
|
}
|
|
191
|
+
|
|
188
192
|
/**
|
|
189
193
|
* Private
|
|
190
194
|
*/
|
|
191
|
-
_name() {
|
|
195
|
+
_name () {
|
|
192
196
|
if (this.parent) return this.parent._name() + ':' + this.name;
|
|
193
197
|
return this.name;
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
log() {
|
|
200
|
+
log () {
|
|
197
201
|
const level = arguments[0];
|
|
198
202
|
const message = hideSensitiveValues(arguments[1]);
|
|
199
203
|
const context = [];
|
|
@@ -204,9 +208,9 @@ class Logger {
|
|
|
204
208
|
context.push(inspectAndHide(arguments[i]));
|
|
205
209
|
}
|
|
206
210
|
if (context.length === 1) {
|
|
207
|
-
meta = {context:
|
|
211
|
+
meta = { context: context[0] };
|
|
208
212
|
} else if (context.length > 1) {
|
|
209
|
-
meta = {context
|
|
213
|
+
meta = { context };
|
|
210
214
|
}
|
|
211
215
|
globalLog(level, this._name(), message, meta);
|
|
212
216
|
}
|
|
@@ -214,69 +218,69 @@ class Logger {
|
|
|
214
218
|
info () { this.log('info', ...arguments); }
|
|
215
219
|
warn () { this.log('warn', ...arguments); }
|
|
216
220
|
error () { this.log('error', ...arguments); }
|
|
217
|
-
debug () {
|
|
221
|
+
debug () {
|
|
218
222
|
if (winstonInstance) {
|
|
219
|
-
this.log('debug', ...arguments);
|
|
223
|
+
this.log('debug', ...arguments);
|
|
220
224
|
}
|
|
221
|
-
this.debugInstance(...arguments);
|
|
222
|
-
}
|
|
225
|
+
this.debugInstance(...arguments);
|
|
226
|
+
}
|
|
223
227
|
|
|
224
228
|
/**
|
|
225
229
|
* get a "sub" Logger
|
|
226
|
-
* @param {Logger} name
|
|
230
|
+
* @param {Logger} name
|
|
227
231
|
* @returns {Logger}
|
|
228
232
|
*/
|
|
229
233
|
getLogger (name) {
|
|
230
234
|
return new Logger(name, this);
|
|
231
235
|
}
|
|
232
236
|
|
|
233
|
-
inspect() { inspect(...arguments); }
|
|
237
|
+
inspect () { inspect(...arguments); }
|
|
234
238
|
}
|
|
235
239
|
|
|
236
240
|
/**
|
|
237
241
|
* Get a new logger, or root loggger if no name is provided
|
|
238
|
-
* @param {string} [name]
|
|
242
|
+
* @param {string} [name]
|
|
239
243
|
* @returns {Logger}
|
|
240
244
|
*/
|
|
241
|
-
function getLogger(name) {
|
|
242
|
-
if (!
|
|
243
|
-
throw new Error('Initalize boiler before using logger')
|
|
245
|
+
function getLogger (name) {
|
|
246
|
+
if (!rootLogger) {
|
|
247
|
+
throw new Error('Initalize boiler before using logger');
|
|
244
248
|
}
|
|
245
|
-
if(!
|
|
249
|
+
if (!name) {
|
|
246
250
|
return rootLogger;
|
|
247
251
|
}
|
|
248
252
|
return rootLogger.getLogger(name);
|
|
249
253
|
}
|
|
250
254
|
|
|
251
255
|
module.exports = {
|
|
252
|
-
getLogger
|
|
253
|
-
setGlobalName
|
|
254
|
-
initLoggerWithConfig
|
|
255
|
-
}
|
|
256
|
+
getLogger,
|
|
257
|
+
setGlobalName,
|
|
258
|
+
initLoggerWithConfig
|
|
259
|
+
};
|
|
256
260
|
|
|
257
261
|
// ----------------- Hide sensite data -------------------- //
|
|
258
262
|
|
|
259
|
-
function inspectAndHide(o) {
|
|
263
|
+
function inspectAndHide (o) {
|
|
260
264
|
if (typeof o === 'undefined') return o;
|
|
261
265
|
if (o instanceof Error) return o;
|
|
262
266
|
return _inspectAndHide(JSON.parse(JSON.stringify(o))); // clone and remove circular
|
|
263
267
|
}
|
|
264
268
|
|
|
265
|
-
function _inspectAndHide(o) {
|
|
269
|
+
function _inspectAndHide (o) {
|
|
266
270
|
if (typeof o === 'string') {
|
|
267
271
|
return hideSensitiveValues(o);
|
|
268
272
|
}
|
|
269
273
|
if (o !== null && typeof o === 'object') {
|
|
270
274
|
if (Array.isArray(o)) {
|
|
271
275
|
const res = [];
|
|
272
|
-
for (
|
|
276
|
+
for (const item of o) {
|
|
273
277
|
res.push(inspectAndHide(item));
|
|
274
278
|
}
|
|
275
279
|
return res;
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
const res = {};
|
|
279
|
-
for (
|
|
283
|
+
for (const key of Object.keys(o)) {
|
|
280
284
|
if (['password', 'passwordHash', 'newPassword'].includes(key)) {
|
|
281
285
|
res[key] = '(hidden password)';
|
|
282
286
|
} else {
|
|
@@ -288,7 +292,6 @@ function _inspectAndHide(o) {
|
|
|
288
292
|
return o;
|
|
289
293
|
}
|
|
290
294
|
|
|
291
|
-
|
|
292
295
|
// Hides sensitive values (auth tokens and passwords) in log messages
|
|
293
296
|
function hideSensitiveValues (msg) {
|
|
294
297
|
if (typeof msg !== 'string') return msg;
|
|
@@ -297,8 +300,8 @@ function hideSensitiveValues (msg) {
|
|
|
297
300
|
const mask = '(hidden)';
|
|
298
301
|
|
|
299
302
|
const res = msg
|
|
300
|
-
.replace(tokenRegexp, 'auth='+mask)
|
|
301
|
-
.replace(passwordRegexp, '$1='+mask);
|
|
302
|
-
|
|
303
|
+
.replace(tokenRegexp, 'auth=' + mask)
|
|
304
|
+
.replace(passwordRegexp, '$1=' + mask);
|
|
305
|
+
|
|
303
306
|
return res;
|
|
304
|
-
}
|
|
307
|
+
}
|