@@ -4,6 +4,7 @@ import { rename, rm } from "node:fs/promises";
44import { buildModuleAnalysisCacheKey } from "../../scripts/shared/module-analysis-cache.ts" ;
55import { createDeterministicImageName } from "../../scripts/shared/deterministic-output.ts" ;
66import { createLogger } from "../../scripts/shared/logger.ts" ;
7+ import { analyzeModule as performModuleAnalysis } from "../../scripts/check-modules/module-analyzer.ts" ;
78import fs from "node:fs" ;
89import normalizeData from "normalize-package-data" ;
910import path from "node:path" ;
@@ -129,6 +130,28 @@ function getErrorMessage(error: unknown): string {
129130 return error instanceof Error ? error . message : String ( error ) ;
130131}
131132
133+ function normalizeIssueList ( issues : unknown ) : string [ ] {
134+ if ( Array . isArray ( issues ) ) {
135+ return issues . filter ( ( issue ) : issue is string => typeof issue === "string" && issue . length > 0 ) ;
136+ }
137+
138+ if ( typeof issues === "string" && issues . length > 0 ) {
139+ return [ issues ] ;
140+ }
141+
142+ return [ ] ;
143+ }
144+
145+ function mergeUniqueIssues ( target : string [ ] , issues : unknown ) : void {
146+ const existing = new Set ( target ) ;
147+ for ( const issue of normalizeIssueList ( issues ) ) {
148+ if ( ! existing . has ( issue ) ) {
149+ target . push ( issue ) ;
150+ existing . add ( issue ) ;
151+ }
152+ }
153+ }
154+
132155/**
133156 * @typedef {Object } ModuleInput
134157 * @property {string } name
@@ -786,16 +809,66 @@ async function enrichModule(module: ModuleInput, config: ProcessModuleConfig): P
786809}
787810
788811/**
789- * Placeholder for future Stage 5 analysis integration
790- * Will include checks like ESLint, npm-check-updates, dependency detection, etc .
812+ * Stage 5: Analyze module for code quality issues, deprecated patterns, and best practices.
813+ * Runs comprehensive checks including deprecated APIs, typos, package validation, and README structure .
791814 *
792815 * @returns {{analysisIssues: string[], recommendations: string[]} }
793816 */
794- function analyzeModule ( _module ?: ModuleInput , _config ?: ProcessModuleConfig ) : AnalysisResult {
795- return {
796- analysisIssues : [ ] ,
797- recommendations : [ ]
798- } ;
817+ async function analyzeModule ( module : ModuleInput , config : ProcessModuleConfig ) : Promise < AnalysisResult > {
818+ const cloneDir = path . join (
819+ config . modulesDir ,
820+ `${ module . name } -----${ module . maintainer } `
821+ ) ;
822+
823+ try {
824+ // Get list of all files in the cloned directory, excluding .git and node_modules
825+ const getAllFiles = ( dir : string , baseDir : string = dir , files : string [ ] = [ ] ) : string [ ] => {
826+ try {
827+ const entries = fs . readdirSync ( dir , { withFileTypes : true } ) ;
828+ for ( const entry of entries ) {
829+ const fullPath = path . join ( dir , entry . name ) ;
830+ const relativePath = path . relative ( baseDir , fullPath ) ;
831+
832+ if ( ! relativePath . includes ( ".git" ) && ! relativePath . includes ( "node_modules" ) ) {
833+ if ( entry . isDirectory ( ) ) {
834+ getAllFiles ( fullPath , baseDir , files ) ;
835+ } else {
836+ files . push ( fullPath ) ;
837+ }
838+ }
839+ }
840+ } catch {
841+ // Silently ignore read errors
842+ }
843+ return files ;
844+ } ;
845+
846+ const files = getAllFiles ( cloneDir ) ;
847+ if ( files . length === 0 ) {
848+ return {
849+ analysisIssues : [ "Error: Unable to read module files for analysis" ] ,
850+ recommendations : [ ]
851+ } ;
852+ }
853+
854+ const analysisResult = await performModuleAnalysis (
855+ cloneDir ,
856+ module . name ,
857+ module . url ,
858+ files
859+ ) ;
860+
861+ return {
862+ analysisIssues : analysisResult . issues ,
863+ recommendations : analysisResult . recommendations
864+ } ;
865+ } catch ( error ) {
866+ const message = error instanceof Error ? error . message : String ( error ) ;
867+ return {
868+ analysisIssues : [ `Analysis error: ${ message } ` ] ,
869+ recommendations : [ ]
870+ } ;
871+ }
799872}
800873
801874/**
@@ -810,7 +883,7 @@ function analyzeModule(_module?: ModuleInput, _config?: ProcessModuleConfig): An
810883 */
811884export async function processModule ( module : ModuleInput , config : ProcessModuleConfig ) : Promise < ModuleResult > {
812885 const startTime = Date . now ( ) ;
813- const allIssues = [ ... ( module . issues || [ ] ) ] ;
886+ const allIssues = normalizeIssueList ( module . issues ) ;
814887 const cacheKey = config . cacheEnabled
815888 ? buildModuleAnalysisCacheKey ( {
816889 module,
@@ -870,7 +943,7 @@ export async function processModule(module: ModuleInput, config: ProcessModuleCo
870943 let enrichResult ;
871944 try {
872945 enrichResult = await enrichModule ( module , config ) ;
873- allIssues . push ( ... enrichResult . enrichIssues ) ;
946+ mergeUniqueIssues ( allIssues , enrichResult . enrichIssues ) ;
874947 }
875948 catch ( error ) {
876949 const message = error instanceof Error ? error . message : String ( error ) ;
@@ -903,20 +976,24 @@ export async function processModule(module: ModuleInput, config: ProcessModuleCo
903976 } ;
904977 }
905978
906- // Stage 5: Analyze (placeholder)
979+ // Stage 5: Analyze
907980 let analysisResult ;
908981 try {
909982 if ( config . moduleLogger ) {
910983 await config . moduleLogger . info ( "analyze" , "Starting analysis stage" ) ;
911984 }
912985
913986 analysisResult = await analyzeModule ( module , config ) ;
914- allIssues . push ( ...analysisResult . analysisIssues ) ;
987+ // Merge analysis issues into the issues list
988+ mergeUniqueIssues ( allIssues , analysisResult . analysisIssues ) ;
989+
990+ // Add recommendations separately if any
991+ mergeUniqueIssues ( allIssues , analysisResult . recommendations ) ;
915992
916993 if ( config . moduleLogger ) {
917994 await config . moduleLogger . info ( "analyze" , "Analysis complete" , {
918- issuesCount : analysisResult . analysisIssues . length ,
919- recommendationsCount : analysisResult . recommendations . length
995+ issuesCount : analysisResult . analysisIssues ? .length || 0 ,
996+ recommendationsCount : analysisResult . recommendations ? .length || 0
920997 } ) ;
921998 }
922999 }
0 commit comments