Skip to content

Commit 9de74b9

Browse files
feat: add script to detect duplicate JS files with TS counterparts
* feat: add script to detect duplicate JS files with TS counterparts Co-Authored-By: Eirik Haugstulen <[email protected]> * fix: improve script security with input validation Co-Authored-By: Eirik Haugstulen <[email protected]> * refactor: enhance error handling and code readability in duplicate JS file detection script * feat: add GitHub workflow to check for duplicate JavaScript files on push and pull request * chore: remove pull request trigger from duplicate check workflow * fix: remove duplicate JavaScript file in WidgetIndicator folder Co-Authored-By: Eirik Haugstulen <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eirik Haugstulen <[email protected]>
1 parent b45290f commit 9de74b9

File tree

3 files changed

+211
-3
lines changed

3 files changed

+211
-3
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Check for Duplicate JS Files
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
8+
jobs:
9+
check_duplicates:
10+
name: Check for duplicate JS files
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Node.js
18+
uses: actions/setup-node@v4
19+
with:
20+
node-version: '18'
21+
22+
- name: Run script to find duplicate JS files
23+
run: node scripts/find-duplicate-js-files.js

scripts/find-duplicate-js-files.js

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#!/usr/bin/env node
2+
/* eslint-disable no-continue */
3+
/* eslint-disable no-console */
4+
/* eslint-disable no-process-exit */
5+
/* eslint-disable complexity */
6+
7+
/**
8+
* This script checks for JavaScript files that have TypeScript counterparts in the same directory.
9+
* It recursively scans the src directory and reports any duplicate files found.
10+
*
11+
* During TypeScript migration, developers sometimes create new TypeScript files (.ts/.tsx)
12+
* but forget to delete the original JavaScript (.js) files. This script helps identify
13+
* such cases to ensure clean migration.
14+
*
15+
* Usage:
16+
* node scripts/find-duplicate-js-files.js
17+
*
18+
* Exit codes:
19+
* 0 - No duplicate files found
20+
* 1 - Duplicate files found (error)
21+
*/
22+
23+
const fs = require('fs');
24+
const path = require('path');
25+
26+
const EXCLUDED_DIRS = ['node_modules', 'build', 'dist', 'coverage', '.git', 'flow-typed', 'public'];
27+
28+
/**
29+
* Recursively gets all files in a directory
30+
* @param {string} dir - Directory to scan
31+
* @param {Array<string>} fileList - Accumulator for file paths
32+
* @returns {Array<string>} List of file paths
33+
*/
34+
function getAllFiles(dir, fileList = []) {
35+
if (!dir || typeof dir !== 'string') {
36+
console.warn('Invalid directory path provided');
37+
return fileList;
38+
}
39+
40+
try {
41+
const files = fs.readdirSync(dir);
42+
43+
for (const file of files) {
44+
if (!file || typeof file !== 'string') {
45+
continue;
46+
}
47+
48+
const filePath = path.join(dir, file);
49+
50+
try {
51+
const stat = fs.statSync(filePath);
52+
53+
if (stat.isDirectory()) {
54+
if (EXCLUDED_DIRS.includes(file)) {
55+
continue;
56+
}
57+
58+
getAllFiles(filePath, fileList);
59+
} else {
60+
fileList.push(filePath);
61+
}
62+
} catch (err) {
63+
console.warn(`Warning: Could not access ${filePath}: ${err.message}`);
64+
}
65+
}
66+
} catch (err) {
67+
console.warn(`Warning: Could not read directory ${dir}: ${err.message}`);
68+
}
69+
70+
return fileList;
71+
}
72+
73+
/**
74+
* Finds JavaScript files that have TypeScript counterparts in the same directory
75+
* @param {string} srcDir - Source directory to scan
76+
* @returns {Array<Object>} List of duplicate JavaScript files with their TypeScript counterparts
77+
*/
78+
function findDuplicateJsFiles(srcDir) {
79+
if (!srcDir || typeof srcDir !== 'string') {
80+
console.warn('Invalid source directory provided');
81+
return [];
82+
}
83+
84+
const allFiles = getAllFiles(srcDir);
85+
const duplicates = [];
86+
87+
const filesByDir = {};
88+
89+
for (const filePath of allFiles) {
90+
if (!filePath || typeof filePath !== 'string') {
91+
continue;
92+
}
93+
94+
const dir = path.dirname(filePath);
95+
const fileName = path.basename(filePath);
96+
97+
if (!filesByDir[dir]) {
98+
filesByDir[dir] = [];
99+
}
100+
101+
filesByDir[dir].push(fileName);
102+
}
103+
104+
for (const dir of Object.keys(filesByDir)) {
105+
const dirFiles = filesByDir[dir];
106+
const baseNames = {};
107+
108+
for (const fileName of dirFiles) {
109+
if (!fileName || typeof fileName !== 'string') {
110+
continue;
111+
}
112+
113+
const ext = path.extname(fileName);
114+
const baseName = fileName.replace(ext, '');
115+
116+
if (!baseNames[baseName]) {
117+
baseNames[baseName] = [];
118+
}
119+
120+
baseNames[baseName].push(fileName);
121+
}
122+
123+
for (const baseName of Object.keys(baseNames)) {
124+
const files = baseNames[baseName];
125+
126+
if (files.length > 1) {
127+
const hasJs = files.some(f => f && typeof f === 'string' && f.endsWith('.js'));
128+
const hasTs = files.some(f => f && typeof f === 'string' && (f.endsWith('.ts') || f.endsWith('.tsx')));
129+
130+
if (hasJs && hasTs) {
131+
const jsFiles = files.filter(f => f && typeof f === 'string' && f.endsWith('.js'));
132+
const tsFiles = files.filter(f => f && typeof f === 'string' && (f.endsWith('.ts') || f.endsWith('.tsx')));
133+
134+
for (const jsFile of jsFiles) {
135+
duplicates.push({
136+
jsFile: path.join(dir, jsFile),
137+
tsFiles: tsFiles.map(tsFile => path.join(dir, tsFile)),
138+
});
139+
}
140+
}
141+
}
142+
}
143+
}
144+
145+
return duplicates;
146+
}
147+
148+
/**
149+
* Main function
150+
*/
151+
function main() {
152+
const srcDir = path.resolve(__dirname, '../src');
153+
console.log(`Checking for duplicate JS files in: ${srcDir}`);
154+
155+
const duplicates = findDuplicateJsFiles(srcDir);
156+
157+
if (duplicates && duplicates.length > 0) {
158+
console.error('Found JavaScript files that have TypeScript counterparts in the same directory:');
159+
console.error('These files should be deleted as part of the TypeScript migration process.\n');
160+
161+
for (const duplicate of duplicates) {
162+
if (!duplicate || !duplicate.jsFile || !Array.isArray(duplicate.tsFiles)) {
163+
continue;
164+
}
165+
166+
console.error(`JavaScript file: ${duplicate.jsFile}`);
167+
console.error('TypeScript counterpart(s):');
168+
169+
for (const tsFile of duplicate.tsFiles) {
170+
if (!tsFile || typeof tsFile !== 'string') {
171+
continue;
172+
}
173+
console.error(` - ${tsFile}`);
174+
}
175+
176+
console.error('');
177+
}
178+
179+
console.error(`Total: ${duplicates.length} duplicate file(s) found.`);
180+
process.exit(1); // Exit with error
181+
} else {
182+
console.log('No duplicate JavaScript files found.');
183+
process.exit(0); // Exit successfully
184+
}
185+
}
186+
187+
// Execute the main function
188+
main();

src/core_modules/capture-core/components/WidgetIndicator/index.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)