Add precommit hook

This commit is contained in:
icld
2025-02-27 10:48:04 -08:00
parent 476d49c204
commit b0de546668
33 changed files with 835 additions and 192 deletions
+36
View File
@@ -0,0 +1,36 @@
# Scripts and Hooks
This directory contains utility scripts for the project.
## Lefthook Configuration
The project uses [Lefthook](https://github.com/evilmartians/lefthook) for git hooks to ensure code quality before commits.
### Pre-commit Hooks
The pre-commit hooks run:
1. **Linting** - Checks and fixes code style issues
2. **Formatting** - Ensures consistent code formatting
3. **Type Checking** - Verifies TypeScript types
These hooks are configured in `lefthook.yaml` in the root directory.
### Usage
The hooks run automatically when you commit code. You can also run them manually:
```bash
# Run all pre-commit hooks
pnpm test:hooks
# Run individual commands
pnpm lint:fix
pnpm format:fix
pnpm check-types
pnpm fix-all
```
## VS Code Integration
TypeScript errors will show up directly in VS Code thanks to the configuration in `.vscode/settings.json`.
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/env node
import chalk from 'chalk'
const command = process.argv[2]
const files = process.argv.slice(3)
// Format the command name for display
const formatCommand = (cmd) => {
switch (cmd) {
case 'lint:fix':
return chalk.blue.bold('LINTING')
case 'format:fix':
return chalk.magenta.bold('FORMATTING')
case 'check-types':
return chalk.yellow.bold('TYPE CHECKING')
case 'fix-all':
return chalk.green.bold('FIXING ALL ISSUES')
default:
return chalk.white.bold(cmd.toUpperCase())
}
}
// Display a header for the command
console.log(
'\n' +
chalk.gray(
'╔═════════════════════════════════════════════════════════════════════════════╗'
)
)
console.log(
chalk.gray('║ ') +
chalk.white.bold(`LEFTHOOK: ${formatCommand(command)}`) +
chalk.gray(' ║')
)
console.log(
chalk.gray(
'╚═════════════════════════════════════════════════════════════════════════════╝\n'
)
)
// If we have files, display them
if (files.length > 0) {
console.log(chalk.gray('Files being processed:'))
for (const file of files) {
console.log(chalk.cyan(`${file}`))
}
console.log('')
}
// Execute the original command
const { execSync } = await import('node:child_process')
try {
// Construct the command based on what was passed
let fullCommand
if (files.length > 0 && command !== 'check-types') {
// For commands that support specific files
fullCommand = `pnpm ${command} ${files.join(' ')}`
} else {
// For commands that run on the whole project
fullCommand = `pnpm ${command}`
}
// Execute the command
execSync(fullCommand, { stdio: 'inherit' })
// Show success message
console.log(
'\n' +
chalk.green.bold('✓ SUCCESS') +
chalk.green(` ${formatCommand(command)} completed successfully`)
)
} catch (error) {
// Show error message
console.log(
'\n' +
chalk.red.bold('✗ ERROR') +
chalk.red(` ${formatCommand(command)} failed`)
)
process.exit(1)
}