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.
149 lines • 6.06 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.installPostInstallHook = installPostInstallHook;
exports.uninstallPostInstallHook = uninstallPostInstallHook;
exports.isPostInstallHookInstalled = isPostInstallHookInstalled;
exports.runPostInstallHook = runPostInstallHook;
const fs_1 = require("fs");
const path_1 = require("path");
const guardian_1 = require("./guardian");
const utils_1 = require("./utils");
const POST_INSTALL_SCRIPT_NAME = "postinstall";
const LOCKFILE_GUARDIAN_HOOK = "npx lockfile-guardian post-install";
/**
* Add post-install script to package.json that will update lockfile hash after installs
*/
function installPostInstallHook(cwd = process.cwd()) {
const packageJsonPath = (0, path_1.join)(cwd, "package.json");
if (!(0, fs_1.existsSync)(packageJsonPath)) {
throw new Error("package.json not found in current directory");
}
let packageJson;
try {
const content = (0, fs_1.readFileSync)(packageJsonPath, "utf8");
packageJson = JSON.parse(content);
}
catch (error) {
throw new Error(`Failed to read or parse package.json: ${error.message}`);
}
// Initialize scripts object if it doesn't exist
if (!packageJson.scripts) {
packageJson.scripts = {};
}
const currentPostInstall = packageJson.scripts[POST_INSTALL_SCRIPT_NAME];
// Check if our hook is already present
if (currentPostInstall &&
currentPostInstall.includes(LOCKFILE_GUARDIAN_HOOK)) {
(0, utils_1.log)("🔒 Lockfile Guardian post-install hook is already configured");
return;
}
// Add or append our hook to the postinstall script
if (currentPostInstall) {
// Append to existing postinstall script
packageJson.scripts[POST_INSTALL_SCRIPT_NAME] = `${currentPostInstall} && ${LOCKFILE_GUARDIAN_HOOK}`;
(0, utils_1.log)("🔒 Added Lockfile Guardian hook to existing postinstall script");
}
else {
// Create new postinstall script
packageJson.scripts[POST_INSTALL_SCRIPT_NAME] = LOCKFILE_GUARDIAN_HOOK;
(0, utils_1.log)("🔒 Created postinstall script with Lockfile Guardian hook");
}
// Write back to package.json with proper formatting
try {
const formattedJson = JSON.stringify(packageJson, null, 2) + "\n";
(0, fs_1.writeFileSync)(packageJsonPath, formattedJson, "utf8");
(0, utils_1.log)("✅ package.json updated successfully");
}
catch (error) {
throw new Error(`Failed to write package.json: ${error.message}`);
}
}
/**
* Remove post-install script hook from package.json
*/
function uninstallPostInstallHook(cwd = process.cwd()) {
const packageJsonPath = (0, path_1.join)(cwd, "package.json");
if (!(0, fs_1.existsSync)(packageJsonPath)) {
(0, utils_1.log)("package.json not found - nothing to uninstall");
return;
}
let packageJson;
try {
const content = (0, fs_1.readFileSync)(packageJsonPath, "utf8");
packageJson = JSON.parse(content);
}
catch (error) {
(0, utils_1.logError)(`Failed to read or parse package.json: ${error.message}`);
return;
}
if (!packageJson.scripts || !packageJson.scripts[POST_INSTALL_SCRIPT_NAME]) {
(0, utils_1.log)("No postinstall script found - nothing to uninstall");
return;
}
const currentPostInstall = packageJson.scripts[POST_INSTALL_SCRIPT_NAME];
// Check if our hook is present
if (!currentPostInstall.includes(LOCKFILE_GUARDIAN_HOOK)) {
(0, utils_1.log)("Lockfile Guardian hook not found in postinstall script");
return;
}
// Remove our hook from the script
let newPostInstall = currentPostInstall
.replace(new RegExp(`\\s*&&\\s*${LOCKFILE_GUARDIAN_HOOK.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), "")
.replace(new RegExp(`^${LOCKFILE_GUARDIAN_HOOK.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*&&\\s*`), "")
.replace(new RegExp(`^${LOCKFILE_GUARDIAN_HOOK.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`), "")
.trim();
if (newPostInstall === "") {
// Remove the entire postinstall script if it's empty
delete packageJson.scripts[POST_INSTALL_SCRIPT_NAME];
(0, utils_1.log)("🔒 Removed postinstall script (was only containing Lockfile Guardian hook)");
}
else {
// Update with the remaining script
packageJson.scripts[POST_INSTALL_SCRIPT_NAME] = newPostInstall;
(0, utils_1.log)("🔒 Removed Lockfile Guardian hook from postinstall script");
}
// Write back to package.json
try {
const formattedJson = JSON.stringify(packageJson, null, 2) + "\n";
(0, fs_1.writeFileSync)(packageJsonPath, formattedJson, "utf8");
(0, utils_1.log)("✅ package.json updated successfully");
}
catch (error) {
(0, utils_1.logError)(`Failed to write package.json: ${error.message}`);
}
}
/**
* Check if post-install hook is installed
*/
function isPostInstallHookInstalled(cwd = process.cwd()) {
const packageJsonPath = (0, path_1.join)(cwd, "package.json");
if (!(0, fs_1.existsSync)(packageJsonPath)) {
return false;
}
try {
const content = (0, fs_1.readFileSync)(packageJsonPath, "utf8");
const packageJson = JSON.parse(content);
const postInstallScript = packageJson.scripts?.[POST_INSTALL_SCRIPT_NAME];
return postInstallScript
? postInstallScript.includes(LOCKFILE_GUARDIAN_HOOK)
: false;
}
catch {
return false;
}
}
/**
* The actual post-install hook that gets called after package installation
*/
function runPostInstallHook(cwd = process.cwd()) {
const config = (0, utils_1.loadConfig)(cwd);
try {
(0, guardian_1.updateHashAfterInstall)(cwd);
}
catch (error) {
if (!config.silent) {
(0, utils_1.logError)(`Lockfile Guardian post-install hook failed: ${error.message}`);
}
}
}
//# sourceMappingURL=post-install.js.map