All files / lib/analyzers mobile-analyzer.js

100% Statements 34/34
93.75% Branches 15/16
100% Functions 2/2
100% Lines 33/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79        8x               8x 8x 3x 3x 3x   3x 2x   3x 1x               8x 8x 1x 1x 1x 1x           8x           8x 26x 3x 3x 3x 3x         8x           8x 27x 2x 2x 2x         8x 8x 8x   8x    
import fs from 'fs-extra';
import path from 'path';
 
export async function analyzeMobile(projectPath) {
  const detected = {
    frameworks: [],
    platforms: [],
    buildTools: [],
    configFiles: []
  };
 
  // Check package.json for React Native/Expo
  const pkgPath = path.join(projectPath, 'package.json');
  if (await fs.pathExists(pkgPath)) {
    try {
      const pkg = await fs.readJson(pkgPath);
      const deps = { ...pkg.dependencies, ...pkg.devDependencies };
 
      if (deps['react-native'] || Object.keys(deps).some(k => k.startsWith('@react-native/'))) {
        detected.frameworks.push('react-native');
      }
      if (deps.expo) {
        detected.buildTools.push('expo');
      }
    } catch (e) {
      // Ignore parse errors
    }
  }
 
  // Check Flutter: pubspec.yaml with sdk: flutter
  const pubspecPath = path.join(projectPath, 'pubspec.yaml');
  if (await fs.pathExists(pubspecPath)) {
    try {
      const content = await fs.readFile(pubspecPath, 'utf8');
      Eif (/sdk:\s*flutter/.test(content)) {
        detected.frameworks.push('flutter');
      }
    } catch (e) {}
  }
 
  // iOS detection
  const iosIndicators = [
    path.join(projectPath, 'ios'),
    path.join(projectPath, '.xcodeproj'),
    path.join(projectPath, 'Podfile'),
    path.join(projectPath, 'Podfile.lock')
  ];
  for (const indicator of iosIndicators) {
    if (await fs.pathExists(indicator)) {
      detected.frameworks.push('ios');
      detected.platforms.push('ios');
      detected.buildTools.push('xcode');
      break;
    }
  }
 
  // Android detection
  const androidIndicators = [
    path.join(projectPath, 'android'),
    path.join(projectPath, 'build.gradle'),
    path.join(projectPath, 'app/build.gradle'),
    path.join(projectPath, 'AndroidManifest.xml')
  ];
  for (const indicator of androidIndicators) {
    if (await fs.pathExists(indicator)) {
      detected.frameworks.push('android');
      detected.platforms.push('android');
      break;
    }
  }
 
  // Deduplicate
  detected.frameworks = [...new Set(detected.frameworks)];
  detected.platforms = [...new Set(detected.platforms)];
  detected.buildTools = [...new Set(detected.buildTools)];
 
  return detected;
}