@contentstack/cli-audit 1.17.0 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +10 -431
- package/lib/audit-base-command.d.ts +4 -1
- package/lib/audit-base-command.js +85 -54
- package/lib/commands/cm/stacks/audit/fix.d.ts +0 -1
- package/lib/commands/cm/stacks/audit/fix.js +0 -1
- package/lib/commands/cm/stacks/audit/index.d.ts +0 -1
- package/lib/commands/cm/stacks/audit/index.js +0 -1
- package/lib/config/index.d.ts +0 -5
- package/lib/config/index.js +9 -16
- package/lib/messages/index.d.ts +0 -1
- package/lib/messages/index.js +1 -2
- package/lib/modules/assets.d.ts +6 -4
- package/lib/modules/assets.js +51 -30
- package/lib/modules/base-class.d.ts +24 -0
- package/lib/modules/base-class.js +54 -0
- package/lib/modules/content-types.d.ts +6 -4
- package/lib/modules/content-types.js +62 -40
- package/lib/modules/custom-roles.d.ts +4 -4
- package/lib/modules/custom-roles.js +82 -61
- package/lib/modules/entries.d.ts +5 -4
- package/lib/modules/entries.js +190 -168
- package/lib/modules/extensions.d.ts +4 -4
- package/lib/modules/extensions.js +78 -58
- package/lib/modules/field_rules.d.ts +4 -4
- package/lib/modules/field_rules.js +69 -52
- package/lib/modules/global-fields.d.ts +3 -1
- package/lib/modules/global-fields.js +4 -2
- package/lib/modules/index.d.ts +2 -2
- package/lib/modules/index.js +3 -3
- package/lib/modules/modulesData.js +8 -17
- package/lib/modules/workflows.d.ts +4 -4
- package/lib/modules/workflows.js +85 -68
- package/lib/types/content-types.d.ts +1 -2
- package/lib/types/content-types.js +0 -1
- package/lib/types/context.d.ts +5 -0
- package/oclif.manifest.json +5 -13
- package/package.json +4 -6
- package/lib/modules/composable-studio.d.ts +0 -40
- package/lib/modules/composable-studio.js +0 -307
- package/lib/types/composable-studio.d.ts +0 -25
- package/lib/types/composable-studio.js +0 -2
|
@@ -33,6 +33,19 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
33
33
|
},
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Create audit context object similar to export command
|
|
38
|
+
*/
|
|
39
|
+
createAuditContext(moduleName) {
|
|
40
|
+
var _a, _b, _c;
|
|
41
|
+
return {
|
|
42
|
+
command: ((_b = (_a = this.context) === null || _a === void 0 ? void 0 : _a.info) === null || _b === void 0 ? void 0 : _b.command) || 'cm:stacks:audit',
|
|
43
|
+
module: moduleName || 'audit',
|
|
44
|
+
email: cli_utilities_1.configHandler.get('email') || '',
|
|
45
|
+
sessionId: ((_c = this.context) === null || _c === void 0 ? void 0 : _c.sessionId) || '',
|
|
46
|
+
authenticationMethod: cli_utilities_1.configHandler.get('authenticationMethod') || '',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
36
49
|
/**
|
|
37
50
|
* The `start` function performs an audit on content types, global fields, entries, and workflows and displays
|
|
38
51
|
* any missing references.
|
|
@@ -40,19 +53,27 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
40
53
|
* being executed.
|
|
41
54
|
*/
|
|
42
55
|
async start(command) {
|
|
43
|
-
var _a, _b;
|
|
44
56
|
this.currentCommand = command;
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
// Set progress supported module and console logs setting BEFORE any log calls
|
|
58
|
+
// This ensures the logger respects the setting when it's initialized
|
|
59
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
60
|
+
// Default to false so progress bars are shown instead of console logs
|
|
61
|
+
if (logConfig.showConsoleLogs === undefined) {
|
|
62
|
+
cli_utilities_1.configHandler.set('log.showConsoleLogs', false);
|
|
63
|
+
}
|
|
64
|
+
cli_utilities_1.configHandler.set('log.progressSupportedModule', 'audit');
|
|
65
|
+
// Initialize audit context
|
|
66
|
+
this.auditContext = this.createAuditContext();
|
|
48
67
|
cli_utilities_1.log.debug(`Starting audit command: ${command}`, this.auditContext);
|
|
49
68
|
cli_utilities_1.log.info(`Starting audit command: ${command}`, this.auditContext);
|
|
69
|
+
// Initialize global summary for progress tracking
|
|
70
|
+
cli_utilities_1.CLIProgressManager.initializeGlobalSummary('AUDIT', '', 'Auditing content...');
|
|
50
71
|
await this.promptQueue();
|
|
51
72
|
await this.createBackUp();
|
|
52
73
|
this.sharedConfig.reportPath = (0, path_1.resolve)(this.flags['report-path'] || process.cwd(), 'audit-report');
|
|
53
74
|
cli_utilities_1.log.debug(`Data directory: ${this.flags['data-dir']}`, this.auditContext);
|
|
54
75
|
cli_utilities_1.log.debug(`Report path: ${this.flags['report-path'] || process.cwd()}`, this.auditContext);
|
|
55
|
-
const { missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow, missingSelectFeild, missingMandatoryFields, missingTitleFields, missingRefInCustomRoles, missingEnvLocalesInAssets, missingEnvLocalesInEntries, missingFieldRules, missingMultipleFields,
|
|
76
|
+
const { missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow, missingSelectFeild, missingMandatoryFields, missingTitleFields, missingRefInCustomRoles, missingEnvLocalesInAssets, missingEnvLocalesInEntries, missingFieldRules, missingMultipleFields, } = await this.scanAndFix();
|
|
56
77
|
if (this.flags['show-console-output']) {
|
|
57
78
|
this.showOutputOnScreen([
|
|
58
79
|
{ module: 'Content types', missingRefs: missingCtRefs },
|
|
@@ -79,7 +100,6 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
79
100
|
this.showOutputOnScreenWorkflowsAndExtension([
|
|
80
101
|
{ module: 'Entries Changed Multiple Fields', missingRefs: missingMultipleFields },
|
|
81
102
|
]);
|
|
82
|
-
this.showOutputOnScreenWorkflowsAndExtension([{ module: 'Studio', missingRefs: missingRefsInComposableStudio }]);
|
|
83
103
|
}
|
|
84
104
|
this.showOutputOnScreenWorkflowsAndExtension([{ module: 'Summary', missingRefs: this.summaryDataToPrint }]);
|
|
85
105
|
if (!(0, isEmpty_1.default)(missingCtRefs) ||
|
|
@@ -93,8 +113,7 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
93
113
|
!(0, isEmpty_1.default)(missingEnvLocalesInAssets) ||
|
|
94
114
|
!(0, isEmpty_1.default)(missingEnvLocalesInEntries) ||
|
|
95
115
|
!(0, isEmpty_1.default)(missingFieldRules) ||
|
|
96
|
-
!(0, isEmpty_1.default)(missingMultipleFields)
|
|
97
|
-
!(0, isEmpty_1.default)(missingRefsInComposableStudio)) {
|
|
116
|
+
!(0, isEmpty_1.default)(missingMultipleFields)) {
|
|
98
117
|
if (this.currentCommand === 'cm:stacks:audit') {
|
|
99
118
|
cli_utilities_1.log.warn(this.$t(messages_1.auditMsg.FINAL_REPORT_PATH, { path: this.sharedConfig.reportPath }), this.auditContext);
|
|
100
119
|
}
|
|
@@ -112,6 +131,10 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
112
131
|
(0, fs_1.rmSync)(this.sharedConfig.basePath, { recursive: true });
|
|
113
132
|
}
|
|
114
133
|
}
|
|
134
|
+
// Print comprehensive summary at the end
|
|
135
|
+
cli_utilities_1.CLIProgressManager.printGlobalSummary();
|
|
136
|
+
// Clear progress module setting now that audit is complete
|
|
137
|
+
(0, cli_utilities_1.clearProgressModuleSetting)();
|
|
115
138
|
return (!(0, isEmpty_1.default)(missingCtRefs) ||
|
|
116
139
|
!(0, isEmpty_1.default)(missingGfRefs) ||
|
|
117
140
|
!(0, isEmpty_1.default)(missingEntryRefs) ||
|
|
@@ -121,8 +144,7 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
121
144
|
!(0, isEmpty_1.default)(missingRefInCustomRoles) ||
|
|
122
145
|
!(0, isEmpty_1.default)(missingEnvLocalesInAssets) ||
|
|
123
146
|
!(0, isEmpty_1.default)(missingEnvLocalesInEntries) ||
|
|
124
|
-
!(0, isEmpty_1.default)(missingFieldRules)
|
|
125
|
-
!(0, isEmpty_1.default)(missingRefsInComposableStudio));
|
|
147
|
+
!(0, isEmpty_1.default)(missingFieldRules));
|
|
126
148
|
}
|
|
127
149
|
/**
|
|
128
150
|
* The `scan` function performs an audit on different modules (content-types, global-fields, and
|
|
@@ -131,11 +153,11 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
131
153
|
* and `missingEntryRefs`.
|
|
132
154
|
*/
|
|
133
155
|
async scanAndFix() {
|
|
134
|
-
var _a, _b, _c, _d, _e, _f;
|
|
156
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
135
157
|
cli_utilities_1.log.debug('Starting scan and fix process', this.auditContext);
|
|
136
158
|
let { ctSchema, gfSchema } = this.getCtAndGfSchema();
|
|
137
159
|
cli_utilities_1.log.info(`Retrieved ${(ctSchema === null || ctSchema === void 0 ? void 0 : ctSchema.length) || 0} content types and ${(gfSchema === null || gfSchema === void 0 ? void 0 : gfSchema.length) || 0} global fields`, this.auditContext);
|
|
138
|
-
let missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow, missingSelectFeild, missingEntry = {}, missingMandatoryFields, missingTitleFields, missingRefInCustomRoles, missingEnvLocalesInAssets, missingEnvLocalesInEntries, missingFieldRules, missingMultipleFields
|
|
160
|
+
let missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow, missingSelectFeild, missingEntry = {}, missingMandatoryFields, missingTitleFields, missingRefInCustomRoles, missingEnvLocalesInAssets, missingEnvLocalesInEntries, missingFieldRules, missingMultipleFields;
|
|
139
161
|
const constructorParam = {
|
|
140
162
|
ctSchema,
|
|
141
163
|
gfSchema,
|
|
@@ -144,50 +166,60 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
144
166
|
};
|
|
145
167
|
let dataModuleWise = await new modules_1.ModuleDataReader((0, cloneDeep_1.default)(constructorParam)).run();
|
|
146
168
|
cli_utilities_1.log.debug(`Data module wise: ${JSON.stringify(dataModuleWise)}`, this.auditContext);
|
|
169
|
+
// Extract logConfig and showConsoleLogs once before the loop to reuse throughout
|
|
170
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
171
|
+
const showConsoleLogs = (_a = logConfig.showConsoleLogs) !== null && _a !== void 0 ? _a : true;
|
|
147
172
|
for (const module of this.sharedConfig.flags.modules || this.sharedConfig.modules) {
|
|
148
173
|
// Update audit context with current module
|
|
149
|
-
this.auditContext =
|
|
174
|
+
this.auditContext = this.createAuditContext(module);
|
|
150
175
|
cli_utilities_1.log.debug(`Starting audit for module: ${module}`, this.auditContext);
|
|
151
176
|
cli_utilities_1.log.info(`Starting audit for module: ${module}`, this.auditContext);
|
|
152
|
-
(
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
177
|
+
// Only show spinner message if console logs are enabled (compatible with line-by-line logs)
|
|
178
|
+
if (showConsoleLogs) {
|
|
179
|
+
(0, log_1.print)([
|
|
180
|
+
{
|
|
181
|
+
bold: true,
|
|
182
|
+
color: 'whiteBright',
|
|
183
|
+
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
|
|
184
|
+
},
|
|
185
|
+
]);
|
|
186
|
+
}
|
|
159
187
|
constructorParam['moduleName'] = module;
|
|
160
188
|
switch (module) {
|
|
161
189
|
case 'assets':
|
|
162
190
|
cli_utilities_1.log.info('Executing assets audit', this.auditContext);
|
|
163
|
-
|
|
191
|
+
const assetsTotalCount = ((_b = dataModuleWise['assets']) === null || _b === void 0 ? void 0 : _b.Total) || 0;
|
|
192
|
+
missingEnvLocalesInAssets = await new modules_1.Assets((0, cloneDeep_1.default)(constructorParam)).run(false, assetsTotalCount);
|
|
164
193
|
await this.prepareReport(module, missingEnvLocalesInAssets);
|
|
165
194
|
this.getAffectedData('assets', dataModuleWise['assets'], missingEnvLocalesInAssets);
|
|
166
195
|
cli_utilities_1.log.success(`Assets audit completed. Found ${Object.keys(missingEnvLocalesInAssets || {}).length} issues`, this.auditContext);
|
|
167
196
|
break;
|
|
168
197
|
case 'content-types':
|
|
169
198
|
cli_utilities_1.log.info('Executing content-types audit', this.auditContext);
|
|
170
|
-
|
|
199
|
+
const contentTypesTotalCount = ((_c = dataModuleWise['content-types']) === null || _c === void 0 ? void 0 : _c.Total) || 0;
|
|
200
|
+
missingCtRefs = await new modules_1.ContentType((0, cloneDeep_1.default)(constructorParam)).run(false, contentTypesTotalCount);
|
|
171
201
|
await this.prepareReport(module, missingCtRefs);
|
|
172
202
|
this.getAffectedData('content-types', dataModuleWise['content-types'], missingCtRefs);
|
|
173
203
|
cli_utilities_1.log.success(`Content-types audit completed. Found ${Object.keys(missingCtRefs || {}).length} issues`, this.auditContext);
|
|
174
204
|
break;
|
|
175
205
|
case 'global-fields':
|
|
176
206
|
cli_utilities_1.log.info('Executing global-fields audit', this.auditContext);
|
|
177
|
-
|
|
207
|
+
const globalFieldsTotalCount = ((_d = dataModuleWise['global-fields']) === null || _d === void 0 ? void 0 : _d.Total) || 0;
|
|
208
|
+
missingGfRefs = await new modules_1.GlobalField((0, cloneDeep_1.default)(constructorParam)).run(false, globalFieldsTotalCount);
|
|
178
209
|
await this.prepareReport(module, missingGfRefs);
|
|
179
210
|
this.getAffectedData('global-fields', dataModuleWise['global-fields'], missingGfRefs);
|
|
180
211
|
cli_utilities_1.log.success(`Global-fields audit completed. Found ${Object.keys(missingGfRefs || {}).length} issues`, this.auditContext);
|
|
181
212
|
break;
|
|
182
213
|
case 'entries':
|
|
183
214
|
cli_utilities_1.log.info('Executing entries audit', this.auditContext);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
215
|
+
const entriesTotalCount = ((_e = dataModuleWise['entries']) === null || _e === void 0 ? void 0 : _e.Total) || 0;
|
|
216
|
+
missingEntry = await new modules_1.Entries((0, cloneDeep_1.default)(constructorParam)).run(entriesTotalCount);
|
|
217
|
+
missingEntryRefs = (_f = missingEntry.missingEntryRefs) !== null && _f !== void 0 ? _f : {};
|
|
218
|
+
missingSelectFeild = (_g = missingEntry.missingSelectFeild) !== null && _g !== void 0 ? _g : {};
|
|
219
|
+
missingMandatoryFields = (_h = missingEntry.missingMandatoryFields) !== null && _h !== void 0 ? _h : {};
|
|
220
|
+
missingTitleFields = (_j = missingEntry.missingTitleFields) !== null && _j !== void 0 ? _j : {};
|
|
221
|
+
missingEnvLocalesInEntries = (_k = missingEntry.missingEnvLocale) !== null && _k !== void 0 ? _k : {};
|
|
222
|
+
missingMultipleFields = (_l = missingEntry.missingMultipleFields) !== null && _l !== void 0 ? _l : {};
|
|
191
223
|
await this.prepareReport(module, missingEntryRefs);
|
|
192
224
|
await this.prepareReport(`Entries_Select_field`, missingSelectFeild);
|
|
193
225
|
await this.prepareReport('Entries_Mandatory_field', missingMandatoryFields);
|
|
@@ -199,26 +231,29 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
199
231
|
break;
|
|
200
232
|
case 'workflows':
|
|
201
233
|
cli_utilities_1.log.info('Executing workflows audit', this.auditContext);
|
|
234
|
+
const workflowsTotalCount = ((_m = dataModuleWise['workflows']) === null || _m === void 0 ? void 0 : _m.Total) || 0;
|
|
202
235
|
missingCtRefsInWorkflow = await new modules_1.Workflows({
|
|
203
236
|
ctSchema,
|
|
204
237
|
moduleName: module,
|
|
205
238
|
config: this.sharedConfig,
|
|
206
239
|
fix: this.currentCommand === 'cm:stacks:audit:fix',
|
|
207
|
-
}).run();
|
|
240
|
+
}).run(workflowsTotalCount);
|
|
208
241
|
await this.prepareReport(module, missingCtRefsInWorkflow);
|
|
209
242
|
this.getAffectedData('workflows', dataModuleWise['workflows'], missingCtRefsInWorkflow);
|
|
210
243
|
cli_utilities_1.log.success(`Workflows audit completed. Found ${Object.keys(missingCtRefsInWorkflow || {}).length} issues`, this.auditContext);
|
|
211
244
|
break;
|
|
212
245
|
case 'extensions':
|
|
213
246
|
cli_utilities_1.log.info('Executing extensions audit', this.auditContext);
|
|
214
|
-
|
|
247
|
+
const extensionsTotalCount = ((_o = dataModuleWise['extensions']) === null || _o === void 0 ? void 0 : _o.Total) || 0;
|
|
248
|
+
missingCtRefsInExtensions = await new modules_1.Extensions((0, cloneDeep_1.default)(constructorParam)).run(extensionsTotalCount);
|
|
215
249
|
await this.prepareReport(module, missingCtRefsInExtensions);
|
|
216
250
|
this.getAffectedData('extensions', dataModuleWise['extensions'], missingCtRefsInExtensions);
|
|
217
251
|
cli_utilities_1.log.success(`Extensions audit completed. Found ${Object.keys(missingCtRefsInExtensions || {}).length} issues`, this.auditContext);
|
|
218
252
|
break;
|
|
219
253
|
case 'custom-roles':
|
|
220
254
|
cli_utilities_1.log.info('Executing custom-roles audit', this.auditContext);
|
|
221
|
-
|
|
255
|
+
const customRolesTotalCount = ((_p = dataModuleWise['custom-roles']) === null || _p === void 0 ? void 0 : _p.Total) || 0;
|
|
256
|
+
missingRefInCustomRoles = await new modules_1.CustomRoles((0, cloneDeep_1.default)(constructorParam)).run(customRolesTotalCount);
|
|
222
257
|
await this.prepareReport(module, missingRefInCustomRoles);
|
|
223
258
|
this.getAffectedData('custom-roles', dataModuleWise['custom-roles'], missingRefInCustomRoles);
|
|
224
259
|
cli_utilities_1.log.success(`Custom-roles audit completed. Found ${Object.keys(missingRefInCustomRoles || {}).length} issues`, this.auditContext);
|
|
@@ -229,31 +264,28 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
229
264
|
const data = this.getCtAndGfSchema();
|
|
230
265
|
constructorParam.ctSchema = data.ctSchema;
|
|
231
266
|
constructorParam.gfSchema = data.gfSchema;
|
|
232
|
-
|
|
267
|
+
const fieldRulesTotalCount = ((_q = dataModuleWise['content-types']) === null || _q === void 0 ? void 0 : _q.Total) || 0;
|
|
268
|
+
missingFieldRules = await new modules_1.FieldRule((0, cloneDeep_1.default)(constructorParam)).run(fieldRulesTotalCount);
|
|
233
269
|
await this.prepareReport(module, missingFieldRules);
|
|
234
270
|
this.getAffectedData('field-rules', dataModuleWise['content-types'], missingFieldRules);
|
|
235
271
|
cli_utilities_1.log.success(`Field-rules audit completed. Found ${Object.keys(missingFieldRules || {}).length} issues`, this.auditContext);
|
|
236
272
|
break;
|
|
237
|
-
case 'composable-studio':
|
|
238
|
-
cli_utilities_1.log.info('Executing composable-studio audit', this.auditContext);
|
|
239
|
-
missingRefsInComposableStudio = await new modules_1.ComposableStudio((0, cloneDeep_1.default)(constructorParam)).run();
|
|
240
|
-
await this.prepareReport(module, missingRefsInComposableStudio);
|
|
241
|
-
this.getAffectedData('composable-studio', dataModuleWise['composable-studio'] || { Total: Object.keys(missingRefsInComposableStudio || {}).length }, missingRefsInComposableStudio);
|
|
242
|
-
cli_utilities_1.log.success(`Composable-studio audit completed. Found ${Object.keys(missingRefsInComposableStudio || {}).length} issues`, this.auditContext);
|
|
243
|
-
break;
|
|
244
273
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
274
|
+
// Only show completion message if console logs are enabled
|
|
275
|
+
if (showConsoleLogs) {
|
|
276
|
+
(0, log_1.print)([
|
|
277
|
+
{
|
|
278
|
+
bold: true,
|
|
279
|
+
color: 'whiteBright',
|
|
280
|
+
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
bold: true,
|
|
284
|
+
message: ' done',
|
|
285
|
+
color: 'whiteBright',
|
|
286
|
+
},
|
|
287
|
+
]);
|
|
288
|
+
}
|
|
257
289
|
}
|
|
258
290
|
cli_utilities_1.log.debug('Scan and fix process completed', this.auditContext);
|
|
259
291
|
this.prepareReport('Summary', this.summaryDataToPrint);
|
|
@@ -272,7 +304,6 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
272
304
|
missingEnvLocalesInEntries,
|
|
273
305
|
missingFieldRules,
|
|
274
306
|
missingMultipleFields,
|
|
275
|
-
missingRefsInComposableStudio,
|
|
276
307
|
};
|
|
277
308
|
}
|
|
278
309
|
/**
|
|
@@ -2,7 +2,6 @@ import { FlagInput } from '@contentstack/cli-utilities';
|
|
|
2
2
|
import { ConfigType } from '../../../../types';
|
|
3
3
|
import { AuditBaseCommand } from '../../../../audit-base-command';
|
|
4
4
|
export default class AuditFix extends AuditBaseCommand {
|
|
5
|
-
static aliases: string[];
|
|
6
5
|
static description: string;
|
|
7
6
|
static examples: string[];
|
|
8
7
|
static flags: FlagInput;
|
|
@@ -27,7 +27,6 @@ class AuditFix extends audit_base_command_1.AuditBaseCommand {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
AuditFix.aliases = ['audit:fix', 'cm:stacks:audit:fix'];
|
|
31
30
|
AuditFix.description = messages_1.auditFixMsg.AUDIT_FIX_CMD_DESCRIPTION;
|
|
32
31
|
AuditFix.examples = [
|
|
33
32
|
'$ <%= config.bin %> <%= command.id %> --copy-dir',
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { FlagInput } from '@contentstack/cli-utilities';
|
|
2
2
|
import { AuditBaseCommand } from '../../../../audit-base-command';
|
|
3
3
|
export default class Audit extends AuditBaseCommand {
|
|
4
|
-
static aliases: string[];
|
|
5
4
|
static description: string;
|
|
6
5
|
static examples: string[];
|
|
7
6
|
static flags: FlagInput;
|
package/lib/config/index.d.ts
CHANGED
package/lib/config/index.js
CHANGED
|
@@ -13,7 +13,6 @@ const config = {
|
|
|
13
13
|
'custom-roles',
|
|
14
14
|
'assets',
|
|
15
15
|
'field-rules',
|
|
16
|
-
'composable-studio',
|
|
17
16
|
],
|
|
18
17
|
'fix-fields': ['reference', 'global_field', 'json:rte', 'json:extension', 'blocks', 'group', 'content_types'],
|
|
19
18
|
'schema-fields-data-type': ['blocks', 'group', 'global_field'],
|
|
@@ -63,11 +62,6 @@ const config = {
|
|
|
63
62
|
dirName: 'environments',
|
|
64
63
|
fileName: 'environments.json',
|
|
65
64
|
},
|
|
66
|
-
'composable-studio': {
|
|
67
|
-
name: 'composable-studio',
|
|
68
|
-
dirName: 'composable_studio',
|
|
69
|
-
fileName: 'composable_studio.json',
|
|
70
|
-
},
|
|
71
65
|
},
|
|
72
66
|
entries: {
|
|
73
67
|
systemKeys: [
|
|
@@ -115,14 +109,13 @@ const config = {
|
|
|
115
109
|
'selectedValue',
|
|
116
110
|
'ct_uid',
|
|
117
111
|
'action',
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
'issues',
|
|
112
|
+
"Module",
|
|
113
|
+
"Total",
|
|
114
|
+
"Fixable",
|
|
115
|
+
"Non-Fixable",
|
|
116
|
+
"Fixed",
|
|
117
|
+
"Not-Fixed",
|
|
118
|
+
"Passed",
|
|
126
119
|
],
|
|
127
120
|
ReportTitleForEntries: {
|
|
128
121
|
Entries_Select_field: 'Entries_Select_field',
|
|
@@ -130,7 +123,7 @@ const config = {
|
|
|
130
123
|
Entries_Title_field: 'Entries_Title_field',
|
|
131
124
|
Entry_Missing_Locale_and_Env: 'Entry_Missing_Locale_and_Env',
|
|
132
125
|
Entry_Missing_Locale_and_Env_in_Publish_Details: 'Entry_Missing_Locale_and_Env_in_Publish_Details',
|
|
133
|
-
Entry_Multiple_Fields:
|
|
126
|
+
Entry_Multiple_Fields: "Entry_Multiple_Fields"
|
|
134
127
|
},
|
|
135
128
|
feild_level_modules: [
|
|
136
129
|
'Entries_Title_field',
|
|
@@ -139,7 +132,7 @@ const config = {
|
|
|
139
132
|
'Entry_Missing_Locale_and_Env_in_Publish_Details',
|
|
140
133
|
'field-rules',
|
|
141
134
|
'Entry_Multiple_Fields',
|
|
142
|
-
'Summary'
|
|
135
|
+
'Summary'
|
|
143
136
|
],
|
|
144
137
|
fixSelectField: false,
|
|
145
138
|
};
|
package/lib/messages/index.d.ts
CHANGED
package/lib/messages/index.js
CHANGED
|
@@ -42,7 +42,6 @@ const auditMsg = {
|
|
|
42
42
|
AUDIT_CMD_DESCRIPTION: 'Perform audits and find possible errors in the exported Contentstack data',
|
|
43
43
|
SCAN_WF_SUCCESS_MSG: 'Successfully completed the scanning of workflow with UID {uid} and name {name}.',
|
|
44
44
|
SCAN_CR_SUCCESS_MSG: 'Successfully completed the scanning of custom role with UID {uid} and name {name}.',
|
|
45
|
-
SCAN_CS_SUCCESS_MSG: 'Successfully completed the scanning of studio project with UID {uid} and name {name}.',
|
|
46
45
|
SCAN_ASSET_SUCCESS_MSG: `Successfully completed the scanning of Asset with UID '{uid}'.`,
|
|
47
46
|
SCAN_ASSET_WARN_MSG: `The locale '{locale}' or environment '{environment}' are not present for asset with uid '{uid}'`,
|
|
48
47
|
ENTRY_PUBLISH_DETAILS: `Removing the publish detials for entry '{uid}' of ct '{ctuid}' in locale '{locale}' as locale '{publocale}' or environment '{environment}' does not exist`,
|
|
@@ -52,7 +51,7 @@ const auditMsg = {
|
|
|
52
51
|
FIELD_RULE_CONDITION_ABSENT: `The operand field '{condition_field}' is not present in the schema of the content-type {ctUid}`,
|
|
53
52
|
FIELD_RULE_TARGET_ABSENT: `The target field '{target_field}' is not present in the schema of the content-type {ctUid}`,
|
|
54
53
|
FIELD_RULE_CONDITION_SCAN_MESSAGE: `Completed Scanning of Field Rule '{num}' condition of Content-type '{ctUid}'`,
|
|
55
|
-
FIELD_RULE_TARGET_SCAN_MESSAGE: `Completed Scanning of Field Rule '{num}' target of Content-type '{ctUid}'
|
|
54
|
+
FIELD_RULE_TARGET_SCAN_MESSAGE: `Completed Scanning of Field Rule '{num}' target of Content-type '{ctUid}'`
|
|
56
55
|
};
|
|
57
56
|
exports.auditMsg = auditMsg;
|
|
58
57
|
const auditFixMsg = {
|
package/lib/modules/assets.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ContentTypeStruct, CtConstructorParam, ModuleConstructorParam, EntryStruct } from '../types';
|
|
2
2
|
import auditConfig from '../config';
|
|
3
|
-
|
|
3
|
+
import BaseClass from './base-class';
|
|
4
|
+
export default class Assets extends BaseClass {
|
|
4
5
|
protected fix: boolean;
|
|
5
6
|
fileName: string;
|
|
6
|
-
config: ConfigType;
|
|
7
7
|
folderPath: string;
|
|
8
8
|
currentUid: string;
|
|
9
9
|
currentTitle: string;
|
|
@@ -18,9 +18,11 @@ export default class Assets {
|
|
|
18
18
|
/**
|
|
19
19
|
* The `run` function checks if a folder path exists, sets the schema based on the module name,
|
|
20
20
|
* iterates over the schema and looks for references, and returns a list of missing references.
|
|
21
|
+
* @param returnFixSchema - If true, returns the fixed schema instead of missing references
|
|
22
|
+
* @param totalCount - Total number of assets to process (for progress tracking)
|
|
21
23
|
* @returns the `missingEnvLocales` object.
|
|
22
24
|
*/
|
|
23
|
-
run(returnFixSchema?: boolean): Promise<Record<string, any> | ContentTypeStruct[]>;
|
|
25
|
+
run(returnFixSchema?: boolean, totalCount?: number): Promise<Record<string, any> | ContentTypeStruct[]>;
|
|
24
26
|
/**
|
|
25
27
|
* @method prerequisiteData
|
|
26
28
|
* The `prerequisiteData` function reads and parses JSON files to retrieve extension and marketplace
|
package/lib/modules/assets.js
CHANGED
|
@@ -7,15 +7,16 @@ const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
|
7
7
|
const messages_1 = require("../messages");
|
|
8
8
|
const values_1 = tslib_1.__importDefault(require("lodash/values"));
|
|
9
9
|
const lodash_1 = require("lodash");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
11
|
+
/* The `Assets` class is responsible for scanning assets, looking for missing environment/locale references,
|
|
12
|
+
and generating a report in JSON and CSV formats. */
|
|
13
|
+
class Assets extends base_class_1.default {
|
|
13
14
|
constructor({ fix, config, moduleName }) {
|
|
15
|
+
super({ config });
|
|
14
16
|
this.locales = [];
|
|
15
17
|
this.environments = [];
|
|
16
18
|
this.schema = [];
|
|
17
19
|
this.missingEnvLocales = {};
|
|
18
|
-
this.config = config;
|
|
19
20
|
this.fix = fix !== null && fix !== void 0 ? fix : false;
|
|
20
21
|
this.moduleName = this.validateModules(moduleName, this.config.moduleConfig);
|
|
21
22
|
this.fileName = config.moduleConfig[this.moduleName].fileName;
|
|
@@ -30,38 +31,54 @@ class Assets {
|
|
|
30
31
|
/**
|
|
31
32
|
* The `run` function checks if a folder path exists, sets the schema based on the module name,
|
|
32
33
|
* iterates over the schema and looks for references, and returns a list of missing references.
|
|
34
|
+
* @param returnFixSchema - If true, returns the fixed schema instead of missing references
|
|
35
|
+
* @param totalCount - Total number of assets to process (for progress tracking)
|
|
33
36
|
* @returns the `missingEnvLocales` object.
|
|
34
37
|
*/
|
|
35
|
-
async run(returnFixSchema = false) {
|
|
38
|
+
async run(returnFixSchema = false, totalCount) {
|
|
36
39
|
var _a;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
try {
|
|
41
|
+
cli_utilities_1.log.debug(`Starting ${this.moduleName} audit process`, this.config.auditContext);
|
|
42
|
+
cli_utilities_1.log.debug(`Data directory: ${this.folderPath}`, this.config.auditContext);
|
|
43
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
44
|
+
if (!(0, fs_1.existsSync)(this.folderPath)) {
|
|
45
|
+
cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
|
|
46
|
+
cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
|
|
47
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
|
|
48
|
+
return returnFixSchema ? [] : {};
|
|
49
|
+
}
|
|
50
|
+
// Load prerequisite data with loading spinner
|
|
51
|
+
await this.withLoadingSpinner('ASSETS: Loading prerequisite data (locales and environments)...', async () => {
|
|
52
|
+
await this.prerequisiteData();
|
|
53
|
+
});
|
|
54
|
+
// Create progress manager if we have a total count
|
|
55
|
+
if (totalCount && totalCount > 0) {
|
|
56
|
+
const progress = this.createSimpleProgress(this.moduleName, totalCount);
|
|
57
|
+
progress.updateStatus('Validating asset references...');
|
|
58
|
+
}
|
|
59
|
+
cli_utilities_1.log.debug('Starting asset Reference, Environment and Locale validation', this.config.auditContext);
|
|
60
|
+
await this.lookForReference();
|
|
61
|
+
if (returnFixSchema) {
|
|
62
|
+
cli_utilities_1.log.debug(`Returning fixed schema with ${((_a = this.schema) === null || _a === void 0 ? void 0 : _a.length) || 0} items`, this.config.auditContext);
|
|
63
|
+
return this.schema;
|
|
64
|
+
}
|
|
65
|
+
cli_utilities_1.log.debug('Cleaning up empty missing environment/locale references', this.config.auditContext);
|
|
66
|
+
for (let propName in this.missingEnvLocales) {
|
|
67
|
+
if (Array.isArray(this.missingEnvLocales[propName])) {
|
|
68
|
+
if (!this.missingEnvLocales[propName].length) {
|
|
69
|
+
delete this.missingEnvLocales[propName];
|
|
70
|
+
}
|
|
59
71
|
}
|
|
60
72
|
}
|
|
73
|
+
const totalIssues = Object.keys(this.missingEnvLocales).length;
|
|
74
|
+
cli_utilities_1.log.debug(`${this.moduleName} audit completed. Found ${totalIssues} assets with missing environment/locale references`, this.config.auditContext);
|
|
75
|
+
this.completeProgress(true);
|
|
76
|
+
return this.missingEnvLocales;
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Assets audit failed');
|
|
80
|
+
throw error;
|
|
61
81
|
}
|
|
62
|
-
const totalIssues = Object.keys(this.missingEnvLocales).length;
|
|
63
|
-
cli_utilities_1.log.debug(`${this.moduleName} audit completed. Found ${totalIssues} assets with missing environment/locale references`, this.config.auditContext);
|
|
64
|
-
return this.missingEnvLocales;
|
|
65
82
|
}
|
|
66
83
|
/**
|
|
67
84
|
* @method prerequisiteData
|
|
@@ -182,6 +199,10 @@ class Assets {
|
|
|
182
199
|
});
|
|
183
200
|
const remainingPublishDetails = ((_d = this.assets[assetUid].publish_details) === null || _d === void 0 ? void 0 : _d.length) || 0;
|
|
184
201
|
cli_utilities_1.log.debug(`Asset ${assetUid} now has ${remainingPublishDetails} valid publish details`, this.config.auditContext);
|
|
202
|
+
// Track progress for each asset processed
|
|
203
|
+
if (this.progressManager) {
|
|
204
|
+
this.progressManager.tick(true, `asset: ${assetUid}`, null);
|
|
205
|
+
}
|
|
185
206
|
if (this.fix) {
|
|
186
207
|
cli_utilities_1.log.debug(`Fixing asset ${assetUid}`, this.config.auditContext);
|
|
187
208
|
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditFixMsg.ASSET_FIX, { uid: assetUid }), this.config.auditContext);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CLIProgressManager } from '@contentstack/cli-utilities';
|
|
2
|
+
import { ConfigType, ModuleConstructorParam } from '../types';
|
|
3
|
+
export default abstract class BaseClass {
|
|
4
|
+
protected progressManager: CLIProgressManager | null;
|
|
5
|
+
protected currentModuleName: string;
|
|
6
|
+
config: ConfigType;
|
|
7
|
+
constructor({ config }: ModuleConstructorParam);
|
|
8
|
+
/**
|
|
9
|
+
* Create simple progress manager
|
|
10
|
+
*/
|
|
11
|
+
protected createSimpleProgress(moduleName: string, total?: number): CLIProgressManager;
|
|
12
|
+
/**
|
|
13
|
+
* Create nested progress manager
|
|
14
|
+
*/
|
|
15
|
+
protected createNestedProgress(moduleName: string): CLIProgressManager;
|
|
16
|
+
/**
|
|
17
|
+
* Complete progress manager
|
|
18
|
+
*/
|
|
19
|
+
protected completeProgress(success?: boolean, error?: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Execute action with loading spinner (if console logs are disabled)
|
|
22
|
+
*/
|
|
23
|
+
protected withLoadingSpinner<T>(message: string, action: () => Promise<T>): Promise<T>;
|
|
24
|
+
}
|