diff --git a/packages/steiger/src/cli.ts b/packages/steiger/src/cli.ts index 4c7dee5..3011cf8 100755 --- a/packages/steiger/src/cli.ts +++ b/packages/steiger/src/cli.ts @@ -11,6 +11,7 @@ import { cosmiconfig } from 'cosmiconfig' import { linter } from './app' import { setConfig, schema as configSchema } from './models/config' +import { applyAutofixes } from './features/autofix' const yargsProgram = yargs(hideBin(process.argv)) .scriptName('steiger') @@ -21,6 +22,11 @@ const yargsProgram = yargs(hideBin(process.argv)) describe: 'watch filesystem changes', type: 'boolean', }) + .option('fix', { + demandOption: false, + describe: 'apply auto-fixes', + type: 'boolean', + }) .string('_') .check((argv) => { const filePaths = argv._ @@ -58,11 +64,19 @@ if (consoleArgs.watch) { const unsubscribe = diagnosticsChanged.watch((state) => { console.clear() reportPretty(state) + if (consoleArgs.fix) { + applyAutofixes(state) + } }) prexit(() => { stopWatching() unsubscribe() }) } else { - await linter.run(resolve(consoleArgs._[0])).then(reportPretty) + const diagnostics = await linter.run(resolve(consoleArgs._[0])) + + reportPretty(diagnostics) + if (consoleArgs.fix) { + applyAutofixes(diagnostics) + } } diff --git a/packages/steiger/src/features/autofix.ts b/packages/steiger/src/features/autofix.ts new file mode 100644 index 0000000..e495a92 --- /dev/null +++ b/packages/steiger/src/features/autofix.ts @@ -0,0 +1,27 @@ +import { dirname, join } from 'node:path' +import { rename, open, mkdir, rm } from 'node:fs/promises' +import type { Diagnostic } from '@feature-sliced/steiger-plugin' + +export async function applyAutofixes(diagnostics: Array) { + return Promise.all( + diagnostics + .flatMap((diagnostic) => diagnostic.fixes ?? []) + .map((fix) => { + switch (fix.type) { + case 'rename': + return rename(fix.path, join(dirname(fix.path), fix.newName)) + case 'create-file': + return open(fix.path, 'w').then((file) => file.close()) + case 'create-folder': + return mkdir(fix.path, { recursive: true }) + case 'delete': + return rm(fix.path, { recursive: true }) + case 'modify-file': + return open(fix.path, 'w').then(async (file) => { + await file.write(fix.content) + return file.close() + }) + } + }), + ) +}