File size: 4,190 Bytes
6b825ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// @ts-check

import fs from "fs";
import path from "path";
import { Request, Response } from 'express';

interface SkillResult {
  name: string;
  skill: string; 
  extension: string; 
}

interface Config {
  project: string;
}

const languageMap: { [key: string]: string } = {
  "js": "JavaScript",
  "ts": "TypeScript",
  "html": "HTML",
  "css": "CSS",
  "json": "JSON",
  "md": "Markdown",
  "py": "Python",
  "java": "Java",
  "c": "C",
  "cpp": "C++",
  "cs": "C#",
  "go": "Go",
  "rb": "Ruby",
  "php": "PHP",
  "swift": "Swift",
  "kt": "Kotlin",
  "sh": "Shell Script",
  "xml": "XML",
  "yaml": "YAML",
  "yml": "YAML",
  "sql": "SQL",
  "jsx": "React (JavaScript)",
  "tsx": "React (TypeScript)",
};

function walkDir(dirPath: string, counts: Map<string, number>): number {
  let totalFiles = 0;
  if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) {
    console.warn(`[Skills Analyzer] Directory not found or not a directory: ${dirPath}`);
    return 0;
  }

  const files = fs.readdirSync(dirPath);
  for (const file of files) {
    const fullPath = path.join(dirPath, file);
    try {
      const stats = fs.statSync(fullPath);
      if (stats.isDirectory()) {
        totalFiles += walkDir(fullPath, counts);
      } else if (stats.isFile()) {
        let ext = path.extname(file);
        if (ext) {
          ext = ext.substring(1).toLowerCase(); 
          counts.set(ext, (counts.get(ext) || 0) + 1);
          totalFiles++;
        }
      }
    } catch (error: any) {
      console.error(`[Skills Analyzer] Error processing file ${fullPath}:`, error.message);
    }
  }
  return totalFiles;
}

async function analyzeProjectSkills(): Promise<{ project: string; skills: SkillResult[] }> {
  const configPath = path.resolve(__dirname, '..', 'config.json');
  console.log(`[Skills Analyzer] Attempting to read config from: ${configPath}`);

  let projectRoot: string;
  try {
    const configContent = fs.readFileSync(configPath, 'utf8');
    const config: Config = JSON.parse(configContent);
    if (!config.project) {
      throw new Error("Missing 'project' key in config.json. Please ensure it's defined.");
    }
    projectRoot = path.resolve(path.dirname(configPath), config.project);
    console.log(`[Skills Analyzer] Project path from config: ${projectRoot}`);
  } catch (error: any) {
    console.error(`[Skills Analyzer] Failed to read or parse config.json:`, error.message);
    return { project: "Unknown Project (config error)", skills: [] };
  }

  const languageCounts = new Map<string, number>();
  const totalFiles = walkDir(projectRoot, languageCounts);

  if (totalFiles === 0) {
    console.warn(`[Skills Analyzer] No files with recognized extensions found in project directory: ${projectRoot}`);
    return { project: projectRoot, skills: [] };
  }

  const skills: SkillResult[] = [];
  for (const [ext, count] of languageCounts.entries()) {
    const percentage = ((count / totalFiles) * 100).toFixed(2);
    const name = languageMap[ext] || ext.toUpperCase(); 
    skills.push({
      name: name.toLowerCase(),
      skill: `${percentage}%`,
      extension: ext, 
    });
  }

  skills.sort((a, b) => parseFloat(b.skill) - parseFloat(a.skill));

  console.log(`[Skills Analyzer] Analysis complete for project: ${projectRoot}. Found ${totalFiles} files.`);
  return { project: projectRoot, skills: skills };
}

interface LoginRouteParams {
  req: Request<any, any, unknown>;
  res: Response;
}

interface LoginExpressRouteModule {
  method: "get" | "post" | "put" | "delete" | "patch" | "options" | "head" | "all";
  path: string;
  install: (params: LoginRouteParams) => Promise<void> | void;
}

export const modules: LoginExpressRouteModule[] = [
  {
    method: "post",
    path: "/skills",
    install: async ({ req, res }: { req: Request; res: Response }) => {
      try {
        const { project, skills } = await analyzeProjectSkills();
        res.json([{ project: project, skills: skills }]);
      } catch (error: any) {
        console.error("[Skills Route] Error serving skills:", error.message);
        res.status(500).json({ error: "Failed to analyze project skills. Check server logs." });
      }
    },
  },
];