mirror of
https://github.com/actualbudget/actual.git
synced 2026-04-29 02:54:09 -05:00
* Apply import sorting with perfectionist/sort-named-imports rule - Add perfectionist/sort-named-imports oxlint rule - Sort named imports: value imports before type imports - Update component-library and desktop-client files to match new rule * Add release notes for linting updates on named imports
103 lines
3.1 KiB
JavaScript
103 lines
3.1 KiB
JavaScript
#!/usr/bin/env node
|
|
import { existsSync } from 'node:fs';
|
|
import { readdir, readFile, writeFile } from 'node:fs/promises';
|
|
import { dirname, extname, join, relative, resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
const buildDir = resolve(__dirname, '../build');
|
|
|
|
async function getAllJsFiles(dir) {
|
|
const files = [];
|
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
|
|
for (const entry of entries) {
|
|
const fullPath = join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
files.push(...(await getAllJsFiles(fullPath)));
|
|
} else if (entry.isFile() && extname(entry.name) === '.js') {
|
|
files.push(fullPath);
|
|
}
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
function resolveImportPath(importPath, fromFile) {
|
|
const baseDir = dirname(fromFile);
|
|
const resolvedPath = resolve(baseDir, importPath);
|
|
|
|
// Check if it's a file with .js extension
|
|
if (existsSync(`${resolvedPath}.js`)) {
|
|
return `${importPath}.js`;
|
|
}
|
|
|
|
// Check if it's a directory with index.js
|
|
if (existsSync(resolvedPath) && existsSync(join(resolvedPath, 'index.js'))) {
|
|
return `${importPath}/index.js`;
|
|
}
|
|
|
|
// Verify the file exists before adding extension
|
|
if (!existsSync(`${resolvedPath}.js`)) {
|
|
console.warn(
|
|
`Warning: Could not resolve import '${importPath}' from ${relative(buildDir, fromFile)}`,
|
|
);
|
|
}
|
|
|
|
// Default: assume it's a file and add .js
|
|
return `${importPath}.js`;
|
|
}
|
|
|
|
function addExtensionsToImports(content, filePath) {
|
|
// Match relative imports: import ... from './path' or import ... from '../path'
|
|
// Also handle: import('./path') and require('./path')
|
|
const importRegex =
|
|
/(?:import\s+(?:(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)(?:\s*,\s*(?:\{[^}]*\}|\*\s+as\s+\w+|\w+))*\s+from\s+)?|import\s*\(|require\s*\()['"](\.\.?\/[^'"]+)['"]/g;
|
|
|
|
return content.replace(importRegex, (match, importPath) => {
|
|
// importPath is the second capture group (the path)
|
|
if (!importPath || typeof importPath !== 'string') {
|
|
return match;
|
|
}
|
|
|
|
// Skip if already has an extension
|
|
if (/\.(js|mjs|ts|mts|json)$/.test(importPath)) {
|
|
return match;
|
|
}
|
|
|
|
// Skip if ends with / (directory import that already has trailing slash)
|
|
if (importPath.endsWith('/')) {
|
|
return match;
|
|
}
|
|
|
|
const newImportPath = resolveImportPath(importPath, filePath);
|
|
return match.replace(importPath, newImportPath);
|
|
});
|
|
}
|
|
|
|
async function processFile(filePath) {
|
|
const content = await readFile(filePath, 'utf-8');
|
|
const newContent = addExtensionsToImports(content, filePath);
|
|
|
|
if (content !== newContent) {
|
|
await writeFile(filePath, newContent, 'utf-8');
|
|
const relativePath = relative(buildDir, filePath);
|
|
console.log(`Updated imports in ${relativePath}`);
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
try {
|
|
const files = await getAllJsFiles(buildDir);
|
|
await Promise.all(files.map(processFile));
|
|
console.log(`Processed ${files.length} files`);
|
|
} catch (error) {
|
|
console.error('Error processing files:', error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main();
|