Skip to content

Instantly share code, notes, and snippets.

@yunusemredilber
Last active September 9, 2025 10:01
Show Gist options
  • Select an option

  • Save yunusemredilber/9d12653903dd79ee479618805205acc0 to your computer and use it in GitHub Desktop.

Select an option

Save yunusemredilber/9d12653903dd79ee479618805205acc0 to your computer and use it in GitHub Desktop.
const { execSync } = require("child_process");
const fs = require("fs");
const packagesToCheck = [
"backslash",
"chalk",
"chalk-template",
"color-convert",
"color-name",
"color-string",
"wrap-ansi",
"supports-hyperlinks",
"strip-ansi",
"slice-ansi",
"simple-swizzle",
"is-arrayish",
"error-ex",
"has-ansi",
"ansi-regex",
"ansi-styles",
"supports-color",
"proto-tinker-wc",
"debug",
];
// Flagged versions
const warnVersions = {
"backslash": ["0.2.1"],
"chalk": ["5.6.1"],
"chalk-template": ["1.1.1"],
"color-convert": ["3.1.1"],
"color-name": ["2.0.1"],
"color-string": ["2.1.1"],
"wrap-ansi": ["9.0.1"],
"supports-hyperlinks": ["4.1.1"],
"strip-ansi": ["7.1.1"],
"slice-ansi": ["7.1.1"],
"simple-swizzle": ["0.2.3"],
"is-arrayish": ["0.3.3"],
"error-ex": ["1.3.3"],
"has-ansi": ["6.0.1"],
"ansi-regex": ["6.2.1"],
"ansi-styles": ["6.2.2"],
"supports-color": ["10.2.1"],
"proto-tinker-wc": ["1.8.7"],
"debug": ["4.4.2"],
};
// Detect package manager
let manager;
if (fs.existsSync("pnpm-lock.yaml")) {
manager = "pnpm";
} else if (fs.existsSync("yarn.lock")) {
manager = "yarn";
} else {
manager = "npm";
}
console.log(`Detected package manager: ${manager}`);
// Collect installed versions
let versions = {};
try {
if (manager === "npm") {
const output = execSync("npm ls --all --json", { stdio: ["pipe", "pipe", "ignore"] }).toString();
const data = JSON.parse(output);
function collectNpm(tree) {
const deps = tree.dependencies || {};
for (const [name, dep] of Object.entries(deps)) {
if (dep.version) {
if (!versions[name]) versions[name] = new Set();
versions[name].add(dep.version);
}
collectNpm(dep);
}
}
collectNpm(data);
} else if (manager === "yarn") {
const output = execSync("yarn list --json --no-progress --pattern ''", { stdio: ["pipe", "pipe"] }).toString();
const lines = output.split("\n").filter(Boolean);
function walkYarnTrees(trees) {
for (const t of trees) {
if (t.name) {
const match = t.name.match(/^([^@]+)@.*:(.+)$/);
if (match) {
const name = match[1];
const version = match[2];
if (!versions[name]) versions[name] = new Set();
versions[name].add(version);
}
}
if (t.children) walkYarnTrees(t.children);
}
}
for (const line of lines) {
let obj;
try { obj = JSON.parse(line); } catch { continue; }
if (obj.type === "tree" && obj.data?.trees) {
walkYarnTrees(obj.data.trees);
}
}
} else if (manager === "pnpm") {
const output = execSync(`pnpm list --parseable --long --depth Infinity | grep -E '${packagesToCheck.join("|")}'`, { stdio: ["pipe", "pipe"] }).toString();
const lines = output.split("\n").filter(Boolean);
for (const line of lines) {
const last = line.split("/").pop(); // get last segment
const match = last.match(/^(@?[^@]+)@(.+)$/);
if (match) {
const name = match[1].split(":")[1];
const version = match[2];
if (!versions[name]) versions[name] = new Set();
versions[name].add(version);
}
}
}
} catch (err) {
console.error("Error collecting versions:", err.message);
process.exit(1);
}
// Print results with warnings
let hasWarnings = false;
packagesToCheck.forEach((pkg) => {
if (versions[pkg]) {
const installed = Array.from(versions[pkg]);
const warnings = installed.filter(v => warnVersions[pkg]?.includes(v));
if (warnings.length > 0) {
console.log(`${pkg}: ${installed.join(", ")} ⚠️ WARNING: flagged version(s): ${warnings.join(", ")}`);
hasWarnings = true;
} else {
console.log(`${pkg}: ${installed.join(", ")}`);
}
} else {
console.log(`${pkg}: (not installed)`);
}
});
if (hasWarnings) process.exit(1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment