@contentstack/cli-audit 1.16.2 → 2.0.0-beta
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 +1 -1
- package/lib/audit-base-command.d.ts +4 -0
- package/lib/audit-base-command.js +81 -39
- 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 -1
- package/lib/modules/index.js +3 -1
- package/lib/modules/workflows.d.ts +4 -4
- package/lib/modules/workflows.js +85 -68
- package/lib/types/context.d.ts +5 -0
- package/oclif.manifest.json +1 -1
- package/package.json +4 -4
package/lib/modules/entries.js
CHANGED
|
@@ -10,10 +10,12 @@ const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
|
10
10
|
const fs_1 = require("fs");
|
|
11
11
|
const content_types_1 = tslib_1.__importDefault(require("./content-types"));
|
|
12
12
|
const messages_1 = require("../messages");
|
|
13
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
13
14
|
const global_fields_1 = tslib_1.__importDefault(require("./global-fields"));
|
|
14
15
|
const lodash_1 = require("lodash");
|
|
15
|
-
class Entries {
|
|
16
|
+
class Entries extends base_class_1.default {
|
|
16
17
|
constructor({ fix, config, moduleName, ctSchema, gfSchema }) {
|
|
18
|
+
super({ config });
|
|
17
19
|
this.extensions = [];
|
|
18
20
|
this.missingRefs = {};
|
|
19
21
|
this.missingSelectFeild = {};
|
|
@@ -24,7 +26,6 @@ class Entries {
|
|
|
24
26
|
this.environments = [];
|
|
25
27
|
this.entryMetaData = [];
|
|
26
28
|
this.moduleName = 'entries';
|
|
27
|
-
this.config = config;
|
|
28
29
|
cli_utilities_1.log.debug(`Initializing Entries module`, this.config.auditContext);
|
|
29
30
|
this.fix = fix !== null && fix !== void 0 ? fix : false;
|
|
30
31
|
this.ctSchema = ctSchema;
|
|
@@ -49,190 +50,211 @@ class Entries {
|
|
|
49
50
|
/**
|
|
50
51
|
* The `run` function checks if a folder path exists, sets the schema based on the module name,
|
|
51
52
|
* iterates over the schema and looks for references, and returns a list of missing references.
|
|
53
|
+
* @param totalCount - Total number of entries to process (for progress tracking)
|
|
52
54
|
* @returns the `missingRefs` object.
|
|
53
55
|
*/
|
|
54
|
-
async run() {
|
|
56
|
+
async run(totalCount) {
|
|
55
57
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
cli_utilities_1.log.debug(`
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
cli_utilities_1.log.debug(`
|
|
118
|
-
this.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
58
|
+
try {
|
|
59
|
+
if (!(0, fs_1.existsSync)(this.folderPath)) {
|
|
60
|
+
cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
|
|
61
|
+
cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
|
|
62
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
cli_utilities_1.log.debug(`Found ${((_a = this.ctSchema) === null || _a === void 0 ? void 0 : _a.length) || 0} content types to audit`, this.config.auditContext);
|
|
66
|
+
cli_utilities_1.log.debug(`Found ${((_b = this.locales) === null || _b === void 0 ? void 0 : _b.length) || 0} locales to process`, this.config.auditContext);
|
|
67
|
+
// Prepare entry metadata with loading spinner
|
|
68
|
+
await this.withLoadingSpinner('ENTRIES: Preparing entry metadata...', async () => {
|
|
69
|
+
await this.prepareEntryMetaData();
|
|
70
|
+
});
|
|
71
|
+
cli_utilities_1.log.debug(`Entry metadata prepared: ${this.entryMetaData.length} entries found`, this.config.auditContext);
|
|
72
|
+
// Fix prerequisite data with loading spinner
|
|
73
|
+
await this.withLoadingSpinner('ENTRIES: Fixing prerequisite data...', async () => {
|
|
74
|
+
await this.fixPrerequisiteData();
|
|
75
|
+
});
|
|
76
|
+
cli_utilities_1.log.debug('Prerequisite data fix completed', this.config.auditContext);
|
|
77
|
+
// Create progress manager if we have a total count
|
|
78
|
+
if (totalCount && totalCount > 0) {
|
|
79
|
+
const progress = this.createSimpleProgress(this.moduleName, totalCount);
|
|
80
|
+
progress.updateStatus('Validating entries...');
|
|
81
|
+
}
|
|
82
|
+
cli_utilities_1.log.debug(`Processing ${this.locales.length} locales and ${this.ctSchema.length} content types`, this.config.auditContext);
|
|
83
|
+
for (const { code } of this.locales) {
|
|
84
|
+
cli_utilities_1.log.debug(`Processing locale: ${code}`, this.config.auditContext);
|
|
85
|
+
for (const ctSchema of this.ctSchema) {
|
|
86
|
+
cli_utilities_1.log.debug(`Processing content type: ${ctSchema.uid} in locale ${code}`, this.config.auditContext);
|
|
87
|
+
const basePath = (0, path_1.join)(this.folderPath, ctSchema.uid, code);
|
|
88
|
+
cli_utilities_1.log.debug(`Base path for entries: ${basePath}`, this.config.auditContext);
|
|
89
|
+
const fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: 'index.json', createDirIfNotExist: false });
|
|
90
|
+
const indexer = fsUtility.indexFileContent;
|
|
91
|
+
cli_utilities_1.log.debug(`Found ${Object.keys(indexer).length} entry files to process`, this.config.auditContext);
|
|
92
|
+
for (const fileIndex in indexer) {
|
|
93
|
+
cli_utilities_1.log.debug(`Processing entry file: ${indexer[fileIndex]}`, this.config.auditContext);
|
|
94
|
+
const entries = (await fsUtility.readChunkFiles.next());
|
|
95
|
+
this.entries = entries;
|
|
96
|
+
cli_utilities_1.log.debug(`Loaded ${Object.keys(entries).length} entries from file`, this.config.auditContext);
|
|
97
|
+
for (const entryUid in this.entries) {
|
|
98
|
+
const entry = this.entries[entryUid];
|
|
99
|
+
const { uid, title } = entry;
|
|
100
|
+
this.currentUid = uid;
|
|
101
|
+
this.currentTitle = title;
|
|
102
|
+
if (this.currentTitle) {
|
|
103
|
+
this.currentTitle = this.removeEmojiAndImages(this.currentTitle);
|
|
104
|
+
}
|
|
105
|
+
cli_utilities_1.log.debug(`Processing entry - title:${this.currentTitle} with uid:(${uid})`, this.config.auditContext);
|
|
106
|
+
if (!this.missingRefs[this.currentUid]) {
|
|
107
|
+
this.missingRefs[this.currentUid] = [];
|
|
108
|
+
}
|
|
109
|
+
if (!this.missingSelectFeild[this.currentUid]) {
|
|
110
|
+
this.missingSelectFeild[this.currentUid] = [];
|
|
111
|
+
}
|
|
112
|
+
if (!this.missingMandatoryFields[this.currentUid]) {
|
|
113
|
+
this.missingMandatoryFields[this.currentUid] = [];
|
|
114
|
+
}
|
|
115
|
+
if (this.fix) {
|
|
116
|
+
cli_utilities_1.log.debug(`Removing missing keys from entry ${uid}`, this.config.auditContext);
|
|
117
|
+
this.removeMissingKeysOnEntry(ctSchema.schema, this.entries[entryUid]);
|
|
118
|
+
}
|
|
119
|
+
cli_utilities_1.log.debug(`Looking for references in entry ${uid}`, this.config.auditContext);
|
|
120
|
+
this.lookForReference([{ locale: code, uid, name: this.removeEmojiAndImages(this.currentTitle) }], ctSchema, this.entries[entryUid]);
|
|
121
|
+
if ((_c = this.missingRefs[this.currentUid]) === null || _c === void 0 ? void 0 : _c.length) {
|
|
122
|
+
cli_utilities_1.log.debug(`Found ${this.missingRefs[this.currentUid].length} missing references for entry ${uid}`, this.config.auditContext);
|
|
123
|
+
this.missingRefs[this.currentUid].forEach((entry) => {
|
|
124
|
+
entry.ct = ctSchema.uid;
|
|
125
|
+
entry.locale = code;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if ((_d = this.missingSelectFeild[this.currentUid]) === null || _d === void 0 ? void 0 : _d.length) {
|
|
129
|
+
cli_utilities_1.log.debug(`Found ${this.missingSelectFeild[this.currentUid].length} missing select fields for entry ${uid}`, this.config.auditContext);
|
|
130
|
+
this.missingSelectFeild[this.currentUid].forEach((entry) => {
|
|
131
|
+
entry.ct = ctSchema.uid;
|
|
132
|
+
entry.locale = code;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if ((_e = this.missingMandatoryFields[this.currentUid]) === null || _e === void 0 ? void 0 : _e.length) {
|
|
136
|
+
cli_utilities_1.log.debug(`Found ${this.missingMandatoryFields[this.currentUid].length} missing mandatory fields for entry ${uid}`, this.config.auditContext);
|
|
137
|
+
this.missingMandatoryFields[this.currentUid].forEach((entry) => {
|
|
138
|
+
entry.ct = ctSchema.uid;
|
|
139
|
+
entry.locale = code;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const fields = this.missingMandatoryFields[uid];
|
|
143
|
+
const isPublished = ((_f = entry.publish_details) === null || _f === void 0 ? void 0 : _f.length) > 0;
|
|
144
|
+
cli_utilities_1.log.debug(`Entry ${uid} published status: ${isPublished}, missing mandatory fields: ${(fields === null || fields === void 0 ? void 0 : fields.length) || 0}`, this.config.auditContext);
|
|
145
|
+
if ((this.fix && fields.length && isPublished) || (!this.fix && fields)) {
|
|
146
|
+
const fixStatus = this.fix ? 'Fixed' : '';
|
|
147
|
+
cli_utilities_1.log.debug(`Applying fix status: ${fixStatus} to ${fields.length} fields`, this.config.auditContext);
|
|
148
|
+
fields === null || fields === void 0 ? void 0 : fields.forEach((field, index) => {
|
|
149
|
+
cli_utilities_1.log.debug(`Processing field ${index + 1}/${fields.length}`, this.config.auditContext);
|
|
150
|
+
field.isPublished = isPublished;
|
|
151
|
+
if (this.fix && isPublished) {
|
|
152
|
+
field.fixStatus = fixStatus;
|
|
153
|
+
cli_utilities_1.log.debug(`Field ${index + 1} marked as published and fixed`, this.config.auditContext);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
139
156
|
if (this.fix && isPublished) {
|
|
140
|
-
|
|
141
|
-
cli_utilities_1.log.
|
|
157
|
+
cli_utilities_1.log.debug(`Fixing mandatory field issue for entry ${uid}`, this.config.auditContext);
|
|
158
|
+
cli_utilities_1.log.error((0, messages_1.$t)(messages_1.auditFixMsg.ENTRY_MANDATORY_FIELD_FIX, { uid, locale: code }), this.config.auditContext);
|
|
159
|
+
entry.publish_details = [];
|
|
142
160
|
}
|
|
143
|
-
});
|
|
144
|
-
if (this.fix && isPublished) {
|
|
145
|
-
cli_utilities_1.log.debug(`Fixing mandatory field issue for entry ${uid}`, this.config.auditContext);
|
|
146
|
-
cli_utilities_1.log.error((0, messages_1.$t)(messages_1.auditFixMsg.ENTRY_MANDATORY_FIELD_FIX, { uid, locale: code }), this.config.auditContext);
|
|
147
|
-
entry.publish_details = [];
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
delete this.missingMandatoryFields[uid];
|
|
152
|
-
}
|
|
153
|
-
const localKey = this.locales.map((locale) => locale.code);
|
|
154
|
-
cli_utilities_1.log.debug(`Available locales: ${localKey.join(', ')}, environments: ${this.environments.join(', ')}`, this.config.auditContext);
|
|
155
|
-
if (((_g = this.entries[entryUid]) === null || _g === void 0 ? void 0 : _g.publish_details) && !Array.isArray(this.entries[entryUid].publish_details)) {
|
|
156
|
-
cli_utilities_1.log.debug(`Entry ${entryUid} has invalid publish_details format`, this.config.auditContext);
|
|
157
|
-
cli_utilities_1.log.debug((0, messages_1.$t)(messages_1.auditMsg.ENTRY_PUBLISH_DETAILS_NOT_EXIST, { uid: entryUid }), this.config.auditContext);
|
|
158
|
-
}
|
|
159
|
-
const originalPublishDetails = ((_j = (_h = this.entries[entryUid]) === null || _h === void 0 ? void 0 : _h.publish_details) === null || _j === void 0 ? void 0 : _j.length) || 0;
|
|
160
|
-
this.entries[entryUid].publish_details = (_k = this.entries[entryUid]) === null || _k === void 0 ? void 0 : _k.publish_details.filter((pd) => {
|
|
161
|
-
var _a;
|
|
162
|
-
cli_utilities_1.log.debug(`Checking publish detail: locale=${pd.locale}, environment=${pd.environment}`, this.config.auditContext);
|
|
163
|
-
if ((localKey === null || localKey === void 0 ? void 0 : localKey.includes(pd.locale)) && ((_a = this.environments) === null || _a === void 0 ? void 0 : _a.includes(pd.environment))) {
|
|
164
|
-
cli_utilities_1.log.debug(`Publish detail valid for entry ${entryUid}: locale=${pd.locale}, environment=${pd.environment}`, this.config.auditContext);
|
|
165
|
-
return true;
|
|
166
161
|
}
|
|
167
162
|
else {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
163
|
+
delete this.missingMandatoryFields[uid];
|
|
164
|
+
}
|
|
165
|
+
const localKey = this.locales.map((locale) => locale.code);
|
|
166
|
+
cli_utilities_1.log.debug(`Available locales: ${localKey.join(', ')}, environments: ${this.environments.join(', ')}`, this.config.auditContext);
|
|
167
|
+
if (((_g = this.entries[entryUid]) === null || _g === void 0 ? void 0 : _g.publish_details) && !Array.isArray(this.entries[entryUid].publish_details)) {
|
|
168
|
+
cli_utilities_1.log.debug(`Entry ${entryUid} has invalid publish_details format`, this.config.auditContext);
|
|
169
|
+
cli_utilities_1.log.debug((0, messages_1.$t)(messages_1.auditMsg.ENTRY_PUBLISH_DETAILS_NOT_EXIST, { uid: entryUid }), this.config.auditContext);
|
|
170
|
+
}
|
|
171
|
+
const originalPublishDetails = ((_j = (_h = this.entries[entryUid]) === null || _h === void 0 ? void 0 : _h.publish_details) === null || _j === void 0 ? void 0 : _j.length) || 0;
|
|
172
|
+
this.entries[entryUid].publish_details = (_k = this.entries[entryUid]) === null || _k === void 0 ? void 0 : _k.publish_details.filter((pd) => {
|
|
173
|
+
var _a;
|
|
174
|
+
cli_utilities_1.log.debug(`Checking publish detail: locale=${pd.locale}, environment=${pd.environment}`, this.config.auditContext);
|
|
175
|
+
if ((localKey === null || localKey === void 0 ? void 0 : localKey.includes(pd.locale)) && ((_a = this.environments) === null || _a === void 0 ? void 0 : _a.includes(pd.environment))) {
|
|
176
|
+
cli_utilities_1.log.debug(`Publish detail valid for entry ${entryUid}: locale=${pd.locale}, environment=${pd.environment}`, this.config.auditContext);
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
cli_utilities_1.log.debug(`Publish detail invalid for entry ${entryUid}: locale=${pd.locale}, environment=${pd.environment}`, this.config.auditContext);
|
|
181
|
+
cli_utilities_1.log.debug((0, messages_1.$t)(messages_1.auditMsg.ENTRY_PUBLISH_DETAILS, {
|
|
182
|
+
uid: entryUid,
|
|
183
|
+
ctuid: ctSchema.uid,
|
|
184
|
+
locale: code,
|
|
185
|
+
publocale: pd.locale,
|
|
186
|
+
environment: pd.environment,
|
|
187
|
+
}), this.config.auditContext);
|
|
188
|
+
if (!Object.keys(this.missingEnvLocale).includes(entryUid)) {
|
|
189
|
+
cli_utilities_1.log.debug(`Creating new missing environment/locale entry for ${entryUid}`, this.config.auditContext);
|
|
190
|
+
this.missingEnvLocale[entryUid] = [
|
|
191
|
+
{
|
|
192
|
+
entry_uid: entryUid,
|
|
193
|
+
publish_locale: pd.locale,
|
|
194
|
+
publish_environment: pd.environment,
|
|
195
|
+
ctUid: ctSchema.uid,
|
|
196
|
+
ctLocale: code,
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
cli_utilities_1.log.debug(`Adding to existing missing environment/locale entry for ${entryUid}`, this.config.auditContext);
|
|
202
|
+
this.missingEnvLocale[entryUid].push({
|
|
180
203
|
entry_uid: entryUid,
|
|
181
204
|
publish_locale: pd.locale,
|
|
182
205
|
publish_environment: pd.environment,
|
|
183
206
|
ctUid: ctSchema.uid,
|
|
184
207
|
ctLocale: code,
|
|
185
|
-
}
|
|
186
|
-
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
187
211
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
});
|
|
213
|
+
const remainingPublishDetails = ((_l = this.entries[entryUid].publish_details) === null || _l === void 0 ? void 0 : _l.length) || 0;
|
|
214
|
+
cli_utilities_1.log.debug(`Entry ${entryUid} publish details: ${originalPublishDetails} -> ${remainingPublishDetails}`, this.config.auditContext);
|
|
215
|
+
const message = (0, messages_1.$t)(messages_1.auditMsg.SCAN_ENTRY_SUCCESS_MSG, {
|
|
216
|
+
title,
|
|
217
|
+
local: code,
|
|
218
|
+
module: this.config.moduleConfig.entries.name,
|
|
219
|
+
});
|
|
220
|
+
cli_utilities_1.log.debug(message, this.config.auditContext);
|
|
221
|
+
cli_utilities_1.log.info(message, this.config.auditContext);
|
|
222
|
+
// Track progress for each entry processed
|
|
223
|
+
if (this.progressManager) {
|
|
224
|
+
this.progressManager.tick(true, `entry: ${title || uid}`, null);
|
|
199
225
|
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
local: code,
|
|
206
|
-
module: this.config.moduleConfig.entries.name,
|
|
207
|
-
});
|
|
208
|
-
cli_utilities_1.log.debug(message, this.config.auditContext);
|
|
209
|
-
cli_utilities_1.log.info(message, this.config.auditContext);
|
|
210
|
-
}
|
|
211
|
-
if (this.fix) {
|
|
212
|
-
cli_utilities_1.log.debug(`Writing fix content for ${Object.keys(this.entries).length} entries`, this.config.auditContext);
|
|
213
|
-
await this.writeFixContent(`${basePath}/${indexer[fileIndex]}`, this.entries);
|
|
226
|
+
}
|
|
227
|
+
if (this.fix) {
|
|
228
|
+
cli_utilities_1.log.debug(`Writing fix content for ${Object.keys(this.entries).length} entries`, this.config.auditContext);
|
|
229
|
+
await this.writeFixContent(`${basePath}/${indexer[fileIndex]}`, this.entries);
|
|
230
|
+
}
|
|
214
231
|
}
|
|
215
232
|
}
|
|
216
233
|
}
|
|
234
|
+
cli_utilities_1.log.debug('Cleaning up empty missing references', this.config.auditContext);
|
|
235
|
+
this.removeEmptyVal();
|
|
236
|
+
const result = {
|
|
237
|
+
missingEntryRefs: this.missingRefs,
|
|
238
|
+
missingSelectFeild: this.missingSelectFeild,
|
|
239
|
+
missingMandatoryFields: this.missingMandatoryFields,
|
|
240
|
+
missingTitleFields: this.missingTitleFields,
|
|
241
|
+
missingEnvLocale: this.missingEnvLocale,
|
|
242
|
+
missingMultipleFields: this.missingMultipleField,
|
|
243
|
+
};
|
|
244
|
+
cli_utilities_1.log.debug(`Entries audit completed. Found issues:`, this.config.auditContext);
|
|
245
|
+
cli_utilities_1.log.debug(`- Missing references: ${Object.keys(this.missingRefs).length}`, this.config.auditContext);
|
|
246
|
+
cli_utilities_1.log.debug(`- Missing select fields: ${Object.keys(this.missingSelectFeild).length}`, this.config.auditContext);
|
|
247
|
+
cli_utilities_1.log.debug(`- Missing mandatory fields: ${Object.keys(this.missingMandatoryFields).length}`, this.config.auditContext);
|
|
248
|
+
cli_utilities_1.log.debug(`- Missing title fields: ${Object.keys(this.missingTitleFields).length}`, this.config.auditContext);
|
|
249
|
+
cli_utilities_1.log.debug(`- Missing environment/locale: ${Object.keys(this.missingEnvLocale).length}`, this.config.auditContext);
|
|
250
|
+
cli_utilities_1.log.debug(`- Missing multiple fields: ${Object.keys(this.missingMultipleField).length}`, this.config.auditContext);
|
|
251
|
+
this.completeProgress(true);
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Entries audit failed');
|
|
256
|
+
throw error;
|
|
217
257
|
}
|
|
218
|
-
cli_utilities_1.log.debug('Cleaning up empty missing references', this.config.auditContext);
|
|
219
|
-
this.removeEmptyVal();
|
|
220
|
-
const result = {
|
|
221
|
-
missingEntryRefs: this.missingRefs,
|
|
222
|
-
missingSelectFeild: this.missingSelectFeild,
|
|
223
|
-
missingMandatoryFields: this.missingMandatoryFields,
|
|
224
|
-
missingTitleFields: this.missingTitleFields,
|
|
225
|
-
missingEnvLocale: this.missingEnvLocale,
|
|
226
|
-
missingMultipleFields: this.missingMultipleField,
|
|
227
|
-
};
|
|
228
|
-
cli_utilities_1.log.debug(`Entries audit completed. Found issues:`, this.config.auditContext);
|
|
229
|
-
cli_utilities_1.log.debug(`- Missing references: ${Object.keys(this.missingRefs).length}`, this.config.auditContext);
|
|
230
|
-
cli_utilities_1.log.debug(`- Missing select fields: ${Object.keys(this.missingSelectFeild).length}`, this.config.auditContext);
|
|
231
|
-
cli_utilities_1.log.debug(`- Missing mandatory fields: ${Object.keys(this.missingMandatoryFields).length}`, this.config.auditContext);
|
|
232
|
-
cli_utilities_1.log.debug(`- Missing title fields: ${Object.keys(this.missingTitleFields).length}`, this.config.auditContext);
|
|
233
|
-
cli_utilities_1.log.debug(`- Missing environment/locale: ${Object.keys(this.missingEnvLocale).length}`, this.config.auditContext);
|
|
234
|
-
cli_utilities_1.log.debug(`- Missing multiple fields: ${Object.keys(this.missingMultipleField).length}`, this.config.auditContext);
|
|
235
|
-
return result;
|
|
236
258
|
}
|
|
237
259
|
/**
|
|
238
260
|
* The function removes any properties from the `missingRefs` object that have an empty array value.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ContentTypeStruct, CtConstructorParam, ModuleConstructorParam, Extension } from '../types';
|
|
2
2
|
import auditConfig from '../config';
|
|
3
|
-
|
|
3
|
+
import BaseClass from './base-class';
|
|
4
|
+
export default class Extensions extends BaseClass {
|
|
4
5
|
protected fix: boolean;
|
|
5
6
|
fileName: any;
|
|
6
|
-
config: ConfigType;
|
|
7
7
|
folderPath: string;
|
|
8
8
|
extensionsSchema: Extension[];
|
|
9
9
|
ctSchema: ContentTypeStruct[];
|
|
@@ -14,7 +14,7 @@ export default class Extensions {
|
|
|
14
14
|
extensionsPath: string;
|
|
15
15
|
constructor({ fix, config, moduleName, ctSchema, }: ModuleConstructorParam & Pick<CtConstructorParam, 'ctSchema'>);
|
|
16
16
|
validateModules(moduleName: keyof typeof auditConfig.moduleConfig, moduleConfig: Record<string, unknown>): keyof typeof auditConfig.moduleConfig;
|
|
17
|
-
run(): Promise<{}>;
|
|
17
|
+
run(totalCount?: number): Promise<{}>;
|
|
18
18
|
fixExtensionsScope(missingCtInExtensions: Extension[]): Promise<void>;
|
|
19
19
|
writeFixContent(fixedExtensions: Record<string, Extension>): Promise<void>;
|
|
20
20
|
}
|
|
@@ -7,9 +7,10 @@ const lodash_1 = require("lodash");
|
|
|
7
7
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
8
8
|
const messages_1 = require("../messages");
|
|
9
9
|
const lodash_2 = require("lodash");
|
|
10
|
-
|
|
10
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
11
|
+
class Extensions extends base_class_1.default {
|
|
11
12
|
constructor({ fix, config, moduleName, ctSchema, }) {
|
|
12
|
-
|
|
13
|
+
super({ config });
|
|
13
14
|
this.fix = fix !== null && fix !== void 0 ? fix : false;
|
|
14
15
|
this.ctSchema = ctSchema;
|
|
15
16
|
this.extensionsSchema = [];
|
|
@@ -38,67 +39,86 @@ class Extensions {
|
|
|
38
39
|
cli_utilities_1.log.debug(`Module ${moduleName} not found, defaulting to 'extensions'`, this.config.auditContext);
|
|
39
40
|
return 'extensions';
|
|
40
41
|
}
|
|
41
|
-
async run() {
|
|
42
|
+
async run(totalCount) {
|
|
42
43
|
var _a, _b;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
this.extensionsPath = path_1.default.join(this.folderPath, this.fileName);
|
|
53
|
-
cli_utilities_1.log.debug(`Extensions file path: ${this.extensionsPath}`, this.config.auditContext);
|
|
54
|
-
cli_utilities_1.log.debug(`Loading extensions schema from file`, this.config.auditContext);
|
|
55
|
-
this.extensionsSchema = (0, fs_1.existsSync)(this.extensionsPath)
|
|
56
|
-
? (0, lodash_2.values)(JSON.parse((0, fs_1.readFileSync)(this.extensionsPath, 'utf-8')))
|
|
57
|
-
: [];
|
|
58
|
-
cli_utilities_1.log.debug(`Loaded ${this.extensionsSchema.length} extensions`, this.config.auditContext);
|
|
59
|
-
cli_utilities_1.log.debug(`Building content type UID set from ${this.ctSchema.length} content types`, this.config.auditContext);
|
|
60
|
-
this.ctSchema.map((ct) => this.ctUidSet.add(ct.uid));
|
|
61
|
-
cli_utilities_1.log.debug(`Content type UID set contains: ${Array.from(this.ctUidSet).join(', ')}`, this.config.auditContext);
|
|
62
|
-
cli_utilities_1.log.debug(`Processing ${this.extensionsSchema.length} extensions`, this.config.auditContext);
|
|
63
|
-
for (const ext of this.extensionsSchema) {
|
|
64
|
-
const { title, uid, scope } = ext;
|
|
65
|
-
cli_utilities_1.log.debug(`Processing extension: ${title} (${uid})`, this.config.auditContext);
|
|
66
|
-
cli_utilities_1.log.debug(`Extension scope content types: ${((_a = scope === null || scope === void 0 ? void 0 : scope.content_types) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'none'}`, this.config.auditContext);
|
|
67
|
-
const ctNotPresent = scope === null || scope === void 0 ? void 0 : scope.content_types.filter((ct) => !this.ctUidSet.has(ct));
|
|
68
|
-
cli_utilities_1.log.debug(`Missing content types in extension: ${(ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.join(', ')) || 'none'}`, this.config.auditContext);
|
|
69
|
-
if ((ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.length) && ext.scope) {
|
|
70
|
-
cli_utilities_1.log.debug(`Extension ${title} has ${ctNotPresent.length} missing content types`, this.config.auditContext);
|
|
71
|
-
ext.content_types = ctNotPresent;
|
|
72
|
-
ctNotPresent.forEach((ct) => {
|
|
73
|
-
var _a;
|
|
74
|
-
cli_utilities_1.log.debug(`Adding missing content type: ${ct} to the Audit report.`, this.config.auditContext);
|
|
75
|
-
(_a = this.missingCts) === null || _a === void 0 ? void 0 : _a.add(ct);
|
|
76
|
-
});
|
|
77
|
-
(_b = this.missingCtInExtensions) === null || _b === void 0 ? void 0 : _b.push((0, lodash_1.cloneDeep)(ext));
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
cli_utilities_1.log.debug(`Extension ${title} has no missing content types`, this.config.auditContext);
|
|
44
|
+
try {
|
|
45
|
+
cli_utilities_1.log.debug(`Starting ${this.moduleName} audit process`, this.config.auditContext);
|
|
46
|
+
cli_utilities_1.log.debug(`Extensions folder path: ${this.folderPath}`, this.config.auditContext);
|
|
47
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
48
|
+
if (!(0, fs_1.existsSync)(this.folderPath)) {
|
|
49
|
+
cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
|
|
50
|
+
cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
|
|
51
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
|
|
52
|
+
return {};
|
|
81
53
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
cli_utilities_1.log.debug(`Total missing content types: ${this.missingCts.size}`, this.config.auditContext);
|
|
90
|
-
if (this.fix && this.missingCtInExtensions.length) {
|
|
91
|
-
cli_utilities_1.log.debug(`Fix mode enabled, fixing ${this.missingCtInExtensions.length} extensions`, this.config.auditContext);
|
|
92
|
-
await this.fixExtensionsScope((0, lodash_1.cloneDeep)(this.missingCtInExtensions));
|
|
93
|
-
this.missingCtInExtensions.forEach((ext) => {
|
|
94
|
-
cli_utilities_1.log.debug(`Marking extension ${ext.title} as fixed`, this.config.auditContext);
|
|
95
|
-
ext.fixStatus = 'Fixed';
|
|
54
|
+
this.extensionsPath = path_1.default.join(this.folderPath, this.fileName);
|
|
55
|
+
cli_utilities_1.log.debug(`Extensions file path: ${this.extensionsPath}`, this.config.auditContext);
|
|
56
|
+
// Load extensions schema with loading spinner
|
|
57
|
+
await this.withLoadingSpinner('EXTENSIONS: Loading extensions schema...', async () => {
|
|
58
|
+
this.extensionsSchema = (0, fs_1.existsSync)(this.extensionsPath)
|
|
59
|
+
? (0, lodash_2.values)(JSON.parse((0, fs_1.readFileSync)(this.extensionsPath, 'utf-8')))
|
|
60
|
+
: [];
|
|
96
61
|
});
|
|
97
|
-
cli_utilities_1.log.debug(`
|
|
62
|
+
cli_utilities_1.log.debug(`Loaded ${this.extensionsSchema.length} extensions`, this.config.auditContext);
|
|
63
|
+
cli_utilities_1.log.debug(`Building content type UID set from ${this.ctSchema.length} content types`, this.config.auditContext);
|
|
64
|
+
this.ctSchema.map((ct) => this.ctUidSet.add(ct.uid));
|
|
65
|
+
cli_utilities_1.log.debug(`Content type UID set contains: ${Array.from(this.ctUidSet).join(', ')}`, this.config.auditContext);
|
|
66
|
+
// Create progress manager if we have a total count
|
|
67
|
+
if (totalCount && totalCount > 0) {
|
|
68
|
+
const progress = this.createSimpleProgress(this.moduleName, totalCount);
|
|
69
|
+
progress.updateStatus('Validating extensions...');
|
|
70
|
+
}
|
|
71
|
+
cli_utilities_1.log.debug(`Processing ${this.extensionsSchema.length} extensions`, this.config.auditContext);
|
|
72
|
+
for (const ext of this.extensionsSchema) {
|
|
73
|
+
const { title, uid, scope } = ext;
|
|
74
|
+
cli_utilities_1.log.debug(`Processing extension: ${title} (${uid})`, this.config.auditContext);
|
|
75
|
+
cli_utilities_1.log.debug(`Extension scope content types: ${((_a = scope === null || scope === void 0 ? void 0 : scope.content_types) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'none'}`, this.config.auditContext);
|
|
76
|
+
const ctNotPresent = scope === null || scope === void 0 ? void 0 : scope.content_types.filter((ct) => !this.ctUidSet.has(ct));
|
|
77
|
+
cli_utilities_1.log.debug(`Missing content types in extension: ${(ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.join(', ')) || 'none'}`, this.config.auditContext);
|
|
78
|
+
if ((ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.length) && ext.scope) {
|
|
79
|
+
cli_utilities_1.log.debug(`Extension ${title} has ${ctNotPresent.length} missing content types`, this.config.auditContext);
|
|
80
|
+
ext.content_types = ctNotPresent;
|
|
81
|
+
ctNotPresent.forEach((ct) => {
|
|
82
|
+
var _a;
|
|
83
|
+
cli_utilities_1.log.debug(`Adding missing content type: ${ct} to the Audit report.`, this.config.auditContext);
|
|
84
|
+
(_a = this.missingCts) === null || _a === void 0 ? void 0 : _a.add(ct);
|
|
85
|
+
});
|
|
86
|
+
(_b = this.missingCtInExtensions) === null || _b === void 0 ? void 0 : _b.push((0, lodash_1.cloneDeep)(ext));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
cli_utilities_1.log.debug(`Extension ${title} has no missing content types`, this.config.auditContext);
|
|
90
|
+
}
|
|
91
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_EXT_SUCCESS_MSG, {
|
|
92
|
+
title,
|
|
93
|
+
module: this.config.moduleConfig[this.moduleName].name,
|
|
94
|
+
uid,
|
|
95
|
+
}), this.config.auditContext);
|
|
96
|
+
// Track progress for each extension processed
|
|
97
|
+
if (this.progressManager) {
|
|
98
|
+
this.progressManager.tick(true, `extension: ${title}`, null);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
cli_utilities_1.log.debug(`Extensions audit completed. Found ${this.missingCtInExtensions.length} extensions with missing content types`, this.config.auditContext);
|
|
102
|
+
cli_utilities_1.log.debug(`Total missing content types: ${this.missingCts.size}`, this.config.auditContext);
|
|
103
|
+
if (this.fix && this.missingCtInExtensions.length) {
|
|
104
|
+
cli_utilities_1.log.debug(`Fix mode enabled, fixing ${this.missingCtInExtensions.length} extensions`, this.config.auditContext);
|
|
105
|
+
await this.fixExtensionsScope((0, lodash_1.cloneDeep)(this.missingCtInExtensions));
|
|
106
|
+
this.missingCtInExtensions.forEach((ext) => {
|
|
107
|
+
cli_utilities_1.log.debug(`Marking extension ${ext.title} as fixed`, this.config.auditContext);
|
|
108
|
+
ext.fixStatus = 'Fixed';
|
|
109
|
+
});
|
|
110
|
+
cli_utilities_1.log.debug(`Extensions fix completed`, this.config.auditContext);
|
|
111
|
+
this.completeProgress(true);
|
|
112
|
+
return this.missingCtInExtensions;
|
|
113
|
+
}
|
|
114
|
+
cli_utilities_1.log.debug(`Extensions audit completed without fixes`, this.config.auditContext);
|
|
115
|
+
this.completeProgress(true);
|
|
98
116
|
return this.missingCtInExtensions;
|
|
99
117
|
}
|
|
100
|
-
|
|
101
|
-
|
|
118
|
+
catch (error) {
|
|
119
|
+
this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Extensions audit failed');
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
102
122
|
}
|
|
103
123
|
async fixExtensionsScope(missingCtInExtensions) {
|
|
104
124
|
var _a, _b, _c, _d;
|