Skip to content

Commit 9ba66e2

Browse files
Merge pull request #2234 from contentstack/v2-beta-dev
V2 beta release
2 parents 954f826 + 5613014 commit 9ba66e2

File tree

195 files changed

+53886
-4725
lines changed

Some content is hidden

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

195 files changed

+53886
-4725
lines changed

.github/workflows/unit-test.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ jobs:
2424
working-directory: ./packages/contentstack-command
2525
run: npm run test:unit
2626

27-
- name: Run tests for Contentstack Command
28-
working-directory: ./packages/contentstack-command
29-
run: npm run test:unit
27+
# - name: Run tests for Contentstack Import Plugin
28+
# working-directory: ./packages/contentstack-import
29+
# run: npm run test:unit
30+
31+
# - name: Run tests for Contentstack Export Plugin
32+
# working-directory: ./packages/contentstack-export
33+
# run: npm run test:unit
3034

3135
- name: Run tests for Audit plugin
3236
working-directory: ./packages/contentstack-audit

.talismanrc

Lines changed: 205 additions & 111 deletions
Large diffs are not rendered by default.

package-lock.json

Lines changed: 1813 additions & 1596 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/contentstack-audit/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ DESCRIPTION
282282
Display help for csdx.
283283
```
284284

285+
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.33/src/commands/help.ts)_
285286
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.33/src/commands/help.ts)_
286287

287288
## `csdx plugins`

packages/contentstack-audit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/cli-audit",
3-
"version": "1.14.2",
3+
"version": "1.16.0",
44
"description": "Contentstack audit plugin",
55
"author": "Contentstack CLI",
66
"homepage": "https://github.com/contentstack/cli",

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

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +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 { cliux, sanitizePath, TableFlags, TableHeader } from '@contentstack/cli-utilities';
8+
import { cliux, sanitizePath, TableFlags, TableHeader, log, configHandler } from '@contentstack/cli-utilities';
99
import { createWriteStream, existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'fs';
1010
import config from './config';
1111
import { print } from './util/log';
@@ -31,11 +31,13 @@ import {
3131
OutputColumn,
3232
RefErrorReturnType,
3333
WorkflowExtensionsRefErrorReturnType,
34+
AuditContext,
3435
} from './types';
3536

3637
export 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

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

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,16 @@ import merge from 'lodash/merge';
22
import isEmpty from 'lodash/isEmpty';
33
import { existsSync, readFileSync } from 'fs';
44
import { Command } from '@contentstack/cli-command';
5-
import { Flags, FlagInput, Interfaces, cliux, ux, PrintOptions } from '@contentstack/cli-utilities';
5+
import { Flags, FlagInput, Interfaces, cliux, ux, handleAndLogError } from '@contentstack/cli-utilities';
66

77
import config from './config';
8-
import { Logger } from './util';
9-
import { ConfigType, LogFn, LoggerType } from './types';
8+
import { ConfigType } from './types';
109
import messages, { $t, commonMsg } from './messages';
1110

1211
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
1312
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
1413

15-
const noLog = (_message: string | any, _logType?: LoggerType | PrintOptions | undefined) => {};
16-
1714
export abstract class BaseCommand<T extends typeof Command> extends Command {
18-
public log!: LogFn;
19-
public logger!: Logger;
2015
public readonly $t = $t;
2116
protected sharedConfig: ConfigType = {
2217
...config,
@@ -71,12 +66,8 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
7166

7267
// Init logger
7368
if (this.flags['external-config']?.noLog) {
74-
this.log = noLog;
7569
ux.action.start = () => {};
7670
ux.action.stop = () => {};
77-
} else {
78-
const logger = new Logger(this.sharedConfig);
79-
this.log = logger.log.bind(logger);
8071
}
8172
}
8273

@@ -117,7 +108,7 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
117108
JSON.parse(readFileSync(this.flags.config, { encoding: 'utf-8' })),
118109
);
119110
} catch (error) {
120-
this.log(error, 'error');
111+
handleAndLogError(error);
121112
}
122113
}
123114
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FlagInput, Flags, ux } from '@contentstack/cli-utilities';
1+
import { FlagInput, Flags, ux, handleAndLogError } from '@contentstack/cli-utilities';
22

33
import config from '../../../../config';
44
import { ConfigType } from '../../../../types';
@@ -68,8 +68,7 @@ export default class AuditFix extends AuditBaseCommand {
6868
return { config: this.sharedConfig, hasFix };
6969
}
7070
} catch (error) {
71-
this.log(error instanceof Error ? error.message : error, 'error');
72-
console.trace(error);
71+
handleAndLogError(error);
7372
ux.action.stop('Process failed.!');
7473
this.exit(1);
7574
}

0 commit comments

Comments
 (0)