@ts-dev-tools/core
Version:
TS dev tools Core
134 lines (133 loc) • 4.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractPackageManagerAdapter = void 0;
const node_child_process_1 = require("node:child_process");
const node_fs_1 = require("node:fs");
class AbstractPackageManagerAdapter {
async getVersion(packageManager, dirPath) {
const raw = (await this.execCommand([packageManager, "--version"], dirPath, true)).trim();
const match = raw.match(/(\d+)\.(\d+)\.(\d+)/);
if (!match) {
return { raw, major: 0, minor: 0, patch: 0 };
}
return {
raw,
major: Number(match[1]),
minor: Number(match[2]),
patch: Number(match[3]),
};
}
async execCommand(args, cwd, silent = false) {
if (Array.isArray(args) && args.length === 0) {
throw new Error("Command args must not be empty");
}
if (typeof args === "string" && args.trim().length === 0) {
throw new Error("Command args must not be empty");
}
if (cwd && !(0, node_fs_1.existsSync)(cwd)) {
throw new Error(`Directory "${cwd}" does not exist`);
}
let cmd;
let cmdArgs;
let useShell = false;
if (Array.isArray(args)) {
const shellOperators = [
">",
"|",
"&&",
"||",
";",
"<",
">>",
"2>",
"&",
"$(",
];
const hasShellSyntax = args.some((arg) => {
const trimmedArg = arg.trim();
return shellOperators.some((op) => trimmedArg.startsWith(op) ||
trimmedArg.endsWith(op) ||
trimmedArg.includes(` ${op} `) ||
trimmedArg.includes(` ${op}`) ||
trimmedArg.includes(`${op} `));
});
if (hasShellSyntax) {
cmd = args.join(" ").trim();
cmdArgs = [];
useShell = true;
}
else {
cmd = args[0];
cmdArgs = args.slice(1);
}
}
else {
cmd = args;
cmdArgs = [];
useShell = true;
}
return new Promise((resolve, reject) => {
const child = (0, node_child_process_1.spawn)(cmd, cmdArgs, {
stdio: silent ? "pipe" : "inherit",
shell: useShell,
windowsVerbatimArguments: true,
cwd,
});
let output = "";
let error = "";
let isSettled = false;
const resolveOnce = (value) => {
if (isSettled) {
return;
}
isSettled = true;
resolve(value);
};
const rejectOnce = (reason) => {
if (isSettled) {
return;
}
isSettled = true;
reject(reason);
};
child.on("error", (spawnError) => {
rejectOnce(spawnError);
});
child.on("close", (code) => {
if (code !== 0) {
rejectOnce(output.length > 0
? output
: error || `Command "${cmd}" failed with exit code ${code}`);
return;
}
resolveOnce(output);
});
if (child.stdout) {
child.stdout.on("data", (data) => {
output += `\n${data}`;
});
}
if (child.stderr) {
child.stderr.on("data", (data) => {
error += `\n${data}`;
});
}
});
}
parseJsonLines(output) {
return output
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line.length > 0)
.map((line) => {
try {
return JSON.parse(line);
}
catch {
return undefined;
}
})
.filter((entry) => entry !== undefined);
}
}
exports.AbstractPackageManagerAdapter = AbstractPackageManagerAdapter;