@karmaniverous/get-dotenv 4.5.0 → 4.5.2
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/dist/getdotenv.cli.mjs +496 -378
- package/dist/index.cjs +496 -378
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +496 -378
- package/package.json +16 -16
package/dist/getdotenv.cli.mjs
CHANGED
|
@@ -6,8 +6,8 @@ import fs$v, { writeFileSync as writeFileSync$1, statSync as statSync$1, readFil
|
|
|
6
6
|
import process$3, { platform as platform$1, hrtime, execPath, execArgv } from 'node:process';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { StringDecoder } from 'node:string_decoder';
|
|
9
|
-
import tty from 'node:tty';
|
|
10
9
|
import { debuglog, stripVTControlCharacters, inspect, promisify as promisify$1, callbackify, aborted } from 'node:util';
|
|
10
|
+
import tty from 'node:tty';
|
|
11
11
|
import require$$0$3 from 'child_process';
|
|
12
12
|
import require$$0$2, { join } from 'path';
|
|
13
13
|
import require$$0$1 from 'fs';
|
|
@@ -4120,56 +4120,220 @@ const getSubprocessResult = ({stdout}) => {
|
|
|
4120
4120
|
throw new TypeError(`Unexpected "${typeof stdout}" stdout in template expression`);
|
|
4121
4121
|
};
|
|
4122
4122
|
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
const
|
|
4123
|
+
const isStandardStream = stream => STANDARD_STREAMS.includes(stream);
|
|
4124
|
+
const STANDARD_STREAMS = [process$3.stdin, process$3.stdout, process$3.stderr];
|
|
4125
|
+
const STANDARD_STREAMS_ALIASES = ['stdin', 'stdout', 'stderr'];
|
|
4126
|
+
const getStreamName = fdNumber => STANDARD_STREAMS_ALIASES[fdNumber] ?? `stdio[${fdNumber}]`;
|
|
4126
4127
|
|
|
4127
|
-
//
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
const
|
|
4128
|
+
// Some options can have different values for `stdout`/`stderr`/`fd3`.
|
|
4129
|
+
// This normalizes those to array of values.
|
|
4130
|
+
// For example, `{verbose: {stdout: 'none', stderr: 'full'}}` becomes `{verbose: ['none', 'none', 'full']}`
|
|
4131
|
+
const normalizeFdSpecificOptions = options => {
|
|
4132
|
+
const optionsCopy = {...options};
|
|
4131
4133
|
|
|
4132
|
-
const
|
|
4133
|
-
|
|
4134
|
+
for (const optionName of FD_SPECIFIC_OPTIONS) {
|
|
4135
|
+
optionsCopy[optionName] = normalizeFdSpecificOption(options, optionName);
|
|
4136
|
+
}
|
|
4137
|
+
|
|
4138
|
+
return optionsCopy;
|
|
4139
|
+
};
|
|
4140
|
+
|
|
4141
|
+
const normalizeFdSpecificOption = (options, optionName) => {
|
|
4142
|
+
const optionBaseArray = Array.from({length: getStdioLength(options) + 1});
|
|
4143
|
+
const optionArray = normalizeFdSpecificValue(options[optionName], optionBaseArray, optionName);
|
|
4144
|
+
return addDefaultValue$1(optionArray, optionName);
|
|
4145
|
+
};
|
|
4146
|
+
|
|
4147
|
+
const getStdioLength = ({stdio}) => Array.isArray(stdio)
|
|
4148
|
+
? Math.max(stdio.length, STANDARD_STREAMS_ALIASES.length)
|
|
4149
|
+
: STANDARD_STREAMS_ALIASES.length;
|
|
4150
|
+
|
|
4151
|
+
const normalizeFdSpecificValue = (optionValue, optionArray, optionName) => isPlainObject(optionValue)
|
|
4152
|
+
? normalizeOptionObject(optionValue, optionArray, optionName)
|
|
4153
|
+
: optionArray.fill(optionValue);
|
|
4154
|
+
|
|
4155
|
+
const normalizeOptionObject = (optionValue, optionArray, optionName) => {
|
|
4156
|
+
for (const fdName of Object.keys(optionValue).sort(compareFdName)) {
|
|
4157
|
+
for (const fdNumber of parseFdName(fdName, optionName, optionArray)) {
|
|
4158
|
+
optionArray[fdNumber] = optionValue[fdName];
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
|
|
4162
|
+
return optionArray;
|
|
4163
|
+
};
|
|
4164
|
+
|
|
4165
|
+
// Ensure priority order when setting both `stdout`/`stderr`, `fd1`/`fd2`, and `all`
|
|
4166
|
+
const compareFdName = (fdNameA, fdNameB) => getFdNameOrder(fdNameA) < getFdNameOrder(fdNameB) ? 1 : -1;
|
|
4167
|
+
|
|
4168
|
+
const getFdNameOrder = fdName => {
|
|
4169
|
+
if (fdName === 'stdout' || fdName === 'stderr') {
|
|
4170
|
+
return 0;
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
return fdName === 'all' ? 2 : 1;
|
|
4174
|
+
};
|
|
4175
|
+
|
|
4176
|
+
const parseFdName = (fdName, optionName, optionArray) => {
|
|
4177
|
+
if (fdName === 'ipc') {
|
|
4178
|
+
return [optionArray.length - 1];
|
|
4179
|
+
}
|
|
4180
|
+
|
|
4181
|
+
const fdNumber = parseFd(fdName);
|
|
4182
|
+
if (fdNumber === undefined || fdNumber === 0) {
|
|
4183
|
+
throw new TypeError(`"${optionName}.${fdName}" is invalid.
|
|
4184
|
+
It must be "${optionName}.stdout", "${optionName}.stderr", "${optionName}.all", "${optionName}.ipc", or "${optionName}.fd3", "${optionName}.fd4" (and so on).`);
|
|
4185
|
+
}
|
|
4186
|
+
|
|
4187
|
+
if (fdNumber >= optionArray.length) {
|
|
4188
|
+
throw new TypeError(`"${optionName}.${fdName}" is invalid: that file descriptor does not exist.
|
|
4189
|
+
Please set the "stdio" option to ensure that file descriptor exists.`);
|
|
4190
|
+
}
|
|
4191
|
+
|
|
4192
|
+
return fdNumber === 'all' ? [1, 2] : [fdNumber];
|
|
4193
|
+
};
|
|
4194
|
+
|
|
4195
|
+
// Use the same syntax for fd-specific options and the `from`/`to` options
|
|
4196
|
+
const parseFd = fdName => {
|
|
4197
|
+
if (fdName === 'all') {
|
|
4198
|
+
return fdName;
|
|
4199
|
+
}
|
|
4200
|
+
|
|
4201
|
+
if (STANDARD_STREAMS_ALIASES.includes(fdName)) {
|
|
4202
|
+
return STANDARD_STREAMS_ALIASES.indexOf(fdName);
|
|
4203
|
+
}
|
|
4204
|
+
|
|
4205
|
+
const regexpResult = FD_REGEXP.exec(fdName);
|
|
4206
|
+
if (regexpResult !== null) {
|
|
4207
|
+
return Number(regexpResult[1]);
|
|
4208
|
+
}
|
|
4209
|
+
};
|
|
4210
|
+
|
|
4211
|
+
const FD_REGEXP = /^fd(\d+)$/;
|
|
4212
|
+
|
|
4213
|
+
const addDefaultValue$1 = (optionArray, optionName) => optionArray.map(optionValue => optionValue === undefined
|
|
4214
|
+
? DEFAULT_OPTIONS[optionName]
|
|
4215
|
+
: optionValue);
|
|
4134
4216
|
|
|
4135
4217
|
// Default value for the `verbose` option
|
|
4136
4218
|
const verboseDefault = debuglog('execa').enabled ? 'full' : 'none';
|
|
4137
4219
|
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4220
|
+
const DEFAULT_OPTIONS = {
|
|
4221
|
+
lines: false,
|
|
4222
|
+
buffer: true,
|
|
4223
|
+
maxBuffer: 1000 * 1000 * 100,
|
|
4224
|
+
verbose: verboseDefault,
|
|
4225
|
+
stripFinalNewline: true,
|
|
4143
4226
|
};
|
|
4144
4227
|
|
|
4145
|
-
//
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
//
|
|
4149
|
-
|
|
4150
|
-
|
|
4228
|
+
// List of options which can have different values for `stdout`/`stderr`
|
|
4229
|
+
const FD_SPECIFIC_OPTIONS = ['lines', 'buffer', 'maxBuffer', 'verbose', 'stripFinalNewline'];
|
|
4230
|
+
|
|
4231
|
+
// Retrieve fd-specific option
|
|
4232
|
+
const getFdSpecificValue = (optionArray, fdNumber) => fdNumber === 'ipc'
|
|
4233
|
+
? optionArray.at(-1)
|
|
4234
|
+
: optionArray[fdNumber];
|
|
4151
4235
|
|
|
4152
4236
|
// The `verbose` option can have different values for `stdout`/`stderr`
|
|
4153
|
-
const isVerbose = verbose => verbose
|
|
4237
|
+
const isVerbose = ({verbose}, fdNumber) => getFdVerbose(verbose, fdNumber) !== 'none';
|
|
4154
4238
|
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
if (verboseItem === false) {
|
|
4158
|
-
throw new TypeError('The "verbose: false" option was renamed to "verbose: \'none\'".');
|
|
4159
|
-
}
|
|
4239
|
+
// Whether IPC and output and logged
|
|
4240
|
+
const isFullVerbose = ({verbose}, fdNumber) => !['none', 'short'].includes(getFdVerbose(verbose, fdNumber));
|
|
4160
4241
|
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4242
|
+
// The `verbose` option can be a function to customize logging
|
|
4243
|
+
const getVerboseFunction = ({verbose}, fdNumber) => {
|
|
4244
|
+
const fdVerbose = getFdVerbose(verbose, fdNumber);
|
|
4245
|
+
return isVerboseFunction(fdVerbose) ? fdVerbose : undefined;
|
|
4246
|
+
};
|
|
4164
4247
|
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4248
|
+
// When using `verbose: {stdout, stderr, fd3, ipc}`:
|
|
4249
|
+
// - `verbose.stdout|stderr|fd3` is used for 'output'
|
|
4250
|
+
// - `verbose.ipc` is only used for 'ipc'
|
|
4251
|
+
// - highest `verbose.*` value is used for 'command', 'error' and 'duration'
|
|
4252
|
+
const getFdVerbose = (verbose, fdNumber) => fdNumber === undefined
|
|
4253
|
+
? getFdGenericVerbose(verbose)
|
|
4254
|
+
: getFdSpecificValue(verbose, fdNumber);
|
|
4255
|
+
|
|
4256
|
+
// When using `verbose: {stdout, stderr, fd3, ipc}` and logging is not specific to a file descriptor.
|
|
4257
|
+
// We then use the highest `verbose.*` value, using the following order:
|
|
4258
|
+
// - function > 'full' > 'short' > 'none'
|
|
4259
|
+
// - if several functions are defined: stdout > stderr > fd3 > ipc
|
|
4260
|
+
const getFdGenericVerbose = verbose => verbose.find(fdVerbose => isVerboseFunction(fdVerbose))
|
|
4261
|
+
?? VERBOSE_VALUES.findLast(fdVerbose => verbose.includes(fdVerbose));
|
|
4262
|
+
|
|
4263
|
+
// Whether the `verbose` option is customized using a function
|
|
4264
|
+
const isVerboseFunction = fdVerbose => typeof fdVerbose === 'function';
|
|
4265
|
+
|
|
4266
|
+
const VERBOSE_VALUES = ['none', 'short', 'full'];
|
|
4267
|
+
|
|
4268
|
+
// Compute `result.command` and `result.escapedCommand`
|
|
4269
|
+
const joinCommand = (filePath, rawArguments) => {
|
|
4270
|
+
const fileAndArguments = [filePath, ...rawArguments];
|
|
4271
|
+
const command = fileAndArguments.join(' ');
|
|
4272
|
+
const escapedCommand = fileAndArguments
|
|
4273
|
+
.map(fileAndArgument => quoteString(escapeControlCharacters(fileAndArgument)))
|
|
4274
|
+
.join(' ');
|
|
4275
|
+
return {command, escapedCommand};
|
|
4276
|
+
};
|
|
4277
|
+
|
|
4278
|
+
// Remove ANSI sequences and escape control characters and newlines
|
|
4279
|
+
const escapeLines = lines => stripVTControlCharacters(lines)
|
|
4280
|
+
.split('\n')
|
|
4281
|
+
.map(line => escapeControlCharacters(line))
|
|
4282
|
+
.join('\n');
|
|
4283
|
+
|
|
4284
|
+
const escapeControlCharacters = line => line.replaceAll(SPECIAL_CHAR_REGEXP, character => escapeControlCharacter(character));
|
|
4285
|
+
|
|
4286
|
+
const escapeControlCharacter = character => {
|
|
4287
|
+
const commonEscape = COMMON_ESCAPES[character];
|
|
4288
|
+
if (commonEscape !== undefined) {
|
|
4289
|
+
return commonEscape;
|
|
4290
|
+
}
|
|
4291
|
+
|
|
4292
|
+
const codepoint = character.codePointAt(0);
|
|
4293
|
+
const codepointHex = codepoint.toString(16);
|
|
4294
|
+
return codepoint <= ASTRAL_START
|
|
4295
|
+
? `\\u${codepointHex.padStart(4, '0')}`
|
|
4296
|
+
: `\\U${codepointHex}`;
|
|
4297
|
+
};
|
|
4298
|
+
|
|
4299
|
+
// Characters that would create issues when printed are escaped using the \u or \U notation.
|
|
4300
|
+
// Those include control characters and newlines.
|
|
4301
|
+
// The \u and \U notation is Bash specific, but there is no way to do this in a shell-agnostic way.
|
|
4302
|
+
// Some shells do not even have a way to print those characters in an escaped fashion.
|
|
4303
|
+
// Therefore, we prioritize printing those safely, instead of allowing those to be copy-pasted.
|
|
4304
|
+
// List of Unicode character categories: https://www.fileformat.info/info/unicode/category/index.htm
|
|
4305
|
+
const SPECIAL_CHAR_REGEXP = /\p{Separator}|\p{Other}/gu;
|
|
4306
|
+
|
|
4307
|
+
// Accepted by $'...' in Bash.
|
|
4308
|
+
// Exclude \a \e \v which are accepted in Bash but not in JavaScript (except \v) and JSON.
|
|
4309
|
+
const COMMON_ESCAPES = {
|
|
4310
|
+
' ': ' ',
|
|
4311
|
+
'\b': '\\b',
|
|
4312
|
+
'\f': '\\f',
|
|
4313
|
+
'\n': '\\n',
|
|
4314
|
+
'\r': '\\r',
|
|
4315
|
+
'\t': '\\t',
|
|
4316
|
+
};
|
|
4317
|
+
|
|
4318
|
+
// Up until that codepoint, \u notation can be used instead of \U
|
|
4319
|
+
const ASTRAL_START = 65_535;
|
|
4320
|
+
|
|
4321
|
+
// Some characters are shell-specific, i.e. need to be escaped when the command is copy-pasted then run.
|
|
4322
|
+
// Escaping is shell-specific. We cannot know which shell is used: `process.platform` detection is not enough.
|
|
4323
|
+
// For example, Windows users could be using `cmd.exe`, Powershell or Bash for Windows which all use different escaping.
|
|
4324
|
+
// We use '...' on Unix, which is POSIX shell compliant and escape all characters but ' so this is fairly safe.
|
|
4325
|
+
// On Windows, we assume cmd.exe is used and escape with "...", which also works with Powershell.
|
|
4326
|
+
const quoteString = escapedArgument => {
|
|
4327
|
+
if (NO_ESCAPE_REGEXP.test(escapedArgument)) {
|
|
4328
|
+
return escapedArgument;
|
|
4169
4329
|
}
|
|
4330
|
+
|
|
4331
|
+
return platform$1 === 'win32'
|
|
4332
|
+
? `"${escapedArgument.replaceAll('"', '""')}"`
|
|
4333
|
+
: `'${escapedArgument.replaceAll('\'', '\'\\\'\'')}'`;
|
|
4170
4334
|
};
|
|
4171
4335
|
|
|
4172
|
-
const
|
|
4336
|
+
const NO_ESCAPE_REGEXP = /^[\w./-]+$/;
|
|
4173
4337
|
|
|
4174
4338
|
function isUnicodeSupported() {
|
|
4175
4339
|
if (process$3.platform !== 'win32') {
|
|
@@ -4463,120 +4627,126 @@ const fallbackSymbols = {...common$7, ...specialFallbackSymbols};
|
|
|
4463
4627
|
const shouldUseMain = isUnicodeSupported();
|
|
4464
4628
|
const figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
4465
4629
|
|
|
4466
|
-
//
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4630
|
+
// eslint-disable-next-line no-warning-comments
|
|
4631
|
+
// TODO: Use a better method when it's added to Node.js (https://github.com/nodejs/node/pull/40240)
|
|
4632
|
+
const hasColors = tty.WriteStream.prototype.hasColors();
|
|
4633
|
+
|
|
4634
|
+
// Intentionally not using template literal for performance.
|
|
4635
|
+
const format = (startCode, endCode) => hasColors ? string => '\u001B[' + startCode + 'm' + string + '\u001B[' + endCode + 'm' : string => string;
|
|
4636
|
+
const bold = format(1, 22);
|
|
4637
|
+
const gray = format(90, 39);
|
|
4638
|
+
|
|
4639
|
+
const redBright = format(91, 39);
|
|
4640
|
+
const yellowBright = format(93, 39);
|
|
4641
|
+
|
|
4642
|
+
// Default when `verbose` is not a function
|
|
4643
|
+
const defaultVerboseFunction = ({
|
|
4644
|
+
type,
|
|
4645
|
+
message,
|
|
4646
|
+
timestamp,
|
|
4647
|
+
piped,
|
|
4648
|
+
commandId,
|
|
4649
|
+
result: {failed = false} = {},
|
|
4650
|
+
options: {reject = true},
|
|
4651
|
+
}) => {
|
|
4652
|
+
const timestampString = serializeTimestamp(timestamp);
|
|
4653
|
+
const icon = ICONS[type]({failed, reject, piped});
|
|
4654
|
+
const color = COLORS[type]({reject});
|
|
4655
|
+
return `${gray(`[${timestampString}]`)} ${gray(`[${commandId}]`)} ${color(icon)} ${color(message)}`;
|
|
4474
4656
|
};
|
|
4475
4657
|
|
|
4476
|
-
//
|
|
4477
|
-
const
|
|
4478
|
-
.split('\n')
|
|
4479
|
-
.map(line => escapeControlCharacters(line))
|
|
4480
|
-
.join('\n');
|
|
4658
|
+
// Prepending the timestamp allows debugging the slow paths of a subprocess
|
|
4659
|
+
const serializeTimestamp = timestamp => `${padField(timestamp.getHours(), 2)}:${padField(timestamp.getMinutes(), 2)}:${padField(timestamp.getSeconds(), 2)}.${padField(timestamp.getMilliseconds(), 3)}`;
|
|
4481
4660
|
|
|
4482
|
-
const
|
|
4661
|
+
const padField = (field, padding) => String(field).padStart(padding, '0');
|
|
4483
4662
|
|
|
4484
|
-
const
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
return commonEscape;
|
|
4663
|
+
const getFinalIcon = ({failed, reject}) => {
|
|
4664
|
+
if (!failed) {
|
|
4665
|
+
return figures.tick;
|
|
4488
4666
|
}
|
|
4489
4667
|
|
|
4490
|
-
|
|
4491
|
-
const codepointHex = codepoint.toString(16);
|
|
4492
|
-
return codepoint <= ASTRAL_START
|
|
4493
|
-
? `\\u${codepointHex.padStart(4, '0')}`
|
|
4494
|
-
: `\\U${codepointHex}`;
|
|
4668
|
+
return reject ? figures.cross : figures.warning;
|
|
4495
4669
|
};
|
|
4496
4670
|
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4671
|
+
const ICONS = {
|
|
4672
|
+
command: ({piped}) => piped ? '|' : '$',
|
|
4673
|
+
output: () => ' ',
|
|
4674
|
+
ipc: () => '*',
|
|
4675
|
+
error: getFinalIcon,
|
|
4676
|
+
duration: getFinalIcon,
|
|
4677
|
+
};
|
|
4504
4678
|
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
const
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
'\t': '\\t',
|
|
4679
|
+
const identity$1 = string => string;
|
|
4680
|
+
|
|
4681
|
+
const COLORS = {
|
|
4682
|
+
command: () => bold,
|
|
4683
|
+
output: () => identity$1,
|
|
4684
|
+
ipc: () => identity$1,
|
|
4685
|
+
error: ({reject}) => reject ? redBright : yellowBright,
|
|
4686
|
+
duration: () => gray,
|
|
4514
4687
|
};
|
|
4515
4688
|
|
|
4516
|
-
//
|
|
4517
|
-
const
|
|
4689
|
+
// Apply the `verbose` function on each line
|
|
4690
|
+
const applyVerboseOnLines = (printedLines, verboseInfo, fdNumber) => {
|
|
4691
|
+
const verboseFunction = getVerboseFunction(verboseInfo, fdNumber);
|
|
4692
|
+
return printedLines
|
|
4693
|
+
.map(({verboseLine, verboseObject}) => applyVerboseFunction(verboseLine, verboseObject, verboseFunction))
|
|
4694
|
+
.filter(printedLine => printedLine !== undefined)
|
|
4695
|
+
.map(printedLine => appendNewline(printedLine))
|
|
4696
|
+
.join('');
|
|
4697
|
+
};
|
|
4518
4698
|
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
// We use '...' on Unix, which is POSIX shell compliant and escape all characters but ' so this is fairly safe.
|
|
4523
|
-
// On Windows, we assume cmd.exe is used and escape with "...", which also works with Powershell.
|
|
4524
|
-
const quoteString = escapedArgument => {
|
|
4525
|
-
if (NO_ESCAPE_REGEXP.test(escapedArgument)) {
|
|
4526
|
-
return escapedArgument;
|
|
4699
|
+
const applyVerboseFunction = (verboseLine, verboseObject, verboseFunction) => {
|
|
4700
|
+
if (verboseFunction === undefined) {
|
|
4701
|
+
return verboseLine;
|
|
4527
4702
|
}
|
|
4528
4703
|
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4704
|
+
const printedLine = verboseFunction(verboseLine, verboseObject);
|
|
4705
|
+
if (typeof printedLine === 'string') {
|
|
4706
|
+
return printedLine;
|
|
4707
|
+
}
|
|
4532
4708
|
};
|
|
4533
4709
|
|
|
4534
|
-
const
|
|
4710
|
+
const appendNewline = printedLine => printedLine.endsWith('\n')
|
|
4711
|
+
? printedLine
|
|
4712
|
+
: `${printedLine}\n`;
|
|
4535
4713
|
|
|
4536
4714
|
// Write synchronously to ensure lines are properly ordered and not interleaved with `stdout`
|
|
4537
|
-
const verboseLog = (
|
|
4538
|
-
const
|
|
4539
|
-
|
|
4715
|
+
const verboseLog = ({type, verboseMessage, fdNumber, verboseInfo, result}) => {
|
|
4716
|
+
const verboseObject = getVerboseObject({type, result, verboseInfo});
|
|
4717
|
+
const printedLines = getPrintedLines(verboseMessage, verboseObject);
|
|
4718
|
+
const finalLines = applyVerboseOnLines(printedLines, verboseInfo, fdNumber);
|
|
4719
|
+
writeFileSync$1(STDERR_FD, finalLines);
|
|
4540
4720
|
};
|
|
4541
4721
|
|
|
4542
|
-
const
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
:
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
color(line),
|
|
4556
|
-
].join(' ');
|
|
4722
|
+
const getVerboseObject = ({
|
|
4723
|
+
type,
|
|
4724
|
+
result,
|
|
4725
|
+
verboseInfo: {escapedCommand, commandId, rawOptions: {piped = false, ...options}},
|
|
4726
|
+
}) => ({
|
|
4727
|
+
type,
|
|
4728
|
+
escapedCommand,
|
|
4729
|
+
commandId: `${commandId}`,
|
|
4730
|
+
timestamp: new Date(),
|
|
4731
|
+
piped,
|
|
4732
|
+
result,
|
|
4733
|
+
options,
|
|
4734
|
+
});
|
|
4557
4735
|
|
|
4558
|
-
const
|
|
4736
|
+
const getPrintedLines = (verboseMessage, verboseObject) => verboseMessage
|
|
4737
|
+
.split('\n')
|
|
4738
|
+
.map(message => getPrintedLine({...verboseObject, message}));
|
|
4559
4739
|
|
|
4560
|
-
|
|
4561
|
-
const
|
|
4562
|
-
|
|
4563
|
-
return `${padField(date.getHours(), 2)}:${padField(date.getMinutes(), 2)}:${padField(date.getSeconds(), 2)}.${padField(date.getMilliseconds(), 3)}`;
|
|
4740
|
+
const getPrintedLine = verboseObject => {
|
|
4741
|
+
const verboseLine = defaultVerboseFunction(verboseObject);
|
|
4742
|
+
return {verboseLine, verboseObject};
|
|
4564
4743
|
};
|
|
4565
4744
|
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
const ICONS = {
|
|
4569
|
-
command: '$',
|
|
4570
|
-
pipedCommand: '|',
|
|
4571
|
-
output: ' ',
|
|
4572
|
-
ipc: '*',
|
|
4573
|
-
error: figures.cross,
|
|
4574
|
-
warning: figures.warning,
|
|
4575
|
-
success: figures.tick,
|
|
4576
|
-
};
|
|
4745
|
+
// Unless a `verbose` function is used, print all logs on `stderr`
|
|
4746
|
+
const STDERR_FD = 2;
|
|
4577
4747
|
|
|
4578
4748
|
// Serialize any type to a line string, for logging
|
|
4579
|
-
const
|
|
4749
|
+
const serializeVerboseMessage = message => {
|
|
4580
4750
|
const messageString = typeof message === 'string' ? message : inspect(message);
|
|
4581
4751
|
const escapedMessage = escapeLines(messageString);
|
|
4582
4752
|
return escapedMessage.replaceAll('\t', ' '.repeat(TAB_SIZE));
|
|
@@ -4585,134 +4755,71 @@ const serializeLogMessage = message => {
|
|
|
4585
4755
|
// Same as `util.inspect()`
|
|
4586
4756
|
const TAB_SIZE = 2;
|
|
4587
4757
|
|
|
4588
|
-
// When `verbose` is `short|full`, print each command
|
|
4589
|
-
const logCommand = (escapedCommand,
|
|
4590
|
-
if (!isVerbose(
|
|
4758
|
+
// When `verbose` is `short|full|custom`, print each command
|
|
4759
|
+
const logCommand = (escapedCommand, verboseInfo) => {
|
|
4760
|
+
if (!isVerbose(verboseInfo)) {
|
|
4591
4761
|
return;
|
|
4592
4762
|
}
|
|
4593
4763
|
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
const getStartTime = () => hrtime.bigint();
|
|
4600
|
-
|
|
4601
|
-
// Compute duration after the subprocess ended.
|
|
4602
|
-
// Printed by the `verbose` option.
|
|
4603
|
-
const getDurationMs = startTime => Number(hrtime.bigint() - startTime) / 1e6;
|
|
4604
|
-
|
|
4605
|
-
const isStandardStream = stream => STANDARD_STREAMS.includes(stream);
|
|
4606
|
-
const STANDARD_STREAMS = [process$3.stdin, process$3.stdout, process$3.stderr];
|
|
4607
|
-
const STANDARD_STREAMS_ALIASES = ['stdin', 'stdout', 'stderr'];
|
|
4608
|
-
const getStreamName = fdNumber => STANDARD_STREAMS_ALIASES[fdNumber] ?? `stdio[${fdNumber}]`;
|
|
4609
|
-
|
|
4610
|
-
// Some options can have different values for `stdout`/`stderr`/`fd3`.
|
|
4611
|
-
// This normalizes those to array of values.
|
|
4612
|
-
// For example, `{verbose: {stdout: 'none', stderr: 'full'}}` becomes `{verbose: ['none', 'none', 'full']}`
|
|
4613
|
-
const normalizeFdSpecificOptions = options => {
|
|
4614
|
-
const optionsCopy = {...options};
|
|
4615
|
-
|
|
4616
|
-
for (const optionName of FD_SPECIFIC_OPTIONS) {
|
|
4617
|
-
optionsCopy[optionName] = normalizeFdSpecificOption(options, optionName);
|
|
4618
|
-
}
|
|
4619
|
-
|
|
4620
|
-
return optionsCopy;
|
|
4764
|
+
verboseLog({
|
|
4765
|
+
type: 'command',
|
|
4766
|
+
verboseMessage: escapedCommand,
|
|
4767
|
+
verboseInfo,
|
|
4768
|
+
});
|
|
4621
4769
|
};
|
|
4622
4770
|
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4771
|
+
// Information computed before spawning, used by the `verbose` option
|
|
4772
|
+
const getVerboseInfo = (verbose, escapedCommand, rawOptions) => {
|
|
4773
|
+
validateVerbose(verbose);
|
|
4774
|
+
const commandId = getCommandId(verbose);
|
|
4775
|
+
return {
|
|
4776
|
+
verbose,
|
|
4777
|
+
escapedCommand,
|
|
4778
|
+
commandId,
|
|
4779
|
+
rawOptions,
|
|
4780
|
+
};
|
|
4627
4781
|
};
|
|
4628
4782
|
|
|
4629
|
-
const
|
|
4630
|
-
? Math.max(stdio.length, STANDARD_STREAMS_ALIASES.length)
|
|
4631
|
-
: STANDARD_STREAMS_ALIASES.length;
|
|
4783
|
+
const getCommandId = verbose => isVerbose({verbose}) ? COMMAND_ID++ : undefined;
|
|
4632
4784
|
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4785
|
+
// Prepending the `pid` is useful when multiple commands print their output at the same time.
|
|
4786
|
+
// However, we cannot use the real PID since this is not available with `child_process.spawnSync()`.
|
|
4787
|
+
// Also, we cannot use the real PID if we want to print it before `child_process.spawn()` is run.
|
|
4788
|
+
// As a pro, it is shorter than a normal PID and never re-uses the same id.
|
|
4789
|
+
// As a con, it cannot be used to send signals.
|
|
4790
|
+
let COMMAND_ID = 0n;
|
|
4636
4791
|
|
|
4637
|
-
const
|
|
4638
|
-
for (const
|
|
4639
|
-
|
|
4640
|
-
|
|
4792
|
+
const validateVerbose = verbose => {
|
|
4793
|
+
for (const fdVerbose of verbose) {
|
|
4794
|
+
if (fdVerbose === false) {
|
|
4795
|
+
throw new TypeError('The "verbose: false" option was renamed to "verbose: \'none\'".');
|
|
4641
4796
|
}
|
|
4642
|
-
}
|
|
4643
|
-
|
|
4644
|
-
return optionArray;
|
|
4645
|
-
};
|
|
4646
4797
|
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
const getFdNameOrder = fdName => {
|
|
4651
|
-
if (fdName === 'stdout' || fdName === 'stderr') {
|
|
4652
|
-
return 0;
|
|
4653
|
-
}
|
|
4654
|
-
|
|
4655
|
-
return fdName === 'all' ? 2 : 1;
|
|
4656
|
-
};
|
|
4657
|
-
|
|
4658
|
-
const parseFdName = (fdName, optionName, optionArray) => {
|
|
4659
|
-
if (fdName === 'ipc') {
|
|
4660
|
-
return [optionArray.length - 1];
|
|
4661
|
-
}
|
|
4662
|
-
|
|
4663
|
-
const fdNumber = parseFd(fdName);
|
|
4664
|
-
if (fdNumber === undefined || fdNumber === 0) {
|
|
4665
|
-
throw new TypeError(`"${optionName}.${fdName}" is invalid.
|
|
4666
|
-
It must be "${optionName}.stdout", "${optionName}.stderr", "${optionName}.all", "${optionName}.ipc", or "${optionName}.fd3", "${optionName}.fd4" (and so on).`);
|
|
4667
|
-
}
|
|
4668
|
-
|
|
4669
|
-
if (fdNumber >= optionArray.length) {
|
|
4670
|
-
throw new TypeError(`"${optionName}.${fdName}" is invalid: that file descriptor does not exist.
|
|
4671
|
-
Please set the "stdio" option to ensure that file descriptor exists.`);
|
|
4672
|
-
}
|
|
4673
|
-
|
|
4674
|
-
return fdNumber === 'all' ? [1, 2] : [fdNumber];
|
|
4675
|
-
};
|
|
4676
|
-
|
|
4677
|
-
// Use the same syntax for fd-specific options and the `from`/`to` options
|
|
4678
|
-
const parseFd = fdName => {
|
|
4679
|
-
if (fdName === 'all') {
|
|
4680
|
-
return fdName;
|
|
4681
|
-
}
|
|
4682
|
-
|
|
4683
|
-
if (STANDARD_STREAMS_ALIASES.includes(fdName)) {
|
|
4684
|
-
return STANDARD_STREAMS_ALIASES.indexOf(fdName);
|
|
4685
|
-
}
|
|
4798
|
+
if (fdVerbose === true) {
|
|
4799
|
+
throw new TypeError('The "verbose: true" option was renamed to "verbose: \'short\'".');
|
|
4800
|
+
}
|
|
4686
4801
|
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4802
|
+
if (!VERBOSE_VALUES.includes(fdVerbose) && !isVerboseFunction(fdVerbose)) {
|
|
4803
|
+
const allowedValues = VERBOSE_VALUES.map(allowedValue => `'${allowedValue}'`).join(', ');
|
|
4804
|
+
throw new TypeError(`The "verbose" option must not be ${fdVerbose}. Allowed values are: ${allowedValues} or a function.`);
|
|
4805
|
+
}
|
|
4690
4806
|
}
|
|
4691
4807
|
};
|
|
4692
4808
|
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
const addDefaultValue$1 = (optionArray, optionName) => optionArray.map(optionValue => optionValue === undefined
|
|
4696
|
-
? DEFAULT_OPTIONS[optionName]
|
|
4697
|
-
: optionValue);
|
|
4698
|
-
|
|
4699
|
-
const DEFAULT_OPTIONS = {
|
|
4700
|
-
lines: false,
|
|
4701
|
-
buffer: true,
|
|
4702
|
-
maxBuffer: 1000 * 1000 * 100,
|
|
4703
|
-
verbose: verboseDefault,
|
|
4704
|
-
stripFinalNewline: true,
|
|
4705
|
-
};
|
|
4809
|
+
// Start counting time before spawning the subprocess
|
|
4810
|
+
const getStartTime = () => hrtime.bigint();
|
|
4706
4811
|
|
|
4707
|
-
//
|
|
4708
|
-
|
|
4812
|
+
// Compute duration after the subprocess ended.
|
|
4813
|
+
// Printed by the `verbose` option.
|
|
4814
|
+
const getDurationMs = startTime => Number(hrtime.bigint() - startTime) / 1e6;
|
|
4709
4815
|
|
|
4710
4816
|
// Compute `result.command`, `result.escapedCommand` and `verbose`-related information
|
|
4711
4817
|
const handleCommand = (filePath, rawArguments, rawOptions) => {
|
|
4712
4818
|
const startTime = getStartTime();
|
|
4713
4819
|
const {command, escapedCommand} = joinCommand(filePath, rawArguments);
|
|
4714
|
-
const
|
|
4715
|
-
|
|
4820
|
+
const verbose = normalizeFdSpecificOption(rawOptions, 'verbose');
|
|
4821
|
+
const verboseInfo = getVerboseInfo(verbose, escapedCommand, {...rawOptions});
|
|
4822
|
+
logCommand(escapedCommand, verboseInfo);
|
|
4716
4823
|
return {
|
|
4717
4824
|
command,
|
|
4718
4825
|
escapedCommand,
|
|
@@ -6577,7 +6684,7 @@ const hasMessageListeners = (anyProcess, ipcEmitter) => ipcEmitter.listenerCount
|
|
|
6577
6684
|
// When `buffer` is `false`, we set up a `message` listener that should be ignored.
|
|
6578
6685
|
// That listener is only meant to intercept `strict` acknowledgement responses.
|
|
6579
6686
|
const getMinListenerCount = anyProcess => SUBPROCESS_OPTIONS.has(anyProcess)
|
|
6580
|
-
&& !SUBPROCESS_OPTIONS.get(anyProcess).options.buffer
|
|
6687
|
+
&& !getFdSpecificValue(SUBPROCESS_OPTIONS.get(anyProcess).options.buffer, 'ipc')
|
|
6581
6688
|
? 1
|
|
6582
6689
|
: 0;
|
|
6583
6690
|
|
|
@@ -7622,11 +7729,12 @@ const getMaxBufferInfo = (error, maxBuffer) => {
|
|
|
7622
7729
|
const {maxBufferInfo: {fdNumber, unit}} = error;
|
|
7623
7730
|
delete error.maxBufferInfo;
|
|
7624
7731
|
|
|
7732
|
+
const threshold = getFdSpecificValue(maxBuffer, fdNumber);
|
|
7625
7733
|
if (fdNumber === 'ipc') {
|
|
7626
|
-
return {streamName: 'IPC output', threshold
|
|
7734
|
+
return {streamName: 'IPC output', threshold, unit: 'messages'};
|
|
7627
7735
|
}
|
|
7628
7736
|
|
|
7629
|
-
return {streamName: getStreamName(fdNumber), threshold
|
|
7737
|
+
return {streamName: getStreamName(fdNumber), threshold, unit};
|
|
7630
7738
|
};
|
|
7631
7739
|
|
|
7632
7740
|
// The only way to apply `maxBuffer` with `spawnSync()` is to use the native `maxBuffer` option Node.js provides.
|
|
@@ -8159,71 +8267,42 @@ function prettyMilliseconds(milliseconds, options) {
|
|
|
8159
8267
|
return result.join(separator);
|
|
8160
8268
|
}
|
|
8161
8269
|
|
|
8162
|
-
// When `verbose` is `short|full`, print each command's error when it fails
|
|
8163
|
-
const logError = (
|
|
8164
|
-
if (
|
|
8165
|
-
|
|
8270
|
+
// When `verbose` is `short|full|custom`, print each command's error when it fails
|
|
8271
|
+
const logError = (result, verboseInfo) => {
|
|
8272
|
+
if (result.failed) {
|
|
8273
|
+
verboseLog({
|
|
8274
|
+
type: 'error',
|
|
8275
|
+
verboseMessage: result.shortMessage,
|
|
8276
|
+
verboseInfo,
|
|
8277
|
+
result,
|
|
8278
|
+
});
|
|
8166
8279
|
}
|
|
8167
|
-
|
|
8168
|
-
const color = reject ? redBright : yellowBright;
|
|
8169
|
-
verboseLog(message, verboseId, icon, color);
|
|
8170
8280
|
};
|
|
8171
8281
|
|
|
8172
|
-
// When `verbose` is `short|full`, print each command's completion, duration and error
|
|
8173
|
-
const
|
|
8174
|
-
|
|
8175
|
-
message: shortMessage,
|
|
8176
|
-
failed,
|
|
8177
|
-
reject,
|
|
8178
|
-
durationMs,
|
|
8179
|
-
verboseInfo,
|
|
8180
|
-
});
|
|
8181
|
-
};
|
|
8182
|
-
|
|
8183
|
-
// Same but for early validation errors
|
|
8184
|
-
const logEarlyResult = (error, startTime, verboseInfo) => {
|
|
8185
|
-
logResult({
|
|
8186
|
-
message: escapeLines(String(error)),
|
|
8187
|
-
failed: true,
|
|
8188
|
-
reject: true,
|
|
8189
|
-
durationMs: getDurationMs(startTime),
|
|
8190
|
-
verboseInfo,
|
|
8191
|
-
});
|
|
8192
|
-
};
|
|
8193
|
-
|
|
8194
|
-
const logResult = ({message, failed, reject, durationMs, verboseInfo: {verbose, verboseId}}) => {
|
|
8195
|
-
if (!isVerbose(verbose)) {
|
|
8282
|
+
// When `verbose` is `short|full|custom`, print each command's completion, duration and error
|
|
8283
|
+
const logResult = (result, verboseInfo) => {
|
|
8284
|
+
if (!isVerbose(verboseInfo)) {
|
|
8196
8285
|
return;
|
|
8197
8286
|
}
|
|
8198
8287
|
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
message,
|
|
8202
|
-
failed,
|
|
8203
|
-
reject,
|
|
8204
|
-
verboseId,
|
|
8205
|
-
icon,
|
|
8206
|
-
});
|
|
8207
|
-
logDuration(durationMs, verboseId, icon);
|
|
8208
|
-
};
|
|
8209
|
-
|
|
8210
|
-
const logDuration = (durationMs, verboseId, icon) => {
|
|
8211
|
-
const durationMessage = `(done in ${prettyMilliseconds(durationMs)})`;
|
|
8212
|
-
verboseLog(durationMessage, verboseId, icon, gray);
|
|
8288
|
+
logError(result, verboseInfo);
|
|
8289
|
+
logDuration(result, verboseInfo);
|
|
8213
8290
|
};
|
|
8214
8291
|
|
|
8215
|
-
const
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8292
|
+
const logDuration = (result, verboseInfo) => {
|
|
8293
|
+
const verboseMessage = `(done in ${prettyMilliseconds(result.durationMs)})`;
|
|
8294
|
+
verboseLog({
|
|
8295
|
+
type: 'duration',
|
|
8296
|
+
verboseMessage,
|
|
8297
|
+
verboseInfo,
|
|
8298
|
+
result,
|
|
8299
|
+
});
|
|
8221
8300
|
};
|
|
8222
8301
|
|
|
8223
8302
|
// Applies the `reject` option.
|
|
8224
8303
|
// Also print the final log line with `verbose`.
|
|
8225
8304
|
const handleResult = (result, verboseInfo, {reject}) => {
|
|
8226
|
-
|
|
8305
|
+
logResult(result, verboseInfo);
|
|
8227
8306
|
|
|
8228
8307
|
if (result.failed && reject) {
|
|
8229
8308
|
throw result;
|
|
@@ -8623,10 +8702,10 @@ const normalizeIpcStdioArray = (stdioArray, ipc) => ipc && !stdioArray.includes(
|
|
|
8623
8702
|
|
|
8624
8703
|
// Add support for `stdin`/`stdout`/`stderr` as an alias for `stdio`.
|
|
8625
8704
|
// Also normalize the `stdio` option.
|
|
8626
|
-
const normalizeStdioOption = ({stdio, ipc, buffer,
|
|
8705
|
+
const normalizeStdioOption = ({stdio, ipc, buffer, ...options}, verboseInfo, isSync) => {
|
|
8627
8706
|
const stdioArray = getStdioArray(stdio, options).map((stdioOption, fdNumber) => addDefaultValue(stdioOption, fdNumber));
|
|
8628
8707
|
return isSync
|
|
8629
|
-
? normalizeStdioSync(stdioArray, buffer,
|
|
8708
|
+
? normalizeStdioSync(stdioArray, buffer, verboseInfo)
|
|
8630
8709
|
: normalizeIpcStdioArray(stdioArray, ipc);
|
|
8631
8710
|
};
|
|
8632
8711
|
|
|
@@ -8667,10 +8746,10 @@ const addDefaultValue = (stdioOption, fdNumber) => {
|
|
|
8667
8746
|
|
|
8668
8747
|
// Using `buffer: false` with synchronous methods implies `stdout`/`stderr`: `ignore`.
|
|
8669
8748
|
// Unless the output is needed, e.g. due to `verbose: 'full'` or to redirecting to a file.
|
|
8670
|
-
const normalizeStdioSync = (stdioArray, buffer,
|
|
8749
|
+
const normalizeStdioSync = (stdioArray, buffer, verboseInfo) => stdioArray.map((stdioOption, fdNumber) =>
|
|
8671
8750
|
!buffer[fdNumber]
|
|
8672
8751
|
&& fdNumber !== 0
|
|
8673
|
-
&&
|
|
8752
|
+
&& !isFullVerbose(verboseInfo, fdNumber)
|
|
8674
8753
|
&& isOutputPipeOnly(stdioOption)
|
|
8675
8754
|
? 'ignore'
|
|
8676
8755
|
: stdioOption);
|
|
@@ -8939,7 +9018,7 @@ const throwOnDuplicateStream = (stdioItem, optionName, type) => {
|
|
|
8939
9018
|
// They are converted into an array of `fileDescriptors`.
|
|
8940
9019
|
// Each `fileDescriptor` is normalized, validated and contains all information necessary for further handling.
|
|
8941
9020
|
const handleStdio = (addProperties, options, verboseInfo, isSync) => {
|
|
8942
|
-
const stdio = normalizeStdioOption(options, isSync);
|
|
9021
|
+
const stdio = normalizeStdioOption(options, verboseInfo, isSync);
|
|
8943
9022
|
const initialFileDescriptors = stdio.map((stdioOption, fdNumber) => getFileDescriptor({
|
|
8944
9023
|
stdioOption,
|
|
8945
9024
|
fdNumber,
|
|
@@ -9645,8 +9724,8 @@ const validateSerializable = newContents => {
|
|
|
9645
9724
|
// `inherit` would result in double printing.
|
|
9646
9725
|
// They can also lead to double printing when passing file descriptor integers or `process.std*`.
|
|
9647
9726
|
// This only leaves with `pipe` and `overlapped`.
|
|
9648
|
-
const shouldLogOutput = ({stdioItems, encoding, verboseInfo
|
|
9649
|
-
&&
|
|
9727
|
+
const shouldLogOutput = ({stdioItems, encoding, verboseInfo, fdNumber}) => fdNumber !== 'all'
|
|
9728
|
+
&& isFullVerbose(verboseInfo, fdNumber)
|
|
9650
9729
|
&& !BINARY_ENCODINGS.has(encoding)
|
|
9651
9730
|
&& fdUsesVerbose(fdNumber)
|
|
9652
9731
|
&& (stdioItems.some(({type, value}) => type === 'native' && PIPED_STDIO_VALUES.has(value))
|
|
@@ -9661,18 +9740,18 @@ const fdUsesVerbose = fdNumber => fdNumber === 1 || fdNumber === 2;
|
|
|
9661
9740
|
const PIPED_STDIO_VALUES = new Set(['pipe', 'overlapped']);
|
|
9662
9741
|
|
|
9663
9742
|
// `verbose: 'full'` printing logic with async methods
|
|
9664
|
-
const logLines = async (linesIterable, stream, verboseInfo) => {
|
|
9743
|
+
const logLines = async (linesIterable, stream, fdNumber, verboseInfo) => {
|
|
9665
9744
|
for await (const line of linesIterable) {
|
|
9666
9745
|
if (!isPipingStream(stream)) {
|
|
9667
|
-
logLine(line, verboseInfo);
|
|
9746
|
+
logLine(line, fdNumber, verboseInfo);
|
|
9668
9747
|
}
|
|
9669
9748
|
}
|
|
9670
9749
|
};
|
|
9671
9750
|
|
|
9672
9751
|
// `verbose: 'full'` printing logic with sync methods
|
|
9673
|
-
const logLinesSync = (linesArray, verboseInfo) => {
|
|
9752
|
+
const logLinesSync = (linesArray, fdNumber, verboseInfo) => {
|
|
9674
9753
|
for (const line of linesArray) {
|
|
9675
|
-
logLine(line, verboseInfo);
|
|
9754
|
+
logLine(line, fdNumber, verboseInfo);
|
|
9676
9755
|
}
|
|
9677
9756
|
};
|
|
9678
9757
|
|
|
@@ -9686,8 +9765,14 @@ const logLinesSync = (linesArray, verboseInfo) => {
|
|
|
9686
9765
|
const isPipingStream = stream => stream._readableState.pipes.length > 0;
|
|
9687
9766
|
|
|
9688
9767
|
// When `verbose` is `full`, print stdout|stderr
|
|
9689
|
-
const logLine = (line,
|
|
9690
|
-
|
|
9768
|
+
const logLine = (line, fdNumber, verboseInfo) => {
|
|
9769
|
+
const verboseMessage = serializeVerboseMessage(line);
|
|
9770
|
+
verboseLog({
|
|
9771
|
+
type: 'output',
|
|
9772
|
+
verboseMessage,
|
|
9773
|
+
fdNumber,
|
|
9774
|
+
verboseInfo,
|
|
9775
|
+
});
|
|
9691
9776
|
};
|
|
9692
9777
|
|
|
9693
9778
|
// Apply `stdout`/`stderr` options, after spawning, in sync mode
|
|
@@ -9732,15 +9817,15 @@ const transformOutputResultSync = (
|
|
|
9732
9817
|
fdNumber,
|
|
9733
9818
|
});
|
|
9734
9819
|
|
|
9735
|
-
|
|
9736
|
-
|
|
9737
|
-
encoding,
|
|
9738
|
-
verboseInfo,
|
|
9820
|
+
logOutputSync({
|
|
9821
|
+
serializedResult,
|
|
9739
9822
|
fdNumber,
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9823
|
+
state,
|
|
9824
|
+
verboseInfo,
|
|
9825
|
+
encoding,
|
|
9826
|
+
stdioItems,
|
|
9827
|
+
objectMode,
|
|
9828
|
+
});
|
|
9744
9829
|
|
|
9745
9830
|
const returnedResult = buffer[fdNumber] ? finalResult : undefined;
|
|
9746
9831
|
|
|
@@ -9786,6 +9871,25 @@ const serializeChunks = ({chunks, objectMode, encoding, lines, stripFinalNewline
|
|
|
9786
9871
|
return {serializedResult};
|
|
9787
9872
|
};
|
|
9788
9873
|
|
|
9874
|
+
const logOutputSync = ({serializedResult, fdNumber, state, verboseInfo, encoding, stdioItems, objectMode}) => {
|
|
9875
|
+
if (!shouldLogOutput({
|
|
9876
|
+
stdioItems,
|
|
9877
|
+
encoding,
|
|
9878
|
+
verboseInfo,
|
|
9879
|
+
fdNumber,
|
|
9880
|
+
})) {
|
|
9881
|
+
return;
|
|
9882
|
+
}
|
|
9883
|
+
|
|
9884
|
+
const linesArray = splitLinesSync(serializedResult, false, objectMode);
|
|
9885
|
+
|
|
9886
|
+
try {
|
|
9887
|
+
logLinesSync(linesArray, fdNumber, verboseInfo);
|
|
9888
|
+
} catch (error) {
|
|
9889
|
+
state.error ??= error;
|
|
9890
|
+
}
|
|
9891
|
+
};
|
|
9892
|
+
|
|
9789
9893
|
// When the `std*` target is a file path/URL or a file descriptor
|
|
9790
9894
|
const writeToFiles = (serializedResult, stdioItems, outputFiles) => {
|
|
9791
9895
|
for (const {path} of stdioItems.filter(({type}) => FILE_TYPES.has(type))) {
|
|
@@ -9923,26 +10027,20 @@ const execaCoreSync = (rawFile, rawArguments, rawOptions) => {
|
|
|
9923
10027
|
// Compute arguments to pass to `child_process.spawnSync()`
|
|
9924
10028
|
const handleSyncArguments = (rawFile, rawArguments, rawOptions) => {
|
|
9925
10029
|
const {command, escapedCommand, startTime, verboseInfo} = handleCommand(rawFile, rawArguments, rawOptions);
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
fileDescriptors,
|
|
9941
|
-
};
|
|
9942
|
-
} catch (error) {
|
|
9943
|
-
logEarlyResult(error, startTime, verboseInfo);
|
|
9944
|
-
throw error;
|
|
9945
|
-
}
|
|
10030
|
+
const syncOptions = normalizeSyncOptions(rawOptions);
|
|
10031
|
+
const {file, commandArguments, options} = normalizeOptions$2(rawFile, rawArguments, syncOptions);
|
|
10032
|
+
validateSyncOptions(options);
|
|
10033
|
+
const fileDescriptors = handleStdioSync(options, verboseInfo);
|
|
10034
|
+
return {
|
|
10035
|
+
file,
|
|
10036
|
+
commandArguments,
|
|
10037
|
+
command,
|
|
10038
|
+
escapedCommand,
|
|
10039
|
+
startTime,
|
|
10040
|
+
verboseInfo,
|
|
10041
|
+
options,
|
|
10042
|
+
fileDescriptors,
|
|
10043
|
+
};
|
|
9946
10044
|
};
|
|
9947
10045
|
|
|
9948
10046
|
// Options normalization logic specific to sync methods
|
|
@@ -11459,26 +11557,19 @@ const getGenerators = ({binary, shouldEncode, encoding, shouldSplit, preserveNew
|
|
|
11459
11557
|
].filter(Boolean);
|
|
11460
11558
|
|
|
11461
11559
|
// Retrieve `result.stdout|stderr|all|stdio[*]`
|
|
11462
|
-
const getStreamOutput = async ({stream, onStreamEnd, fdNumber, encoding, buffer, maxBuffer, lines, allMixed, stripFinalNewline, verboseInfo, streamInfo
|
|
11463
|
-
|
|
11464
|
-
|
|
11560
|
+
const getStreamOutput = async ({stream, onStreamEnd, fdNumber, encoding, buffer, maxBuffer, lines, allMixed, stripFinalNewline, verboseInfo, streamInfo}) => {
|
|
11561
|
+
const logPromise = logOutputAsync({
|
|
11562
|
+
stream,
|
|
11563
|
+
onStreamEnd,
|
|
11564
|
+
fdNumber,
|
|
11465
11565
|
encoding,
|
|
11566
|
+
allMixed,
|
|
11466
11567
|
verboseInfo,
|
|
11467
|
-
|
|
11468
|
-
})
|
|
11469
|
-
const linesIterable = iterateForResult({
|
|
11470
|
-
stream,
|
|
11471
|
-
onStreamEnd,
|
|
11472
|
-
lines: true,
|
|
11473
|
-
encoding,
|
|
11474
|
-
stripFinalNewline: true,
|
|
11475
|
-
allMixed,
|
|
11476
|
-
});
|
|
11477
|
-
logLines(linesIterable, stream, verboseInfo);
|
|
11478
|
-
}
|
|
11568
|
+
streamInfo,
|
|
11569
|
+
});
|
|
11479
11570
|
|
|
11480
11571
|
if (!buffer) {
|
|
11481
|
-
await resumeStream(stream);
|
|
11572
|
+
await Promise.all([resumeStream(stream), logPromise]);
|
|
11482
11573
|
return;
|
|
11483
11574
|
}
|
|
11484
11575
|
|
|
@@ -11491,14 +11582,39 @@ const getStreamOutput = async ({stream, onStreamEnd, fdNumber, encoding, buffer,
|
|
|
11491
11582
|
stripFinalNewline: stripFinalNewlineValue,
|
|
11492
11583
|
allMixed,
|
|
11493
11584
|
});
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11585
|
+
const [output] = await Promise.all([
|
|
11586
|
+
getStreamContents({
|
|
11587
|
+
stream,
|
|
11588
|
+
iterable,
|
|
11589
|
+
fdNumber,
|
|
11590
|
+
encoding,
|
|
11591
|
+
maxBuffer,
|
|
11592
|
+
lines,
|
|
11593
|
+
}),
|
|
11594
|
+
logPromise,
|
|
11595
|
+
]);
|
|
11596
|
+
return output;
|
|
11597
|
+
};
|
|
11598
|
+
|
|
11599
|
+
const logOutputAsync = async ({stream, onStreamEnd, fdNumber, encoding, allMixed, verboseInfo, streamInfo: {fileDescriptors}}) => {
|
|
11600
|
+
if (!shouldLogOutput({
|
|
11601
|
+
stdioItems: fileDescriptors[fdNumber]?.stdioItems,
|
|
11602
|
+
encoding,
|
|
11603
|
+
verboseInfo,
|
|
11497
11604
|
fdNumber,
|
|
11605
|
+
})) {
|
|
11606
|
+
return;
|
|
11607
|
+
}
|
|
11608
|
+
|
|
11609
|
+
const linesIterable = iterateForResult({
|
|
11610
|
+
stream,
|
|
11611
|
+
onStreamEnd,
|
|
11612
|
+
lines: true,
|
|
11498
11613
|
encoding,
|
|
11499
|
-
|
|
11500
|
-
|
|
11614
|
+
stripFinalNewline: true,
|
|
11615
|
+
allMixed,
|
|
11501
11616
|
});
|
|
11617
|
+
await logLines(linesIterable, stream, fdNumber, verboseInfo);
|
|
11502
11618
|
};
|
|
11503
11619
|
|
|
11504
11620
|
// When using `buffer: false`, users need to read `subprocess.stdout|stderr|all` right away
|
|
@@ -11734,10 +11850,16 @@ const getAllMixed = ({all, stdout, stderr}) => all
|
|
|
11734
11850
|
&& stdout.readableObjectMode !== stderr.readableObjectMode;
|
|
11735
11851
|
|
|
11736
11852
|
// When `verbose` is `'full'`, print IPC messages from the subprocess
|
|
11737
|
-
const shouldLogIpc =
|
|
11738
|
-
|
|
11739
|
-
const logIpcOutput = (message,
|
|
11740
|
-
|
|
11853
|
+
const shouldLogIpc = verboseInfo => isFullVerbose(verboseInfo, 'ipc');
|
|
11854
|
+
|
|
11855
|
+
const logIpcOutput = (message, verboseInfo) => {
|
|
11856
|
+
const verboseMessage = serializeVerboseMessage(message);
|
|
11857
|
+
verboseLog({
|
|
11858
|
+
type: 'ipc',
|
|
11859
|
+
verboseMessage,
|
|
11860
|
+
fdNumber: 'ipc',
|
|
11861
|
+
verboseInfo,
|
|
11862
|
+
});
|
|
11741
11863
|
};
|
|
11742
11864
|
|
|
11743
11865
|
// Iterate through IPC messages sent by the subprocess
|
|
@@ -11754,8 +11876,8 @@ const waitForIpcOutput = async ({
|
|
|
11754
11876
|
}
|
|
11755
11877
|
|
|
11756
11878
|
const isVerbose = shouldLogIpc(verboseInfo);
|
|
11757
|
-
const buffer = bufferArray
|
|
11758
|
-
const maxBuffer = maxBufferArray
|
|
11879
|
+
const buffer = getFdSpecificValue(bufferArray, 'ipc');
|
|
11880
|
+
const maxBuffer = getFdSpecificValue(maxBufferArray, 'ipc');
|
|
11759
11881
|
|
|
11760
11882
|
for await (const message of loopOnMessages({
|
|
11761
11883
|
anyProcess: subprocess,
|
|
@@ -12308,25 +12430,19 @@ const execaCoreAsync = (rawFile, rawArguments, rawOptions, createNested) => {
|
|
|
12308
12430
|
// Compute arguments to pass to `child_process.spawn()`
|
|
12309
12431
|
const handleAsyncArguments = (rawFile, rawArguments, rawOptions) => {
|
|
12310
12432
|
const {command, escapedCommand, startTime, verboseInfo} = handleCommand(rawFile, rawArguments, rawOptions);
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
|
|
12314
|
-
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
12318
|
-
|
|
12319
|
-
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
fileDescriptors,
|
|
12325
|
-
};
|
|
12326
|
-
} catch (error) {
|
|
12327
|
-
logEarlyResult(error, startTime, verboseInfo);
|
|
12328
|
-
throw error;
|
|
12329
|
-
}
|
|
12433
|
+
const {file, commandArguments, options: normalizedOptions} = normalizeOptions$2(rawFile, rawArguments, rawOptions);
|
|
12434
|
+
const options = handleAsyncOptions(normalizedOptions);
|
|
12435
|
+
const fileDescriptors = handleStdioAsync(options, verboseInfo);
|
|
12436
|
+
return {
|
|
12437
|
+
file,
|
|
12438
|
+
commandArguments,
|
|
12439
|
+
command,
|
|
12440
|
+
escapedCommand,
|
|
12441
|
+
startTime,
|
|
12442
|
+
verboseInfo,
|
|
12443
|
+
options,
|
|
12444
|
+
fileDescriptors,
|
|
12445
|
+
};
|
|
12330
12446
|
};
|
|
12331
12447
|
|
|
12332
12448
|
// Options normalization logic specific to async methods.
|
|
@@ -32347,14 +32463,14 @@ const getDotenvCliOptions2Options = ({ paths, pathsDelimiter, pathsDelimiterPatt
|
|
|
32347
32463
|
..._.omit(rest, ['debug', 'scripts']),
|
|
32348
32464
|
paths: paths?.split(pathsDelimiterPattern
|
|
32349
32465
|
? RegExp(pathsDelimiterPattern)
|
|
32350
|
-
: pathsDelimiter ?? ' ') ?? [],
|
|
32466
|
+
: (pathsDelimiter ?? ' ')) ?? [],
|
|
32351
32467
|
vars: _.fromPairs(vars
|
|
32352
32468
|
?.split(varsDelimiterPattern
|
|
32353
32469
|
? RegExp(varsDelimiterPattern)
|
|
32354
|
-
: varsDelimiter ?? ' ')
|
|
32470
|
+
: (varsDelimiter ?? ' '))
|
|
32355
32471
|
.map((v) => v.split(varsAssignorPattern
|
|
32356
32472
|
? RegExp(varsAssignorPattern)
|
|
32357
|
-
: varsAssignor ?? '='))),
|
|
32473
|
+
: (varsAssignor ?? '=')))),
|
|
32358
32474
|
});
|
|
32359
32475
|
const resolveGetDotenvOptions = async (customOptions) => {
|
|
32360
32476
|
const localPkgDir = await packageDirectory();
|
|
@@ -32886,7 +33002,8 @@ const getDotenv = async (options = {}) => {
|
|
|
32886
33002
|
for (const key in dynamic)
|
|
32887
33003
|
Object.assign(dotenv, {
|
|
32888
33004
|
[key]: _.isFunction(dynamic[key])
|
|
32889
|
-
?
|
|
33005
|
+
? // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
33006
|
+
dynamic[key](dotenv, env ?? defaultEnv)
|
|
32890
33007
|
: dynamic[key],
|
|
32891
33008
|
});
|
|
32892
33009
|
}
|
|
@@ -32918,9 +33035,10 @@ const getDotenv = async (options = {}) => {
|
|
|
32918
33035
|
|
|
32919
33036
|
const resolveCommand = (scripts, command) => (scripts && _.isObject(scripts[command])
|
|
32920
33037
|
? scripts[command].cmd
|
|
32921
|
-
: scripts?.[command] ?? command);
|
|
33038
|
+
: (scripts?.[command] ?? command));
|
|
32922
33039
|
const resolveShell = (scripts, command, shell) => scripts && _.isObject(scripts[command])
|
|
32923
|
-
?
|
|
33040
|
+
? // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
33041
|
+
scripts[command].shell
|
|
32924
33042
|
: shell;
|
|
32925
33043
|
|
|
32926
33044
|
/*
|