Skip to content

Commit 70d1461

Browse files
committed
added all plugins
1 parent d255420 commit 70d1461

565 files changed

Lines changed: 56181 additions & 15422 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.talismanrc

Lines changed: 361 additions & 439 deletions
Large diffs are not rendered by default.

packages/contentstack-audit/README.md

Lines changed: 10 additions & 431 deletions
Large diffs are not rendered by default.

packages/contentstack-audit/package.json

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/cli-audit",
3-
"version": "1.17.0",
3+
"version": "2.0.0-beta.2",
44
"description": "Contentstack audit plugin",
55
"author": "Contentstack CLI",
66
"homepage": "https://github.com/contentstack/cli",
@@ -18,11 +18,10 @@
1818
"/oclif.manifest.json"
1919
],
2020
"dependencies": {
21-
"@contentstack/cli-command": "workspace:*",
22-
"@contentstack/cli-utilities": "workspace:*",
21+
"@contentstack/cli-command": "~1.7.2",
22+
"@contentstack/cli-utilities": "~1.17.2",
2323
"@oclif/core": "^4.3.0",
2424
"@oclif/plugin-help": "^6.2.28",
25-
"@oclif/plugin-plugins": "^5.4.54",
2625
"chalk": "^4.1.2",
2726
"fast-csv": "^4.3.6",
2827
"fs-extra": "^11.3.0",
@@ -45,16 +44,15 @@
4544
"nyc": "^15.1.0",
4645
"oclif": "^4.17.46",
4746
"shx": "^0.4.0",
48-
"sinon": "^19.0.5",
47+
"sinon": "^21.0.1",
4948
"ts-node": "^10.9.2",
5049
"typescript": "^5.8.3"
5150
},
5251
"oclif": {
5352
"bin": "csdx",
5453
"commands": "./lib/commands",
5554
"plugins": [
56-
"@oclif/plugin-help",
57-
"@oclif/plugin-plugins"
55+
"@oclif/plugin-help"
5856
],
5957
"topicSeparator": ":",
6058
"additionalHelpFlags": [
@@ -66,7 +64,7 @@
6664
"repositoryPrefix": "<%- repo %>/blob/main/packages/contentstack-audit/<%- commandPath %>"
6765
},
6866
"scripts": {
69-
"build": "shx rm -rf lib && tsc -b",
67+
"build": "pnpm compile",
7068
"lint": "eslint . --ext .ts --config .eslintrc",
7169
"postpack": "shx rm -f oclif.manifest.json",
7270
"posttest": "npm run lint",

packages/contentstack-audit/src/audit-base-command.ts

Lines changed: 66 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,7 @@ import { v4 as uuid } from 'uuid';
55
import isEmpty from 'lodash/isEmpty';
66
import { join, resolve } from 'path';
77
import cloneDeep from 'lodash/cloneDeep';
8-
import {
9-
cliux,
10-
sanitizePath,
11-
TableFlags,
12-
TableHeader,
13-
log,
14-
configHandler,
15-
createLogContext,
16-
} from '@contentstack/cli-utilities';
8+
import { cliux, sanitizePath, TableFlags, TableHeader, log, configHandler, CLIProgressManager, clearProgressModuleSetting } from '@contentstack/cli-utilities';
179
import { createWriteStream, existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'fs';
1810
import config from './config';
1911
import { print } from './util/log';
@@ -67,12 +59,19 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
6759
*/
6860
async start(command: CommandNames): Promise<boolean> {
6961
this.currentCommand = command;
70-
// Initialize audit context (reused, no need to call again in scanAndFix)
71-
createLogContext(this.context?.info?.command, '', configHandler.get('authenticationMethod'));
72-
this.auditContext = { module: 'audit' };
73-
log.debug(`Starting audit command: ${command}`, this.auditContext);
74-
log.info(`Starting audit command: ${command}`, this.auditContext);
75-
62+
63+
// Set progress supported module and console logs setting BEFORE any log calls
64+
// This ensures the logger respects the setting when it's initialized
65+
const logConfig = configHandler.get('log') || {};
66+
// Default to false so progress bars are shown instead of console logs
67+
if (logConfig.showConsoleLogs === undefined) {
68+
configHandler.set('log.showConsoleLogs', false);
69+
}
70+
configHandler.set('log.progressSupportedModule', 'audit');
71+
72+
// Initialize global summary for progress tracking
73+
CLIProgressManager.initializeGlobalSummary('AUDIT', '', 'Auditing content...');
74+
7675
await this.promptQueue();
7776
await this.createBackUp();
7877
this.sharedConfig.reportPath = resolve(this.flags['report-path'] || process.cwd(), 'audit-report');
@@ -165,6 +164,12 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
165164
}
166165
}
167166

167+
// Print comprehensive summary at the end
168+
CLIProgressManager.printGlobalSummary();
169+
170+
// Clear progress module setting now that audit is complete
171+
clearProgressModuleSetting();
172+
168173
return (
169174
!isEmpty(missingCtRefs) ||
170175
!isEmpty(missingGfRefs) ||
@@ -229,26 +234,35 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
229234

230235
let dataModuleWise: Record<string, any> = await new ModuleDataReader(cloneDeep(constructorParam)).run();
231236
log.debug(`Data module wise: ${JSON.stringify(dataModuleWise)}`, this.auditContext);
237+
238+
// Extract logConfig and showConsoleLogs once before the loop to reuse throughout
239+
const logConfig = configHandler.get('log') || {};
240+
const showConsoleLogs = logConfig.showConsoleLogs ?? true;
241+
232242
for (const module of this.sharedConfig.flags.modules || this.sharedConfig.modules) {
233243
// Update audit context with current module
234244
this.auditContext = { module: module };
235245
log.debug(`Starting audit for module: ${module}`, this.auditContext);
236246
log.info(`Starting audit for module: ${module}`, this.auditContext);
237247

238-
print([
239-
{
240-
bold: true,
241-
color: 'whiteBright',
242-
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
243-
},
244-
]);
248+
// Only show spinner message if console logs are enabled (compatible with line-by-line logs)
249+
if (showConsoleLogs) {
250+
print([
251+
{
252+
bold: true,
253+
color: 'whiteBright',
254+
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
255+
},
256+
]);
257+
}
245258

246259
constructorParam['moduleName'] = module;
247260

248261
switch (module) {
249262
case 'assets':
250263
log.info('Executing assets audit', this.auditContext);
251-
missingEnvLocalesInAssets = await new Assets(cloneDeep(constructorParam)).run();
264+
const assetsTotalCount = dataModuleWise['assets']?.Total || 0;
265+
missingEnvLocalesInAssets = await new Assets(cloneDeep(constructorParam)).run(false, assetsTotalCount);
252266
await this.prepareReport(module, missingEnvLocalesInAssets);
253267
this.getAffectedData('assets', dataModuleWise['assets'], missingEnvLocalesInAssets);
254268
log.success(
@@ -258,7 +272,8 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
258272
break;
259273
case 'content-types':
260274
log.info('Executing content-types audit', this.auditContext);
261-
missingCtRefs = await new ContentType(cloneDeep(constructorParam)).run();
275+
const contentTypesTotalCount = dataModuleWise['content-types']?.Total || 0;
276+
missingCtRefs = await new ContentType(cloneDeep(constructorParam)).run(false, contentTypesTotalCount);
262277
await this.prepareReport(module, missingCtRefs);
263278
this.getAffectedData('content-types', dataModuleWise['content-types'], missingCtRefs);
264279
log.success(
@@ -268,7 +283,8 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
268283
break;
269284
case 'global-fields':
270285
log.info('Executing global-fields audit', this.auditContext);
271-
missingGfRefs = await new GlobalField(cloneDeep(constructorParam)).run();
286+
const globalFieldsTotalCount = dataModuleWise['global-fields']?.Total || 0;
287+
missingGfRefs = await new GlobalField(cloneDeep(constructorParam)).run(false, globalFieldsTotalCount);
272288
await this.prepareReport(module, missingGfRefs);
273289
this.getAffectedData('global-fields', dataModuleWise['global-fields'], missingGfRefs);
274290
log.success(
@@ -278,7 +294,8 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
278294
break;
279295
case 'entries':
280296
log.info('Executing entries audit', this.auditContext);
281-
missingEntry = await new Entries(cloneDeep(constructorParam)).run();
297+
const entriesTotalCount = dataModuleWise['entries']?.Total || 0;
298+
missingEntry = await new Entries(cloneDeep(constructorParam)).run(entriesTotalCount);
282299
missingEntryRefs = missingEntry.missingEntryRefs ?? {};
283300
missingSelectFeild = missingEntry.missingSelectFeild ?? {};
284301
missingMandatoryFields = missingEntry.missingMandatoryFields ?? {};
@@ -305,12 +322,13 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
305322
break;
306323
case 'workflows':
307324
log.info('Executing workflows audit', this.auditContext);
325+
const workflowsTotalCount = dataModuleWise['workflows']?.Total || 0;
308326
missingCtRefsInWorkflow = await new Workflows({
309327
ctSchema,
310328
moduleName: module,
311329
config: this.sharedConfig,
312330
fix: this.currentCommand === 'cm:stacks:audit:fix',
313-
}).run();
331+
}).run(workflowsTotalCount);
314332
await this.prepareReport(module, missingCtRefsInWorkflow);
315333
this.getAffectedData('workflows', dataModuleWise['workflows'], missingCtRefsInWorkflow);
316334
log.success(
@@ -321,7 +339,8 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
321339
break;
322340
case 'extensions':
323341
log.info('Executing extensions audit', this.auditContext);
324-
missingCtRefsInExtensions = await new Extensions(cloneDeep(constructorParam)).run();
342+
const extensionsTotalCount = dataModuleWise['extensions']?.Total || 0;
343+
missingCtRefsInExtensions = await new Extensions(cloneDeep(constructorParam)).run(extensionsTotalCount);
325344
await this.prepareReport(module, missingCtRefsInExtensions);
326345
this.getAffectedData('extensions', dataModuleWise['extensions'], missingCtRefsInExtensions);
327346
log.success(
@@ -331,7 +350,8 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
331350
break;
332351
case 'custom-roles':
333352
log.info('Executing custom-roles audit', this.auditContext);
334-
missingRefInCustomRoles = await new CustomRoles(cloneDeep(constructorParam)).run();
353+
const customRolesTotalCount = dataModuleWise['custom-roles']?.Total || 0;
354+
missingRefInCustomRoles = await new CustomRoles(cloneDeep(constructorParam)).run(customRolesTotalCount);
335355
await this.prepareReport(module, missingRefInCustomRoles);
336356
this.getAffectedData('custom-roles', dataModuleWise['custom-roles'], missingRefInCustomRoles);
337357
log.success(
@@ -346,7 +366,8 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
346366
const data = this.getCtAndGfSchema();
347367
constructorParam.ctSchema = data.ctSchema;
348368
constructorParam.gfSchema = data.gfSchema;
349-
missingFieldRules = await new FieldRule(cloneDeep(constructorParam)).run();
369+
const fieldRulesTotalCount = dataModuleWise['content-types']?.Total || 0;
370+
missingFieldRules = await new FieldRule(cloneDeep(constructorParam)).run(fieldRulesTotalCount);
350371
await this.prepareReport(module, missingFieldRules);
351372
this.getAffectedData('field-rules', dataModuleWise['content-types'], missingFieldRules);
352373
log.success(
@@ -372,18 +393,21 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
372393
break;
373394
}
374395

375-
print([
376-
{
377-
bold: true,
378-
color: 'whiteBright',
379-
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
380-
},
381-
{
382-
bold: true,
383-
message: ' done',
384-
color: 'whiteBright',
385-
},
386-
]);
396+
// Only show completion message if console logs are enabled
397+
if (showConsoleLogs) {
398+
print([
399+
{
400+
bold: true,
401+
color: 'whiteBright',
402+
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
403+
},
404+
{
405+
bold: true,
406+
message: ' done',
407+
color: 'whiteBright',
408+
},
409+
]);
410+
}
387411
}
388412

389413
log.debug('Scan and fix process completed', this.auditContext);

packages/contentstack-audit/src/commands/cm/stacks/audit/fix.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import { getJsonInputFlags, tableFlags } from '../../../../util';
99
const jsonFlag = getJsonInputFlags({ hidden: true });
1010

1111
export default class AuditFix extends AuditBaseCommand {
12-
static aliases: string[] = ['audit:fix', 'cm:stacks:audit:fix'];
13-
1412
static description = auditFixMsg.AUDIT_FIX_CMD_DESCRIPTION;
1513

1614
static examples = [

packages/contentstack-audit/src/commands/cm/stacks/audit/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import { AuditBaseCommand } from '../../../../audit-base-command';
66
import { tableFlags } from '../../../../util';
77

88
export default class Audit extends AuditBaseCommand {
9-
static aliases: string[] = ['audit', 'cm:stacks:audit'];
10-
119
static description = auditMsg.AUDIT_CMD_DESCRIPTION;
1210

1311
static examples = [

packages/contentstack-audit/src/modules/assets.ts

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { join, resolve } from 'path';
22
import { existsSync, readFileSync, writeFileSync } from 'fs';
33
import { FsUtility, sanitizePath, cliux, log } from '@contentstack/cli-utilities';
44
import {
5-
ConfigType,
65
ContentTypeStruct,
76
CtConstructorParam,
87
ModuleConstructorParam,
@@ -12,13 +11,13 @@ import auditConfig from '../config';
1211
import { $t, auditFixMsg, auditMsg, commonMsg } from '../messages';
1312
import values from 'lodash/values';
1413
import { keys } from 'lodash';
14+
import BaseClass from './base-class';
1515

16-
/* The `ContentType` class is responsible for scanning content types, looking for references, and
17-
generating a report in JSON and CSV formats. */
18-
export default class Assets {
16+
/* The `Assets` class is responsible for scanning assets, looking for missing environment/locale references,
17+
and generating a report in JSON and CSV formats. */
18+
export default class Assets extends BaseClass {
1919
protected fix: boolean;
2020
public fileName: string;
21-
public config: ConfigType;
2221
public folderPath: string;
2322
public currentUid!: string;
2423
public currentTitle!: string;
@@ -30,7 +29,7 @@ export default class Assets {
3029
public moduleName: keyof typeof auditConfig.moduleConfig;
3130

3231
constructor({ fix, config, moduleName }: ModuleConstructorParam & CtConstructorParam) {
33-
this.config = config;
32+
super({ config });
3433
this.fix = fix ?? false;
3534
this.moduleName = this.validateModules(moduleName!, this.config.moduleConfig);
3635
this.fileName = config.moduleConfig[this.moduleName].fileName;
@@ -52,25 +51,36 @@ export default class Assets {
5251
/**
5352
* The `run` function checks if a folder path exists, sets the schema based on the module name,
5453
* iterates over the schema and looks for references, and returns a list of missing references.
54+
* @param returnFixSchema - If true, returns the fixed schema instead of missing references
55+
* @param totalCount - Total number of assets to process (for progress tracking)
5556
* @returns the `missingEnvLocales` object.
5657
*/
57-
async run(returnFixSchema = false) {
58-
log.debug(`Starting ${this.moduleName} audit process`, this.config.auditContext);
59-
log.debug(`Data directory: ${this.folderPath}`, this.config.auditContext);
60-
log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
61-
62-
if (!existsSync(this.folderPath)) {
63-
log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
64-
log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
65-
cliux.print($t(auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
66-
return returnFixSchema ? [] : {};
67-
}
58+
async run(returnFixSchema = false, totalCount?: number) {
59+
try {
60+
log.debug(`Starting ${this.moduleName} audit process`, this.config.auditContext);
61+
log.debug(`Data directory: ${this.folderPath}`, this.config.auditContext);
62+
log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
6863

69-
log.debug('Loading prerequisite data (locales and environments)', this.config.auditContext);
70-
await this.prerequisiteData();
64+
if (!existsSync(this.folderPath)) {
65+
log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
66+
log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
67+
cliux.print($t(auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
68+
return returnFixSchema ? [] : {};
69+
}
70+
71+
// Load prerequisite data with loading spinner
72+
await this.withLoadingSpinner('ASSETS: Loading prerequisite data (locales and environments)...', async () => {
73+
await this.prerequisiteData();
74+
});
75+
76+
// Create progress manager if we have a total count
77+
if (totalCount && totalCount > 0) {
78+
const progress = this.createSimpleProgress(this.moduleName, totalCount);
79+
progress.updateStatus('Validating asset references...');
80+
}
7181

72-
log.debug('Starting asset Reference, Environment and Locale validation', this.config.auditContext);
73-
await this.lookForReference();
82+
log.debug('Starting asset Reference, Environment and Locale validation', this.config.auditContext);
83+
await this.lookForReference();
7484

7585
if (returnFixSchema) {
7686
log.debug(`Returning fixed schema with ${this.schema?.length || 0} items`, this.config.auditContext);
@@ -86,9 +96,15 @@ export default class Assets {
8696
}
8797
}
8898

89-
const totalIssues = Object.keys(this.missingEnvLocales).length;
90-
log.debug(`${this.moduleName} audit completed. Found ${totalIssues} assets with missing environment/locale references`, this.config.auditContext);
91-
return this.missingEnvLocales;
99+
const totalIssues = Object.keys(this.missingEnvLocales).length;
100+
log.debug(`${this.moduleName} audit completed. Found ${totalIssues} assets with missing environment/locale references`, this.config.auditContext);
101+
102+
this.completeProgress(true);
103+
return this.missingEnvLocales;
104+
} catch (error: any) {
105+
this.completeProgress(false, error?.message || 'Assets audit failed');
106+
throw error;
107+
}
92108
}
93109

94110
/**
@@ -227,6 +243,11 @@ export default class Assets {
227243
const remainingPublishDetails = this.assets[assetUid].publish_details?.length || 0;
228244
log.debug(`Asset ${assetUid} now has ${remainingPublishDetails} valid publish details`, this.config.auditContext);
229245

246+
// Track progress for each asset processed
247+
if (this.progressManager) {
248+
this.progressManager.tick(true, `asset: ${assetUid}`, null);
249+
}
250+
230251
if (this.fix) {
231252
log.debug(`Fixing asset ${assetUid}`, this.config.auditContext);
232253
log.info($t(auditFixMsg.ASSET_FIX, { uid: assetUid }), this.config.auditContext);

0 commit comments

Comments
 (0)