# All files / lib/analyzers cloud-analyzer.js

80% Statements 56/70
65.9% Branches 29/44
40% Functions 2/5
83.33% Lines 55/66

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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122

    8x

    8x
    8x
    1x
    1x

    8x
    8x
    1x
    1x

    8x
    8x

    8x
    8x
    8x
    1x

    8x
    8x
    2x
    2x
    2x
    2x
    2x

    8x
    8x
    1x
    1x

    8x
    8x
    8x
    1x
    1x

    8x
    8x
    1x
    1x
    1x

    1x
    1x
    1x

    1x

    1x

    8x
    8x
    1x
    1x
    1x

    1x
    1x

    8x
    8x

    8x
    8x
    8x
    8x

    8x

     import fs from 'fs-extra';
    import path from 'path';
    import { recursiveGlob } from './utils.js';

    export async function analyzeCloud(projectPath) {
      const detected = {
        providers: [],
        services: [],
        configFiles: [],
        orchestration: []
      };

      // Docker
      const dockerfilePath = path.join(projectPath, 'Dockerfile');
      if (await fs.pathExists(dockerfilePath)) {
        detected.configFiles.push('Dockerfile');
        detected.providers.push('docker');
      }

      const composePath = path.join(projectPath, 'docker-compose.yml');
      if (await fs.pathExists(composePath)) {
        detected.configFiles.push('docker-compose.yml');
        detected.providers.push('docker');
      }

      const dockerignorePath = path.join(projectPath, '.dockerignore');
      Iif (await fs.pathExists(dockerignorePath)) {
        detected.configFiles.push('.dockerignore');
      }

      // Kubernetes
      const k8sDir = path.join(projectPath, 'k8s');
      const helmDir = path.join(projectPath, 'helm');
      if (await fs.pathExists(k8sDir) || await fs.pathExists(helmDir)) {
        detected.orchestration.push('kubernetes');
      }

      // Check YAML files for apiVersion
      const yamlFiles = await recursiveGlob(projectPath, '**/*.yaml');
      for (const file of yamlFiles.slice(0, 10)) { // Limit to avoid performance issues
        try {
          const content = await fs.readFile(file, 'utf8');
          Eif (content.includes('apiVersion:')) {
            detected.orchestration.push('kubernetes');
            break;
          }
        } catch (e) {}
      }

      // Terraform
      const tfFiles = await recursiveGlob(projectPath, '**/*.tf');
      if (tfFiles.length > 0) {
        detected.configFiles.push(...tfFiles.slice(0, 5)); // limit to 5
        detected.providers.push('terraform');
      }

      // Serverless Framework
      const serverlessYml = path.join(projectPath, 'serverless.yml');
      const serverlessYaml = path.join(projectPath, 'serverless.yaml');
      if (await fs.pathExists(serverlessYml) || await fs.pathExists(serverlessYaml)) {
        detected.configFiles.push('serverless.yml');
        detected.providers.push('serverless');
      }

      // Package.json → cloud SDKs
      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 };

          Eif (deps['aws-sdk'] || Object.keys(deps).some(k => k.startsWith('@aws-sdk/'))) {
            detected.providers.push('aws');
            detected.services.push('s3', 'lambda', 'ec2', 'dynamodb');
          }
          Iif (deps['@google-cloud/*'] || deps.firebase) {
            detected.providers.push('gcp');
          }
          Iif (Object.keys(deps).some(k => k.startsWith('@azure/'))) {
            detected.providers.push('azure');
          }
        } catch (e) {}
      }

      // Go modules
      const goModPath = path.join(projectPath, 'go.mod');
      if (await fs.pathExists(goModPath)) {
        try {
          const content = await fs.readFile(goModPath, 'utf8');
          Iif (content.includes('github.com/aws/aws-sdk-go')) {
            detected.providers.push('aws');
          }
          Eif (content.includes('cloud.google.com/go')) {
            detected.providers.push('gcp');
          }
        } catch (e) {}
      }

      // Python requirements
      const reqPath = path.join(projectPath, 'requirements.txt');
      Iif (await fs.pathExists(reqPath)) {
        try {
          const content = await fs.readFile(reqPath, 'utf8');
          const lines = content.toLowerCase().split('\n');
          if (lines.some(l => l.includes('boto3') || l.includes('aws-'))) {
            detected.providers.push('aws');
          }
          if (lines.some(l => l.includes('google-cloud'))) {
            detected.providers.push('gcp');
          }
        } catch (e) {}
      }

      // Deduplicate
      detected.providers = [...new Set(detected.providers)];
      detected.services = [...new Set(detected.services)];
      detected.configFiles = [...new Set(detected.configFiles)];
      detected.orchestration = [...new Set(detected.orchestration)];

      return detected;
    }