@salesforce/core 4.0.0 → 4.0.1
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.txt +1 -1
- package/README.md +93 -44
- package/lib/config/aliasesConfig.d.ts +12 -0
- package/lib/config/aliasesConfig.js +28 -0
- package/lib/config/authInfoConfig.d.ts +19 -0
- package/lib/config/authInfoConfig.js +35 -0
- package/lib/config/config.d.ts +87 -22
- package/lib/config/config.js +117 -65
- package/lib/config/configAggregator.d.ts +41 -35
- package/lib/config/configAggregator.js +102 -73
- package/lib/config/configFile.d.ts +2 -2
- package/lib/config/configFile.js +38 -29
- package/lib/config/configGroup.d.ts +141 -0
- package/lib/config/configGroup.js +225 -0
- package/lib/config/configStore.d.ts +9 -9
- package/lib/config/configStore.js +17 -15
- package/lib/config/envVars.d.ts +15 -9
- package/lib/config/envVars.js +71 -47
- package/lib/config/orgUsersConfig.js +2 -0
- package/lib/config/sandboxOrgConfig.js +2 -0
- package/lib/config/sandboxProcessCache.d.ts +16 -0
- package/lib/config/sandboxProcessCache.js +38 -0
- package/lib/config/tokensConfig.d.ts +10 -0
- package/lib/config/tokensConfig.js +29 -0
- package/lib/config/ttlConfig.d.ts +34 -0
- package/lib/config/ttlConfig.js +50 -0
- package/lib/crypto/crypto.js +15 -22
- package/lib/crypto/keyChain.js +2 -3
- package/lib/crypto/keyChainImpl.d.ts +5 -3
- package/lib/crypto/keyChainImpl.js +58 -61
- package/lib/crypto/secureBuffer.d.ts +1 -1
- package/lib/deviceOauthService.d.ts +3 -3
- package/lib/deviceOauthService.js +27 -25
- package/lib/exported.d.ts +15 -12
- package/lib/exported.js +28 -16
- package/lib/global.d.ts +11 -3
- package/lib/global.js +39 -12
- package/lib/lifecycleEvents.d.ts +1 -1
- package/lib/lifecycleEvents.js +3 -0
- package/lib/logger.d.ts +19 -9
- package/lib/logger.js +112 -86
- package/lib/messages.d.ts +53 -36
- package/lib/messages.js +81 -91
- package/lib/org/authInfo.d.ts +56 -20
- package/lib/org/authInfo.js +232 -131
- package/lib/org/authRemover.d.ts +8 -7
- package/lib/org/authRemover.js +32 -28
- package/lib/org/connection.d.ts +13 -37
- package/lib/org/connection.js +78 -124
- package/lib/org/index.js +5 -1
- package/lib/org/org.d.ts +151 -48
- package/lib/org/org.js +466 -220
- package/lib/org/orgConfigProperties.d.ts +64 -3
- package/lib/org/orgConfigProperties.js +96 -4
- package/lib/org/permissionSetAssignment.js +4 -13
- package/lib/org/scratchOrgCache.d.ts +20 -0
- package/lib/org/scratchOrgCache.js +33 -0
- package/lib/org/scratchOrgCreate.d.ts +28 -17
- package/lib/org/scratchOrgCreate.js +125 -53
- package/lib/org/scratchOrgErrorCodes.d.ts +9 -3
- package/lib/org/scratchOrgErrorCodes.js +34 -17
- package/lib/org/scratchOrgFeatureDeprecation.js +1 -6
- package/lib/org/scratchOrgInfoApi.d.ts +21 -47
- package/lib/org/scratchOrgInfoApi.js +129 -63
- package/lib/org/scratchOrgInfoGenerator.d.ts +6 -5
- package/lib/org/scratchOrgInfoGenerator.js +76 -62
- package/lib/org/scratchOrgLifecycleEvents.d.ts +10 -0
- package/lib/org/scratchOrgLifecycleEvents.js +41 -0
- package/lib/org/scratchOrgSettingsGenerator.d.ts +44 -21
- package/lib/org/scratchOrgSettingsGenerator.js +165 -98
- package/lib/org/scratchOrgTypes.d.ts +43 -0
- package/lib/org/scratchOrgTypes.js +9 -0
- package/lib/org/user.d.ts +1 -1
- package/lib/org/user.js +25 -34
- package/lib/schema/printer.d.ts +6 -0
- package/lib/schema/printer.js +34 -31
- package/lib/schema/validator.d.ts +12 -10
- package/lib/schema/validator.js +56 -76
- package/lib/{sfdxError.d.ts → sfError.d.ts} +12 -20
- package/lib/{sfdxError.js → sfError.js} +40 -30
- package/lib/{sfdxProject.d.ts → sfProject.d.ts} +75 -35
- package/lib/sfProject.js +651 -0
- package/lib/{globalInfo → stateAggregator}/accessors/aliasAccessor.d.ts +27 -12
- package/lib/{globalInfo → stateAggregator}/accessors/aliasAccessor.js +47 -31
- package/lib/stateAggregator/accessors/orgAccessor.d.ts +101 -0
- package/lib/stateAggregator/accessors/orgAccessor.js +240 -0
- package/lib/stateAggregator/accessors/sandboxAccessor.d.ts +8 -0
- package/lib/stateAggregator/accessors/sandboxAccessor.js +28 -0
- package/lib/stateAggregator/accessors/tokenAccessor.d.ts +63 -0
- package/lib/stateAggregator/accessors/tokenAccessor.js +80 -0
- package/lib/stateAggregator/index.d.ts +4 -0
- package/lib/stateAggregator/index.js +27 -0
- package/lib/stateAggregator/stateAggregator.d.ts +25 -0
- package/lib/stateAggregator/stateAggregator.js +46 -0
- package/lib/status/myDomainResolver.d.ts +1 -1
- package/lib/status/myDomainResolver.js +4 -4
- package/lib/status/pollingClient.js +4 -4
- package/lib/status/streamingClient.d.ts +2 -2
- package/lib/status/streamingClient.js +58 -63
- package/lib/status/types.d.ts +2 -2
- package/lib/testSetup.d.ts +206 -75
- package/lib/testSetup.js +463 -165
- package/lib/util/cache.d.ts +2 -2
- package/lib/util/cache.js +6 -6
- package/lib/util/checkLightningDomain.js +3 -4
- package/lib/util/directoryWriter.d.ts +12 -0
- package/lib/util/directoryWriter.js +54 -0
- package/lib/util/getJwtAudienceUrl.js +1 -1
- package/lib/util/internal.d.ts +28 -2
- package/lib/util/internal.js +65 -8
- package/lib/util/jsonXmlTools.js +2 -4
- package/lib/util/mapKeys.d.ts +9 -9
- package/lib/util/mapKeys.js +13 -9
- package/lib/util/sfdc.d.ts +51 -51
- package/lib/util/sfdc.js +74 -79
- package/lib/util/sfdcUrl.d.ts +5 -19
- package/lib/util/sfdcUrl.js +40 -49
- package/lib/util/structuredWriter.d.ts +9 -0
- package/lib/util/structuredWriter.js +3 -0
- package/lib/util/zipWriter.d.ts +8 -6
- package/lib/util/zipWriter.js +13 -13
- package/lib/webOAuthServer.d.ts +20 -6
- package/lib/webOAuthServer.js +102 -56
- package/messageTransformer/messageTransformer.ts +93 -0
- package/messages/auth.md +9 -1
- package/messages/config.md +42 -6
- package/messages/connection.md +8 -0
- package/messages/core.md +10 -0
- package/messages/envVars.md +37 -3
- package/messages/org.md +21 -1
- package/messages/scratchOrgCreate.md +2 -6
- package/messages/scratchOrgErrorCodes.md +17 -1
- package/messages/scratchOrgInfoApi.md +9 -0
- package/messages/scratchOrgInfoGenerator.md +9 -1
- package/package.json +121 -46
- package/CHANGELOG.md +0 -1244
- package/lib/config/keychainConfig.d.ts +0 -19
- package/lib/config/keychainConfig.js +0 -43
- package/lib/globalInfo/accessors/orgAccessor.d.ts +0 -13
- package/lib/globalInfo/accessors/orgAccessor.js +0 -45
- package/lib/globalInfo/accessors/tokenAccessor.d.ts +0 -13
- package/lib/globalInfo/accessors/tokenAccessor.js +0 -35
- package/lib/globalInfo/globalInfoConfig.d.ts +0 -36
- package/lib/globalInfo/globalInfoConfig.js +0 -105
- package/lib/globalInfo/index.d.ts +0 -6
- package/lib/globalInfo/index.js +0 -29
- package/lib/globalInfo/sfdxDataHandler.d.ts +0 -43
- package/lib/globalInfo/sfdxDataHandler.js +0 -217
- package/lib/globalInfo/types.d.ts +0 -39
- package/lib/globalInfo/types.js +0 -10
- package/lib/sfdxProject.js +0 -557
- package/lib/util/fs.d.ts +0 -201
- package/lib/util/fs.js +0 -378
package/lib/logger.js
CHANGED
|
@@ -11,14 +11,15 @@ const events_1 = require("events");
|
|
|
11
11
|
const os = require("os");
|
|
12
12
|
const path = require("path");
|
|
13
13
|
const stream_1 = require("stream");
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
14
16
|
// @ts-ignore
|
|
15
17
|
const Bunyan = require("@salesforce/bunyan");
|
|
16
18
|
const kit_1 = require("@salesforce/kit");
|
|
17
19
|
const ts_types_1 = require("@salesforce/ts-types");
|
|
18
20
|
const Debug = require("debug");
|
|
19
21
|
const global_1 = require("./global");
|
|
20
|
-
const
|
|
21
|
-
const fs_1 = require("./util/fs");
|
|
22
|
+
const sfError_1 = require("./sfError");
|
|
22
23
|
/**
|
|
23
24
|
* Standard `Logger` levels.
|
|
24
25
|
*
|
|
@@ -34,7 +35,7 @@ var LoggerLevel;
|
|
|
34
35
|
LoggerLevel[LoggerLevel["FATAL"] = 60] = "FATAL";
|
|
35
36
|
})(LoggerLevel = exports.LoggerLevel || (exports.LoggerLevel = {}));
|
|
36
37
|
/**
|
|
37
|
-
*
|
|
38
|
+
* `Logger` format types.
|
|
38
39
|
*/
|
|
39
40
|
var LoggerFormat;
|
|
40
41
|
(function (LoggerFormat) {
|
|
@@ -68,10 +69,21 @@ class Logger {
|
|
|
68
69
|
*
|
|
69
70
|
* @param optionsOrName A set of `LoggerOptions` or name to use with the default options.
|
|
70
71
|
*
|
|
71
|
-
* **Throws** *{@link
|
|
72
|
+
* **Throws** *{@link SfError}{ name: 'RedundantRootLoggerError' }* More than one attempt is made to construct the root
|
|
72
73
|
* `Logger`.
|
|
73
74
|
*/
|
|
74
75
|
constructor(optionsOrName) {
|
|
76
|
+
/**
|
|
77
|
+
* The default rotation period for logs. Example '1d' will rotate logs daily (at midnight).
|
|
78
|
+
* See 'period' docs here: https://github.com/forcedotcom/node-bunyan#stream-type-rotating-file
|
|
79
|
+
*/
|
|
80
|
+
this.logRotationPeriod = new kit_1.Env().getString('SF_LOG_ROTATION_PERIOD') ?? '1d';
|
|
81
|
+
/**
|
|
82
|
+
* The number of backup rotated log files to keep.
|
|
83
|
+
* Example: '3' will have the base sf.log file, and the past 3 (period) log files.
|
|
84
|
+
* See 'count' docs here: https://github.com/forcedotcom/node-bunyan#stream-type-rotating-file
|
|
85
|
+
*/
|
|
86
|
+
this.logRotationCount = new kit_1.Env().getNumber('SF_LOG_ROTATION_COUNT') ?? 2;
|
|
75
87
|
/**
|
|
76
88
|
* Whether debug is enabled for this Logger.
|
|
77
89
|
*/
|
|
@@ -102,11 +114,11 @@ class Logger {
|
|
|
102
114
|
options = optionsOrName;
|
|
103
115
|
}
|
|
104
116
|
if (Logger.rootLogger && options.name === Logger.ROOT_NAME) {
|
|
105
|
-
throw new
|
|
117
|
+
throw new sfError_1.SfError('Can not create another root logger.', 'RedundantRootLoggerError');
|
|
106
118
|
}
|
|
107
119
|
// Inspect format to know what logging format to use then delete from options to
|
|
108
120
|
// ensure it doesn't conflict with Bunyan.
|
|
109
|
-
this.format = options.format
|
|
121
|
+
this.format = options.format ?? LoggerFormat.JSON;
|
|
110
122
|
delete options.format;
|
|
111
123
|
// If the log format is LOGFMT, we need to convert any stream(s) into a LOGFMT type stream.
|
|
112
124
|
if (this.format === LoggerFormat.LOGFMT && options.stream) {
|
|
@@ -127,7 +139,7 @@ class Logger {
|
|
|
127
139
|
this.bunyan.streams = [];
|
|
128
140
|
}
|
|
129
141
|
// all SFDX loggers must filter sensitive data
|
|
130
|
-
this.addFilter((...args) =>
|
|
142
|
+
this.addFilter((...args) => filterSecrets(...args));
|
|
131
143
|
if (global_1.Global.getEnvironmentMode() !== global_1.Mode.TEST) {
|
|
132
144
|
Logger.lifecycle.on('uncaughtException', this.uncaughtExceptionHandler);
|
|
133
145
|
Logger.lifecycle.on('exit', this.exitHandler);
|
|
@@ -143,7 +155,8 @@ class Logger {
|
|
|
143
155
|
}
|
|
144
156
|
const rootLogger = (this.rootLogger = new Logger(Logger.ROOT_NAME).setLevel());
|
|
145
157
|
// disable log file writing, if applicable
|
|
146
|
-
|
|
158
|
+
const disableLogFile = new kit_1.Env().getString('SF_DISABLE_LOG_FILE');
|
|
159
|
+
if (disableLogFile !== 'true' && global_1.Global.getEnvironmentMode() !== global_1.Mode.TEST) {
|
|
147
160
|
await rootLogger.addLogFileStream(global_1.Global.LOG_FILE_PATH);
|
|
148
161
|
}
|
|
149
162
|
rootLogger.enableDEBUG();
|
|
@@ -198,13 +211,13 @@ class Logger {
|
|
|
198
211
|
*
|
|
199
212
|
* @param {string} levelName The level name to convert to a `LoggerLevel` enum value.
|
|
200
213
|
*
|
|
201
|
-
* **Throws** *{@link
|
|
214
|
+
* **Throws** *{@link SfError}{ name: 'UnrecognizedLoggerLevelNameError' }* The level name was not case-insensitively recognized as a valid `LoggerLevel` value.
|
|
202
215
|
* @see {@Link LoggerLevel}
|
|
203
216
|
*/
|
|
204
217
|
static getLevelByName(levelName) {
|
|
205
218
|
levelName = levelName.toUpperCase();
|
|
206
219
|
if (!(0, ts_types_1.isKeyOf)(LoggerLevel, levelName)) {
|
|
207
|
-
throw new
|
|
220
|
+
throw new sfError_1.SfError(`Invalid log level "${levelName}".`, 'UnrecognizedLoggerLevelNameError');
|
|
208
221
|
}
|
|
209
222
|
return LoggerLevel[levelName];
|
|
210
223
|
}
|
|
@@ -228,34 +241,37 @@ class Logger {
|
|
|
228
241
|
async addLogFileStream(logFile) {
|
|
229
242
|
try {
|
|
230
243
|
// Check if we have write access to the log file (i.e., we created it already)
|
|
231
|
-
await
|
|
244
|
+
await fs.promises.access(logFile, fs.constants.W_OK);
|
|
232
245
|
}
|
|
233
246
|
catch (err1) {
|
|
234
247
|
try {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
248
|
+
if (process.platform === 'win32') {
|
|
249
|
+
await fs.promises.mkdir(path.dirname(logFile), { recursive: true });
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
await fs.promises.mkdir(path.dirname(logFile), { recursive: true, mode: 0o700 });
|
|
253
|
+
}
|
|
238
254
|
}
|
|
239
255
|
catch (err2) {
|
|
240
|
-
|
|
256
|
+
throw sfError_1.SfError.wrap(err2);
|
|
241
257
|
}
|
|
242
258
|
try {
|
|
243
|
-
await
|
|
259
|
+
await fs.promises.writeFile(logFile, '', { mode: '600' });
|
|
244
260
|
}
|
|
245
261
|
catch (err3) {
|
|
246
|
-
throw
|
|
262
|
+
throw sfError_1.SfError.wrap(err3);
|
|
247
263
|
}
|
|
248
264
|
}
|
|
249
265
|
// avoid multiple streams to same log file
|
|
250
266
|
if (!this.bunyan.streams.find(
|
|
251
267
|
// No bunyan typings
|
|
252
268
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
253
|
-
(stream) => stream.type === 'file' && stream.path === logFile)) {
|
|
254
|
-
// TODO: rotating-file
|
|
255
|
-
// https://github.com/trentm/node-bunyan#stream-type-rotating-file
|
|
269
|
+
(stream) => stream.type === 'rotating-file' && stream.path === logFile)) {
|
|
256
270
|
this.addStream({
|
|
257
|
-
type: 'file',
|
|
271
|
+
type: 'rotating-file',
|
|
258
272
|
path: logFile,
|
|
273
|
+
period: this.logRotationPeriod,
|
|
274
|
+
count: this.logRotationCount,
|
|
259
275
|
level: this.bunyan.level(),
|
|
260
276
|
});
|
|
261
277
|
}
|
|
@@ -268,34 +284,37 @@ class Logger {
|
|
|
268
284
|
addLogFileStreamSync(logFile) {
|
|
269
285
|
try {
|
|
270
286
|
// Check if we have write access to the log file (i.e., we created it already)
|
|
271
|
-
|
|
287
|
+
fs.accessSync(logFile, fs.constants.W_OK);
|
|
272
288
|
}
|
|
273
289
|
catch (err1) {
|
|
274
290
|
try {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
291
|
+
if (process.platform === 'win32') {
|
|
292
|
+
fs.mkdirSync(path.dirname(logFile), { recursive: true });
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
fs.mkdirSync(path.dirname(logFile), { recursive: true, mode: 0o700 });
|
|
296
|
+
}
|
|
278
297
|
}
|
|
279
298
|
catch (err2) {
|
|
280
|
-
|
|
299
|
+
throw sfError_1.SfError.wrap(err2);
|
|
281
300
|
}
|
|
282
301
|
try {
|
|
283
|
-
|
|
302
|
+
fs.writeFileSync(logFile, '', { mode: '600' });
|
|
284
303
|
}
|
|
285
304
|
catch (err3) {
|
|
286
|
-
throw
|
|
305
|
+
throw sfError_1.SfError.wrap(err3);
|
|
287
306
|
}
|
|
288
307
|
}
|
|
289
308
|
// avoid multiple streams to same log file
|
|
290
309
|
if (!this.bunyan.streams.find(
|
|
291
310
|
// No bunyan typings
|
|
292
311
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
293
|
-
(stream) => stream.type === 'file' && stream.path === logFile)) {
|
|
294
|
-
// TODO: rotating-file
|
|
295
|
-
// https://github.com/trentm/node-bunyan#stream-type-rotating-file
|
|
312
|
+
(stream) => stream.type === 'rotating-file' && stream.path === logFile)) {
|
|
296
313
|
this.addStream({
|
|
297
|
-
type: 'file',
|
|
314
|
+
type: 'rotating-file',
|
|
298
315
|
path: logFile,
|
|
316
|
+
period: this.logRotationPeriod,
|
|
317
|
+
count: this.logRotationCount,
|
|
299
318
|
level: this.bunyan.level(),
|
|
300
319
|
});
|
|
301
320
|
}
|
|
@@ -319,7 +338,7 @@ class Logger {
|
|
|
319
338
|
*
|
|
320
339
|
* @param {LoggerLevelValue} [level] The logger level.
|
|
321
340
|
*
|
|
322
|
-
* **Throws** *{@link
|
|
341
|
+
* **Throws** *{@link SfError}{ name: 'UnrecognizedLoggerLevelNameError' }* A value of `level` read from `SFDX_LOG_LEVEL`
|
|
323
342
|
* was invalid.
|
|
324
343
|
*
|
|
325
344
|
* ```
|
|
@@ -335,7 +354,8 @@ class Logger {
|
|
|
335
354
|
*/
|
|
336
355
|
setLevel(level) {
|
|
337
356
|
if (level == null) {
|
|
338
|
-
|
|
357
|
+
const logLevelFromEnvVar = new kit_1.Env().getString('SF_LOG_LEVEL');
|
|
358
|
+
level = logLevelFromEnvVar ? Logger.getLevelByName(logLevelFromEnvVar) : Logger.DEFAULT_LEVEL;
|
|
339
359
|
}
|
|
340
360
|
this.bunyan.level(level);
|
|
341
361
|
return this;
|
|
@@ -343,7 +363,9 @@ class Logger {
|
|
|
343
363
|
/**
|
|
344
364
|
* Gets the underlying Bunyan logger.
|
|
345
365
|
*/
|
|
346
|
-
//
|
|
366
|
+
// leave this typed as any to keep if from trying to export the type from the untyped bunyan module
|
|
367
|
+
// this prevents consumers from getting node_modules/@salesforce/core/lib/logger.d.ts:281:24 - error TS2304: Cannot find name 'Bunyan'.
|
|
368
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
|
|
347
369
|
getBunyanLogger() {
|
|
348
370
|
return this.bunyan;
|
|
349
371
|
}
|
|
@@ -400,7 +422,8 @@ class Logger {
|
|
|
400
422
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
401
423
|
this.bunyan.streams.forEach(async (stream) => {
|
|
402
424
|
if (stream.type === 'file') {
|
|
403
|
-
|
|
425
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
426
|
+
content += await fs.promises.readFile(stream.path, 'utf8');
|
|
404
427
|
}
|
|
405
428
|
});
|
|
406
429
|
return content;
|
|
@@ -412,7 +435,6 @@ class Logger {
|
|
|
412
435
|
* @param filter A function with signature `(...args: any[]) => any[]` that transforms log message arguments.
|
|
413
436
|
*/
|
|
414
437
|
addFilter(filter) {
|
|
415
|
-
// eslint disable-line @typescript-eslint/no-explicit-any
|
|
416
438
|
if (!this.bunyan.filters) {
|
|
417
439
|
this.bunyan.filters = [];
|
|
418
440
|
}
|
|
@@ -421,8 +443,7 @@ class Logger {
|
|
|
421
443
|
/**
|
|
422
444
|
* Close the logger, including any streams, and remove all listeners.
|
|
423
445
|
*
|
|
424
|
-
* @param fn A function with signature `(stream: LoggerStream) => void` to call for each stream with
|
|
425
|
-
* the stream as an arg.
|
|
446
|
+
* @param fn A function with signature `(stream: LoggerStream) => void` to call for each stream with the stream as an arg.
|
|
426
447
|
*/
|
|
427
448
|
close(fn) {
|
|
428
449
|
if (this.bunyan.streams) {
|
|
@@ -452,7 +473,7 @@ class Logger {
|
|
|
452
473
|
*/
|
|
453
474
|
child(name, fields = {}) {
|
|
454
475
|
if (!name) {
|
|
455
|
-
throw new
|
|
476
|
+
throw new sfError_1.SfError('LoggerNameRequired');
|
|
456
477
|
}
|
|
457
478
|
fields.log = name;
|
|
458
479
|
const child = new Logger(name);
|
|
@@ -480,6 +501,7 @@ class Logger {
|
|
|
480
501
|
*/
|
|
481
502
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
482
503
|
trace(...args) {
|
|
504
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
483
505
|
this.bunyan.trace(this.applyFilters(LoggerLevel.TRACE, ...args));
|
|
484
506
|
return this;
|
|
485
507
|
}
|
|
@@ -542,8 +564,10 @@ class Logger {
|
|
|
542
564
|
*/
|
|
543
565
|
fatal(...args) {
|
|
544
566
|
// always show fatal to stderr
|
|
545
|
-
//
|
|
546
|
-
console.error(
|
|
567
|
+
// IMPORTANT:
|
|
568
|
+
// Do not use console.error() here, if fatal() is called from the uncaughtException handler, it
|
|
569
|
+
// will be re-thrown and caught again by the uncaughtException handler, causing an infinite loop.
|
|
570
|
+
console.log(...args); // eslint-disable-line no-console
|
|
547
571
|
this.bunyan.fatal(this.applyFilters(LoggerLevel.FATAL, ...args));
|
|
548
572
|
return this;
|
|
549
573
|
}
|
|
@@ -561,6 +585,7 @@ class Logger {
|
|
|
561
585
|
stream: new stream_1.Writable({
|
|
562
586
|
write: (chunk, encoding, next) => {
|
|
563
587
|
try {
|
|
588
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
564
589
|
const json = (0, kit_1.parseJsonMap)(chunk.toString());
|
|
565
590
|
const logLevel = (0, ts_types_1.ensureNumber)(json.level);
|
|
566
591
|
if (this.getLevel() <= logLevel) {
|
|
@@ -595,11 +620,14 @@ class Logger {
|
|
|
595
620
|
}
|
|
596
621
|
return args && args.length === 1 ? args[0] : args;
|
|
597
622
|
}
|
|
623
|
+
// eslint-disable-next-line class-methods-use-this
|
|
598
624
|
createLogFmtFormatterStream(loggerStream) {
|
|
599
625
|
const logFmtWriteableStream = new stream_1.Writable({
|
|
600
626
|
write: (chunk, enc, cb) => {
|
|
601
627
|
try {
|
|
628
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
602
629
|
const parsedJSON = JSON.parse(chunk.toString());
|
|
630
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
603
631
|
const keys = Object.keys(parsedJSON);
|
|
604
632
|
let logEntry = '';
|
|
605
633
|
keys.forEach((key) => {
|
|
@@ -662,50 +690,48 @@ const FILTERED_KEYS = [
|
|
|
662
690
|
{ name: 'sfdxauthurl', regex: 'sfdx[^\'"]*auth[^\'"]*url' },
|
|
663
691
|
];
|
|
664
692
|
// SFDX code and plugins should never show tokens or connect app information in the logs
|
|
665
|
-
const
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
_arg = '<Buffer>';
|
|
675
|
-
}
|
|
676
|
-
else if ((0, ts_types_1.isObject)(arg)) {
|
|
677
|
-
_arg = JSON.stringify(arg);
|
|
678
|
-
}
|
|
679
|
-
else if ((0, ts_types_1.isString)(arg)) {
|
|
680
|
-
_arg = arg;
|
|
681
|
-
}
|
|
682
|
-
else {
|
|
683
|
-
_arg = '';
|
|
684
|
-
}
|
|
685
|
-
const HIDDEN = 'HIDDEN';
|
|
686
|
-
FILTERED_KEYS.forEach((key) => {
|
|
687
|
-
let expElement = key;
|
|
688
|
-
let expName = key;
|
|
689
|
-
// Filtered keys can be strings or objects containing regular expression components.
|
|
690
|
-
if ((0, ts_types_1.isPlainObject)(key)) {
|
|
691
|
-
expElement = key.regex;
|
|
692
|
-
expName = key.name;
|
|
693
|
-
}
|
|
694
|
-
const hiddenAttrMessage = `"<${expName} - ${HIDDEN}>"`;
|
|
695
|
-
// Match all json attribute values case insensitive: ex. {" Access*^&(*()^* Token " : " 45143075913458901348905 \n\t" ...}
|
|
696
|
-
const regexTokens = new RegExp(`(['"][^'"]*${expElement}[^'"]*['"]\\s*:\\s*)['"][^'"]*['"]`, 'gi');
|
|
697
|
-
_arg = _arg.replace(regexTokens, `$1${hiddenAttrMessage}`);
|
|
698
|
-
// Match all key value attribute case insensitive: ex. {" key\t" : ' access_token ' , " value " : " dsafgasr431 " ....}
|
|
699
|
-
const keyRegex = new RegExp(`(['"]\\s*key\\s*['"]\\s*:)\\s*['"]\\s*${expElement}\\s*['"]\\s*.\\s*['"]\\s*value\\s*['"]\\s*:\\s*['"]\\s*[^'"]*['"]`, 'gi');
|
|
700
|
-
_arg = _arg.replace(keyRegex, `$1${hiddenAttrMessage}`);
|
|
701
|
-
});
|
|
702
|
-
_arg = _arg.replace(/(00D\w{12,15})![.\w]*/, `<${HIDDEN}>`);
|
|
703
|
-
// return an object if an object was logged; otherwise return the filtered string.
|
|
704
|
-
return (0, ts_types_1.isObject)(arg) ? (0, kit_1.parseJson)(_arg) : _arg;
|
|
693
|
+
const filterSecrets = (...args) => args.map((arg) => {
|
|
694
|
+
if ((0, ts_types_1.isArray)(arg)) {
|
|
695
|
+
return filterSecrets(...arg);
|
|
696
|
+
}
|
|
697
|
+
if (arg) {
|
|
698
|
+
let mutableArg;
|
|
699
|
+
// Normalize all objects into a string. This includes errors.
|
|
700
|
+
if (arg instanceof Buffer) {
|
|
701
|
+
mutableArg = '<Buffer>';
|
|
705
702
|
}
|
|
706
|
-
else {
|
|
707
|
-
|
|
703
|
+
else if ((0, ts_types_1.isObject)(arg)) {
|
|
704
|
+
mutableArg = JSON.stringify(arg);
|
|
708
705
|
}
|
|
709
|
-
|
|
710
|
-
|
|
706
|
+
else if ((0, ts_types_1.isString)(arg)) {
|
|
707
|
+
mutableArg = arg;
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
mutableArg = '';
|
|
711
|
+
}
|
|
712
|
+
const HIDDEN = 'HIDDEN';
|
|
713
|
+
FILTERED_KEYS.forEach((key) => {
|
|
714
|
+
let expElement = key;
|
|
715
|
+
let expName = key;
|
|
716
|
+
// Filtered keys can be strings or objects containing regular expression components.
|
|
717
|
+
if ((0, ts_types_1.isPlainObject)(key)) {
|
|
718
|
+
expElement = key.regex;
|
|
719
|
+
expName = key.name;
|
|
720
|
+
}
|
|
721
|
+
const hiddenAttrMessage = `"<${expName} - ${HIDDEN}>"`;
|
|
722
|
+
// Match all json attribute values case insensitive: ex. {" Access*^&(*()^* Token " : " 45143075913458901348905 \n\t" ...}
|
|
723
|
+
const regexTokens = new RegExp(`(['"][^'"]*${expElement}[^'"]*['"]\\s*:\\s*)['"][^'"]*['"]`, 'gi');
|
|
724
|
+
mutableArg = mutableArg.replace(regexTokens, `$1${hiddenAttrMessage}`);
|
|
725
|
+
// Match all key value attribute case insensitive: ex. {" key\t" : ' access_token ' , " value " : " dsafgasr431 " ....}
|
|
726
|
+
const keyRegex = new RegExp(`(['"]\\s*key\\s*['"]\\s*:)\\s*['"]\\s*${expElement}\\s*['"]\\s*.\\s*['"]\\s*value\\s*['"]\\s*:\\s*['"]\\s*[^'"]*['"]`, 'gi');
|
|
727
|
+
mutableArg = mutableArg.replace(keyRegex, `$1${hiddenAttrMessage}`);
|
|
728
|
+
});
|
|
729
|
+
mutableArg = mutableArg.replace(/(00D\w{12,15})![.\w]*/, `<${HIDDEN}>`);
|
|
730
|
+
// return an object if an object was logged; otherwise return the filtered string.
|
|
731
|
+
return (0, ts_types_1.isObject)(arg) ? (0, kit_1.parseJson)(mutableArg) : mutableArg;
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
return arg;
|
|
735
|
+
}
|
|
736
|
+
});
|
|
711
737
|
//# sourceMappingURL=logger.js.map
|
package/lib/messages.d.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { AnyJson } from '@salesforce/ts-types';
|
|
2
|
-
import {
|
|
3
|
-
export
|
|
2
|
+
import { SfError } from './sfError';
|
|
3
|
+
export type Tokens = Array<string | boolean | number | null | undefined>;
|
|
4
|
+
export type StructuredMessage = {
|
|
5
|
+
message: string;
|
|
6
|
+
name: string;
|
|
7
|
+
actions?: string[];
|
|
8
|
+
};
|
|
4
9
|
/**
|
|
5
10
|
* A loader function to return messages.
|
|
6
11
|
*
|
|
7
12
|
* @param locale The local set by the framework.
|
|
8
13
|
*/
|
|
9
|
-
export
|
|
10
|
-
export
|
|
14
|
+
export type LoaderFunction<T extends string> = (locale: string) => Messages<T>;
|
|
15
|
+
export type StoredMessage = string | string[] | {
|
|
11
16
|
[s: string]: StoredMessage;
|
|
12
17
|
};
|
|
13
|
-
export
|
|
18
|
+
export type StoredMessageMap = Map<string, StoredMessage>;
|
|
14
19
|
/**
|
|
15
20
|
* The core message framework manages messages and allows them to be accessible by
|
|
16
21
|
* all plugins and consumers of sfdx-core. It is set up to handle localization down
|
|
@@ -75,14 +80,14 @@ export declare type StoredMessageMap = Map<string, StoredMessage>;
|
|
|
75
80
|
*
|
|
76
81
|
* // Now you can use the messages from anywhere in your code or file.
|
|
77
82
|
* // If using importMessageDirectory, the bundle name is the file name.
|
|
78
|
-
* const messages: Messages = Messages.
|
|
83
|
+
* const messages: Messages = Messages.loadMessages(packageName, bundleName);
|
|
79
84
|
*
|
|
80
85
|
* // Messages now contains all the message in the bundleName file.
|
|
81
86
|
* messages.getMessage('authInfoCreationError');
|
|
82
87
|
* ```
|
|
83
88
|
*/
|
|
84
89
|
export declare class Messages<T extends string> {
|
|
85
|
-
|
|
90
|
+
readonly messages: StoredMessageMap;
|
|
86
91
|
private static loaders;
|
|
87
92
|
private static bundles;
|
|
88
93
|
/**
|
|
@@ -96,7 +101,7 @@ export declare class Messages<T extends string> {
|
|
|
96
101
|
/**
|
|
97
102
|
* Create a new messages bundle.
|
|
98
103
|
*
|
|
99
|
-
* **Note:** Use {Messages.
|
|
104
|
+
* **Note:** Use {Messages.loadMessages} unless you are writing your own loader function.
|
|
100
105
|
*
|
|
101
106
|
* @param bundleName The bundle name.
|
|
102
107
|
* @param locale The locale.
|
|
@@ -117,7 +122,7 @@ export declare class Messages<T extends string> {
|
|
|
117
122
|
*/
|
|
118
123
|
static getLocale(): string;
|
|
119
124
|
/**
|
|
120
|
-
* Set a custom loader function for a package and bundle that will be called on {@link Messages.
|
|
125
|
+
* Set a custom loader function for a package and bundle that will be called on {@link Messages.loadMessages}.
|
|
121
126
|
*
|
|
122
127
|
* @param packageName The npm package name.
|
|
123
128
|
* @param bundle The name of the bundle.
|
|
@@ -143,7 +148,7 @@ export declare class Messages<T extends string> {
|
|
|
143
148
|
static importMessageFile(packageName: string, filePath: string): void;
|
|
144
149
|
/**
|
|
145
150
|
* Import all json and js files in a messages directory. Use the file name as the bundle key when
|
|
146
|
-
* {@link Messages.
|
|
151
|
+
* {@link Messages.loadMessages} is called. By default, we're assuming the moduleDirectoryPart is a
|
|
147
152
|
* typescript project and will truncate to root path (where the package.json file is). If your messages
|
|
148
153
|
* directory is in another spot or you are not using typescript, pass in false for truncateToProjectPath.
|
|
149
154
|
*
|
|
@@ -162,38 +167,15 @@ export declare class Messages<T extends string> {
|
|
|
162
167
|
* Load messages for a given package and bundle. If the bundle is not already cached, use the loader function
|
|
163
168
|
* created from {@link Messages.setLoaderFunction} or {@link Messages.importMessagesDirectory}.
|
|
164
169
|
*
|
|
165
|
-
* **NOTE: Use {@link Messages.load} instead for safe message validation and usage.**
|
|
166
|
-
*
|
|
167
170
|
* ```typescript
|
|
168
171
|
* Messages.importMessagesDirectory(__dirname);
|
|
169
|
-
* const messages = Messages.
|
|
172
|
+
* const messages = Messages.loadMessages('packageName', 'bundleName');
|
|
170
173
|
* ```
|
|
171
174
|
*
|
|
172
175
|
* @param packageName The name of the npm package.
|
|
173
176
|
* @param bundleName The name of the bundle to load.
|
|
174
177
|
*/
|
|
175
178
|
static loadMessages(packageName: string, bundleName: string): Messages<string>;
|
|
176
|
-
/**
|
|
177
|
-
* Load messages for a given package and bundle. If the bundle is not already cached, use the loader function
|
|
178
|
-
* created from {@link Messages.setLoaderFunction} or {@link Messages.importMessagesDirectory}.
|
|
179
|
-
*
|
|
180
|
-
* The message keys that will be used must be passed in for validation. This prevents runtime errors if messages are used but not defined.
|
|
181
|
-
*
|
|
182
|
-
* **NOTE: This should be defined at the top of the file so validation is done at load time rather than runtime.**
|
|
183
|
-
*
|
|
184
|
-
* ```typescript
|
|
185
|
-
* Messages.importMessagesDirectory(__dirname);
|
|
186
|
-
* const messages = Messages.load('packageName', 'bundleName', [
|
|
187
|
-
* 'messageKey1',
|
|
188
|
-
* 'messageKey2',
|
|
189
|
-
* ]);
|
|
190
|
-
* ```
|
|
191
|
-
*
|
|
192
|
-
* @param packageName The name of the npm package.
|
|
193
|
-
* @param bundleName The name of the bundle to load.
|
|
194
|
-
* @param keys The message keys that will be used.
|
|
195
|
-
*/
|
|
196
|
-
static load<T extends string>(packageName: string, bundleName: string, keys: [T, ...T[]]): Messages<T>;
|
|
197
179
|
/**
|
|
198
180
|
* Check if a bundle already been loaded.
|
|
199
181
|
*
|
|
@@ -244,9 +226,44 @@ export declare class Messages<T extends string> {
|
|
|
244
226
|
* @param key The key of the error message.
|
|
245
227
|
* @param tokens The error message tokens.
|
|
246
228
|
* @param actionTokens The action messages tokens.
|
|
247
|
-
* @param exitCodeOrCause The exit code which will be used by SfdxCommand or
|
|
229
|
+
* @param exitCodeOrCause The exit code which will be used by SfdxCommand or the underlying error that caused this error to be raised.
|
|
248
230
|
* @param cause The underlying error that caused this error to be raised.
|
|
249
231
|
*/
|
|
250
|
-
createError(key: T, tokens?: Tokens, actionTokens?: Tokens, exitCodeOrCause?: number | Error, cause?: Error):
|
|
232
|
+
createError(key: T, tokens?: Tokens, actionTokens?: Tokens, exitCodeOrCause?: number | Error, cause?: Error): SfError;
|
|
233
|
+
/**
|
|
234
|
+
* Convenience method to create warning using message labels.
|
|
235
|
+
*
|
|
236
|
+
* `warning.name` will be the upper-cased key, remove prefixed `warning.` and will always end in Warning.
|
|
237
|
+
* `warning.actions` will be loaded using `${key}.actions` if available.
|
|
238
|
+
*
|
|
239
|
+
* @param key The key of the warning message.
|
|
240
|
+
* @param tokens The warning message tokens.
|
|
241
|
+
* @param actionTokens The action messages tokens.
|
|
242
|
+
*/
|
|
243
|
+
createWarning(key: T, tokens?: Tokens, actionTokens?: Tokens): StructuredMessage;
|
|
244
|
+
/**
|
|
245
|
+
* Convenience method to create info using message labels.
|
|
246
|
+
*
|
|
247
|
+
* `info.name` will be the upper-cased key, remove prefixed `info.` and will always end in Info.
|
|
248
|
+
* `info.actions` will be loaded using `${key}.actions` if available.
|
|
249
|
+
*
|
|
250
|
+
* @param key The key of the warning message.
|
|
251
|
+
* @param tokens The warning message tokens.
|
|
252
|
+
* @param actionTokens The action messages tokens.
|
|
253
|
+
*/
|
|
254
|
+
createInfo(key: T, tokens?: Tokens, actionTokens?: Tokens): StructuredMessage;
|
|
255
|
+
/**
|
|
256
|
+
* Formats message contents given a message type, key, tokens and actions tokens
|
|
257
|
+
*
|
|
258
|
+
* `<type>.name` will be the upper-cased key, remove prefixed `<type>.` and will always end in 'Error | Warning | Info.
|
|
259
|
+
* `<type>.actions` will be loaded using `${key}.actions` if available.
|
|
260
|
+
*
|
|
261
|
+
* @param type The type of the message set must 'error' | 'warning' | 'info'.
|
|
262
|
+
* @param key The key of the warning message.
|
|
263
|
+
* @param tokens The warning message tokens.
|
|
264
|
+
* @param actionTokens The action messages tokens.
|
|
265
|
+
* @param preserveName Do not require that the name end in the type ('error' | 'warning' | 'info').
|
|
266
|
+
*/
|
|
267
|
+
private formatMessageContents;
|
|
251
268
|
private getMessageWithMap;
|
|
252
269
|
}
|