@contentstack/cli-audit 1.14.2 → 1.16.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 +13 -13
- 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 +478 -63
- 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
package/lib/modules/assets.js
CHANGED
|
@@ -10,12 +10,11 @@ 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 Assets {
|
|
13
|
-
constructor({
|
|
13
|
+
constructor({ fix, config, moduleName }) {
|
|
14
14
|
this.locales = [];
|
|
15
15
|
this.environments = [];
|
|
16
16
|
this.schema = [];
|
|
17
17
|
this.missingEnvLocales = {};
|
|
18
|
-
this.log = log;
|
|
19
18
|
this.config = config;
|
|
20
19
|
this.fix = fix !== null && fix !== void 0 ? fix : false;
|
|
21
20
|
this.moduleName = this.validateModules(moduleName, this.config.moduleConfig);
|
|
@@ -34,16 +33,25 @@ class Assets {
|
|
|
34
33
|
* @returns the `missingEnvLocales` object.
|
|
35
34
|
*/
|
|
36
35
|
async run(returnFixSchema = false) {
|
|
36
|
+
var _a;
|
|
37
|
+
cli_utilities_1.log.debug(`Starting ${this.moduleName} audit process`, this.config.auditContext);
|
|
38
|
+
cli_utilities_1.log.debug(`Data directory: ${this.folderPath}`, this.config.auditContext);
|
|
39
|
+
cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
|
|
37
40
|
if (!(0, fs_1.existsSync)(this.folderPath)) {
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
|
|
42
|
+
cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
|
|
43
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
|
|
40
44
|
return returnFixSchema ? [] : {};
|
|
41
45
|
}
|
|
46
|
+
cli_utilities_1.log.debug('Loading prerequisite data (locales and environments)', this.config.auditContext);
|
|
42
47
|
await this.prerequisiteData();
|
|
48
|
+
cli_utilities_1.log.debug('Starting asset Reference, Environment and Locale validation', this.config.auditContext);
|
|
43
49
|
await this.lookForReference();
|
|
44
50
|
if (returnFixSchema) {
|
|
51
|
+
cli_utilities_1.log.debug(`Returning fixed schema with ${((_a = this.schema) === null || _a === void 0 ? void 0 : _a.length) || 0} items`, this.config.auditContext);
|
|
45
52
|
return this.schema;
|
|
46
53
|
}
|
|
54
|
+
cli_utilities_1.log.debug('Cleaning up empty missing environment/locale references', this.config.auditContext);
|
|
47
55
|
for (let propName in this.missingEnvLocales) {
|
|
48
56
|
if (Array.isArray(this.missingEnvLocales[propName])) {
|
|
49
57
|
if (!this.missingEnvLocales[propName].length) {
|
|
@@ -51,6 +59,8 @@ class Assets {
|
|
|
51
59
|
}
|
|
52
60
|
}
|
|
53
61
|
}
|
|
62
|
+
const totalIssues = Object.keys(this.missingEnvLocales).length;
|
|
63
|
+
cli_utilities_1.log.debug(`${this.moduleName} audit completed. Found ${totalIssues} assets with missing environment/locale references`, this.config.auditContext);
|
|
54
64
|
return this.missingEnvLocales;
|
|
55
65
|
}
|
|
56
66
|
/**
|
|
@@ -59,17 +69,33 @@ class Assets {
|
|
|
59
69
|
* app data, and stores them in the `extensions` array.
|
|
60
70
|
*/
|
|
61
71
|
async prerequisiteData() {
|
|
62
|
-
|
|
72
|
+
cli_utilities_1.log.debug('Loading prerequisite data (locales and environments)', this.config.auditContext);
|
|
73
|
+
cli_utilities_1.log.info(messages_1.auditMsg.PREPARING_ENTRY_METADATA, this.config.auditContext);
|
|
63
74
|
const localesFolderPath = (0, path_1.resolve)(this.config.basePath, this.config.moduleConfig.locales.dirName);
|
|
64
75
|
const localesPath = (0, path_1.join)(localesFolderPath, this.config.moduleConfig.locales.fileName);
|
|
65
76
|
const masterLocalesPath = (0, path_1.join)(localesFolderPath, 'master-locale.json');
|
|
77
|
+
cli_utilities_1.log.debug(`Loading locales from: ${localesFolderPath}`, this.config.auditContext);
|
|
78
|
+
cli_utilities_1.log.debug(`Master locales path: ${masterLocalesPath}`, this.config.auditContext);
|
|
79
|
+
cli_utilities_1.log.debug(`Locales path: ${localesPath}`, this.config.auditContext);
|
|
66
80
|
this.locales = (0, fs_1.existsSync)(masterLocalesPath) ? (0, values_1.default)(JSON.parse((0, fs_1.readFileSync)(masterLocalesPath, 'utf8'))) : [];
|
|
81
|
+
cli_utilities_1.log.debug(`Loaded ${this.locales.length} locales from master-locale.json`, this.config.auditContext);
|
|
67
82
|
if ((0, fs_1.existsSync)(localesPath)) {
|
|
68
|
-
|
|
83
|
+
cli_utilities_1.log.debug(`Loading additional locales from: ${localesPath}`, this.config.auditContext);
|
|
84
|
+
const additionalLocales = (0, values_1.default)(JSON.parse((0, fs_1.readFileSync)(localesPath, 'utf8')));
|
|
85
|
+
this.locales.push(...additionalLocales);
|
|
86
|
+
cli_utilities_1.log.debug(`Added ${additionalLocales.length} additional locales`, this.config.auditContext);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
cli_utilities_1.log.debug('No additional locales file found', this.config.auditContext);
|
|
69
90
|
}
|
|
70
91
|
this.locales = this.locales.map((locale) => locale.code);
|
|
92
|
+
cli_utilities_1.log.debug(`Total locales loaded: ${this.locales.length}`, this.config.auditContext);
|
|
93
|
+
cli_utilities_1.log.debug(`Locale codes: ${this.locales.join(', ')}`, this.config.auditContext);
|
|
71
94
|
const environmentPath = (0, path_1.resolve)(this.config.basePath, this.config.moduleConfig.environments.dirName, this.config.moduleConfig.environments.fileName);
|
|
95
|
+
cli_utilities_1.log.debug(`Loading environments from: ${environmentPath}`, this.config.auditContext);
|
|
72
96
|
this.environments = (0, fs_1.existsSync)(environmentPath) ? (0, lodash_1.keys)(JSON.parse((0, fs_1.readFileSync)(environmentPath, 'utf8'))) : [];
|
|
97
|
+
cli_utilities_1.log.debug(`Total environments loaded: ${this.environments.length}`, this.config.auditContext);
|
|
98
|
+
cli_utilities_1.log.debug(`Environment names: ${this.environments.join(', ')}`, this.config.auditContext);
|
|
73
99
|
}
|
|
74
100
|
/**
|
|
75
101
|
* The function checks if it can write the fix content to a file and if so, it writes the content as
|
|
@@ -77,61 +103,93 @@ class Assets {
|
|
|
77
103
|
*/
|
|
78
104
|
async writeFixContent(filePath, schema) {
|
|
79
105
|
var _a;
|
|
106
|
+
cli_utilities_1.log.debug(`Starting writeFixContent process for: ${filePath}`, this.config.auditContext);
|
|
80
107
|
let canWrite = true;
|
|
81
108
|
if (this.fix) {
|
|
109
|
+
cli_utilities_1.log.debug('Fix mode enabled, checking write permissions', this.config.auditContext);
|
|
82
110
|
if (!this.config.flags['copy-dir'] && !((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm)) {
|
|
111
|
+
cli_utilities_1.log.debug(`Asking user for confirmation to write fix content (--yes flag: ${this.config.flags.yes})`, this.config.auditContext);
|
|
83
112
|
canWrite = this.config.flags.yes || (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
|
|
84
113
|
}
|
|
114
|
+
else {
|
|
115
|
+
cli_utilities_1.log.debug('Skipping confirmation due to copy-dir or external-config flags', this.config.auditContext);
|
|
116
|
+
}
|
|
85
117
|
if (canWrite) {
|
|
118
|
+
cli_utilities_1.log.debug(`Writing fixed assets to: ${filePath}`, this.config.auditContext);
|
|
86
119
|
(0, fs_1.writeFileSync)(filePath, JSON.stringify(schema));
|
|
120
|
+
cli_utilities_1.log.debug(`Successfully wrote ${Object.keys(schema).length} assets to file`, this.config.auditContext);
|
|
87
121
|
}
|
|
122
|
+
else {
|
|
123
|
+
cli_utilities_1.log.debug('User declined to write fix content', this.config.auditContext);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
cli_utilities_1.log.debug('Skipping writeFixContent - not in fix mode', this.config.auditContext);
|
|
88
128
|
}
|
|
89
129
|
}
|
|
90
130
|
/**
|
|
91
131
|
* This function traverse over the publish detials of the assets and remove the publish details where the locale or environment does not exist
|
|
92
132
|
*/
|
|
93
133
|
async lookForReference() {
|
|
94
|
-
var _a, _b;
|
|
134
|
+
var _a, _b, _c, _d;
|
|
135
|
+
cli_utilities_1.log.debug('Starting asset reference validation', this.config.auditContext);
|
|
95
136
|
let basePath = (0, path_1.join)(this.folderPath);
|
|
137
|
+
cli_utilities_1.log.debug(`Assets base path: ${basePath}`, this.config.auditContext);
|
|
96
138
|
let fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: 'assets.json' });
|
|
97
139
|
let indexer = fsUtility.indexFileContent;
|
|
140
|
+
cli_utilities_1.log.debug(`Found ${Object.keys(indexer).length} asset files to process`, this.config.auditContext);
|
|
98
141
|
for (const fileIndex in indexer) {
|
|
142
|
+
cli_utilities_1.log.debug(`Processing asset file: ${indexer[fileIndex]}`, this.config.auditContext);
|
|
99
143
|
const assets = (await fsUtility.readChunkFiles.next());
|
|
100
144
|
this.assets = assets;
|
|
145
|
+
cli_utilities_1.log.debug(`Loaded ${Object.keys(assets).length} assets from file`, this.config.auditContext);
|
|
101
146
|
for (const assetUid in assets) {
|
|
147
|
+
cli_utilities_1.log.debug(`Processing asset: ${assetUid}`, this.config.auditContext);
|
|
102
148
|
if (((_a = this.assets[assetUid]) === null || _a === void 0 ? void 0 : _a.publish_details) && !Array.isArray(this.assets[assetUid].publish_details)) {
|
|
103
|
-
|
|
149
|
+
cli_utilities_1.log.debug(`Asset ${assetUid} has invalid publish_details format`, this.config.auditContext);
|
|
150
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.ASSET_NOT_EXIST, { uid: assetUid }), { color: 'red' });
|
|
104
151
|
}
|
|
105
|
-
|
|
152
|
+
const publishDetails = (_b = this.assets[assetUid]) === null || _b === void 0 ? void 0 : _b.publish_details;
|
|
153
|
+
cli_utilities_1.log.debug(`Asset ${assetUid} has ${(publishDetails === null || publishDetails === void 0 ? void 0 : publishDetails.length) || 0} publish details`, this.config.auditContext);
|
|
154
|
+
this.assets[assetUid].publish_details = (_c = this.assets[assetUid]) === null || _c === void 0 ? void 0 : _c.publish_details.filter((pd) => {
|
|
106
155
|
var _a, _b;
|
|
156
|
+
cli_utilities_1.log.debug(`Checking publish detail: locale=${pd === null || pd === void 0 ? void 0 : pd.locale}, environment=${pd === null || pd === void 0 ? void 0 : pd.environment}`, this.config.auditContext);
|
|
107
157
|
if (((_a = this.locales) === null || _a === void 0 ? void 0 : _a.includes(pd === null || pd === void 0 ? void 0 : pd.locale)) && ((_b = this.environments) === null || _b === void 0 ? void 0 : _b.includes(pd === null || pd === void 0 ? void 0 : pd.environment))) {
|
|
108
|
-
|
|
158
|
+
cli_utilities_1.log.debug(`Publish detail valid for asset ${assetUid}: locale=${pd.locale}, environment=${pd.environment}`, this.config.auditContext);
|
|
159
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_ASSET_SUCCESS_MSG, { uid: assetUid }), this.config.auditContext);
|
|
109
160
|
return true;
|
|
110
161
|
}
|
|
111
162
|
else {
|
|
112
|
-
|
|
163
|
+
cli_utilities_1.log.debug(`Publish detail invalid for asset ${assetUid}: locale=${pd.locale}, environment=${pd.environment}`, this.config.auditContext);
|
|
164
|
+
cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.SCAN_ASSET_WARN_MSG, { uid: assetUid, locale: pd.locale, environment: pd.environment }), { color: 'yellow' });
|
|
113
165
|
if (!Object.keys(this.missingEnvLocales).includes(assetUid)) {
|
|
166
|
+
cli_utilities_1.log.debug(`Creating new missing reference entry for asset ${assetUid}`, this.config.auditContext);
|
|
114
167
|
this.missingEnvLocales[assetUid] = [
|
|
115
168
|
{ asset_uid: assetUid, publish_locale: pd.locale, publish_environment: pd.environment },
|
|
116
169
|
];
|
|
117
170
|
}
|
|
118
171
|
else {
|
|
172
|
+
cli_utilities_1.log.debug(`Adding to existing missing reference entry for asset ${assetUid}`, this.config.auditContext);
|
|
119
173
|
this.missingEnvLocales[assetUid].push({
|
|
120
174
|
asset_uid: assetUid,
|
|
121
175
|
publish_locale: pd.locale,
|
|
122
176
|
publish_environment: pd.environment,
|
|
123
177
|
});
|
|
124
178
|
}
|
|
125
|
-
|
|
179
|
+
cli_utilities_1.log.success((0, messages_1.$t)(messages_1.auditMsg.SCAN_ASSET_SUCCESS_MSG, { uid: assetUid }), this.config.auditContext);
|
|
126
180
|
return false;
|
|
127
181
|
}
|
|
128
182
|
});
|
|
183
|
+
const remainingPublishDetails = ((_d = this.assets[assetUid].publish_details) === null || _d === void 0 ? void 0 : _d.length) || 0;
|
|
184
|
+
cli_utilities_1.log.debug(`Asset ${assetUid} now has ${remainingPublishDetails} valid publish details`, this.config.auditContext);
|
|
129
185
|
if (this.fix) {
|
|
130
|
-
|
|
186
|
+
cli_utilities_1.log.debug(`Fixing asset ${assetUid}`, this.config.auditContext);
|
|
187
|
+
cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditFixMsg.ASSET_FIX, { uid: assetUid }), this.config.auditContext);
|
|
131
188
|
await this.writeFixContent(`${basePath}/${indexer[fileIndex]}`, this.assets);
|
|
132
189
|
}
|
|
133
190
|
}
|
|
134
191
|
}
|
|
192
|
+
cli_utilities_1.log.debug(`Asset reference validation completed. Processed ${Object.keys(this.missingEnvLocales).length} assets with issues`, this.config.auditContext);
|
|
135
193
|
}
|
|
136
194
|
}
|
|
137
195
|
exports.default = Assets;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigType, ModularBlockType, ContentTypeStruct, GroupFieldDataType, RefErrorReturnType, CtConstructorParam, GlobalFieldDataType, JsonRTEFieldDataType, ModularBlocksDataType, ModuleConstructorParam, ReferenceFieldDataType, ContentTypeSchemaType, ExtensionOrAppFieldDataType } from '../types';
|
|
2
2
|
import auditConfig from '../config';
|
|
3
3
|
export default class ContentType {
|
|
4
|
-
log: LogFn;
|
|
5
4
|
protected fix: boolean;
|
|
6
5
|
fileName: string;
|
|
7
6
|
config: ConfigType;
|
|
@@ -15,7 +14,7 @@ export default class ContentType {
|
|
|
15
14
|
protected schema: ContentTypeStruct[];
|
|
16
15
|
protected missingRefs: Record<string, any>;
|
|
17
16
|
moduleName: keyof typeof auditConfig.moduleConfig;
|
|
18
|
-
constructor({
|
|
17
|
+
constructor({ fix, config, moduleName, ctSchema, gfSchema }: ModuleConstructorParam & CtConstructorParam);
|
|
19
18
|
validateModules(moduleName: keyof typeof auditConfig.moduleConfig, moduleConfig: Record<string, unknown>): keyof typeof auditConfig.moduleConfig;
|
|
20
19
|
/**
|
|
21
20
|
* The `run` function checks if a folder path exists, sets the schema based on the module name,
|
|
@@ -127,7 +126,7 @@ export default class ContentType {
|
|
|
127
126
|
* contains properties such as `data_type`, `field_metadata`, `uid`, `name`, etc.
|
|
128
127
|
* @returns an array of ContentTypeSchemaType objects.
|
|
129
128
|
*/
|
|
130
|
-
runFixOnSchema(tree: Record<string, unknown>[], schema: ContentTypeSchemaType[]):
|
|
129
|
+
runFixOnSchema(tree: Record<string, unknown>[], schema: ContentTypeSchemaType[]): any[];
|
|
131
130
|
/**
|
|
132
131
|
* The function fixes global field references in a tree structure by adding missing references and
|
|
133
132
|
* returning the field if the reference exists, otherwise returning null.
|