@doist/react-compiler-tracker
Advanced tools
+7
-0
@@ -5,2 +5,9 @@ # Changelog | ||
| ## [2.1.1](https://github.com/Doist/react-compiler-tracker/compare/react-compiler-tracker-v2.1.0...react-compiler-tracker-v2.1.1) (2026-01-24) | ||
| ### Bug Fixes | ||
| * auto-detect deleted files in `--stage-record-file` ([#38](https://github.com/Doist/react-compiler-tracker/issues/38)) ([0428732](https://github.com/Doist/react-compiler-tracker/commit/04287326a598bd2f8d99e16a58ef513d55bb5367)) | ||
| ## [2.1.0](https://github.com/Doist/react-compiler-tracker/compare/react-compiler-tracker-v2.0.3...react-compiler-tracker-v2.1.0) (2026-01-22) | ||
@@ -7,0 +14,0 @@ |
@@ -63,3 +63,3 @@ import { execSync } from 'node:child_process'; | ||
| expect(output).toContain('π Checking all 5 source files for React Compiler errors and recreating recordsβ¦'); | ||
| expect(output).toContain('β Records file completed. Found 4 total React Compiler issues across 2 files'); | ||
| expect(output).toContain('β Records saved to .react-compiler.rec.json. Found 4 total React Compiler issues across 2 files'); | ||
| const records = JSON.parse(readFileSync(recordsPath, 'utf8')); | ||
@@ -117,15 +117,9 @@ expect(records.recordVersion).toBe(1); | ||
| expect(records.files['src/deleted-file.tsx']).toEqual({ CompileError: 2 }); | ||
| // Now run --stage-record-file with the deleted file path | ||
| // The file src/deleted-file.tsx doesn't exist, simulating deletion | ||
| const output = runCLI([ | ||
| '--stage-record-file', | ||
| 'src/good-component.tsx', | ||
| 'src/deleted-file.tsx', | ||
| ]); | ||
| // Should log the deleted file being removed | ||
| // Run --stage-record-file WITHOUT the deleted file in arguments | ||
| // (simulating lint-staged which doesn't pass deleted files) | ||
| // The tool should auto-detect that src/deleted-file.tsx no longer exists | ||
| const output = runCLI(['--stage-record-file', 'src/good-component.tsx']); | ||
| expect(output).toContain('ποΈ Removing 1 deleted file from records:'); | ||
| expect(output).toContain('β’ src/deleted-file.tsx'); | ||
| // Should check only existing files (1 file, not 2) | ||
| expect(output).toContain('π Checking 1 file for React Compiler errors'); | ||
| // Should not error on the deleted file | ||
| expect(output).not.toContain('File not found'); | ||
@@ -132,0 +126,0 @@ // Verify the deleted file was removed from records |
+19
-16
@@ -38,7 +38,4 @@ #!/usr/bin/env node | ||
| }); | ||
| const { existing, deleted } = sourceFiles.partitionByExistence(filePaths); | ||
| return await runStageRecords({ | ||
| existingFilePaths: existing, | ||
| allFilePaths: filePaths, | ||
| deletedFilePaths: deleted, | ||
| filePaths, | ||
| recordsFilePath: config.recordsFile, | ||
@@ -108,6 +105,6 @@ }); | ||
| if (totalErrors > 0) { | ||
| console.log(`β Records file completed. Found ${totalErrors} total React Compiler issues across ${compilerErrors.size} files`); | ||
| console.log(`β Records saved to ${recordsFilePath}. Found ${totalErrors} total React Compiler issues across ${compilerErrors.size} files`); | ||
| } | ||
| else { | ||
| console.log('π No React Compiler errors found'); | ||
| console.log(`π Records saved to ${recordsFilePath}. No React Compiler errors found`); | ||
| } | ||
@@ -119,5 +116,11 @@ } | ||
| * If errors have increased, the process will exit with code 1 and the records file will not be updated. | ||
| * Deleted files are automatically removed from the records. | ||
| * Deleted files are automatically detected by checking which recorded files no longer exist on disk. | ||
| */ | ||
| async function runStageRecords({ existingFilePaths, allFilePaths, deletedFilePaths, recordsFilePath, }) { | ||
| async function runStageRecords({ filePaths, recordsFilePath, }) { | ||
| const records = recordsFile.load(recordsFilePath); | ||
| const recordedFilePaths = records ? Object.keys(records.files) : []; | ||
| const { deleted: deletedFromRecords } = sourceFiles.partitionByExistence(recordedFilePaths); | ||
| const { existing: existingFilePaths, deleted: deletedFromInput } = sourceFiles.partitionByExistence(filePaths); | ||
| const allDeletedFilePaths = [...new Set([...deletedFromRecords, ...deletedFromInput])]; | ||
| const allFilePaths = [...new Set([...filePaths, ...deletedFromRecords])]; | ||
| if (!allFilePaths.length) { | ||
@@ -127,6 +130,6 @@ console.log('β No files to check'); | ||
| } | ||
| if (deletedFilePaths.length > 0) { | ||
| const deletedFileWord = pluralize(deletedFilePaths.length, 'file', 'files'); | ||
| const fileList = deletedFilePaths.map((f) => ` β’ ${f}`).join('\n'); | ||
| console.log(`ποΈ Removing ${deletedFilePaths.length} deleted ${deletedFileWord} from records:\n${fileList}`); | ||
| if (allDeletedFilePaths.length > 0) { | ||
| const deletedFileWord = pluralize(allDeletedFilePaths.length, 'file', 'files'); | ||
| const fileList = allDeletedFilePaths.map((f) => ` β’ ${f}`).join('\n'); | ||
| console.log(`ποΈ Removing ${allDeletedFilePaths.length} deleted ${deletedFileWord} from records:\n${fileList}`); | ||
| } | ||
@@ -147,3 +150,3 @@ if (!existingFilePaths.length) { | ||
| }); | ||
| const records = checkErrorChanges({ filePaths: existingFilePaths, recordsFilePath }); | ||
| checkErrorChanges({ filePaths: existingFilePaths, recordsFilePath, records }); | ||
| // | ||
@@ -165,3 +168,3 @@ // Update and stage records file (includes deleted files so they get removed from records) | ||
| } | ||
| console.log('β No new React Compiler errors'); | ||
| console.log(`β Records saved to ${recordsFilePath}. No new React Compiler errors`); | ||
| } | ||
@@ -227,4 +230,4 @@ /** | ||
| */ | ||
| function checkErrorChanges({ filePaths, recordsFilePath, }) { | ||
| const records = recordsFile.load(recordsFilePath); | ||
| function checkErrorChanges({ filePaths, recordsFilePath, records: providedRecords, }) { | ||
| const records = providedRecords ?? recordsFile.load(recordsFilePath); | ||
| const { increases, decreases } = recordsFile.getErrorChanges({ | ||
@@ -231,0 +234,0 @@ filePaths, |
+3
-2
| { | ||
| "name": "@doist/react-compiler-tracker", | ||
| "version": "2.1.0", | ||
| "version": "2.1.1", | ||
| "description": "A React Compiler violation tracker to help migrations and prevent regressions", | ||
@@ -16,3 +16,3 @@ "type": "module", | ||
| "fix:biome": "biome check --write", | ||
| "build": "tsc", | ||
| "build": "rimraf dist && tsc", | ||
| "prepare": "husky", | ||
@@ -51,2 +51,3 @@ "test": "vitest run", | ||
| "devDependencies": { | ||
| "rimraf": "6.0.1", | ||
| "@biomejs/biome": "2.3.11", | ||
@@ -53,0 +54,0 @@ "@doist/tsconfig": "2.0.1", |
+4
-3
@@ -77,3 +77,3 @@ # React Compiler Tracker | ||
| Checks the provided files and updates the records. Exits with code 1 if errors increase (preventing the commit), otherwise updates the records file for the checked files. Reports when errors decrease, celebrating your progress. Deleted files are automatically removed from the records. | ||
| Checks the provided files and updates the records. Exits with code 1 if errors increase (preventing the commit), otherwise updates the records file for the checked files. Reports when errors decrease, celebrating your progress. Deleted files are automatically removed from the records (no need to pass their paths). | ||
@@ -134,4 +134,5 @@ ```bash | ||
| #!/bin/sh | ||
| # Get staged files (including deleted) and pass them to the tracker | ||
| FILES=$(git diff --diff-filter=ACMRD --cached --name-only -- '*.tsx' '*.ts' '*.jsx' '*.js' | tr '\n' ' ') | ||
| # Get staged files and pass them to the tracker | ||
| # (deleted files are auto-detected from records, no need to pass them) | ||
| FILES=$(git diff --diff-filter=ACMR --cached --name-only -- '*.tsx' '*.ts' '*.jsx' '*.js' | tr '\n' ' ') | ||
| if [ -n "$FILES" ]; then | ||
@@ -138,0 +139,0 @@ npx @doist/react-compiler-tracker --stage-record-file $FILES |
59829
1.36%144
0.7%12
9.09%1154
-0.26%