@@ -5,7 +5,7 @@ import { v4 as uuid } from 'uuid';
55import isEmpty from 'lodash/isEmpty' ;
66import { join , resolve } from 'path' ;
77import cloneDeep from 'lodash/cloneDeep' ;
8- import { cliux , sanitizePath , TableFlags , TableHeader } from '@contentstack/cli-utilities' ;
8+ import { cliux , sanitizePath , TableFlags , TableHeader , log , configHandler } from '@contentstack/cli-utilities' ;
99import { createWriteStream , existsSync , mkdirSync , readFileSync , writeFileSync , rmSync } from 'fs' ;
1010import config from './config' ;
1111import { print } from './util/log' ;
@@ -31,11 +31,13 @@ import {
3131 OutputColumn ,
3232 RefErrorReturnType ,
3333 WorkflowExtensionsRefErrorReturnType ,
34+ AuditContext ,
3435} from './types' ;
3536
3637export abstract class AuditBaseCommand extends BaseCommand < typeof AuditBaseCommand > {
3738 private currentCommand ! : CommandNames ;
3839 private readonly summaryDataToPrint : Record < string , any > = [ ] ;
40+ protected auditContext ! : AuditContext ;
3941 get fixStatus ( ) {
4042 return {
4143 fixStatus : {
@@ -48,6 +50,19 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
4850 } ;
4951 }
5052
53+ /**
54+ * Create audit context object similar to export command
55+ */
56+ private createAuditContext ( moduleName ?: string ) : AuditContext {
57+ return {
58+ command : this . context ?. info ?. command || 'cm:stacks:audit' ,
59+ module : moduleName || 'audit' ,
60+ email : configHandler . get ( 'email' ) || '' ,
61+ sessionId : this . context ?. sessionId || '' ,
62+ authenticationMethod : configHandler . get ( 'authenticationMethod' ) || '' ,
63+ } ;
64+ }
65+
5166 /**
5267 * The `start` function performs an audit on content types, global fields, entries, and workflows and displays
5368 * any missing references.
@@ -56,9 +71,17 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
5671 */
5772 async start ( command : CommandNames ) : Promise < boolean > {
5873 this . currentCommand = command ;
74+ // Initialize audit context
75+ this . auditContext = this . createAuditContext ( ) ;
76+ log . debug ( `Starting audit command: ${ command } ` , this . auditContext ) ;
77+ log . info ( `Starting audit command: ${ command } ` , this . auditContext ) ;
78+
79+
5980 await this . promptQueue ( ) ;
6081 await this . createBackUp ( ) ;
6182 this . sharedConfig . reportPath = resolve ( this . flags [ 'report-path' ] || process . cwd ( ) , 'audit-report' ) ;
83+ log . debug ( `Data directory: ${ this . flags [ 'data-dir' ] } ` , this . auditContext ) ;
84+ log . debug ( `Report path: ${ this . flags [ 'report-path' ] || process . cwd ( ) } ` , this . auditContext ) ;
6285
6386 const {
6487 missingCtRefs,
@@ -122,13 +145,13 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
122145 ! isEmpty ( missingMultipleFields )
123146 ) {
124147 if ( this . currentCommand === 'cm:stacks:audit' ) {
125- this . log ( this . $t ( auditMsg . FINAL_REPORT_PATH , { path : this . sharedConfig . reportPath } ) , 'warn' ) ;
148+ log . warn ( this . $t ( auditMsg . FINAL_REPORT_PATH , { path : this . sharedConfig . reportPath } ) , this . auditContext ) ;
126149 } else {
127- this . log ( this . $t ( this . messages . FIXED_CONTENT_PATH_MAG , { path : this . sharedConfig . basePath } ) , 'warn' ) ;
150+ log . warn ( this . $t ( this . messages . FIXED_CONTENT_PATH_MAG , { path : this . sharedConfig . basePath } ) , this . auditContext ) ;
128151 }
129152 } else {
130- this . log ( this . messages . NO_MISSING_REF_FOUND , 'info' ) ;
131- this . log ( '' ) ;
153+ log . info ( this . messages . NO_MISSING_REF_FOUND , this . auditContext ) ;
154+ cliux . print ( '' ) ;
132155
133156 if (
134157 this . flags [ 'copy-dir' ] &&
@@ -161,14 +184,24 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
161184 * and `missingEntryRefs`.
162185 */
163186 async scanAndFix ( ) {
187+ log . debug ( 'Starting scan and fix process' , this . auditContext ) ;
164188 let { ctSchema, gfSchema } = this . getCtAndGfSchema ( ) ;
189+ log . info ( `Retrieved ${ ctSchema ?. length || 0 } content types and ${ gfSchema ?. length || 0 } global fields` , this . auditContext ) ;
190+
165191 let missingCtRefs ,
166192 missingGfRefs ,
167193 missingEntryRefs ,
168194 missingCtRefsInExtensions ,
169195 missingCtRefsInWorkflow ,
170196 missingSelectFeild ,
171- missingEntry ,
197+ missingEntry : {
198+ missingEntryRefs ?: Record < string , any > ;
199+ missingSelectFeild ?: Record < string , any > ;
200+ missingMandatoryFields ?: Record < string , any > ;
201+ missingTitleFields ?: Record < string , any > ;
202+ missingEnvLocale ?: Record < string , any > ;
203+ missingMultipleFields ?: Record < string , any > ;
204+ } = { } ,
172205 missingMandatoryFields ,
173206 missingTitleFields ,
174207 missingRefInCustomRoles ,
@@ -180,13 +213,21 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
180213 const constructorParam : ModuleConstructorParam & CtConstructorParam = {
181214 ctSchema,
182215 gfSchema,
183- log : this . log ,
184- config : this . sharedConfig ,
216+ config : {
217+ ...this . sharedConfig ,
218+ auditContext : this . auditContext ,
219+ } ,
185220 fix : this . currentCommand === 'cm:stacks:audit:fix' ,
186221 } ;
187222
188223 let dataModuleWise : Record < string , any > = await new ModuleDataReader ( cloneDeep ( constructorParam ) ) . run ( ) ;
224+ log . debug ( `Data module wise: ${ JSON . stringify ( dataModuleWise ) } ` , this . auditContext ) ;
189225 for ( const module of this . sharedConfig . flags . modules || this . sharedConfig . modules ) {
226+ // Update audit context with current module
227+ this . auditContext = this . createAuditContext ( module ) ;
228+ log . debug ( `Starting audit for module: ${ module } ` , this . auditContext ) ;
229+ log . info ( `Starting audit for module: ${ module } ` , this . auditContext ) ;
230+
190231 print ( [
191232 {
192233 bold : true ,
@@ -199,21 +240,28 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
199240
200241 switch ( module ) {
201242 case 'assets' :
243+ log . info ( 'Executing assets audit' , this . auditContext ) ;
202244 missingEnvLocalesInAssets = await new Assets ( cloneDeep ( constructorParam ) ) . run ( ) ;
203245 await this . prepareReport ( module , missingEnvLocalesInAssets ) ;
204246 this . getAffectedData ( 'assets' , dataModuleWise [ 'assets' ] , missingEnvLocalesInAssets ) ;
247+ log . success ( `Assets audit completed. Found ${ Object . keys ( missingEnvLocalesInAssets || { } ) . length } issues` , this . auditContext ) ;
205248 break ;
206249 case 'content-types' :
250+ log . info ( 'Executing content-types audit' , this . auditContext ) ;
207251 missingCtRefs = await new ContentType ( cloneDeep ( constructorParam ) ) . run ( ) ;
208252 await this . prepareReport ( module , missingCtRefs ) ;
209253 this . getAffectedData ( 'content-types' , dataModuleWise [ 'content-types' ] , missingCtRefs ) ;
254+ log . success ( `Content-types audit completed. Found ${ Object . keys ( missingCtRefs || { } ) . length } issues` , this . auditContext ) ;
210255 break ;
211256 case 'global-fields' :
257+ log . info ( 'Executing global-fields audit' , this . auditContext ) ;
212258 missingGfRefs = await new GlobalField ( cloneDeep ( constructorParam ) ) . run ( ) ;
213259 await this . prepareReport ( module , missingGfRefs ) ;
214260 this . getAffectedData ( 'global-fields' , dataModuleWise [ 'global-fields' ] , missingGfRefs ) ;
261+ log . success ( `Global-fields audit completed. Found ${ Object . keys ( missingGfRefs || { } ) . length } issues` , this . auditContext ) ;
215262 break ;
216263 case 'entries' :
264+ log . info ( 'Executing entries audit' , this . auditContext ) ;
217265 missingEntry = await new Entries ( cloneDeep ( constructorParam ) ) . run ( ) ;
218266 missingEntryRefs = missingEntry . missingEntryRefs ?? { } ;
219267 missingSelectFeild = missingEntry . missingSelectFeild ?? { } ;
@@ -233,39 +281,47 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
233281
234282 await this . prepareReport ( 'Entry_Multiple_Fields' , missingMultipleFields ) ;
235283 this . getAffectedData ( 'entries' , dataModuleWise [ 'entries' ] , missingEntry ) ;
284+ log . success ( `Entries audit completed. Found ${ Object . keys ( missingEntryRefs || { } ) . length } reference issues` , this . auditContext ) ;
236285
237286 break ;
238287 case 'workflows' :
288+ log . info ( 'Executing workflows audit' , this . auditContext ) ;
239289 missingCtRefsInWorkflow = await new Workflows ( {
240290 ctSchema,
241- log : this . log ,
242291 moduleName : module ,
243292 config : this . sharedConfig ,
244293 fix : this . currentCommand === 'cm:stacks:audit:fix' ,
245294 } ) . run ( ) ;
246295 await this . prepareReport ( module , missingCtRefsInWorkflow ) ;
247296 this . getAffectedData ( 'workflows' , dataModuleWise [ 'workflows' ] , missingCtRefsInWorkflow ) ;
297+ log . success ( `Workflows audit completed. Found ${ Object . keys ( missingCtRefsInWorkflow || { } ) . length } issues` , this . auditContext ) ;
248298
249299 break ;
250300 case 'extensions' :
301+ log . info ( 'Executing extensions audit' , this . auditContext ) ;
251302 missingCtRefsInExtensions = await new Extensions ( cloneDeep ( constructorParam ) ) . run ( ) ;
252303 await this . prepareReport ( module , missingCtRefsInExtensions ) ;
253304 this . getAffectedData ( 'extensions' , dataModuleWise [ 'extensions' ] , missingCtRefsInExtensions ) ;
305+ log . success ( `Extensions audit completed. Found ${ Object . keys ( missingCtRefsInExtensions || { } ) . length } issues` , this . auditContext ) ;
254306 break ;
255307 case 'custom-roles' :
308+ log . info ( 'Executing custom-roles audit' , this . auditContext ) ;
256309 missingRefInCustomRoles = await new CustomRoles ( cloneDeep ( constructorParam ) ) . run ( ) ;
257310 await this . prepareReport ( module , missingRefInCustomRoles ) ;
258311 this . getAffectedData ( 'custom-roles' , dataModuleWise [ 'custom-roles' ] , missingRefInCustomRoles ) ;
312+ log . success ( `Custom-roles audit completed. Found ${ Object . keys ( missingRefInCustomRoles || { } ) . length } issues` , this . auditContext ) ;
259313
260314 break ;
261315 case 'field-rules' :
316+ log . info ( 'Executing field-rules audit' , this . auditContext ) ;
262317 // NOTE: We are using the fixed content-type for validation of field rules
263318 const data = this . getCtAndGfSchema ( ) ;
264319 constructorParam . ctSchema = data . ctSchema ;
265320 constructorParam . gfSchema = data . gfSchema ;
266321 missingFieldRules = await new FieldRule ( cloneDeep ( constructorParam ) ) . run ( ) ;
267322 await this . prepareReport ( module , missingFieldRules ) ;
268323 this . getAffectedData ( 'field-rules' , dataModuleWise [ 'content-types' ] , missingFieldRules ) ;
324+ log . success ( `Field-rules audit completed. Found ${ Object . keys ( missingFieldRules || { } ) . length } issues` , this . auditContext ) ;
269325 break ;
270326 }
271327
@@ -283,6 +339,7 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
283339 ] ) ;
284340 }
285341
342+ log . debug ( 'Scan and fix process completed' , this . auditContext ) ;
286343 this . prepareReport ( 'Summary' , this . summaryDataToPrint ) ;
287344 this . prepareCSV ( 'Summary' , this . summaryDataToPrint ) ;
288345 return {
@@ -376,7 +433,7 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
376433 */
377434 showOutputOnScreen ( allMissingRefs : { module : string ; missingRefs ?: Record < string , any > } [ ] ) {
378435 if ( this . sharedConfig . showTerminalOutput && ! this . flags [ 'external-config' ] ?. noTerminalOutput ) {
379- this . log ( '' ) ; // NOTE adding new line
436+ cliux . print ( '' ) ; // NOTE adding new line
380437 for ( const { module, missingRefs } of allMissingRefs ) {
381438 if ( ! isEmpty ( missingRefs ) ) {
382439 print ( [
@@ -423,7 +480,7 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
423480 ] ;
424481
425482 cliux . table ( tableHeaders , tableValues , { ...( this . flags as TableFlags ) } ) ;
426- this . log ( '' ) ; // NOTE adding new line
483+ cliux . print ( '' ) ; // NOTE adding new line
427484 }
428485 }
429486 }
@@ -434,15 +491,15 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
434491 if ( ! this . sharedConfig . showTerminalOutput || this . flags [ 'external-config' ] ?. noTerminalOutput ) {
435492 return ;
436493 }
437- this . log ( '' ) ; // Adding a new line
494+ cliux . print ( '' ) ; // Adding a new line
438495
439496 for ( let { module, missingRefs } of allMissingRefs ) {
440497 if ( isEmpty ( missingRefs ) ) {
441498 continue ;
442499 }
443500
444501 print ( [ { bold : true , color : 'cyan' , message : ` ${ module } ` } ] ) ;
445-
502+
446503 const tableValues = Object . values ( missingRefs ) . flat ( ) ;
447504 missingRefs = Object . values ( missingRefs ) . flat ( ) ;
448505 const tableKeys = Object . keys ( missingRefs [ 0 ] ) ;
@@ -471,7 +528,7 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
471528 } ) ) ;
472529
473530 cliux . table ( tableHeaders , tableValues , { ...( this . flags as TableFlags ) } ) ;
474- this . log ( '' ) ; // Adding a new line
531+ cliux . print ( '' ) ; // Adding a new line
475532 }
476533 }
477534
@@ -493,19 +550,29 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
493550 | 'Summary' ,
494551 listOfMissingRefs : Record < string , any > ,
495552 ) : Promise < void > {
496- if ( isEmpty ( listOfMissingRefs ) ) return Promise . resolve ( void 0 ) ;
553+ log . debug ( `Preparing report for module: ${ moduleName } ` , this . auditContext ) ;
554+ log . debug ( `Report path: ${ this . sharedConfig . reportPath } ` , this . auditContext ) ;
555+ log . info ( `Missing references count: ${ Object . keys ( listOfMissingRefs ) . length } ` , this . auditContext ) ;
556+
557+ if ( isEmpty ( listOfMissingRefs ) ) {
558+ log . debug ( `No missing references found for ${ moduleName } , skipping report generation` , this . auditContext ) ;
559+ return Promise . resolve ( void 0 ) ;
560+ }
497561
498562 if ( ! existsSync ( this . sharedConfig . reportPath ) ) {
563+ log . debug ( `Creating report directory: ${ this . sharedConfig . reportPath } ` , this . auditContext ) ;
499564 mkdirSync ( this . sharedConfig . reportPath , { recursive : true } ) ;
565+ } else {
566+ log . debug ( `Report directory already exists: ${ this . sharedConfig . reportPath } ` , this . auditContext ) ;
500567 }
501568
502569 // NOTE write int json
503- writeFileSync (
504- join ( sanitizePath ( this . sharedConfig . reportPath ) , `${ sanitizePath ( moduleName ) } .json` ) ,
505- JSON . stringify ( listOfMissingRefs ) ,
506- ) ;
570+ const jsonFilePath = join ( sanitizePath ( this . sharedConfig . reportPath ) , `${ sanitizePath ( moduleName ) } .json` ) ;
571+ log . debug ( `Writing JSON report to: ${ jsonFilePath } ` , this . auditContext ) ;
572+ writeFileSync ( jsonFilePath , JSON . stringify ( listOfMissingRefs ) ) ;
507573
508574 // NOTE write into CSV
575+ log . debug ( `Preparing CSV report for: ${ moduleName } ` , this . auditContext ) ;
509576 return this . prepareCSV ( moduleName , listOfMissingRefs ) ;
510577 }
511578
0 commit comments