UNPKG

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
"use strict"; 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