commit-guardian
Version:
Interactive CLI tool with browser-based GitHub-style diff viewer for reviewing and approving git changes before commit. Features React-based UI, approval workflow, line comments, and safe commit protection.
146 lines (145 loc) ⢠5.68 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const simple_git_1 = require("simple-git");
const open_1 = __importDefault(require("open"));
const server_1 = require("../server/server");
const program = new commander_1.Command();
program
.name('commit-guardian')
.description('š”ļø Commit Guardian - Review changes before commit')
.version('1.0.11')
.option('-m, --message <message>', 'Commit message (REQUIRED)')
.option('-p, --port <port>', 'Port number', '3456')
.option('--no-open', 'Don\'t automatically open browser')
.helpOption('-h, --help', 'Show this help message')
.action(async (options) => {
if (!options.message) {
console.error('ā Error: Commit message is required');
console.error('');
console.error('Usage: commit-guardian -m <commit-message>');
console.error('');
console.error('Examples:');
console.error(' commit-guardian -m "Add new feature"');
console.error(' commit-guardian --message "Fix bug in login"');
process.exit(1);
}
try {
// Check if we're in a git repository
const git = (0, simple_git_1.simpleGit)();
const isRepo = await git.checkIsRepo();
if (!isRepo) {
console.error('ā Error: Not a git repository');
process.exit(1);
}
// Check for changes
const status = await git.status();
const stagedFiles = status.staged.length;
const modifiedFiles = status.modified.length;
const hasChanges = stagedFiles > 0 || modifiedFiles > 0;
if (!hasChanges) {
console.error('ā Error: No staged changes found');
console.error('');
console.error('You need to stage files before committing.');
console.error('Please use git add to stage specific files:');
console.error('');
if (status.not_added.length > 0) {
console.error('š Untracked files that can be added:');
status.not_added.forEach(file => {
console.error(` git add ${file}`);
});
console.error('');
}
if (status.modified.length > 0) {
console.error('š Modified files that can be staged:');
status.modified.forEach(file => {
console.error(` git add ${file}`);
});
console.error('');
}
console.error('š” Avoid using:');
console.error(' git add . (adds all files)');
console.error(' git add -A (adds all files)');
console.error('');
console.error('Instead, add files individually for better control.');
console.error('');
console.error('š”ļø Commit Guardian - Review changes before commit');
process.exit(1);
}
console.log('š”ļø Commit Guardian - Review changes before commit');
console.log('');
console.log('š Changes detected:');
if (stagedFiles > 0)
console.log(' ⢠Staged changes found');
if (modifiedFiles > 0)
console.log(' ⢠Unstaged changes found');
console.log(`š Default commit message: "${options.message}"`);
console.log('');
// Start the server
const port = parseInt(options.port);
const { server, url } = await (0, server_1.startServer)({
port,
commitMessage: options.message,
onApproval: (approved, message, reason, comments) => {
// This callback is called when approval/rejection happens
// Server will shut down automatically
}
});
console.log('š Opening browser...');
console.log('');
console.log('ā³ Waiting for your review...');
console.log(' ⢠Review changes in browser');
console.log(' ⢠Add comments if needed');
console.log(' ⢠Approve to commit or reject to cancel');
console.log('');
console.log('Press Ctrl+C to cancel');
// Open browser if not disabled
if (options.open !== false) {
try {
await (0, open_1.default)(url);
}
catch (error) {
console.log('Could not open browser automatically. Please visit:', url);
}
}
// Handle graceful shutdown
process.on('SIGINT', () => {
console.log('\n\nš Review cancelled');
server.close(() => {
process.exit(0);
});
});
process.on('SIGTERM', () => {
console.log('\n\nš Review cancelled');
server.close(() => {
process.exit(0);
});
});
}
catch (error) {
console.error('ā Error:', error instanceof Error ? error.message : 'Unknown error');
process.exit(1);
}
});
// Check for required dependencies
const checkDependencies = () => {
try {
require('express');
require('simple-git');
require('open');
require('commander');
}
catch (error) {
console.error('ā Missing dependencies. Please install:');
console.error(' npm install');
process.exit(1);
}
};
if (require.main === module) {
checkDependencies();
program.parse();
}