This project is designed to help developers understand and mitigate code injection and XSS vulnerabilities. It includes a backend API and a frontend interface for testing various attack vectors in a controlled environment.
157 lines
4.9 KiB
TypeScript
157 lines
4.9 KiB
TypeScript
import { exec, execSync } from 'child_process';
|
|
import { promises as fs } from 'fs';
|
|
import chalk from 'chalk';
|
|
import ora from 'ora';
|
|
|
|
const commitTypes: Record<string, string> = {
|
|
feat: '✨',
|
|
fix: '🐛',
|
|
docs: '📚',
|
|
style: '🎨',
|
|
refactor: '🔨',
|
|
test: '✅',
|
|
chore: '🛠️',
|
|
perf: '⚡',
|
|
ci: '🔧',
|
|
build: '📦',
|
|
revert: '⏪',
|
|
};
|
|
|
|
const defaultEmoji = '🔖';
|
|
|
|
async function run(): Promise<void> {
|
|
const spinner = ora('Running custom commit message check...').start();
|
|
|
|
try {
|
|
console.log(chalk.blue('Running custom commit message check...'));
|
|
console.log();
|
|
|
|
const commitMsgFile = process.argv[2];
|
|
|
|
if (!commitMsgFile) {
|
|
spinner.fail('Error: Commit message file path not provided.');
|
|
console.error(chalk.red('Error: Commit message file path not provided.'));
|
|
process.exit(1);
|
|
}
|
|
|
|
const commitMsg = (await fs.readFile(commitMsgFile, 'utf8')).trim();
|
|
|
|
// Check for duplicate commit messages in the last 100 commits
|
|
const duplicateCommitMsg = execSync(`git log -n 100 --pretty=format:%s`)
|
|
.toString()
|
|
.split('\n');
|
|
|
|
// Extract emojis from commitTypes
|
|
const emojis = Object.values(commitTypes);
|
|
|
|
// Function to remove an emoji from the start of the string
|
|
const removeEmoji = (message: string): string => {
|
|
for (const emoji of emojis) {
|
|
if (message.startsWith(emoji)) {
|
|
return message.slice(emoji.length).trim();
|
|
}
|
|
}
|
|
if (message.startsWith(defaultEmoji)) {
|
|
return message.slice(defaultEmoji.length).trim();
|
|
}
|
|
return message;
|
|
};
|
|
|
|
const cleanMessages = duplicateCommitMsg.map(removeEmoji);
|
|
|
|
if (cleanMessages.includes(commitMsg)) {
|
|
spinner.fail(chalk.bold.red('Duplicate Commit Detected'));
|
|
console.log();
|
|
console.error(
|
|
chalk.white.bgRed.bold(' ERROR: ') +
|
|
chalk.redBright(' A duplicate commit message has been detected.')
|
|
);
|
|
console.log();
|
|
console.log(
|
|
chalk.yellowBright('TIP: ') +
|
|
chalk.white(' Please use a unique commit message to keep the history clean.')
|
|
);
|
|
console.log();
|
|
process.exit(1);
|
|
}
|
|
|
|
spinner.succeed('Message is not duplicated');
|
|
console.log(chalk.green('Message is not duplicated'));
|
|
console.log();
|
|
} catch (err) {
|
|
spinner.fail('Error running custom commit message check.');
|
|
console.error(chalk.red('Error:', err));
|
|
process.exit(1);
|
|
}
|
|
|
|
const spinner2 = ora('Running commitlint...').start();
|
|
|
|
try {
|
|
console.log(chalk.blue('Running commitlint...'));
|
|
console.log();
|
|
|
|
const commitMsgFile = process.argv[2];
|
|
|
|
if (!commitMsgFile) {
|
|
spinner2.fail('Error: Commit message file path not provided.');
|
|
console.error(chalk.red('Error: Commit message file path not provided.'));
|
|
process.exit(1);
|
|
}
|
|
|
|
const commitMsg = (await fs.readFile(commitMsgFile, 'utf8')).trim();
|
|
|
|
// Run commitlint
|
|
exec(
|
|
`npx commitlint --edit ${commitMsgFile}`,
|
|
async (error, stdout, stderr) => {
|
|
if (error) {
|
|
spinner2.fail('Commitlint check failed.');
|
|
console.error(chalk.red(stdout || stderr));
|
|
console.error(chalk.red('Commitlint check failed.'));
|
|
console.log();
|
|
console.error(
|
|
chalk.yellow('Hint: Commit message should follow the Conventional Commits standard.')
|
|
);
|
|
console.error(chalk.yellow('See: https://www.conventionalcommits.org/en/v1.0.0/'));
|
|
console.error(chalk.yellow('Examples:'));
|
|
console.error(chalk.yellow(' feat: add a new feature'));
|
|
console.error(chalk.yellow(' fix: fix a bug'));
|
|
console.error(chalk.yellow(' docs: update documentation'));
|
|
process.exit(1);
|
|
} else {
|
|
spinner2.succeed('Commitlint check passed.');
|
|
console.log(chalk.green('Commitlint check passed.'));
|
|
console.log(chalk.green(stdout));
|
|
|
|
// Add emoji to the commit message
|
|
const commitRegex = /^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?:\s.+/;
|
|
const match = commitMsg.match(commitRegex);
|
|
|
|
if (match) {
|
|
const commitType = match[1];
|
|
const emoji = commitTypes[commitType] || defaultEmoji;
|
|
const newCommitMsg = `${emoji} ${commitMsg}`;
|
|
await fs.writeFile(commitMsgFile, newCommitMsg + '\n', 'utf8');
|
|
console.log(chalk.green('Commit message updated with emoji:'), newCommitMsg);
|
|
} else {
|
|
const newCommitMsg = `${defaultEmoji} ${commitMsg}`;
|
|
await fs.writeFile(commitMsgFile, newCommitMsg + '\n', 'utf8');
|
|
console.log(
|
|
chalk.yellow('Commit message did not match expected format, added default emoji:'),
|
|
newCommitMsg
|
|
);
|
|
}
|
|
|
|
process.exit(0);
|
|
}
|
|
}
|
|
);
|
|
} catch (err) {
|
|
spinner2.fail('Error running commitlint.');
|
|
console.error(chalk.red('Error:', err));
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
run();
|