@socketsecurity/lib
Version:
Core utilities and infrastructure for Socket.dev security tools
210 lines (209 loc) • 7.11 kB
JavaScript
;
/* Socket Lib - Built with esbuild */
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var mask_exports = {};
__export(mask_exports, {
attachOutputMask: () => attachOutputMask,
createKeyboardHandler: () => createKeyboardHandler,
createOutputMask: () => createOutputMask,
runWithMask: () => runWithMask
});
module.exports = __toCommonJS(mask_exports);
var import_child_process = require("child_process");
var import_readline = __toESM(require("readline"));
var import_spinner = require("../spinner.js");
var import_clear = require("./clear.js");
var import_stdout = require("./stdout.js");
const spinner = (0, import_spinner.getDefaultSpinner)();
function createOutputMask(options = {}) {
const { showOutput = false } = options;
return {
isSpinning: !showOutput,
outputBuffer: [],
stderrCapture: "",
stdoutCapture: "",
verbose: showOutput
};
}
function createKeyboardHandler(mask, child, options = {}) {
const { message = "Running\u2026", toggleText = "to see full output" } = options;
return (_str, key) => {
if (key?.ctrl && key.name === "o") {
mask.verbose = !mask.verbose;
if (mask.verbose) {
if (mask.isSpinning) {
spinner.stop();
mask.isSpinning = false;
}
(0, import_clear.clearLine)();
if (mask.outputBuffer.length > 0) {
console.log("--- Output (ctrl+o to hide) ---");
mask.outputBuffer.forEach((line) => {
(0, import_stdout.write)(line);
});
}
} else {
if (mask.outputBuffer.length > 0) {
const lineCount = mask.outputBuffer.join("").split("\n").length + 1;
for (let i = 0; i < lineCount; i += 1) {
process.stdout.write("\x1B[1A\x1B[2K");
}
}
(0, import_clear.clearLine)();
mask.outputBuffer = [];
if (!mask.isSpinning) {
spinner.start(`${message} (ctrl+o ${toggleText})`);
mask.isSpinning = true;
}
}
} else if (key?.ctrl && key.name === "c") {
child.kill("SIGTERM");
if (process.stdin.isTTY) {
process.stdin.setRawMode(false);
}
throw new Error("Process cancelled by user");
}
};
}
function attachOutputMask(child, options = {}) {
return new Promise((resolve, reject) => {
const { message = "Running\u2026" } = options;
const mask = createOutputMask(options);
if (mask.isSpinning && process.stdout.isTTY) {
spinner.start(
`${message} (ctrl+o ${options.toggleText || "to see full output"})`
);
}
if (process.stdin.isTTY) {
import_readline.default.emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);
const keypressHandler = createKeyboardHandler(mask, child, options);
process.stdin.on("keypress", keypressHandler);
child.on("exit", () => {
if (process.stdin.isTTY) {
process.stdin.setRawMode(false);
process.stdin.removeListener("keypress", keypressHandler);
}
});
}
if (child.stdout) {
child.stdout.on("data", (data) => {
const text = data.toString();
mask.stdoutCapture += text;
if (options.filterOutput && !options.filterOutput(text, "stdout")) {
return void 0;
}
if (mask.verbose) {
(0, import_stdout.write)(text);
} else {
mask.outputBuffer.push(text);
const lines = mask.outputBuffer.join("").split("\n");
if (lines.length > 1e3) {
mask.outputBuffer = [lines.slice(-1e3).join("\n")];
}
}
return void 0;
});
}
if (child.stderr) {
child.stderr.on("data", (data) => {
const text = data.toString();
mask.stderrCapture += text;
if (options.filterOutput && !options.filterOutput(text, "stderr")) {
return void 0;
}
if (mask.verbose) {
process.stderr.write(text);
} else {
mask.outputBuffer.push(text);
}
return void 0;
});
}
child.on("exit", (code) => {
if (process.stdin.isTTY) {
process.stdin.setRawMode(false);
}
let finalCode = code || 0;
if (options.overrideExitCode) {
const overridden = options.overrideExitCode(
finalCode,
mask.stdoutCapture,
mask.stderrCapture
);
if (overridden !== void 0) {
finalCode = overridden;
}
}
if (mask.isSpinning) {
if (finalCode === 0) {
spinner.successAndStop(`${message} completed`);
} else {
spinner.failAndStop(`${message} failed`);
if (mask.outputBuffer.length > 0 && !mask.verbose) {
console.log("\n--- Output ---");
mask.outputBuffer.forEach((line) => {
(0, import_stdout.write)(line);
});
}
}
}
resolve(finalCode);
});
child.on("error", (error) => {
if (process.stdin.isTTY) {
process.stdin.setRawMode(false);
}
if (mask.isSpinning) {
spinner.failAndStop(`${message} error`);
}
reject(error);
});
});
}
async function runWithMask(command, args = [], options = {}) {
const {
message = "Running\u2026",
showOutput = false,
toggleText = "to see output",
...spawnOptions
} = options;
const child = (0, import_child_process.spawn)(command, args, {
stdio: ["inherit", "pipe", "pipe"],
...spawnOptions
});
return await attachOutputMask(child, { message, showOutput, toggleText });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
attachOutputMask,
createKeyboardHandler,
createOutputMask,
runWithMask
});