lockfile-guardian
Version:
Never forget to install dependencies again! Automatically detect when your lock files change after git operations and warn you (or auto-install) when your dependencies are out of sync.
136 lines • 5.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.storeCurrentHash = storeCurrentHash;
exports.getStoredHash = getStoredHash;
exports.clearStoredHash = clearStoredHash;
exports.checkLockfile = checkLockfile;
exports.updateHashAfterInstall = updateHashAfterInstall;
const fs_1 = require("fs");
const child_process_1 = require("child_process");
const utils_1 = require("./utils");
function storeCurrentHash(cwd = process.cwd()) {
const lockfileInfo = (0, utils_1.findLockfile)(cwd);
if (!lockfileInfo) {
return; // No lockfile found
}
const dataPath = (0, utils_1.getGuardianDataPath)(cwd);
(0, fs_1.writeFileSync)(dataPath, lockfileInfo.hash, "utf8");
}
function getStoredHash(cwd = process.cwd()) {
const dataPath = (0, utils_1.getGuardianDataPath)(cwd);
if (!(0, fs_1.existsSync)(dataPath)) {
return null;
}
try {
return (0, fs_1.readFileSync)(dataPath, "utf8").trim();
}
catch {
return null;
}
}
function clearStoredHash(cwd = process.cwd()) {
const dataPath = (0, utils_1.getGuardianDataPath)(cwd);
if ((0, fs_1.existsSync)(dataPath)) {
(0, fs_1.unlinkSync)(dataPath);
}
}
function createWarningBox(lockfileName, installCommand) {
const separator = "=====================================";
return [
separator,
"⚠️ DEPENDENCIES OUT OF DATE ⚠️",
separator,
`Lock file ${lockfileName} has changed!`,
"",
"Run this command to update:",
` ${installCommand}`,
separator,
].join("\n");
}
function runInstallCommand(command, cwd) {
return new Promise((resolve) => {
const [cmd, ...args] = command.split(" ");
const child = (0, child_process_1.spawn)(cmd, args, {
cwd,
stdio: "inherit",
shell: true,
});
child.on("close", (code) => {
resolve(code === 0);
});
child.on("error", () => {
resolve(false);
});
});
}
/**
* Check if lockfile has changed compared to stored hash.
* This function only checks and warns - it doesn't update the stored hash.
* Hash updates should happen via post-install scripts when packages are actually installed.
*/
async function checkLockfile(isHook = false, cwd = process.cwd()) {
const config = (0, utils_1.loadConfig)(cwd);
const lockfileInfo = (0, utils_1.findLockfile)(cwd);
if (!lockfileInfo) {
if (!isHook) {
(0, utils_1.logError)("No lockfile found. Supported lockfiles: pnpm-lock.yaml, yarn.lock, package-lock.json");
}
return;
}
// Check node_modules gitignore
if (config.checkNodeModules && !(0, utils_1.isNodeModulesIgnored)(cwd)) {
(0, utils_1.logWarning)("⚠️ Warning: node_modules is not in .gitignore");
}
const storedHash = getStoredHash(cwd);
const currentHash = lockfileInfo.hash;
// First run or no stored hash - store current hash without warning
if (!storedHash) {
storeCurrentHash(cwd);
if (!isHook) {
(0, utils_1.log)("🔒 Lockfile Guardian initialized", config.silent);
}
return;
}
// No changes detected
if (storedHash === currentHash) {
if (!isHook) {
(0, utils_1.log)("✅ Dependencies are up to date", config.silent);
}
return;
}
// Changes detected!
const lockfileName = lockfileInfo.packageManager.lockFile;
const installCommand = lockfileInfo.packageManager.installCommand;
if (config.autoInstall) {
(0, utils_1.log)(`🔒 Lock file ${lockfileName} has changed!`, config.silent);
(0, utils_1.log)(`🔒 Auto-installing dependencies with ${lockfileInfo.packageManager.name}...`, config.silent);
const success = await runInstallCommand(installCommand, cwd);
if (success) {
(0, utils_1.log)("🔒 Dependencies updated successfully!", config.silent);
// Note: Hash will be updated by post-install script, not here
}
else {
(0, utils_1.logError)("🔒 Failed to install dependencies. Please run manually:");
(0, utils_1.logError)(` ${installCommand}`);
}
}
else {
// Show warning - don't update hash until user actually runs install
const warningMessage = createWarningBox(lockfileName, installCommand);
(0, utils_1.logWarning)(warningMessage);
}
}
/**
* Called by post-install scripts to update the stored hash after successful package installation.
* This ensures we only track hash changes when packages are actually installed.
*/
function updateHashAfterInstall(cwd = process.cwd()) {
const config = (0, utils_1.loadConfig)(cwd);
const lockfileInfo = (0, utils_1.findLockfile)(cwd);
if (!lockfileInfo) {
return;
}
storeCurrentHash(cwd);
(0, utils_1.log)("🔒 Lockfile Guardian: Dependencies hash updated", config.silent);
}
//# sourceMappingURL=guardian.js.map