@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
|
@@ -10,7 +10,7 @@ const lodash_1 = require("lodash");
|
|
|
10
10
|
/* The `ContentType` class is responsible for scanning content types, looking for references, and
|
|
11
11
|
generating a report in JSON and CSV formats. */
|
|
12
12
|
class FieldRule {
|
|
13
|
-
constructor({
|
|
13
|
+
constructor({ fix, config, moduleName, ctSchema, gfSchema }) {
|
|
14
14
|
this.extensions = [];
|
|
15
15
|
this.inMemoryFix = false;
|
|
16
16
|
this.schema = [];
|
|
@@ -21,19 +21,30 @@ class FieldRule {
|
|
|
21
21
|
this.missingEnvLocale = {};
|
|
22
22
|
this.entryMetaData = [];
|
|
23
23
|
this.action = ['show', 'hide'];
|
|
24
|
-
this.log = log;
|
|
25
24
|
this.config = config;
|
|
26
25
|
this.fix = fix !== null && fix !== void 0 ? fix : false;
|
|
27
26
|
this.ctSchema = ctSchema;
|
|
28
27
|
this.gfSchema = gfSchema;
|
|
28
|
+
cli_utilities_1.log.debug(`Initializing FieldRule module`, this.config.auditContext);
|
|
29
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
30
|
+
cli_utilities_1.log.debug(`Content types count: ${(ctSchema === null || ctSchema === void 0 ? void 0 : ctSchema.length) || 0}`, this.config.auditContext);
|
|
31
|
+
cli_utilities_1.log.debug(`Global fields count: ${(gfSchema === null || gfSchema === void 0 ? void 0 : gfSchema.length) || 0}`, this.config.auditContext);
|
|
32
|
+
cli_utilities_1.log.debug(`Module name: ${moduleName}`, this.config.auditContext);
|
|
29
33
|
this.moduleName = this.validateModules(moduleName, this.config.moduleConfig);
|
|
30
34
|
this.fileName = config.moduleConfig[this.moduleName].fileName;
|
|
35
|
+
cli_utilities_1.log.debug(`File name: ${this.fileName}`, this.config.auditContext);
|
|
31
36
|
this.folderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.basePath), (0, cli_utilities_1.sanitizePath)(config.moduleConfig[this.moduleName].dirName));
|
|
37
|
+
cli_utilities_1.log.debug(`Folder path: ${this.folderPath}`, this.config.auditContext);
|
|
38
|
+
cli_utilities_1.log.debug(`FieldRule module initialization completed`, this.config.auditContext);
|
|
32
39
|
}
|
|
33
40
|
validateModules(moduleName, moduleConfig) {
|
|
41
|
+
cli_utilities_1.log.debug(`Validating module: ${moduleName}`, this.config.auditContext);
|
|
42
|
+
cli_utilities_1.log.debug(`Available modules: ${Object.keys(moduleConfig).join(', ')}`, this.config.auditContext);
|
|
34
43
|
if (Object.keys(moduleConfig).includes(moduleName)) {
|
|
44
|
+
cli_utilities_1.log.debug(`Module ${moduleName} is valid`, this.config.auditContext);
|
|
35
45
|
return moduleName;
|
|
36
46
|
}
|
|
47
|
+
cli_utilities_1.log.debug(`Module ${moduleName} not found, defaulting to 'content-types'`, this.config.auditContext);
|
|
37
48
|
return 'content-types';
|
|
38
49
|
}
|
|
39
50
|
/**
|
|
@@ -42,108 +53,178 @@ class FieldRule {
|
|
|
42
53
|
* @returns the `missingRefs` object.
|
|
43
54
|
*/
|
|
44
55
|
async run() {
|
|
45
|
-
var _a;
|
|
56
|
+
var _a, _b, _c;
|
|
57
|
+
cli_utilities_1.log.debug(`Starting ${this.moduleName} field rules audit process`, this.config.auditContext);
|
|
58
|
+
cli_utilities_1.log.debug(`Field rules folder path: ${this.folderPath}`, this.config.auditContext);
|
|
59
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
46
60
|
if (!(0, fs_1.existsSync)(this.folderPath)) {
|
|
47
|
-
|
|
48
|
-
|
|
61
|
+
cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
|
|
62
|
+
cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
|
|
63
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
|
|
49
64
|
return {};
|
|
50
65
|
}
|
|
51
66
|
this.schema = this.moduleName === 'content-types' ? this.ctSchema : this.gfSchema;
|
|
67
|
+
cli_utilities_1.log.debug(`Using ${this.moduleName} schema with ${((_a = this.schema) === null || _a === void 0 ? void 0 : _a.length) || 0} items`, this.config.auditContext);
|
|
68
|
+
cli_utilities_1.log.debug(`Loading prerequisite data`, this.config.auditContext);
|
|
52
69
|
await this.prerequisiteData();
|
|
70
|
+
cli_utilities_1.log.debug(`Loaded ${this.extensions.length} extensions`, this.config.auditContext);
|
|
71
|
+
cli_utilities_1.log.debug(`Preparing entry metadata`, this.config.auditContext);
|
|
53
72
|
await this.prepareEntryMetaData();
|
|
54
|
-
|
|
73
|
+
cli_utilities_1.log.debug(`Prepared metadata for ${this.entryMetaData.length} entries`, this.config.auditContext);
|
|
74
|
+
cli_utilities_1.log.debug(`Processing ${((_b = this.schema) === null || _b === void 0 ? void 0 : _b.length) || 0} schemas for field rules`, this.config.auditContext);
|
|
75
|
+
for (const schema of (_c = this.schema) !== null && _c !== void 0 ? _c : []) {
|
|
55
76
|
this.currentUid = schema.uid;
|
|
56
77
|
this.currentTitle = schema.title;
|
|
57
78
|
this.missingRefs[this.currentUid] = [];
|
|
58
79
|
const { uid, title } = schema;
|
|
80
|
+
cli_utilities_1.log.debug(`Processing schema: ${title} (${uid})`, this.config.auditContext);
|
|
81
|
+
cli_utilities_1.log.debug(`Field rules count: ${Array.isArray(schema.field_rules) ? schema.field_rules.length : 0}`, this.config.auditContext);
|
|
82
|
+
cli_utilities_1.log.debug(`Looking for references in schema: ${title}`, this.config.auditContext);
|
|
59
83
|
await this.lookForReference([{ uid, name: title }], schema, null);
|
|
84
|
+
cli_utilities_1.log.debug(`Schema map contains ${this.schemaMap.length} field references`, this.config.auditContext);
|
|
60
85
|
this.missingRefs[this.currentUid] = [];
|
|
61
86
|
if (this.fix) {
|
|
87
|
+
cli_utilities_1.log.debug(`Fixing field rules for schema: ${title}`, this.config.auditContext);
|
|
62
88
|
this.fixFieldRules(schema);
|
|
63
89
|
}
|
|
64
90
|
else {
|
|
91
|
+
cli_utilities_1.log.debug(`Validating field rules for schema: ${title}`, this.config.auditContext);
|
|
65
92
|
this.validateFieldRules(schema);
|
|
66
93
|
}
|
|
67
94
|
this.schemaMap = [];
|
|
68
|
-
|
|
95
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_CT_SUCCESS_MSG, { title, module: this.config.moduleConfig[this.moduleName].name }), this.config.auditContext);
|
|
69
96
|
}
|
|
70
97
|
if (this.fix) {
|
|
98
|
+
cli_utilities_1.log.debug(`Fix mode enabled, writing fix content`, this.config.auditContext);
|
|
71
99
|
await this.writeFixContent();
|
|
72
100
|
}
|
|
101
|
+
cli_utilities_1.log.debug(`Cleaning up empty missing references`, this.config.auditContext);
|
|
73
102
|
for (let propName in this.missingRefs) {
|
|
74
103
|
if (!this.missingRefs[propName].length) {
|
|
104
|
+
cli_utilities_1.log.debug(`Removing empty missing references for: ${propName}`, this.config.auditContext);
|
|
75
105
|
delete this.missingRefs[propName];
|
|
76
106
|
}
|
|
77
107
|
}
|
|
108
|
+
cli_utilities_1.log.debug(`Field rules audit completed. Found ${Object.keys(this.missingRefs).length} schemas with issues`, this.config.auditContext);
|
|
78
109
|
return this.missingRefs;
|
|
79
110
|
}
|
|
80
111
|
validateFieldRules(schema) {
|
|
112
|
+
cli_utilities_1.log.debug(`Validating field rules for schema: ${schema.uid}`, this.config.auditContext);
|
|
81
113
|
if (Array.isArray(schema.field_rules)) {
|
|
114
|
+
cli_utilities_1.log.debug(`Found ${schema.field_rules.length} field rules to validate`, this.config.auditContext);
|
|
82
115
|
let count = 0;
|
|
83
|
-
schema.field_rules.forEach((fr) => {
|
|
84
|
-
|
|
116
|
+
schema.field_rules.forEach((fr, index) => {
|
|
117
|
+
var _a, _b;
|
|
118
|
+
cli_utilities_1.log.debug(`Validating field rule ${index + 1}`, this.config.auditContext);
|
|
119
|
+
cli_utilities_1.log.debug(`Field rule actions count: ${((_a = fr.actions) === null || _a === void 0 ? void 0 : _a.length) || 0}`, this.config.auditContext);
|
|
120
|
+
cli_utilities_1.log.debug(`Field rule conditions count: ${((_b = fr.conditions) === null || _b === void 0 ? void 0 : _b.length) || 0}`, this.config.auditContext);
|
|
121
|
+
fr.actions.forEach((actions, actionIndex) => {
|
|
122
|
+
cli_utilities_1.log.debug(`Validating action ${actionIndex + 1}: target_field=${actions.target_field}`, this.config.auditContext);
|
|
85
123
|
if (!this.schemaMap.includes(actions.target_field)) {
|
|
86
|
-
|
|
124
|
+
cli_utilities_1.log.debug(`Missing target field: ${actions.target_field}`, this.config.auditContext);
|
|
125
|
+
cli_utilities_1.log.error((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_TARGET_ABSENT, {
|
|
87
126
|
target_field: actions.target_field,
|
|
88
127
|
ctUid: schema.uid,
|
|
89
|
-
}),
|
|
128
|
+
}), this.config.auditContext);
|
|
90
129
|
this.addMissingReferences(actions);
|
|
91
130
|
}
|
|
92
|
-
|
|
131
|
+
else {
|
|
132
|
+
cli_utilities_1.log.debug(`Target field ${actions.target_field} is valid`, this.config.auditContext);
|
|
133
|
+
}
|
|
134
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_TARGET_SCAN_MESSAGE, { num: count.toString(), ctUid: schema.uid }), this.config.auditContext);
|
|
93
135
|
});
|
|
94
|
-
fr.conditions.forEach((actions) => {
|
|
136
|
+
fr.conditions.forEach((actions, conditionIndex) => {
|
|
137
|
+
cli_utilities_1.log.debug(`Validating condition ${conditionIndex + 1}: operand_field=${actions.operand_field}`, this.config.auditContext);
|
|
95
138
|
if (!this.schemaMap.includes(actions.operand_field)) {
|
|
139
|
+
cli_utilities_1.log.debug(`Missing operand field: ${actions.operand_field}`, this.config.auditContext);
|
|
96
140
|
this.addMissingReferences(actions);
|
|
97
|
-
|
|
141
|
+
cli_utilities_1.log.error((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_CONDITION_ABSENT, { condition_field: actions.operand_field }), this.config.auditContext);
|
|
98
142
|
}
|
|
99
|
-
|
|
143
|
+
else {
|
|
144
|
+
cli_utilities_1.log.debug(`Operand field ${actions.operand_field} is valid`, this.config.auditContext);
|
|
145
|
+
}
|
|
146
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_CONDITION_SCAN_MESSAGE, { num: count.toString(), ctUid: schema.uid }), this.config.auditContext);
|
|
100
147
|
});
|
|
101
148
|
count = count + 1;
|
|
102
149
|
});
|
|
103
150
|
}
|
|
151
|
+
else {
|
|
152
|
+
cli_utilities_1.log.debug(`No field rules found in schema: ${schema.uid}`, this.config.auditContext);
|
|
153
|
+
}
|
|
154
|
+
cli_utilities_1.log.debug(`Field rules validation completed for schema: ${schema.uid}`, this.config.auditContext);
|
|
104
155
|
}
|
|
105
156
|
fixFieldRules(schema) {
|
|
106
|
-
|
|
157
|
+
cli_utilities_1.log.debug(`Fixing field rules for schema: ${schema.uid}`, this.config.auditContext);
|
|
158
|
+
if (!Array.isArray(schema.field_rules)) {
|
|
159
|
+
cli_utilities_1.log.debug(`No field rules found in schema: ${schema.uid}`, this.config.auditContext);
|
|
107
160
|
return;
|
|
161
|
+
}
|
|
162
|
+
cli_utilities_1.log.debug(`Found ${schema.field_rules.length} field rules to fix`, this.config.auditContext);
|
|
108
163
|
schema.field_rules = schema.field_rules
|
|
109
164
|
.map((fr, index) => {
|
|
110
|
-
var _a, _b, _c, _d;
|
|
111
|
-
|
|
165
|
+
var _a, _b, _c, _d, _e, _f;
|
|
166
|
+
cli_utilities_1.log.debug(`Fixing field rule ${index + 1}`, this.config.auditContext);
|
|
167
|
+
cli_utilities_1.log.debug(`Original actions count: ${((_a = fr.actions) === null || _a === void 0 ? void 0 : _a.length) || 0}`, this.config.auditContext);
|
|
168
|
+
cli_utilities_1.log.debug(`Original conditions count: ${((_b = fr.conditions) === null || _b === void 0 ? void 0 : _b.length) || 0}`, this.config.auditContext);
|
|
169
|
+
const validActions = (_d = (_c = fr.actions) === null || _c === void 0 ? void 0 : _c.filter(action => {
|
|
112
170
|
const isValid = this.schemaMap.includes(action.target_field);
|
|
171
|
+
cli_utilities_1.log.debug(`Action target_field=${action.target_field}, valid=${isValid}`, this.config.auditContext);
|
|
113
172
|
const logMsg = isValid
|
|
114
173
|
? messages_1.auditMsg.FIELD_RULE_TARGET_SCAN_MESSAGE
|
|
115
174
|
: messages_1.auditMsg.FIELD_RULE_TARGET_ABSENT;
|
|
116
|
-
|
|
175
|
+
if (isValid) {
|
|
176
|
+
cli_utilities_1.log.info((0, messages_1.$t)(logMsg, Object.assign({ num: index.toString(), ctUid: schema.uid }, (action.target_field && { target_field: action.target_field }))), this.config.auditContext);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
cli_utilities_1.log.error((0, messages_1.$t)(logMsg, Object.assign({ num: index.toString(), ctUid: schema.uid }, (action.target_field && { target_field: action.target_field }))), this.config.auditContext);
|
|
180
|
+
}
|
|
117
181
|
if (!isValid) {
|
|
182
|
+
cli_utilities_1.log.debug(`Fixing invalid action target_field: ${action.target_field}`, this.config.auditContext);
|
|
118
183
|
this.addMissingReferences(action, 'Fixed');
|
|
119
|
-
|
|
184
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditFixMsg.FIELD_RULE_FIX_MESSAGE, {
|
|
120
185
|
num: index.toString(),
|
|
121
186
|
ctUid: schema.uid
|
|
122
|
-
}),
|
|
187
|
+
}), this.config.auditContext);
|
|
123
188
|
}
|
|
124
189
|
return isValid;
|
|
125
|
-
})) !== null &&
|
|
126
|
-
|
|
190
|
+
})) !== null && _d !== void 0 ? _d : [];
|
|
191
|
+
cli_utilities_1.log.debug(`Valid actions after filtering: ${validActions.length}`, this.config.auditContext);
|
|
192
|
+
const validConditions = (_f = (_e = fr.conditions) === null || _e === void 0 ? void 0 : _e.filter(condition => {
|
|
127
193
|
const isValid = this.schemaMap.includes(condition.operand_field);
|
|
194
|
+
cli_utilities_1.log.debug(`Condition operand_field=${condition.operand_field}, valid=${isValid}`, this.config.auditContext);
|
|
128
195
|
const logMsg = isValid
|
|
129
196
|
? messages_1.auditMsg.FIELD_RULE_CONDITION_SCAN_MESSAGE
|
|
130
197
|
: messages_1.auditMsg.FIELD_RULE_CONDITION_ABSENT;
|
|
131
|
-
|
|
198
|
+
if (isValid) {
|
|
199
|
+
cli_utilities_1.log.info((0, messages_1.$t)(logMsg, Object.assign({ num: index.toString(), ctUid: schema.uid }, (condition.operand_field && { condition_field: condition.operand_field }))), this.config.auditContext);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
cli_utilities_1.log.error((0, messages_1.$t)(logMsg, Object.assign({ num: index.toString(), ctUid: schema.uid }, (condition.operand_field && { condition_field: condition.operand_field }))), this.config.auditContext);
|
|
203
|
+
}
|
|
132
204
|
if (!isValid) {
|
|
205
|
+
cli_utilities_1.log.debug(`Fixing invalid condition operand_field: ${condition.operand_field}`, this.config.auditContext);
|
|
133
206
|
this.addMissingReferences(condition, 'Fixed');
|
|
134
|
-
|
|
207
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditFixMsg.FIELD_RULE_FIX_MESSAGE, {
|
|
135
208
|
num: index.toString(),
|
|
136
209
|
ctUid: schema.uid
|
|
137
|
-
}),
|
|
210
|
+
}), this.config.auditContext);
|
|
138
211
|
}
|
|
139
212
|
return isValid;
|
|
140
|
-
})) !== null &&
|
|
141
|
-
|
|
213
|
+
})) !== null && _f !== void 0 ? _f : [];
|
|
214
|
+
cli_utilities_1.log.debug(`Valid conditions after filtering: ${validConditions.length}`, this.config.auditContext);
|
|
215
|
+
const shouldKeepRule = validActions.length && validConditions.length;
|
|
216
|
+
cli_utilities_1.log.debug(`Field rule ${index + 1} ${shouldKeepRule ? 'kept' : 'removed'} (actions: ${validActions.length}, conditions: ${validConditions.length})`, this.config.auditContext);
|
|
217
|
+
return shouldKeepRule ? Object.assign(Object.assign({}, fr), { actions: validActions, conditions: validConditions }) : null;
|
|
142
218
|
})
|
|
143
219
|
.filter(Boolean);
|
|
220
|
+
cli_utilities_1.log.debug(`Field rules fix completed for schema: ${schema.uid}. ${schema.field_rules.length} rules remaining`, this.config.auditContext);
|
|
144
221
|
}
|
|
145
222
|
addMissingReferences(actions, fixStatus) {
|
|
223
|
+
cli_utilities_1.log.debug(`Adding missing reference for schema: ${this.currentUid}`, this.config.auditContext);
|
|
224
|
+
cli_utilities_1.log.debug(`Action data: ${JSON.stringify(actions)}`, this.config.auditContext);
|
|
225
|
+
cli_utilities_1.log.debug(`Fix status: ${fixStatus || 'none'}`, this.config.auditContext);
|
|
146
226
|
if (fixStatus) {
|
|
227
|
+
cli_utilities_1.log.debug(`Recording fixed missing reference`, this.config.auditContext);
|
|
147
228
|
this.missingRefs[this.currentUid].push({
|
|
148
229
|
ctUid: this.currentUid,
|
|
149
230
|
action: actions,
|
|
@@ -151,8 +232,10 @@ class FieldRule {
|
|
|
151
232
|
});
|
|
152
233
|
}
|
|
153
234
|
else {
|
|
235
|
+
cli_utilities_1.log.debug(`Recording missing reference for validation`, this.config.auditContext);
|
|
154
236
|
this.missingRefs[this.currentUid].push({ ctUid: this.currentUid, action: actions });
|
|
155
237
|
}
|
|
238
|
+
cli_utilities_1.log.debug(`Missing references count for ${this.currentUid}: ${this.missingRefs[this.currentUid].length}`, this.config.auditContext);
|
|
156
239
|
}
|
|
157
240
|
/**
|
|
158
241
|
* @method prerequisiteData
|
|
@@ -161,98 +244,188 @@ class FieldRule {
|
|
|
161
244
|
*/
|
|
162
245
|
async prerequisiteData() {
|
|
163
246
|
var _a;
|
|
247
|
+
cli_utilities_1.log.debug(`Loading prerequisite data`, this.config.auditContext);
|
|
164
248
|
const extensionPath = (0, path_1.resolve)(this.config.basePath, 'extensions', 'extensions.json');
|
|
165
249
|
const marketplacePath = (0, path_1.resolve)(this.config.basePath, 'marketplace_apps', 'marketplace_apps.json');
|
|
250
|
+
cli_utilities_1.log.debug(`Extensions path: ${extensionPath}`, this.config.auditContext);
|
|
251
|
+
cli_utilities_1.log.debug(`Marketplace apps path: ${marketplacePath}`, this.config.auditContext);
|
|
166
252
|
if ((0, fs_1.existsSync)(extensionPath)) {
|
|
253
|
+
cli_utilities_1.log.debug(`Loading extensions from file`, this.config.auditContext);
|
|
167
254
|
try {
|
|
168
255
|
this.extensions = Object.keys(JSON.parse((0, fs_1.readFileSync)(extensionPath, 'utf8')));
|
|
256
|
+
cli_utilities_1.log.debug(`Loaded ${this.extensions.length} extensions`, this.config.auditContext);
|
|
169
257
|
}
|
|
170
|
-
catch (error) {
|
|
258
|
+
catch (error) {
|
|
259
|
+
cli_utilities_1.log.debug(`Error loading extensions: ${error}`, this.config.auditContext);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
cli_utilities_1.log.debug(`Extensions file not found`, this.config.auditContext);
|
|
171
264
|
}
|
|
172
265
|
if ((0, fs_1.existsSync)(marketplacePath)) {
|
|
266
|
+
cli_utilities_1.log.debug(`Loading marketplace apps from file`, this.config.auditContext);
|
|
173
267
|
try {
|
|
174
268
|
const marketplaceApps = JSON.parse((0, fs_1.readFileSync)(marketplacePath, 'utf8'));
|
|
269
|
+
cli_utilities_1.log.debug(`Found ${marketplaceApps.length} marketplace apps`, this.config.auditContext);
|
|
175
270
|
for (const app of marketplaceApps) {
|
|
271
|
+
cli_utilities_1.log.debug(`Processing marketplace app: ${app.uid}`, this.config.auditContext);
|
|
176
272
|
const metaData = (0, map_1.default)((0, map_1.default)((_a = app === null || app === void 0 ? void 0 : app.ui_location) === null || _a === void 0 ? void 0 : _a.locations, 'meta').flat(), 'extension_uid').filter((val) => val);
|
|
273
|
+
cli_utilities_1.log.debug(`Found ${metaData.length} extension UIDs in app`, this.config.auditContext);
|
|
177
274
|
this.extensions.push(...metaData);
|
|
178
275
|
}
|
|
179
276
|
}
|
|
180
|
-
catch (error) {
|
|
277
|
+
catch (error) {
|
|
278
|
+
cli_utilities_1.log.debug(`Error loading marketplace apps: ${error}`, this.config.auditContext);
|
|
279
|
+
}
|
|
181
280
|
}
|
|
281
|
+
else {
|
|
282
|
+
cli_utilities_1.log.debug(`Marketplace apps file not found`, this.config.auditContext);
|
|
283
|
+
}
|
|
284
|
+
cli_utilities_1.log.debug(`Prerequisite data loading completed. Total extensions: ${this.extensions.length}`, this.config.auditContext);
|
|
182
285
|
}
|
|
183
286
|
/**
|
|
184
287
|
* The function checks if it can write the fix content to a file and if so, it writes the content as
|
|
185
288
|
* JSON to the specified file path.
|
|
186
289
|
*/
|
|
187
290
|
async writeFixContent() {
|
|
188
|
-
var _a, _b;
|
|
291
|
+
var _a, _b, _c, _d;
|
|
292
|
+
cli_utilities_1.log.debug(`Writing fix content`, this.config.auditContext);
|
|
293
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
294
|
+
cli_utilities_1.log.debug(`Copy directory flag: ${this.config.flags['copy-dir']}`, this.config.auditContext);
|
|
295
|
+
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);
|
|
296
|
+
cli_utilities_1.log.debug(`Yes flag: ${this.config.flags.yes}`, this.config.auditContext);
|
|
189
297
|
let canWrite = true;
|
|
190
298
|
if (this.fix) {
|
|
191
|
-
if (!this.config.flags['copy-dir'] && !((
|
|
192
|
-
|
|
299
|
+
if (!this.config.flags['copy-dir'] && !((_b = this.config.flags['external-config']) === null || _b === void 0 ? void 0 : _b.skipConfirm)) {
|
|
300
|
+
cli_utilities_1.log.debug(`Asking user for confirmation to write fix content`, this.config.auditContext);
|
|
301
|
+
canWrite = (_c = this.config.flags.yes) !== null && _c !== void 0 ? _c : (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
|
|
302
|
+
cli_utilities_1.log.debug(`User confirmation: ${canWrite}`, this.config.auditContext);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
cli_utilities_1.log.debug(`Skipping confirmation due to flags`, this.config.auditContext);
|
|
193
306
|
}
|
|
194
307
|
if (canWrite) {
|
|
195
|
-
|
|
308
|
+
const outputPath = (0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName);
|
|
309
|
+
cli_utilities_1.log.debug(`Writing fixed schema to: ${outputPath}`, this.config.auditContext);
|
|
310
|
+
cli_utilities_1.log.debug(`Schema items to write: ${((_d = this.schema) === null || _d === void 0 ? void 0 : _d.length) || 0}`, this.config.auditContext);
|
|
311
|
+
(0, fs_1.writeFileSync)(outputPath, JSON.stringify(this.schema));
|
|
312
|
+
cli_utilities_1.log.debug(`Successfully wrote fixed schema to file`, this.config.auditContext);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
cli_utilities_1.log.debug(`Skipping file write - user declined confirmation`, this.config.auditContext);
|
|
196
316
|
}
|
|
197
317
|
}
|
|
318
|
+
else {
|
|
319
|
+
cli_utilities_1.log.debug(`Skipping file write - fix mode disabled`, this.config.auditContext);
|
|
320
|
+
}
|
|
198
321
|
}
|
|
199
322
|
async lookForReference(tree, field, parent = null) {
|
|
200
|
-
var _a, _b;
|
|
201
|
-
|
|
202
|
-
|
|
323
|
+
var _a, _b, _c;
|
|
324
|
+
cli_utilities_1.log.debug(`Looking for references in field: ${field.uid || field.title || 'unknown'}`, this.config.auditContext);
|
|
325
|
+
cli_utilities_1.log.debug(`Parent: ${parent || 'none'}`, this.config.auditContext);
|
|
326
|
+
cli_utilities_1.log.debug(`Schema fields count: ${((_a = field.schema) === null || _a === void 0 ? void 0 : _a.length) || 0}`, this.config.auditContext);
|
|
327
|
+
const fixTypes = (_b = this.config.flags['fix-only']) !== null && _b !== void 0 ? _b : this.config['fix-fields'];
|
|
328
|
+
cli_utilities_1.log.debug(`Fix types: ${fixTypes.join(', ')}`, this.config.auditContext);
|
|
329
|
+
for (let child of (_c = field.schema) !== null && _c !== void 0 ? _c : []) {
|
|
330
|
+
const fieldPath = parent !== null ? `${parent}.${child === null || child === void 0 ? void 0 : child.uid}` : child.uid;
|
|
331
|
+
cli_utilities_1.log.debug(`Processing field: ${child.uid} (${child.data_type}) at path: ${fieldPath}`, this.config.auditContext);
|
|
203
332
|
if (parent !== null) {
|
|
204
333
|
this.schemaMap.push(`${parent}.${child === null || child === void 0 ? void 0 : child.uid}`);
|
|
205
334
|
}
|
|
206
335
|
else {
|
|
207
336
|
this.schemaMap.push(child.uid);
|
|
208
337
|
}
|
|
209
|
-
if (!fixTypes.includes(child.data_type) && child.data_type !== 'json')
|
|
338
|
+
if (!fixTypes.includes(child.data_type) && child.data_type !== 'json') {
|
|
339
|
+
cli_utilities_1.log.debug(`Skipping field ${child.uid} - data type ${child.data_type} not in fix types`, this.config.auditContext);
|
|
210
340
|
continue;
|
|
341
|
+
}
|
|
342
|
+
cli_utilities_1.log.debug(`Validating field ${child.uid} of type ${child.data_type}`, this.config.auditContext);
|
|
211
343
|
switch (child.data_type) {
|
|
212
344
|
case 'global_field':
|
|
345
|
+
cli_utilities_1.log.debug(`Validating global field: ${child.uid}`, this.config.auditContext);
|
|
213
346
|
await this.validateGlobalField([...tree, { uid: child.uid, name: child.display_name }], child, parent ? `${parent}.${child === null || child === void 0 ? void 0 : child.uid}` : child === null || child === void 0 ? void 0 : child.uid);
|
|
214
347
|
break;
|
|
215
348
|
case 'blocks':
|
|
349
|
+
cli_utilities_1.log.debug(`Validating modular blocks field: ${child.uid}`, this.config.auditContext);
|
|
216
350
|
await this.validateModularBlocksField([...tree, { uid: child.uid, name: child.display_name }], child, parent ? `${parent}.${child === null || child === void 0 ? void 0 : child.uid}` : child === null || child === void 0 ? void 0 : child.uid);
|
|
217
351
|
break;
|
|
218
352
|
case 'group':
|
|
353
|
+
cli_utilities_1.log.debug(`Validating group field: ${child.uid}`, this.config.auditContext);
|
|
219
354
|
await this.validateGroupField([...tree, { uid: child.uid, name: child.display_name }], child, parent ? `${parent}.${child === null || child === void 0 ? void 0 : child.uid}` : child === null || child === void 0 ? void 0 : child.uid);
|
|
220
355
|
break;
|
|
221
356
|
}
|
|
222
357
|
}
|
|
358
|
+
cli_utilities_1.log.debug(`Reference lookup completed for field: ${field.uid || field.title || 'unknown'}`, this.config.auditContext);
|
|
223
359
|
}
|
|
224
360
|
async validateGlobalField(tree, field, parent) {
|
|
361
|
+
cli_utilities_1.log.debug(`Validating global field: ${field.uid} (${field.display_name})`, this.config.auditContext);
|
|
362
|
+
cli_utilities_1.log.debug(`Tree depth: ${tree.length}`, this.config.auditContext);
|
|
363
|
+
cli_utilities_1.log.debug(`Parent: ${parent || 'none'}`, this.config.auditContext);
|
|
225
364
|
await this.lookForReference(tree, field, parent);
|
|
365
|
+
cli_utilities_1.log.debug(`Global field validation completed: ${field.uid}`, this.config.auditContext);
|
|
226
366
|
}
|
|
227
367
|
async validateModularBlocksField(tree, field, parent) {
|
|
368
|
+
cli_utilities_1.log.debug(`Validating modular blocks field: ${field.uid} (${field.display_name})`, this.config.auditContext);
|
|
369
|
+
cli_utilities_1.log.debug(`Tree depth: ${tree.length}`, this.config.auditContext);
|
|
370
|
+
cli_utilities_1.log.debug(`Parent: ${parent || 'none'}`, this.config.auditContext);
|
|
228
371
|
const { blocks } = field;
|
|
372
|
+
cli_utilities_1.log.debug(`Found ${blocks.length} blocks to validate`, this.config.auditContext);
|
|
229
373
|
for (const block of blocks) {
|
|
230
374
|
const { uid, title } = block;
|
|
231
|
-
|
|
375
|
+
cli_utilities_1.log.debug(`Validating block: ${uid} (${title})`, this.config.auditContext);
|
|
376
|
+
const updatedTree = [...tree, { uid, name: title }];
|
|
377
|
+
const blockParent = parent + '.' + block.uid;
|
|
378
|
+
cli_utilities_1.log.debug(`Updated tree depth: ${updatedTree.length}, block parent: ${blockParent}`, this.config.auditContext);
|
|
379
|
+
await this.lookForReference(updatedTree, block, blockParent);
|
|
380
|
+
cli_utilities_1.log.debug(`Block validation completed: ${uid}`, this.config.auditContext);
|
|
232
381
|
}
|
|
382
|
+
cli_utilities_1.log.debug(`Modular blocks field validation completed: ${field.uid}`, this.config.auditContext);
|
|
233
383
|
}
|
|
234
384
|
async validateGroupField(tree, field, parent) {
|
|
385
|
+
cli_utilities_1.log.debug(`Validating group field: ${field.uid} (${field.display_name})`, this.config.auditContext);
|
|
386
|
+
cli_utilities_1.log.debug(`Tree depth: ${tree.length}`, this.config.auditContext);
|
|
387
|
+
cli_utilities_1.log.debug(`Parent: ${parent || 'none'}`, this.config.auditContext);
|
|
235
388
|
// NOTE Any Group Field related logic can be added here (Ex data serialization or picking any metadata for report etc.,)
|
|
236
389
|
await this.lookForReference(tree, field, parent);
|
|
390
|
+
cli_utilities_1.log.debug(`Group field validation completed: ${field.uid}`, this.config.auditContext);
|
|
237
391
|
}
|
|
238
392
|
async prepareEntryMetaData() {
|
|
239
|
-
var _a;
|
|
240
|
-
|
|
393
|
+
var _a, _b;
|
|
394
|
+
cli_utilities_1.log.debug(`Preparing entry metadata`, this.config.auditContext);
|
|
395
|
+
cli_utilities_1.log.info(messages_1.auditMsg.PREPARING_ENTRY_METADATA, this.config.auditContext);
|
|
241
396
|
const localesFolderPath = (0, path_1.resolve)(this.config.basePath, this.config.moduleConfig.locales.dirName);
|
|
242
397
|
const localesPath = (0, path_1.join)(localesFolderPath, this.config.moduleConfig.locales.fileName);
|
|
243
398
|
const masterLocalesPath = (0, path_1.join)(localesFolderPath, 'master-locale.json');
|
|
399
|
+
cli_utilities_1.log.debug(`Locales folder path: ${localesFolderPath}`, this.config.auditContext);
|
|
400
|
+
cli_utilities_1.log.debug(`Locales path: ${localesPath}`, this.config.auditContext);
|
|
401
|
+
cli_utilities_1.log.debug(`Master locales path: ${masterLocalesPath}`, this.config.auditContext);
|
|
402
|
+
cli_utilities_1.log.debug(`Loading master locales`, this.config.auditContext);
|
|
244
403
|
this.locales = (0, fs_1.existsSync)(masterLocalesPath) ? (0, lodash_1.values)(JSON.parse((0, fs_1.readFileSync)(masterLocalesPath, 'utf8'))) : [];
|
|
404
|
+
cli_utilities_1.log.debug(`Loaded ${this.locales.length} master locales`, this.config.auditContext);
|
|
245
405
|
if ((0, fs_1.existsSync)(localesPath)) {
|
|
406
|
+
cli_utilities_1.log.debug(`Loading additional locales from file`, this.config.auditContext);
|
|
246
407
|
this.locales.push(...(0, lodash_1.values)(JSON.parse((0, fs_1.readFileSync)(localesPath, 'utf8'))));
|
|
408
|
+
cli_utilities_1.log.debug(`Total locales after loading: ${this.locales.length}`, this.config.auditContext);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
cli_utilities_1.log.debug(`Additional locales file not found`, this.config.auditContext);
|
|
247
412
|
}
|
|
248
413
|
const entriesFolderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.basePath), 'entries');
|
|
414
|
+
cli_utilities_1.log.debug(`Entries folder path: ${entriesFolderPath}`, this.config.auditContext);
|
|
415
|
+
cli_utilities_1.log.debug(`Processing ${this.locales.length} locales and ${((_a = this.ctSchema) === null || _a === void 0 ? void 0 : _a.length) || 0} content types`, this.config.auditContext);
|
|
249
416
|
for (const { code } of this.locales) {
|
|
250
|
-
|
|
417
|
+
cli_utilities_1.log.debug(`Processing locale: ${code}`, this.config.auditContext);
|
|
418
|
+
for (const { uid } of (_b = this.ctSchema) !== null && _b !== void 0 ? _b : []) {
|
|
419
|
+
cli_utilities_1.log.debug(`Processing content type: ${uid}`, this.config.auditContext);
|
|
251
420
|
let basePath = (0, path_1.join)(entriesFolderPath, uid, code);
|
|
421
|
+
cli_utilities_1.log.debug(`Base path: ${basePath}`, this.config.auditContext);
|
|
252
422
|
let fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: 'index.json' });
|
|
253
423
|
let indexer = fsUtility.indexFileContent;
|
|
424
|
+
cli_utilities_1.log.debug(`Found ${Object.keys(indexer).length} entry files`, this.config.auditContext);
|
|
254
425
|
for (const _ in indexer) {
|
|
426
|
+
cli_utilities_1.log.debug(`Loading entries from file`, this.config.auditContext);
|
|
255
427
|
const entries = (await fsUtility.readChunkFiles.next());
|
|
428
|
+
cli_utilities_1.log.debug(`Loaded ${Object.keys(entries).length} entries`, this.config.auditContext);
|
|
256
429
|
for (const entryUid in entries) {
|
|
257
430
|
let { title } = entries[entryUid];
|
|
258
431
|
this.entryMetaData.push({ uid: entryUid, title, ctUid: uid });
|
|
@@ -260,6 +433,7 @@ class FieldRule {
|
|
|
260
433
|
}
|
|
261
434
|
}
|
|
262
435
|
}
|
|
436
|
+
cli_utilities_1.log.debug(`Entry metadata preparation completed. Total entries: ${this.entryMetaData.length}`, this.config.auditContext);
|
|
263
437
|
}
|
|
264
438
|
}
|
|
265
439
|
exports.default = FieldRule;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const content_types_1 = tslib_1.__importDefault(require("./content-types"));
|
|
5
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
5
6
|
class GlobalField extends content_types_1.default {
|
|
6
7
|
/**
|
|
7
8
|
* The above function is an asynchronous function that runs a validation and returns any missing
|
|
@@ -9,8 +10,13 @@ class GlobalField extends content_types_1.default {
|
|
|
9
10
|
* @returns the value of the variable `missingRefs`.
|
|
10
11
|
*/
|
|
11
12
|
async run(returnFixSchema = false) {
|
|
13
|
+
cli_utilities_1.log.debug(`Starting GlobalField audit process`, this.config.auditContext);
|
|
14
|
+
cli_utilities_1.log.debug(`Return fix schema: ${returnFixSchema}`, this.config.auditContext);
|
|
12
15
|
// NOTE add any validation if required
|
|
16
|
+
cli_utilities_1.log.debug(`Calling parent ContentType.run() method`, this.config.auditContext);
|
|
13
17
|
const missingRefs = await super.run(returnFixSchema);
|
|
18
|
+
cli_utilities_1.log.debug(`Parent method completed, found ${Object.keys(missingRefs || {}).length} missing references`, this.config.auditContext);
|
|
19
|
+
cli_utilities_1.log.debug(`GlobalField audit completed`, this.config.auditContext);
|
|
14
20
|
return missingRefs;
|
|
15
21
|
}
|
|
16
22
|
/**
|
|
@@ -21,11 +27,17 @@ class GlobalField extends content_types_1.default {
|
|
|
21
27
|
* @param {ModularBlocksDataType} field - The `field` parameter is of type `ModularBlocksDataType`.
|
|
22
28
|
*/
|
|
23
29
|
async validateModularBlocksField(tree, field) {
|
|
30
|
+
cli_utilities_1.log.debug(`[GLOBAL-FIELDS] Validating modular blocks field: ${field.uid}`, this.config.auditContext);
|
|
31
|
+
cli_utilities_1.log.debug(`Tree depth: ${tree.length}`, this.config.auditContext);
|
|
24
32
|
const { blocks } = field;
|
|
33
|
+
cli_utilities_1.log.debug(`Found ${blocks.length} blocks to validate`, this.config.auditContext);
|
|
25
34
|
// NOTE Traverse each and every module and look for reference
|
|
26
35
|
for (const block of blocks) {
|
|
36
|
+
cli_utilities_1.log.debug(`Validating block: ${block.uid} (${block.title})`, this.config.auditContext);
|
|
27
37
|
await this.lookForReference(tree, block);
|
|
38
|
+
cli_utilities_1.log.debug(`Block validation completed: ${block.uid}`, this.config.auditContext);
|
|
28
39
|
}
|
|
40
|
+
cli_utilities_1.log.debug(`[GLOBAL-FIELDS] Modular blocks field validation completed: ${field.uid}`, this.config.auditContext);
|
|
29
41
|
}
|
|
30
42
|
/**
|
|
31
43
|
* The function "validateGroupField" performs group field validation by looking for a reference in a
|
|
@@ -36,8 +48,13 @@ class GlobalField extends content_types_1.default {
|
|
|
36
48
|
* @param {GroupFieldDataType} field - The `field` parameter is of type `GroupFieldDataType`.
|
|
37
49
|
*/
|
|
38
50
|
async validateGroupField(tree, field) {
|
|
51
|
+
cli_utilities_1.log.debug(`[GLOBAL-FIELDS] Validating group field: ${field.uid} (${field.display_name})`, this.config.auditContext);
|
|
52
|
+
cli_utilities_1.log.debug(`Tree depth: ${tree.length}`, this.config.auditContext);
|
|
39
53
|
// NOTE Any Group Field related logic can be added here (Ex data serialization or picking any metadata for report etc.,)
|
|
40
|
-
|
|
54
|
+
const updatedTree = [...tree, { uid: field.uid, name: field.display_name }];
|
|
55
|
+
cli_utilities_1.log.debug(`Updated tree depth: ${updatedTree.length}`, this.config.auditContext);
|
|
56
|
+
await this.lookForReference(updatedTree, field);
|
|
57
|
+
cli_utilities_1.log.debug(`[GLOBAL-FIELDS] Group field validation completed: ${field.uid}`, this.config.auditContext);
|
|
41
58
|
}
|
|
42
59
|
}
|
|
43
60
|
exports.default = GlobalField;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigType, ContentTypeStruct, CtConstructorParam, ModuleConstructorParam } from '../types';
|
|
2
2
|
export default class ModuleDataReader {
|
|
3
|
-
log: LogFn;
|
|
4
3
|
config: ConfigType;
|
|
5
4
|
folderPath: string;
|
|
6
5
|
assets: Record<string, any>;
|
|
@@ -10,7 +9,7 @@ export default class ModuleDataReader {
|
|
|
10
9
|
environments: string[];
|
|
11
10
|
auditData: Record<string, unknown>;
|
|
12
11
|
protected schema: ContentTypeStruct[];
|
|
13
|
-
constructor({
|
|
12
|
+
constructor({ config, ctSchema, gfSchema }: ModuleConstructorParam & CtConstructorParam);
|
|
14
13
|
getModuleItemCount(moduleName: string): Promise<number>;
|
|
15
14
|
readUsingFsModule(path: string): Promise<Record<string, any>>;
|
|
16
15
|
readEntryAssetsModule(basePath: string, module: string): Promise<number>;
|