删除 node_modules

This commit is contained in:
2025-06-22 17:27:35 +08:00
parent ebcd00ed99
commit 912d2d4a12
3852 changed files with 0 additions and 1061355 deletions

View File

@@ -1,24 +0,0 @@
import prettyMs from 'pretty-ms';
import {isVerbose} from './values.js';
import {verboseLog} from './log.js';
import {logError} from './error.js';
// When `verbose` is `short|full|custom`, print each command's completion, duration and error
export const logResult = (result, verboseInfo) => {
if (!isVerbose(verboseInfo)) {
return;
}
logError(result, verboseInfo);
logDuration(result, verboseInfo);
};
const logDuration = (result, verboseInfo) => {
const verboseMessage = `(done in ${prettyMs(result.durationMs)})`;
verboseLog({
type: 'duration',
verboseMessage,
verboseInfo,
result,
});
};

View File

@@ -1,26 +0,0 @@
import {getVerboseFunction} from './values.js';
// Apply the `verbose` function on each line
export const applyVerboseOnLines = (printedLines, verboseInfo, fdNumber) => {
const verboseFunction = getVerboseFunction(verboseInfo, fdNumber);
return printedLines
.map(({verboseLine, verboseObject}) => applyVerboseFunction(verboseLine, verboseObject, verboseFunction))
.filter(printedLine => printedLine !== undefined)
.map(printedLine => appendNewline(printedLine))
.join('');
};
const applyVerboseFunction = (verboseLine, verboseObject, verboseFunction) => {
if (verboseFunction === undefined) {
return verboseLine;
}
const printedLine = verboseFunction(verboseLine, verboseObject);
if (typeof printedLine === 'string') {
return printedLine;
}
};
const appendNewline = printedLine => printedLine.endsWith('\n')
? printedLine
: `${printedLine}\n`;

View File

@@ -1,54 +0,0 @@
import figures from 'figures';
import {
gray,
bold,
redBright,
yellowBright,
} from 'yoctocolors';
// Default when `verbose` is not a function
export const defaultVerboseFunction = ({
type,
message,
timestamp,
piped,
commandId,
result: {failed = false} = {},
options: {reject = true},
}) => {
const timestampString = serializeTimestamp(timestamp);
const icon = ICONS[type]({failed, reject, piped});
const color = COLORS[type]({reject});
return `${gray(`[${timestampString}]`)} ${gray(`[${commandId}]`)} ${color(icon)} ${color(message)}`;
};
// Prepending the timestamp allows debugging the slow paths of a subprocess
const serializeTimestamp = timestamp => `${padField(timestamp.getHours(), 2)}:${padField(timestamp.getMinutes(), 2)}:${padField(timestamp.getSeconds(), 2)}.${padField(timestamp.getMilliseconds(), 3)}`;
const padField = (field, padding) => String(field).padStart(padding, '0');
const getFinalIcon = ({failed, reject}) => {
if (!failed) {
return figures.tick;
}
return reject ? figures.cross : figures.warning;
};
const ICONS = {
command: ({piped}) => piped ? '|' : '$',
output: () => ' ',
ipc: () => '*',
error: getFinalIcon,
duration: getFinalIcon,
};
const identity = string => string;
const COLORS = {
command: () => bold,
output: () => identity,
ipc: () => identity,
error: ({reject}) => reject ? redBright : yellowBright,
duration: () => gray,
};

View File

@@ -1,13 +0,0 @@
import {verboseLog} from './log.js';
// When `verbose` is `short|full|custom`, print each command's error when it fails
export const logError = (result, verboseInfo) => {
if (result.failed) {
verboseLog({
type: 'error',
verboseMessage: result.shortMessage,
verboseInfo,
result,
});
}
};

View File

@@ -1,39 +0,0 @@
import {isVerbose, VERBOSE_VALUES, isVerboseFunction} from './values.js';
// Information computed before spawning, used by the `verbose` option
export const getVerboseInfo = (verbose, escapedCommand, rawOptions) => {
validateVerbose(verbose);
const commandId = getCommandId(verbose);
return {
verbose,
escapedCommand,
commandId,
rawOptions,
};
};
const getCommandId = verbose => isVerbose({verbose}) ? COMMAND_ID++ : undefined;
// Prepending the `pid` is useful when multiple commands print their output at the same time.
// However, we cannot use the real PID since this is not available with `child_process.spawnSync()`.
// Also, we cannot use the real PID if we want to print it before `child_process.spawn()` is run.
// As a pro, it is shorter than a normal PID and never re-uses the same id.
// As a con, it cannot be used to send signals.
let COMMAND_ID = 0n;
const validateVerbose = verbose => {
for (const fdVerbose of verbose) {
if (fdVerbose === false) {
throw new TypeError('The "verbose: false" option was renamed to "verbose: \'none\'".');
}
if (fdVerbose === true) {
throw new TypeError('The "verbose: true" option was renamed to "verbose: \'short\'".');
}
if (!VERBOSE_VALUES.includes(fdVerbose) && !isVerboseFunction(fdVerbose)) {
const allowedValues = VERBOSE_VALUES.map(allowedValue => `'${allowedValue}'`).join(', ');
throw new TypeError(`The "verbose" option must not be ${fdVerbose}. Allowed values are: ${allowedValues} or a function.`);
}
}
};

View File

@@ -1,15 +0,0 @@
import {verboseLog, serializeVerboseMessage} from './log.js';
import {isFullVerbose} from './values.js';
// When `verbose` is `'full'`, print IPC messages from the subprocess
export const shouldLogIpc = verboseInfo => isFullVerbose(verboseInfo, 'ipc');
export const logIpcOutput = (message, verboseInfo) => {
const verboseMessage = serializeVerboseMessage(message);
verboseLog({
type: 'ipc',
verboseMessage,
fdNumber: 'ipc',
verboseInfo,
});
};

View File

@@ -1,54 +0,0 @@
import {inspect} from 'node:util';
import {escapeLines} from '../arguments/escape.js';
import {defaultVerboseFunction} from './default.js';
import {applyVerboseOnLines} from './custom.js';
// This prints on stderr.
// If the subprocess prints on stdout and is using `stdout: 'inherit'`,
// there is a chance both writes will compete (introducing a race condition).
// This means their respective order is not deterministic.
// In particular, this means the verbose command lines might be after the start of the subprocess output.
// Using synchronous I/O does not solve this problem.
// However, this only seems to happen when the stdout/stderr target
// (e.g. a terminal) is being written to by many subprocesses at once, which is unlikely in real scenarios.
export const verboseLog = ({type, verboseMessage, fdNumber, verboseInfo, result}) => {
const verboseObject = getVerboseObject({type, result, verboseInfo});
const printedLines = getPrintedLines(verboseMessage, verboseObject);
const finalLines = applyVerboseOnLines(printedLines, verboseInfo, fdNumber);
if (finalLines !== '') {
console.warn(finalLines.slice(0, -1));
}
};
const getVerboseObject = ({
type,
result,
verboseInfo: {escapedCommand, commandId, rawOptions: {piped = false, ...options}},
}) => ({
type,
escapedCommand,
commandId: `${commandId}`,
timestamp: new Date(),
piped,
result,
options,
});
const getPrintedLines = (verboseMessage, verboseObject) => verboseMessage
.split('\n')
.map(message => getPrintedLine({...verboseObject, message}));
const getPrintedLine = verboseObject => {
const verboseLine = defaultVerboseFunction(verboseObject);
return {verboseLine, verboseObject};
};
// Serialize any type to a line string, for logging
export const serializeVerboseMessage = message => {
const messageString = typeof message === 'string' ? message : inspect(message);
const escapedMessage = escapeLines(messageString);
return escapedMessage.replaceAll('\t', ' '.repeat(TAB_SIZE));
};
// Same as `util.inspect()`
const TAB_SIZE = 2;

View File

@@ -1,60 +0,0 @@
import {BINARY_ENCODINGS} from '../arguments/encoding-option.js';
import {TRANSFORM_TYPES} from '../stdio/type.js';
import {verboseLog, serializeVerboseMessage} from './log.js';
import {isFullVerbose} from './values.js';
// `ignore` opts-out of `verbose` for a specific stream.
// `ipc` cannot use piping.
// `inherit` would result in double printing.
// They can also lead to double printing when passing file descriptor integers or `process.std*`.
// This only leaves with `pipe` and `overlapped`.
export const shouldLogOutput = ({stdioItems, encoding, verboseInfo, fdNumber}) => fdNumber !== 'all'
&& isFullVerbose(verboseInfo, fdNumber)
&& !BINARY_ENCODINGS.has(encoding)
&& fdUsesVerbose(fdNumber)
&& (stdioItems.some(({type, value}) => type === 'native' && PIPED_STDIO_VALUES.has(value))
|| stdioItems.every(({type}) => TRANSFORM_TYPES.has(type)));
// Printing input streams would be confusing.
// Files and streams can produce big outputs, which we don't want to print.
// We could print `stdio[3+]` but it often is redirected to files and streams, with the same issue.
// So we only print stdout and stderr.
const fdUsesVerbose = fdNumber => fdNumber === 1 || fdNumber === 2;
const PIPED_STDIO_VALUES = new Set(['pipe', 'overlapped']);
// `verbose: 'full'` printing logic with async methods
export const logLines = async (linesIterable, stream, fdNumber, verboseInfo) => {
for await (const line of linesIterable) {
if (!isPipingStream(stream)) {
logLine(line, fdNumber, verboseInfo);
}
}
};
// `verbose: 'full'` printing logic with sync methods
export const logLinesSync = (linesArray, fdNumber, verboseInfo) => {
for (const line of linesArray) {
logLine(line, fdNumber, verboseInfo);
}
};
// When `subprocess.stdout|stderr.pipe()` is called, `verbose` becomes a noop.
// This prevents the following problems:
// - `.pipe()` achieves the same result as using `stdout: 'inherit'`, `stdout: stream`, etc. which also make `verbose` a noop.
// For example, `subprocess.stdout.pipe(process.stdin)` would print each line twice.
// - When chaining subprocesses with `subprocess.pipe(otherSubprocess)`, only the last one should print its output.
// Detecting whether `.pipe()` is impossible without monkey-patching it, so we use the following undocumented property.
// This is not a critical behavior since changes of the following property would only make `verbose` more verbose.
const isPipingStream = stream => stream._readableState.pipes.length > 0;
// When `verbose` is `full`, print stdout|stderr
const logLine = (line, fdNumber, verboseInfo) => {
const verboseMessage = serializeVerboseMessage(line);
verboseLog({
type: 'output',
verboseMessage,
fdNumber,
verboseInfo,
});
};

View File

@@ -1,15 +0,0 @@
import {isVerbose} from './values.js';
import {verboseLog} from './log.js';
// When `verbose` is `short|full|custom`, print each command
export const logCommand = (escapedCommand, verboseInfo) => {
if (!isVerbose(verboseInfo)) {
return;
}
verboseLog({
type: 'command',
verboseMessage: escapedCommand,
verboseInfo,
});
};

View File

@@ -1,33 +0,0 @@
import {getFdSpecificValue} from '../arguments/specific.js';
// The `verbose` option can have different values for `stdout`/`stderr`
export const isVerbose = ({verbose}, fdNumber) => getFdVerbose(verbose, fdNumber) !== 'none';
// Whether IPC and output and logged
export const isFullVerbose = ({verbose}, fdNumber) => !['none', 'short'].includes(getFdVerbose(verbose, fdNumber));
// The `verbose` option can be a function to customize logging
export const getVerboseFunction = ({verbose}, fdNumber) => {
const fdVerbose = getFdVerbose(verbose, fdNumber);
return isVerboseFunction(fdVerbose) ? fdVerbose : undefined;
};
// When using `verbose: {stdout, stderr, fd3, ipc}`:
// - `verbose.stdout|stderr|fd3` is used for 'output'
// - `verbose.ipc` is only used for 'ipc'
// - highest `verbose.*` value is used for 'command', 'error' and 'duration'
const getFdVerbose = (verbose, fdNumber) => fdNumber === undefined
? getFdGenericVerbose(verbose)
: getFdSpecificValue(verbose, fdNumber);
// When using `verbose: {stdout, stderr, fd3, ipc}` and logging is not specific to a file descriptor.
// We then use the highest `verbose.*` value, using the following order:
// - function > 'full' > 'short' > 'none'
// - if several functions are defined: stdout > stderr > fd3 > ipc
const getFdGenericVerbose = verbose => verbose.find(fdVerbose => isVerboseFunction(fdVerbose))
?? VERBOSE_VALUES.findLast(fdVerbose => verbose.includes(fdVerbose));
// Whether the `verbose` option is customized using a function
export const isVerboseFunction = fdVerbose => typeof fdVerbose === 'function';
export const VERBOSE_VALUES = ['none', 'short', 'full'];