🚨 Active Supply Chain Attack:node-ipc Package Compromised.Learn More →
Socket
Book a DemoSign in
Socket

@doist/react-compiler-tracker

Package Overview
Dependencies
Maintainers
9
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@doist/react-compiler-tracker - npm Package Compare versions

Comparing version
2.0.2
to
2.0.3
+7
-0
CHANGELOG.md

@@ -5,2 +5,9 @@ # Changelog

## [2.0.3](https://github.com/Doist/react-compiler-tracker/compare/react-compiler-tracker-v2.0.2...react-compiler-tracker-v2.0.3) (2026-01-19)
### Bug Fixes
* handle shell-escaped file paths ([#29](https://github.com/Doist/react-compiler-tracker/issues/29)) ([ae78e6a](https://github.com/Doist/react-compiler-tracker/commit/ae78e6afa1ec766a3f9d68ceb67c4accd6556b83))
## [2.0.2](https://github.com/Doist/react-compiler-tracker/compare/react-compiler-tracker-v2.0.1...react-compiler-tracker-v2.0.2) (2026-01-18)

@@ -7,0 +14,0 @@

+10
-4

@@ -35,3 +35,3 @@ import { execSync } from 'node:child_process';

const output = runCLI();
expect(output).toContain('🔍 Checking all 4 source files for React Compiler errors…');
expect(output).toContain('🔍 Checking all 5 source files for React Compiler errors…');
expect(output).toContain('⚠️ Found 4 React Compiler issues across 2 files');

@@ -55,5 +55,11 @@ expect(() => JSON.parse(readFileSync(recordsPath, 'utf8'))).toThrow();

});
it('handles shell-escaped file paths with $ character', () => {
// Simulate what CI tools do when passing filenames with $ through shell variables
const output = runCLI(['--check-files', 'src/route.\\$param.tsx']);
expect(output).toContain('🔍 Checking 1 files for React Compiler errors…');
expect(output).not.toContain('File not found');
});
it('accepts --overwrite flag', () => {
const output = runCLI(['--overwrite']);
expect(output).toContain('🔍 Checking all 4 source files for React Compiler errors and recreating records…');
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');

@@ -109,4 +115,4 @@ const records = JSON.parse(readFileSync(recordsPath, 'utf8'));

const output = runCLI();
// Should only find .tsx files (2 instead of 4)
expect(output).toContain('🔍 Checking all 2 source files for React Compiler errors…');
// Should only find .tsx files (3 instead of 5)
expect(output).toContain('🔍 Checking all 3 source files for React Compiler errors…');
});

@@ -113,0 +119,0 @@ it('uses custom recordsFile from config', () => {

@@ -30,4 +30,4 @@ import { execSync } from 'node:child_process';

/**
* Normalizes file paths by converting absolute paths to cwd-relative
* and stripping the git prefix when present.
* Normalizes file paths by unescaping shell-escaped characters, converting
* absolute paths to cwd-relative, and stripping the git prefix when present.
*

@@ -38,2 +38,6 @@ * When running from a package subdirectory in a monorepo, file paths from git

*
* Shell escapes (e.g., \$ → $) are only applied to paths containing forward
* slashes, which indicates Unix-style paths. Paths using only backslashes
* (Windows native paths) are preserved to avoid corrupting path separators.
*
* @example

@@ -46,2 +50,8 @@ * // When cwd is apps/frontend/ (prefix is "apps/frontend/")

*
* // Shell-escaped characters are unescaped (Unix-style paths)
* normalizeFilePaths(["src/route.\\$id.tsx"]) // => ["src/route.$id.tsx"]
*
* // Windows-style paths are preserved (no forward slashes)
* normalizeFilePaths(["src\\utils\\file.ts"]) // => ["src\\utils\\file.ts"]
*
* // Paths that don't start with prefix are unchanged

@@ -54,11 +64,20 @@ * normalizeFilePaths(["src/file.tsx"]) // => ["src/file.tsx"]

return filePaths.map((filePath) => {
// Only unescape shell-escaped characters for Unix-style paths (containing /).
// Windows paths use \ as separator, so we preserve them to avoid corruption.
// This handles Git Bash on Windows and Windows CI which use forward slashes.
// We only unescape non-alphanumeric characters since shells don't escape letters/digits,
// but Windows separators are typically followed by alphanumeric directory names.
// This preserves mixed paths like src/utils\file.ts (valid on Windows).
const normalized = filePath.includes('/')
? filePath.replace(/\\([^a-zA-Z0-9])/g, '$1')
: filePath;
// Handle absolute paths by converting to cwd-relative
if (filePath.startsWith('/')) {
return relative(cwd, filePath);
if (normalized.startsWith('/')) {
return relative(cwd, normalized);
}
// Handle monorepo prefix stripping
if (prefix && filePath.startsWith(prefix)) {
return filePath.slice(prefix.length);
if (prefix && normalized.startsWith(prefix)) {
return normalized.slice(prefix.length);
}
return filePath;
return normalized;
});

@@ -65,0 +84,0 @@ }

@@ -93,2 +93,55 @@ import { execSync } from 'node:child_process';

});
it('unescapes shell-escaped $ characters', () => {
vi.mocked(execSync).mockReturnValue('\n');
const result = normalizeFilePaths(['src/route.\\$id.tsx', 'src/draft.\\$slug.tsx']);
expect(result).toEqual(['src/route.$id.tsx', 'src/draft.$slug.tsx']);
});
it('unescapes shell-escaped spaces', () => {
vi.mocked(execSync).mockReturnValue('\n');
const result = normalizeFilePaths(['src/file\\ with\\ spaces.tsx']);
expect(result).toEqual(['src/file with spaces.tsx']);
});
it('unescapes multiple different escape characters', () => {
vi.mocked(execSync).mockReturnValue('\n');
const result = normalizeFilePaths(['src/route.\\$id\\ (copy).tsx']);
expect(result).toEqual(['src/route.$id (copy).tsx']);
});
it('handles paths with no escapes unchanged', () => {
vi.mocked(execSync).mockReturnValue('\n');
const result = normalizeFilePaths(['src/normal-file.tsx']);
expect(result).toEqual(['src/normal-file.tsx']);
});
it('unescapes before stripping prefix', () => {
vi.mocked(execSync).mockReturnValue('apps/frontend/\n');
const result = normalizeFilePaths(['apps/frontend/src/route.\\$id.tsx']);
expect(result).toEqual(['src/route.$id.tsx']);
});
it('preserves Windows-style paths with backslash separators', () => {
vi.mocked(execSync).mockReturnValue('\n');
const result = normalizeFilePaths(['src\\utils\\file.ts', 'src\\components\\Button.tsx']);
expect(result).toEqual(['src\\utils\\file.ts', 'src\\components\\Button.tsx']);
});
it('preserves Windows paths with $ in filename', () => {
vi.mocked(execSync).mockReturnValue('\n');
const result = normalizeFilePaths(['src\\$files.ts', 'src\\routes\\$id.tsx']);
expect(result).toEqual(['src\\$files.ts', 'src\\routes\\$id.tsx']);
});
it('does not unescape bare filenames without forward slashes', () => {
vi.mocked(execSync).mockReturnValue('\n');
// Bare filenames without / are ambiguous, so we preserve them
const result = normalizeFilePaths(['\\$id.tsx', 'file.tsx']);
expect(result).toEqual(['\\$id.tsx', 'file.tsx']);
});
it('preserves mixed paths with both forward and back slashes', () => {
vi.mocked(execSync).mockReturnValue('\n');
// Mixed paths are valid on Windows - backslash separators should be preserved
const result = normalizeFilePaths(['src/utils\\file.ts', 'src/components\\Button.tsx']);
expect(result).toEqual(['src/utils\\file.ts', 'src/components\\Button.tsx']);
});
it('unescapes special chars in mixed paths while preserving backslash separators', () => {
vi.mocked(execSync).mockReturnValue('\n');
// Should unescape \$ (non-alphanumeric) but preserve \s in utils\subdir (alphanumeric)
const result = normalizeFilePaths(['src/utils\\subdir/route.\\$id.tsx']);
expect(result).toEqual(['src/utils\\subdir/route.$id.tsx']);
});
});

@@ -95,0 +148,0 @@ describe('filterByGlob', () => {

{
"name": "@doist/react-compiler-tracker",
"version": "2.0.2",
"version": "2.0.3",
"description": "A React Compiler violation tracker to help migrations and prevent regressions",

@@ -52,3 +52,3 @@ "type": "module",

"@types/babel__core": "7.20.5",
"@types/node": "25.0.6",
"@types/node": "25.0.8",
"babel-plugin-react-compiler": "1.0.0",

@@ -60,3 +60,3 @@ "husky": "9.1.7",

"typescript": "5.9.3",
"vitest": "4.0.16"
"vitest": "4.0.17"
},

@@ -63,0 +63,0 @@ "peerDependencies": {