| #!/usr/bin/env node |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| const { execFileSync } = require('child_process'); |
| const fs = require('fs'); |
| const path = require('path'); |
|
|
| const MAX_STDIN = 1024 * 1024; |
| let data = ''; |
| process.stdin.setEncoding('utf8'); |
|
|
| process.stdin.on('data', chunk => { |
| if (data.length < MAX_STDIN) { |
| const remaining = MAX_STDIN - data.length; |
| data += chunk.substring(0, remaining); |
| } |
| }); |
|
|
| function findProjectRoot(startDir) { |
| let dir = startDir; |
| while (dir !== path.dirname(dir)) { |
| if (fs.existsSync(path.join(dir, 'package.json'))) return dir; |
| dir = path.dirname(dir); |
| } |
| return startDir; |
| } |
|
|
| function detectFormatter(projectRoot) { |
| const biomeConfigs = ['biome.json', 'biome.jsonc']; |
| for (const cfg of biomeConfigs) { |
| if (fs.existsSync(path.join(projectRoot, cfg))) return 'biome'; |
| } |
|
|
| const prettierConfigs = [ |
| '.prettierrc', |
| '.prettierrc.json', |
| '.prettierrc.js', |
| '.prettierrc.cjs', |
| '.prettierrc.mjs', |
| '.prettierrc.yml', |
| '.prettierrc.yaml', |
| '.prettierrc.toml', |
| 'prettier.config.js', |
| 'prettier.config.cjs', |
| 'prettier.config.mjs', |
| ]; |
| for (const cfg of prettierConfigs) { |
| if (fs.existsSync(path.join(projectRoot, cfg))) return 'prettier'; |
| } |
|
|
| return null; |
| } |
|
|
| function getFormatterCommand(formatter, filePath) { |
| const npxBin = process.platform === 'win32' ? 'npx.cmd' : 'npx'; |
| if (formatter === 'biome') { |
| return { bin: npxBin, args: ['@biomejs/biome', 'format', '--write', filePath] }; |
| } |
| if (formatter === 'prettier') { |
| return { bin: npxBin, args: ['prettier', '--write', filePath] }; |
| } |
| return null; |
| } |
|
|
| process.stdin.on('end', () => { |
| try { |
| const input = JSON.parse(data); |
| const filePath = input.tool_input?.file_path; |
|
|
| if (filePath && /\.(ts|tsx|js|jsx)$/.test(filePath)) { |
| try { |
| const projectRoot = findProjectRoot(path.dirname(path.resolve(filePath))); |
| const formatter = detectFormatter(projectRoot); |
| const cmd = getFormatterCommand(formatter, filePath); |
|
|
| if (cmd) { |
| execFileSync(cmd.bin, cmd.args, { |
| cwd: projectRoot, |
| stdio: ['pipe', 'pipe', 'pipe'], |
| timeout: 15000 |
| }); |
| } |
| } catch { |
| |
| } |
| } |
| } catch { |
| |
| } |
|
|
| process.stdout.write(data); |
| process.exit(0); |
| }); |
|
|