@contentstack/cli-audit 1.14.1 → 1.15.0
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/README.md +9 -9
- package/lib/audit-base-command.d.ts +6 -1
- package/lib/audit-base-command.js +67 -14
- package/lib/base-command.d.ts +1 -4
- package/lib/base-command.js +1 -8
- package/lib/commands/cm/stacks/audit/fix.js +1 -2
- package/lib/commands/cm/stacks/audit/index.js +1 -2
- package/lib/modules/assets.d.ts +2 -3
- package/lib/modules/assets.js +71 -13
- package/lib/modules/content-types.d.ts +3 -4
- package/lib/modules/content-types.js +254 -43
- package/lib/modules/custom-roles.d.ts +2 -3
- package/lib/modules/custom-roles.js +98 -18
- package/lib/modules/entries.d.ts +3 -18
- package/lib/modules/entries.js +456 -61
- package/lib/modules/extensions.d.ts +2 -3
- package/lib/modules/extensions.js +81 -17
- package/lib/modules/field_rules.d.ts +2 -3
- package/lib/modules/field_rules.js +216 -42
- package/lib/modules/global-fields.js +18 -1
- package/lib/modules/modulesData.d.ts +2 -3
- package/lib/modules/modulesData.js +71 -9
- package/lib/modules/workflows.d.ts +2 -3
- package/lib/modules/workflows.js +98 -18
- package/lib/types/content-types.d.ts +1 -2
- package/lib/types/context.d.ts +8 -0
- package/lib/types/context.js +2 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
|
@@ -5,72 +5,134 @@ const fs_1 = require("fs");
|
|
|
5
5
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
6
|
const lodash_1 = require("lodash");
|
|
7
7
|
class ModuleDataReader {
|
|
8
|
-
constructor({
|
|
8
|
+
constructor({ config, ctSchema, gfSchema }) {
|
|
9
9
|
this.locales = [];
|
|
10
10
|
this.environments = [];
|
|
11
11
|
this.auditData = {};
|
|
12
12
|
this.schema = [];
|
|
13
|
-
this.log = log;
|
|
14
13
|
this.config = config;
|
|
15
14
|
this.ctSchema = ctSchema;
|
|
16
15
|
this.gfSchema = gfSchema;
|
|
16
|
+
cli_utilities_1.log.debug(`Initializing ModuleDataReader`, this.config.auditContext);
|
|
17
|
+
cli_utilities_1.log.debug(`Content types count: ${ctSchema.length}`, this.config.auditContext);
|
|
18
|
+
cli_utilities_1.log.debug(`Global fields count: ${gfSchema.length}`, this.config.auditContext);
|
|
17
19
|
this.folderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.basePath));
|
|
20
|
+
cli_utilities_1.log.debug(`Folder path: ${this.folderPath}`, this.config.auditContext);
|
|
21
|
+
cli_utilities_1.log.debug(`ModuleDataReader initialization completed`, this.config.auditContext);
|
|
18
22
|
}
|
|
19
23
|
async getModuleItemCount(moduleName) {
|
|
24
|
+
cli_utilities_1.log.debug(`Getting item count for module: ${moduleName}`, this.config.auditContext);
|
|
20
25
|
let count = 0;
|
|
21
26
|
switch (moduleName) {
|
|
22
27
|
case "content-types":
|
|
28
|
+
cli_utilities_1.log.debug(`Counting content types`, this.config.auditContext);
|
|
23
29
|
count = this.ctSchema.length;
|
|
30
|
+
cli_utilities_1.log.debug(`Content types count: ${count}`, this.config.auditContext);
|
|
24
31
|
break;
|
|
25
32
|
case 'global-fields':
|
|
33
|
+
cli_utilities_1.log.debug(`Counting global fields`, this.config.auditContext);
|
|
26
34
|
count = this.gfSchema.length;
|
|
35
|
+
cli_utilities_1.log.debug(`Global fields count: ${count}`, this.config.auditContext);
|
|
27
36
|
break;
|
|
28
|
-
case 'assets':
|
|
29
|
-
|
|
37
|
+
case 'assets': {
|
|
38
|
+
cli_utilities_1.log.debug(`Counting assets`, this.config.auditContext);
|
|
39
|
+
const assetsPath = (0, path_1.join)(this.folderPath, 'assets');
|
|
40
|
+
cli_utilities_1.log.debug(`Assets path: ${assetsPath}`, this.config.auditContext);
|
|
41
|
+
count = await this.readEntryAssetsModule(assetsPath, 'assets') || 0;
|
|
42
|
+
cli_utilities_1.log.debug(`Assets count: ${count}`, this.config.auditContext);
|
|
30
43
|
break;
|
|
44
|
+
}
|
|
31
45
|
case 'entries':
|
|
46
|
+
cli_utilities_1.log.debug(`Counting entries`, this.config.auditContext);
|
|
32
47
|
{
|
|
33
48
|
const localesFolderPath = (0, path_1.resolve)(this.config.basePath, this.config.moduleConfig.locales.dirName);
|
|
34
49
|
const localesPath = (0, path_1.join)(localesFolderPath, this.config.moduleConfig.locales.fileName);
|
|
35
50
|
const masterLocalesPath = (0, path_1.join)(localesFolderPath, 'master-locale.json');
|
|
51
|
+
cli_utilities_1.log.debug(`Locales folder path: ${localesFolderPath}`, this.config.auditContext);
|
|
52
|
+
cli_utilities_1.log.debug(`Locales path: ${localesPath}`, this.config.auditContext);
|
|
53
|
+
cli_utilities_1.log.debug(`Master locales path: ${masterLocalesPath}`, this.config.auditContext);
|
|
54
|
+
cli_utilities_1.log.debug(`Loading master locales`, this.config.auditContext);
|
|
36
55
|
this.locales = (0, lodash_1.values)(await this.readUsingFsModule(masterLocalesPath));
|
|
56
|
+
cli_utilities_1.log.debug(`Loaded ${this.locales.length} master locales: ${this.locales.map(locale => locale.code).join(', ')}`, this.config.auditContext);
|
|
37
57
|
if ((0, fs_1.existsSync)(localesPath)) {
|
|
58
|
+
cli_utilities_1.log.debug(`Loading additional locales from file`, this.config.auditContext);
|
|
38
59
|
this.locales.push(...(0, lodash_1.values)(JSON.parse((0, fs_1.readFileSync)(localesPath, 'utf8'))));
|
|
60
|
+
cli_utilities_1.log.debug(`Total locales after loading: ${this.locales.length} - ${this.locales.map(locale => locale.code).join(', ')}`, this.config.auditContext);
|
|
39
61
|
}
|
|
62
|
+
else {
|
|
63
|
+
cli_utilities_1.log.debug(`Additional locales file not found`, this.config.auditContext);
|
|
64
|
+
}
|
|
65
|
+
cli_utilities_1.log.debug(`Processing ${this.locales.length} locales and ${this.ctSchema.length} content types`, this.config.auditContext);
|
|
40
66
|
for (const { code } of this.locales) {
|
|
67
|
+
cli_utilities_1.log.debug(`Processing locale: ${code}`, this.config.auditContext);
|
|
41
68
|
for (const ctSchema of this.ctSchema) {
|
|
69
|
+
cli_utilities_1.log.debug(`Processing content type: ${ctSchema.uid}`, this.config.auditContext);
|
|
42
70
|
const basePath = (0, path_1.join)(this.folderPath, 'entries', ctSchema.uid, code);
|
|
43
|
-
|
|
71
|
+
cli_utilities_1.log.debug(`Base path: ${basePath}`, this.config.auditContext);
|
|
72
|
+
const entryCount = await this.readEntryAssetsModule(basePath, 'index') || 0;
|
|
73
|
+
cli_utilities_1.log.debug(`Found ${entryCount} entries for ${ctSchema.uid} in ${code}`, this.config.auditContext);
|
|
74
|
+
count = count + entryCount;
|
|
44
75
|
}
|
|
45
76
|
}
|
|
77
|
+
cli_utilities_1.log.debug(`Total entries count: ${count}`, this.config.auditContext);
|
|
46
78
|
}
|
|
47
79
|
break;
|
|
48
80
|
case 'custom-roles':
|
|
49
81
|
case 'extensions':
|
|
50
|
-
case 'workflows':
|
|
51
|
-
|
|
82
|
+
case 'workflows': {
|
|
83
|
+
cli_utilities_1.log.debug(`Counting ${moduleName}`, this.config.auditContext);
|
|
84
|
+
const modulePath = (0, path_1.resolve)(this.folderPath, (0, cli_utilities_1.sanitizePath)(this.config.moduleConfig[moduleName].dirName), (0, cli_utilities_1.sanitizePath)(this.config.moduleConfig[moduleName].fileName));
|
|
85
|
+
cli_utilities_1.log.debug(`Reading module: ${moduleName} from file: ${modulePath}`, this.config.auditContext);
|
|
86
|
+
const moduleData = await this.readUsingFsModule(modulePath);
|
|
87
|
+
count = (0, lodash_1.keys)(moduleData).length;
|
|
88
|
+
cli_utilities_1.log.debug(`module:${moduleName} count: ${count}`, this.config.auditContext);
|
|
52
89
|
break;
|
|
90
|
+
}
|
|
53
91
|
}
|
|
92
|
+
cli_utilities_1.log.debug(`Module ${moduleName} item count: ${count}`, this.config.auditContext);
|
|
54
93
|
return count;
|
|
55
94
|
}
|
|
56
95
|
async readUsingFsModule(path) {
|
|
96
|
+
cli_utilities_1.log.debug(`Reading file: ${path}`, this.config.auditContext);
|
|
57
97
|
const data = (0, fs_1.existsSync)(path) ? (JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'))) : [];
|
|
98
|
+
cli_utilities_1.log.debug(`File ${(0, fs_1.existsSync)(path) ? 'exists' : 'not found'}, data type: ${Array.isArray(data) ? 'array' : 'object'}`, this.config.auditContext);
|
|
99
|
+
if ((0, fs_1.existsSync)(path)) {
|
|
100
|
+
const dataSize = Array.isArray(data) ? data.length : Object.keys(data).length;
|
|
101
|
+
cli_utilities_1.log.debug(`Loaded ${dataSize} items from file`, this.config.auditContext);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
cli_utilities_1.log.debug(`Returning empty array for non-existent file`, this.config.auditContext);
|
|
105
|
+
}
|
|
58
106
|
return data;
|
|
59
107
|
}
|
|
60
108
|
async readEntryAssetsModule(basePath, module) {
|
|
109
|
+
cli_utilities_1.log.debug(`Reading entry/assets module: ${module}`, this.config.auditContext);
|
|
110
|
+
cli_utilities_1.log.debug(`Base path: ${basePath}`, this.config.auditContext);
|
|
61
111
|
let fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: `${module}.json` });
|
|
62
112
|
let indexer = fsUtility.indexFileContent;
|
|
113
|
+
cli_utilities_1.log.debug(`Found ${Object.keys(indexer).length} index files`, this.config.auditContext);
|
|
63
114
|
let count = 0;
|
|
64
115
|
for (const _ in indexer) {
|
|
116
|
+
cli_utilities_1.log.debug(`Reading chunk file`, this.config.auditContext);
|
|
65
117
|
const entries = (await fsUtility.readChunkFiles.next());
|
|
66
|
-
|
|
118
|
+
const chunkCount = Object.keys(entries).length;
|
|
119
|
+
cli_utilities_1.log.debug(`Loaded ${chunkCount} items from chunk`, this.config.auditContext);
|
|
120
|
+
count = count + chunkCount;
|
|
67
121
|
}
|
|
122
|
+
cli_utilities_1.log.debug(`Total ${module} count: ${count}`, this.config.auditContext);
|
|
68
123
|
return count;
|
|
69
124
|
}
|
|
70
125
|
async run() {
|
|
126
|
+
cli_utilities_1.log.debug(`Starting ModuleDataReader run process`, this.config.auditContext);
|
|
127
|
+
cli_utilities_1.log.debug(`Available modules: ${Object.keys(this.config.moduleConfig).join(', ')}`, this.config.auditContext);
|
|
71
128
|
await Promise.allSettled(Object.keys(this.config.moduleConfig).map(async (module) => {
|
|
72
|
-
|
|
129
|
+
cli_utilities_1.log.debug(`Processing module: ${module}`, this.config.auditContext);
|
|
130
|
+
const count = await this.getModuleItemCount(module);
|
|
131
|
+
this.auditData[module] = { Total: count };
|
|
132
|
+
cli_utilities_1.log.debug(`Module ${module} processed with count: ${count}`, this.config.auditContext);
|
|
73
133
|
}));
|
|
134
|
+
cli_utilities_1.log.debug(`ModuleDataReader run completed`, this.config.auditContext);
|
|
135
|
+
cli_utilities_1.log.debug(`Audit data: ${JSON.stringify(this.auditData)}`, this.config.auditContext);
|
|
74
136
|
return this.auditData;
|
|
75
137
|
}
|
|
76
138
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigType, ContentTypeStruct, CtConstructorParam, ModuleConstructorParam, Workflow } from '../types';
|
|
2
2
|
import auditConfig from '../config';
|
|
3
3
|
export default class Workflows {
|
|
4
|
-
log: LogFn;
|
|
5
4
|
protected fix: boolean;
|
|
6
5
|
fileName: any;
|
|
7
6
|
config: ConfigType;
|
|
@@ -14,7 +13,7 @@ export default class Workflows {
|
|
|
14
13
|
missingCts: Set<string>;
|
|
15
14
|
workflowPath: string;
|
|
16
15
|
isBranchFixDone: boolean;
|
|
17
|
-
constructor({
|
|
16
|
+
constructor({ fix, config, moduleName, ctSchema, }: ModuleConstructorParam & Pick<CtConstructorParam, 'ctSchema'>);
|
|
18
17
|
validateModules(moduleName: keyof typeof auditConfig.moduleConfig, moduleConfig: Record<string, unknown>): keyof typeof auditConfig.moduleConfig;
|
|
19
18
|
/**
|
|
20
19
|
* Check whether the given path for the workflow exists or not
|
package/lib/modules/workflows.js
CHANGED
|
@@ -7,25 +7,35 @@ const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
|
7
7
|
const messages_1 = require("../messages");
|
|
8
8
|
const lodash_2 = require("lodash");
|
|
9
9
|
class Workflows {
|
|
10
|
-
constructor({
|
|
11
|
-
this.log = log;
|
|
10
|
+
constructor({ fix, config, moduleName, ctSchema, }) {
|
|
12
11
|
this.config = config;
|
|
13
12
|
this.fix = fix !== null && fix !== void 0 ? fix : false;
|
|
14
13
|
this.ctSchema = ctSchema;
|
|
15
14
|
this.workflowSchema = [];
|
|
15
|
+
cli_utilities_1.log.debug(`Initializing Workflows module`, this.config.auditContext);
|
|
16
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
17
|
+
cli_utilities_1.log.debug(`Content types count: ${ctSchema.length}`, this.config.auditContext);
|
|
18
|
+
cli_utilities_1.log.debug(`Module name: ${moduleName}`, this.config.auditContext);
|
|
16
19
|
this.moduleName = this.validateModules(moduleName, this.config.moduleConfig);
|
|
17
20
|
this.fileName = config.moduleConfig[this.moduleName].fileName;
|
|
21
|
+
cli_utilities_1.log.debug(`File name: ${this.fileName}`, this.config.auditContext);
|
|
18
22
|
this.folderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.basePath), (0, cli_utilities_1.sanitizePath)(config.moduleConfig[this.moduleName].dirName));
|
|
23
|
+
cli_utilities_1.log.debug(`Folder path: ${this.folderPath}`, this.config.auditContext);
|
|
19
24
|
this.ctUidSet = new Set(['$all']);
|
|
20
25
|
this.missingCtInWorkflows = [];
|
|
21
26
|
this.missingCts = new Set();
|
|
22
27
|
this.workflowPath = '';
|
|
23
28
|
this.isBranchFixDone = false;
|
|
29
|
+
cli_utilities_1.log.debug(`Workflows module initialization completed`, this.config.auditContext);
|
|
24
30
|
}
|
|
25
31
|
validateModules(moduleName, moduleConfig) {
|
|
32
|
+
cli_utilities_1.log.debug(`Validating module: ${moduleName}`, this.config.auditContext);
|
|
33
|
+
cli_utilities_1.log.debug(`Available modules: ${Object.keys(moduleConfig).join(', ')}`, this.config.auditContext);
|
|
26
34
|
if (Object.keys(moduleConfig).includes(moduleName)) {
|
|
35
|
+
cli_utilities_1.log.debug(`Module ${moduleName} is valid`, this.config.auditContext);
|
|
27
36
|
return moduleName;
|
|
28
37
|
}
|
|
38
|
+
cli_utilities_1.log.debug(`Module ${moduleName} not found, defaulting to 'workflows'`, this.config.auditContext);
|
|
29
39
|
return 'workflows';
|
|
30
40
|
}
|
|
31
41
|
/**
|
|
@@ -35,93 +45,163 @@ class Workflows {
|
|
|
35
45
|
* @returns Array of object containing the workflow name, uid and content_types that are missing
|
|
36
46
|
*/
|
|
37
47
|
async run() {
|
|
38
|
-
var _a, _b, _c;
|
|
48
|
+
var _a, _b, _c, _d, _e;
|
|
39
49
|
if (!(0, fs_1.existsSync)(this.folderPath)) {
|
|
40
|
-
|
|
41
|
-
|
|
50
|
+
cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
|
|
51
|
+
cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
|
|
52
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
|
|
42
53
|
return {};
|
|
43
54
|
}
|
|
44
55
|
this.workflowPath = (0, path_1.join)(this.folderPath, this.fileName);
|
|
56
|
+
cli_utilities_1.log.debug(`Workflows file path: ${this.workflowPath}`, this.config.auditContext);
|
|
57
|
+
cli_utilities_1.log.debug(`Loading workflows schema from file`, this.config.auditContext);
|
|
45
58
|
this.workflowSchema = (0, fs_1.existsSync)(this.workflowPath)
|
|
46
59
|
? (0, lodash_2.values)(JSON.parse((0, fs_1.readFileSync)(this.workflowPath, 'utf8')))
|
|
47
60
|
: [];
|
|
61
|
+
cli_utilities_1.log.debug(`Loaded ${this.workflowSchema.length} workflows`, this.config.auditContext);
|
|
62
|
+
cli_utilities_1.log.debug(`Building content type UID set from ${this.ctSchema.length} content types`, this.config.auditContext);
|
|
48
63
|
this.ctSchema.forEach((ct) => this.ctUidSet.add(ct.uid));
|
|
64
|
+
cli_utilities_1.log.debug(`Content type UID set contains: ${Array.from(this.ctUidSet).join(', ')}`, this.config.auditContext);
|
|
65
|
+
cli_utilities_1.log.debug(`Processing ${this.workflowSchema.length} workflows`, this.config.auditContext);
|
|
49
66
|
for (const workflow of this.workflowSchema) {
|
|
67
|
+
const { name, uid } = workflow;
|
|
68
|
+
cli_utilities_1.log.debug(`Processing workflow: ${name} (${uid})`, this.config.auditContext);
|
|
69
|
+
cli_utilities_1.log.debug(`Workflow content types: ${((_a = workflow.content_types) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'none'}`, this.config.auditContext);
|
|
70
|
+
cli_utilities_1.log.debug(`Workflow branches: ${((_b = workflow.branches) === null || _b === void 0 ? void 0 : _b.join(', ')) || 'none'}`, this.config.auditContext);
|
|
50
71
|
const ctNotPresent = workflow.content_types.filter((ct) => !this.ctUidSet.has(ct));
|
|
72
|
+
cli_utilities_1.log.debug(`Missing content types in workflow: ${(ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.join(', ')) || 'none'}`, this.config.auditContext);
|
|
73
|
+
cli_utilities_1.log.debug(`Config branch : ${this.config.branch}`, this.config.auditContext);
|
|
51
74
|
let branchesToBeRemoved = [];
|
|
52
|
-
if ((
|
|
53
|
-
branchesToBeRemoved = ((
|
|
75
|
+
if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.branch) {
|
|
76
|
+
branchesToBeRemoved = ((_d = workflow === null || workflow === void 0 ? void 0 : workflow.branches) === null || _d === void 0 ? void 0 : _d.filter((branch) => { var _a; return branch !== ((_a = this.config) === null || _a === void 0 ? void 0 : _a.branch); })) || [];
|
|
77
|
+
cli_utilities_1.log.debug(`Branches to be removed: ${(branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.join(', ')) || 'none'}`, this.config.auditContext);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
cli_utilities_1.log.debug(`No branch configuration found`, this.config.auditContext);
|
|
54
81
|
}
|
|
55
82
|
if (ctNotPresent.length || (branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.length)) {
|
|
83
|
+
cli_utilities_1.log.debug(`Workflow ${name} has issues - missing content types: ${ctNotPresent.length}, branches to remove: ${branchesToBeRemoved.length}`, this.config.auditContext);
|
|
56
84
|
const tempwf = (0, lodash_1.cloneDeep)(workflow);
|
|
57
85
|
tempwf.content_types = ctNotPresent || [];
|
|
58
|
-
if ((workflow === null || workflow === void 0 ? void 0 : workflow.branches) && ((
|
|
86
|
+
if ((workflow === null || workflow === void 0 ? void 0 : workflow.branches) && ((_e = this.config) === null || _e === void 0 ? void 0 : _e.branch)) {
|
|
59
87
|
tempwf.branches = branchesToBeRemoved;
|
|
60
88
|
}
|
|
61
89
|
if (branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.length) {
|
|
90
|
+
cli_utilities_1.log.debug(`Branch fix will be needed`, this.config.auditContext);
|
|
62
91
|
this.isBranchFixDone = true;
|
|
63
92
|
}
|
|
64
|
-
ctNotPresent.forEach((ct) =>
|
|
93
|
+
ctNotPresent.forEach((ct) => {
|
|
94
|
+
cli_utilities_1.log.debug(`Adding missing content type: ${ct} to the Audit report.`, this.config.auditContext);
|
|
95
|
+
this.missingCts.add(ct);
|
|
96
|
+
});
|
|
65
97
|
this.missingCtInWorkflows.push(tempwf);
|
|
66
98
|
}
|
|
67
|
-
|
|
99
|
+
else {
|
|
100
|
+
cli_utilities_1.log.debug(`Workflow ${name} has no issues`, this.config.auditContext);
|
|
101
|
+
}
|
|
102
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_WF_SUCCESS_MSG, {
|
|
68
103
|
name: workflow.name,
|
|
69
104
|
uid: workflow.uid,
|
|
70
|
-
}),
|
|
105
|
+
}), this.config.auditContext);
|
|
71
106
|
}
|
|
107
|
+
cli_utilities_1.log.debug(`Workflows audit completed. Found ${this.missingCtInWorkflows.length} workflows with issues`, this.config.auditContext);
|
|
108
|
+
cli_utilities_1.log.debug(`Total missing content types: ${this.missingCts.size}`, this.config.auditContext);
|
|
109
|
+
cli_utilities_1.log.debug(`Branch fix needed: ${this.isBranchFixDone}`, this.config.auditContext);
|
|
72
110
|
if (this.fix && (this.missingCtInWorkflows.length || this.isBranchFixDone)) {
|
|
111
|
+
cli_utilities_1.log.debug(`Fix mode enabled, fixing ${this.missingCtInWorkflows.length} workflows`, this.config.auditContext);
|
|
73
112
|
await this.fixWorkflowSchema();
|
|
74
|
-
this.missingCtInWorkflows.forEach((wf) =>
|
|
113
|
+
this.missingCtInWorkflows.forEach((wf) => {
|
|
114
|
+
cli_utilities_1.log.debug(`Marking workflow ${wf.name} as fixed`, this.config.auditContext);
|
|
115
|
+
wf.fixStatus = 'Fixed';
|
|
116
|
+
});
|
|
117
|
+
cli_utilities_1.log.debug(`Workflows fix completed`, this.config.auditContext);
|
|
118
|
+
return this.missingCtInWorkflows;
|
|
75
119
|
}
|
|
120
|
+
cli_utilities_1.log.debug(`Workflows audit completed without fixes`, this.config.auditContext);
|
|
76
121
|
return this.missingCtInWorkflows;
|
|
77
122
|
}
|
|
78
123
|
async fixWorkflowSchema() {
|
|
79
124
|
var _a;
|
|
125
|
+
cli_utilities_1.log.debug(`Starting workflow schema fix`, this.config.auditContext);
|
|
80
126
|
const newWorkflowSchema = (0, fs_1.existsSync)(this.workflowPath)
|
|
81
127
|
? JSON.parse((0, fs_1.readFileSync)(this.workflowPath, 'utf8'))
|
|
82
128
|
: {};
|
|
129
|
+
cli_utilities_1.log.debug(`Loaded ${Object.keys(newWorkflowSchema).length} workflows for fixing`, this.config.auditContext);
|
|
83
130
|
if (Object.keys(newWorkflowSchema).length !== 0) {
|
|
131
|
+
cli_utilities_1.log.debug(`Processing ${this.workflowSchema.length} workflows for fixes`, this.config.auditContext);
|
|
84
132
|
for (const workflow of this.workflowSchema) {
|
|
133
|
+
const { name, uid } = workflow;
|
|
134
|
+
cli_utilities_1.log.debug(`Fixing workflow: ${name} (${uid})`, this.config.auditContext);
|
|
85
135
|
const fixedCts = workflow.content_types.filter((ct) => !this.missingCts.has(ct));
|
|
136
|
+
cli_utilities_1.log.debug(`Fixed content types: ${fixedCts.join(', ') || 'none'}`, this.config.auditContext);
|
|
86
137
|
const fixedBranches = [];
|
|
87
138
|
if (this.config.branch) {
|
|
139
|
+
cli_utilities_1.log.debug(`Config branch : ${this.config.branch}`, this.config.auditContext);
|
|
140
|
+
cli_utilities_1.log.debug(`Processing branches for workflow ${name}`, this.config.auditContext);
|
|
88
141
|
(_a = workflow === null || workflow === void 0 ? void 0 : workflow.branches) === null || _a === void 0 ? void 0 : _a.forEach((branch) => {
|
|
89
142
|
var _a;
|
|
90
143
|
if (branch !== ((_a = this.config) === null || _a === void 0 ? void 0 : _a.branch)) {
|
|
91
|
-
|
|
92
|
-
|
|
144
|
+
cli_utilities_1.log.debug(`Removing branch: ${branch} from workflow ${name}`, this.config.auditContext);
|
|
145
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.commonMsg.WF_BRANCH_REMOVAL, { uid, name, branch }), { color: 'yellow' });
|
|
93
146
|
}
|
|
94
147
|
else {
|
|
148
|
+
cli_utilities_1.log.debug(`Keeping branch: ${branch} for workflow ${name}`, this.config.auditContext);
|
|
95
149
|
fixedBranches.push(branch);
|
|
96
150
|
}
|
|
97
151
|
});
|
|
98
152
|
if (fixedBranches.length > 0) {
|
|
153
|
+
cli_utilities_1.log.debug(`Setting ${fixedBranches.length} fixed branches for workflow ${name}`, this.config.auditContext);
|
|
99
154
|
newWorkflowSchema[workflow.uid].branches = fixedBranches;
|
|
100
155
|
}
|
|
101
156
|
}
|
|
157
|
+
else {
|
|
158
|
+
cli_utilities_1.log.debug(`No branch configuration for workflow ${name}`, this.config.auditContext);
|
|
159
|
+
}
|
|
102
160
|
if (fixedCts.length) {
|
|
161
|
+
cli_utilities_1.log.debug(`Setting ${fixedCts.length} fixed content types for workflow ${name}`, this.config.auditContext);
|
|
103
162
|
newWorkflowSchema[workflow.uid].content_types = fixedCts;
|
|
104
163
|
}
|
|
105
164
|
else {
|
|
106
165
|
const { name, uid } = workflow;
|
|
166
|
+
cli_utilities_1.log.debug(`No valid content types for workflow ${name}, considering deletion`, this.config.auditContext);
|
|
107
167
|
const warningMessage = (0, messages_1.$t)(messages_1.commonMsg.WORKFLOW_FIX_WARN, { name, uid });
|
|
108
|
-
|
|
168
|
+
cli_utilities_1.cliux.print(warningMessage, { color: 'yellow' });
|
|
109
169
|
if (this.config.flags.yes || (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.WORKFLOW_FIX_CONFIRMATION))) {
|
|
170
|
+
cli_utilities_1.log.debug(`Deleting workflow ${name} (${uid})`, this.config.auditContext);
|
|
110
171
|
delete newWorkflowSchema[workflow.uid];
|
|
111
172
|
}
|
|
173
|
+
else {
|
|
174
|
+
cli_utilities_1.log.debug(`Keeping workflow ${name} (${uid}) despite no valid content types`, this.config.auditContext);
|
|
175
|
+
}
|
|
112
176
|
}
|
|
113
177
|
}
|
|
114
178
|
}
|
|
179
|
+
else {
|
|
180
|
+
cli_utilities_1.log.debug(`No workflows found to fix`, this.config.auditContext);
|
|
181
|
+
}
|
|
182
|
+
cli_utilities_1.log.debug(`Workflow schema fix completed`, this.config.auditContext);
|
|
115
183
|
await this.writeFixContent(newWorkflowSchema);
|
|
116
184
|
}
|
|
117
185
|
async writeFixContent(newWorkflowSchema) {
|
|
118
|
-
var _a;
|
|
186
|
+
var _a, _b;
|
|
187
|
+
cli_utilities_1.log.debug(`Writing fix content`, this.config.auditContext);
|
|
188
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
189
|
+
cli_utilities_1.log.debug(`Copy directory flag: ${this.config.flags['copy-dir']}`, this.config.auditContext);
|
|
190
|
+
cli_utilities_1.log.debug(`External config skip confirm: ${(_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm}`, this.config.auditContext);
|
|
191
|
+
cli_utilities_1.log.debug(`Yes flag: ${this.config.flags.yes}`, this.config.auditContext);
|
|
192
|
+
cli_utilities_1.log.debug(`Workflows to write: ${Object.keys(newWorkflowSchema).length}`, this.config.auditContext);
|
|
119
193
|
if (this.fix &&
|
|
120
194
|
(this.config.flags['copy-dir'] ||
|
|
121
|
-
((
|
|
195
|
+
((_b = this.config.flags['external-config']) === null || _b === void 0 ? void 0 : _b.skipConfirm) ||
|
|
122
196
|
this.config.flags.yes ||
|
|
123
197
|
(await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
|
|
124
|
-
|
|
198
|
+
const outputPath = (0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName);
|
|
199
|
+
cli_utilities_1.log.debug(`Writing fixed workflows to: ${outputPath}`, this.config.auditContext);
|
|
200
|
+
(0, fs_1.writeFileSync)(outputPath, JSON.stringify(newWorkflowSchema));
|
|
201
|
+
cli_utilities_1.log.debug(`Successfully wrote fixed workflows to file`, this.config.auditContext);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
cli_utilities_1.log.debug(`Skipping file write - fix mode disabled or user declined confirmation`, this.config.auditContext);
|
|
125
205
|
}
|
|
126
206
|
}
|
|
127
207
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import config from '../config';
|
|
2
2
|
import { AnyProperty } from './common';
|
|
3
|
-
import { ConfigType
|
|
3
|
+
import { ConfigType } from './utils';
|
|
4
4
|
type ContentTypeSchemaType = ReferenceFieldDataType | GlobalFieldDataType | ExtensionOrAppFieldDataType | JsonRTEFieldDataType | GroupFieldDataType | ModularBlocksDataType | SelectFeildStruct | any;
|
|
5
5
|
type ContentTypeStruct = {
|
|
6
6
|
field_rules: any;
|
|
@@ -12,7 +12,6 @@ type ContentTypeStruct = {
|
|
|
12
12
|
multiple: boolean;
|
|
13
13
|
};
|
|
14
14
|
type ModuleConstructorParam = {
|
|
15
|
-
log: LogFn;
|
|
16
15
|
fix?: boolean;
|
|
17
16
|
config: ConfigType;
|
|
18
17
|
moduleName?: keyof typeof config.moduleConfig;
|
package/lib/types/index.d.ts
CHANGED
package/lib/types/index.js
CHANGED
|
@@ -8,3 +8,4 @@ tslib_1.__exportStar(require("./content-types"), exports);
|
|
|
8
8
|
tslib_1.__exportStar(require("./workflow"), exports);
|
|
9
9
|
tslib_1.__exportStar(require("./extensions"), exports);
|
|
10
10
|
tslib_1.__exportStar(require("./custom-role"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./context"), exports);
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-audit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "Contentstack audit plugin",
|
|
5
5
|
"author": "Contentstack CLI",
|
|
6
6
|
"homepage": "https://github.com/contentstack/cli",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@contentstack/cli-command": "~1.6.1",
|
|
22
|
-
"@contentstack/cli-utilities": "~1.14.
|
|
22
|
+
"@contentstack/cli-utilities": "~1.14.3",
|
|
23
23
|
"@oclif/core": "^4.3.0",
|
|
24
24
|
"@oclif/plugin-help": "^6.2.28",
|
|
25
25
|
"@oclif/plugin-plugins": "^5.4.38",
|