check-lib-imports.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #!/usr/bin/env node
  2. import fs from 'fs';
  3. import path from 'path';
  4. import { fileURLToPath } from 'url';
  5. const __filename = fileURLToPath(import.meta.url);
  6. const __dirname = path.dirname(__filename);
  7. // Check if we're running from the dashboard directory or root directory
  8. const currentDir = process.cwd();
  9. const isDashboardDir = currentDir.endsWith('packages/dashboard');
  10. const LIB_DIR = isDashboardDir
  11. ? path.join(__dirname, '../src/lib')
  12. : path.join(currentDir, 'packages/dashboard/src/lib');
  13. // Allowlist of @/ imports that are safe to keep
  14. const ALLOWED_IMPORTS = ['@/lib/trans.js', '@/lib/utils.js', '@/components/ui'];
  15. function findHookFiles(dir) {
  16. const files = [];
  17. function traverse(currentDir) {
  18. const items = fs.readdirSync(currentDir);
  19. for (const item of items) {
  20. const fullPath = path.join(currentDir, item);
  21. const stat = fs.statSync(fullPath);
  22. if (stat.isDirectory()) {
  23. traverse(fullPath);
  24. } else if (item.startsWith('use-') && (item.endsWith('.ts') || item.endsWith('.tsx'))) {
  25. files.push(fullPath);
  26. }
  27. }
  28. }
  29. traverse(dir);
  30. return files;
  31. }
  32. function checkFileForBadImports(filePath) {
  33. const content = fs.readFileSync(filePath, 'utf8');
  34. const lines = content.split('\n');
  35. const badImports = [];
  36. for (let i = 0; i < lines.length; i++) {
  37. const line = lines[i];
  38. const trimmedLine = line.trim();
  39. // Check for import statements that start with @/
  40. if (trimmedLine.startsWith('import') && trimmedLine.includes('@/')) {
  41. // Check if this import is in the allowlist
  42. const isAllowed = ALLOWED_IMPORTS.some(allowed => {
  43. if (allowed.endsWith('/')) {
  44. // For directory patterns like '@/components/ui'
  45. return trimmedLine.includes(allowed);
  46. } else {
  47. // For exact file matches
  48. return trimmedLine.includes(allowed);
  49. }
  50. });
  51. if (!isAllowed) {
  52. badImports.push({
  53. line: i + 1,
  54. content: trimmedLine,
  55. });
  56. }
  57. }
  58. }
  59. return badImports;
  60. }
  61. function main() {
  62. console.log('🔍 Checking for @/ imports in hook files (use-*.ts/tsx) in src/lib directory...\n');
  63. console.log('✅ Allowed imports:');
  64. ALLOWED_IMPORTS.forEach(allowed => {
  65. console.log(` - ${allowed}`);
  66. });
  67. console.log('');
  68. if (!fs.existsSync(LIB_DIR)) {
  69. console.error('❌ src/lib directory not found!');
  70. process.exit(1);
  71. }
  72. const files = findHookFiles(LIB_DIR);
  73. let hasBadImports = false;
  74. let totalBadImports = 0;
  75. for (const file of files) {
  76. const relativePath = path.relative(process.cwd(), file);
  77. const badImports = checkFileForBadImports(file);
  78. if (badImports.length > 0) {
  79. hasBadImports = true;
  80. totalBadImports += badImports.length;
  81. console.log(`❌ ${relativePath}:`);
  82. for (const badImport of badImports) {
  83. console.log(` Line ${badImport.line}: ${badImport.content}`);
  84. }
  85. console.log('');
  86. }
  87. }
  88. if (hasBadImports) {
  89. console.log(`❌ Found ${totalBadImports} bad import(s) in ${files.length} hook file(s)`);
  90. console.log('💡 All imports in hook files should use relative paths, except for allowed imports');
  91. process.exit(1);
  92. } else {
  93. console.log(`✅ No bad imports found in ${files.length} hook file(s)`);
  94. console.log('🎉 All imports in hook files are using relative paths or allowed @/ paths');
  95. }
  96. }
  97. main();