Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e8c0eb5
feat: Added Audit and audit fix for Select fields in entries and mino…
cs-raj Apr 27, 2024
1ad7460
Merge remote-tracking branch 'origin/development' into feat/CS-44502
cs-raj Apr 27, 2024
dd691e7
PR fixes and version bump of CLI
cs-raj Apr 29, 2024
4476bfd
PR fixes
cs-raj Apr 29, 2024
73e36f5
Merge pull request #1391 from contentstack/staging-to-development
cs-raj Apr 29, 2024
c433a1d
Merge branch 'development' into feat/CS-44502
cs-raj Apr 29, 2024
393fa49
PR fixes and lock-file update
cs-raj Apr 29, 2024
fcd54b8
log removal
cs-raj Apr 29, 2024
6a7a823
Merge pull request #1389 from contentstack/feat/CS-44502
cs-raj Apr 29, 2024
43a68b5
Merge branch 'staging' into staging-to-development
cs-raj May 3, 2024
551c0b6
Lock-file and readme update
cs-raj May 3, 2024
f50b1b4
Merge pull request #1398 from contentstack/staging-to-development
cs-raj May 3, 2024
e9800f0
added audit and audit fix for mandatory fields in Entries, and added …
cs-raj May 6, 2024
d2a9de3
PR fixes and lock-file update
cs-raj May 6, 2024
43c1988
PR comment fixes
cs-raj May 6, 2024
69fe156
added condition to show extension updated message successfully, in ma…
cs-raj May 6, 2024
2e0ad9a
formatting
cs-raj May 6, 2024
696b556
PR change
cs-raj May 6, 2024
291679f
displaying the audit report for the mandatory feilds in case of no pu…
cs-raj May 6, 2024
528dbeb
Merge pull request #1400 from contentstack/fix/DX-54
cs-raj May 6, 2024
71ca574
removing redundant checks
cs-raj May 6, 2024
d35443c
Merge branch 'development' into feat/DX-523
cs-raj May 7, 2024
4cde239
Merge pull request #1399 from contentstack/feat/DX-523
cs-raj May 7, 2024
91cc0a3
used the length property to validate the missing mandatory fields, av…
cs-raj May 7, 2024
95ad166
Merge pull request #1402 from contentstack/bugfix/DX-552
cs-raj May 7, 2024
8470a58
lock-file update
cs-raj May 8, 2024
3cf1e9d
Merge pull request #1403 from contentstack/fix/lock-files
cs-raj May 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
384 changes: 181 additions & 203 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/contentstack-audit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ $ npm install -g @contentstack/cli-audit
$ csdx COMMAND
running command...
$ csdx (--version|-v)
@contentstack/cli-audit/1.5.4 darwin-arm64 node-v21.6.2
@contentstack/cli-audit/1.6.0 darwin-arm64 node-v21.6.2
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-audit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/cli-audit",
"version": "1.5.4",
"version": "1.6.0",
"description": "Contentstack audit plugin",
"author": "Contentstack CLI",
"homepage": "https://github.com/contentstack/cli",
Expand Down
73 changes: 60 additions & 13 deletions packages/contentstack-audit/src/audit-base-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,15 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
await this.createBackUp();
this.sharedConfig.reportPath = resolve(this.flags['report-path'] || process.cwd(), 'audit-report');

const { missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow } =
await this.scanAndFix();
const {
missingCtRefs,
missingGfRefs,
missingEntryRefs,
missingCtRefsInExtensions,
missingCtRefsInWorkflow,
missingSelectFeild,
missingMandatoryFields,
} = await this.scanAndFix();

this.showOutputOnScreen([
{ module: 'Content types', missingRefs: missingCtRefs },
Expand All @@ -58,12 +65,17 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
]);
this.showOutputOnScreenWorkflowsAndExtension([{ module: 'Extensions', missingRefs: missingCtRefsInExtensions }]);
this.showOutputOnScreenWorkflowsAndExtension([{ module: 'Workflows', missingRefs: missingCtRefsInWorkflow }]);
this.showOutputOnScreenWorkflowsAndExtension([{ module: 'Entries Select Field', missingRefs: missingSelectFeild }]);
this.showOutputOnScreenWorkflowsAndExtension([
{ module: 'Entries Mandatory Field', missingRefs: missingMandatoryFields },
]);
if (
!isEmpty(missingCtRefs) ||
!isEmpty(missingGfRefs) ||
!isEmpty(missingEntryRefs) ||
!isEmpty(missingCtRefsInWorkflow) ||
!isEmpty(missingCtRefsInExtensions)
!isEmpty(missingCtRefsInExtensions) ||
!isEmpty(missingSelectFeild)
) {
if (this.currentCommand === 'cm:stacks:audit') {
this.log(this.$t(auditMsg.FINAL_REPORT_PATH, { path: this.sharedConfig.reportPath }), 'warn');
Expand All @@ -89,7 +101,8 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
!isEmpty(missingGfRefs) ||
!isEmpty(missingEntryRefs) ||
!isEmpty(missingCtRefsInWorkflow) ||
!isEmpty(missingCtRefsInExtensions)
!isEmpty(missingCtRefsInExtensions) ||
!isEmpty(missingSelectFeild)
);
}

Expand All @@ -101,7 +114,15 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
*/
async scanAndFix() {
let { ctSchema, gfSchema } = this.getCtAndGfSchema();
let missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow;
let missingCtRefs,
missingGfRefs,
missingEntryRefs,
missingCtRefsInExtensions,
missingCtRefsInWorkflow,
missingSelectFeild,
missingEntry,
missingMandatoryFields;

for (const module of this.sharedConfig.flags.modules || this.sharedConfig.modules) {
print([
{
Expand Down Expand Up @@ -129,8 +150,15 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
await this.prepareReport(module, missingGfRefs);
break;
case 'entries':
missingEntryRefs = await new Entries(cloneDeep(constructorParam)).run();
missingEntry = await new Entries(cloneDeep(constructorParam)).run();
missingEntryRefs = missingEntry.missingEntryRefs ?? {};
missingSelectFeild = missingEntry.missingSelectFeild ?? {};
missingMandatoryFields = missingEntry.missingMandatoryFields ?? {};
await this.prepareReport(module, missingEntryRefs);

await this.prepareReport(`Entries_Select_feild`, missingSelectFeild);

await this.prepareReport('Entries_Mandatory_feild', missingMandatoryFields);
break;
case 'workflows':
missingCtRefsInWorkflow = await new Workflows({
Expand Down Expand Up @@ -162,7 +190,15 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
]);
}

return { missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow };
return {
missingCtRefs,
missingGfRefs,
missingEntryRefs,
missingCtRefsInExtensions,
missingCtRefsInWorkflow,
missingSelectFeild,
missingMandatoryFields,
};
}

/**
Expand Down Expand Up @@ -297,26 +333,31 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
}
this.log(''); // Adding a new line

for (const { module, missingRefs } of allMissingRefs) {
for (let { module, missingRefs } of allMissingRefs) {
if (isEmpty(missingRefs)) {
continue;
}

print([{ bold: true, color: 'cyan', message: ` ${module}` }]);

const tableValues = Object.values(missingRefs).flat();

missingRefs = Object.values(missingRefs).flat();
const tableKeys = Object.keys(missingRefs[0]);
const arrayOfObjects = tableKeys.map((key) => {
if (['title', 'name', 'uid', 'content_types', 'branches', 'fixStatus'].includes(key)) {
if (config.OutputTableKeys.includes(key)) {
return {
[key]: {
minWidth: 7,
header: key,
get: (row: Record<string, unknown>) => {
if (key === 'fixStatus') {
return chalk.green(typeof row[key] === 'object' ? JSON.stringify(row[key]) : row[key]);
} else if (key === 'content_types' || key === 'branches') {
} else if (
key === 'content_types' ||
key === 'branches' ||
key === 'missingCTSelectFieldValues' ||
key === 'missingFieldUid'
) {
return chalk.red(typeof row[key] === 'object' ? JSON.stringify(row[key]) : row[key]);
} else {
return chalk.white(typeof row[key] === 'object' ? JSON.stringify(row[key]) : row[key]);
Expand Down Expand Up @@ -344,7 +385,10 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
* reference name and the value represents additional information about the missing reference.
* @returns The function `prepareReport` returns a Promise that resolves to `void`.
*/
prepareReport(moduleName: keyof typeof config.moduleConfig, listOfMissingRefs: Record<string, any>): Promise<void> {
prepareReport(
moduleName: keyof typeof config.moduleConfig | keyof typeof config.ReportTitleForEntries,
listOfMissingRefs: Record<string, any>,
): Promise<void> {
if (isEmpty(listOfMissingRefs)) return Promise.resolve(void 0);

if (!existsSync(this.sharedConfig.reportPath)) {
Expand All @@ -368,7 +412,10 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
* corresponding value is an array of objects that contain details about the missing reference.
* @returns The function `prepareCSV` returns a Promise that resolves to `void`.
*/
prepareCSV(moduleName: keyof typeof config.moduleConfig, listOfMissingRefs: Record<string, any>): Promise<void> {
prepareCSV(
moduleName: keyof typeof config.moduleConfig | keyof typeof config.ReportTitleForEntries,
listOfMissingRefs: Record<string, any>,
): Promise<void> {
const csvPath = join(this.sharedConfig.reportPath, `${moduleName}.csv`);

return new Promise<void>((resolve, reject) => {
Expand Down
22 changes: 22 additions & 0 deletions packages/contentstack-audit/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,28 @@ const config = {
'publish_details',
],
},
//These keys will be used output the modules with issues and fixes on console
OutputTableKeys: [
'title',
'name',
'uid',
'content_types',
'branches',
'fixStatus',
'tree',
'display_name',
'display_type',
'missingRefs',
'treeStr',
'missingCTSelectFieldValues',
'min_instance',
'missingFieldUid',
'isPublished',
],
ReportTitleForEntries: {
Entries_Select_feild: 'Entries_Select_feild',
Entries_Mandatory_feild: 'Entries_Mandatory_feild',
},
};

export default config;
2 changes: 2 additions & 0 deletions packages/contentstack-audit/src/messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const auditFixMsg = {
EMPTY_FIX_MSG: 'Successfully removed the empty field/block found at {path} from the schema.',
AUDIT_FIX_CMD_DESCRIPTION: 'Perform audits and fix possible errors in the exported Contentstack data.',
WF_FIX_MSG: 'Successfully removed the workflow {uid} named {name}.',
ENTRY_MANDATORY_FIELD_FIX: `Removing the publish details from entry uid '{uid}' from locale '{locale}'`,
ENTRY_SELECT_FIELD_FIX: `Adding the value '{value}' in select field of uid '{uid}'`
};

const messages: typeof errors &
Expand Down
4 changes: 2 additions & 2 deletions packages/contentstack-audit/src/modules/content-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ export default class ContentType {
...this.validateReferenceField(
[...tree, { uid: field.uid, name: child.display_name }],
child as ReferenceFieldDataType,
),
);
),
);
break;
case 'global_field':
await this.validateGlobalField(
Expand Down
Loading