@contentstack/cli-audit 1.10.0 → 1.12.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.
@@ -67,6 +67,7 @@ class Entries {
67
67
  const { uid, title } = entry;
68
68
  this.currentUid = uid;
69
69
  this.currentTitle = title;
70
+ this.currentTitle = this.removeEmojiAndImages(this.currentTitle);
70
71
  if (!this.missingRefs[this.currentUid]) {
71
72
  this.missingRefs[this.currentUid] = [];
72
73
  }
@@ -79,7 +80,7 @@ class Entries {
79
80
  if (this.fix) {
80
81
  this.removeMissingKeysOnEntry(ctSchema.schema, this.entries[entryUid]);
81
82
  }
82
- this.lookForReference([{ locale: code, uid, name: title }], ctSchema, this.entries[entryUid]);
83
+ this.lookForReference([{ locale: code, uid, name: this.removeEmojiAndImages(title) }], ctSchema, this.entries[entryUid]);
83
84
  if ((_a = this.missingRefs[this.currentUid]) === null || _a === void 0 ? void 0 : _a.length) {
84
85
  this.missingRefs[this.currentUid].forEach((entry) => {
85
86
  entry.ct = ctSchema.uid;
@@ -251,7 +252,7 @@ class Entries {
251
252
  let canWrite = true;
252
253
  if (this.fix) {
253
254
  if (!this.config.flags['copy-dir'] && !((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm)) {
254
- canWrite = this.config.flags.yes || (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
255
+ canWrite = this.config.flags.yes || (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
255
256
  }
256
257
  if (canWrite) {
257
258
  (0, fs_1.writeFileSync)(filePath, JSON.stringify(schema));
@@ -641,6 +642,9 @@ class Entries {
641
642
  * @returns if there is missing field returns field and path
642
643
  * Else empty array
643
644
  */
645
+ removeEmojiAndImages(str) {
646
+ return str.replace(/[\p{Emoji}\p{Emoji_Presentation}\p{Emoji_Modifier}\p{Emoji_Modifier_Base}\p{Emoji_Component}]+/gu, '');
647
+ }
644
648
  validateSelectField(tree, fieldStructure, field) {
645
649
  const { display_name, enum: selectOptions, multiple, min_instance, display_type, data_type } = fieldStructure;
646
650
  if (field === null ||
@@ -74,7 +74,7 @@ class Extensions {
74
74
  }
75
75
  else {
76
76
  this.log((0, messages_1.$t)(messages_1.commonMsg.EXTENSION_FIX_WARN, { title: title, uid }), { color: 'yellow' });
77
- const shouldDelete = this.config.flags.yes || (await cli_utilities_1.ux.confirm(messages_1.commonMsg.EXTENSION_FIX_CONFIRMATION));
77
+ const shouldDelete = this.config.flags.yes || (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.EXTENSION_FIX_CONFIRMATION));
78
78
  if (shouldDelete) {
79
79
  delete newExtensionSchema[uid];
80
80
  }
@@ -88,7 +88,7 @@ class Extensions {
88
88
  (this.config.flags['copy-dir'] ||
89
89
  ((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm) ||
90
90
  this.config.flags.yes ||
91
- (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
91
+ (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
92
92
  (0, fs_1.writeFileSync)((0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName), JSON.stringify(fixedExtensions));
93
93
  }
94
94
  }
@@ -0,0 +1,54 @@
1
+ import { Locale } from '@contentstack/cli-utilities';
2
+ import { LogFn, ConfigType, ModularBlockType, ContentTypeStruct, GroupFieldDataType, CtConstructorParam, GlobalFieldDataType, ModularBlocksDataType, ModuleConstructorParam, EntryStruct } from '../types';
3
+ import auditConfig from '../config';
4
+ export default class FieldRule {
5
+ log: LogFn;
6
+ protected fix: boolean;
7
+ fileName: string;
8
+ config: ConfigType;
9
+ folderPath: string;
10
+ currentUid: string;
11
+ currentTitle: string;
12
+ extensions: string[];
13
+ inMemoryFix: boolean;
14
+ gfSchema: ContentTypeStruct[];
15
+ ctSchema: ContentTypeStruct[];
16
+ protected schema: ContentTypeStruct[];
17
+ protected missingRefs: Record<string, any>;
18
+ moduleName: keyof typeof auditConfig.moduleConfig;
19
+ schemaMap: any;
20
+ locales: Locale[];
21
+ protected entries: Record<string, EntryStruct>;
22
+ protected missingSelectFeild: Record<string, any>;
23
+ protected missingMandatoryFields: Record<string, any>;
24
+ protected missingEnvLocale: Record<string, any>;
25
+ entryMetaData: Record<string, any>[];
26
+ action: string[];
27
+ constructor({ log, fix, config, moduleName, ctSchema, gfSchema }: ModuleConstructorParam & CtConstructorParam);
28
+ validateModules(moduleName: keyof typeof auditConfig.moduleConfig, moduleConfig: Record<string, unknown>): keyof typeof auditConfig.moduleConfig;
29
+ /**
30
+ * The `run` function checks if a folder path exists, sets the schema based on the module name,
31
+ * iterates over the schema and looks for references, and returns a list of missing references.
32
+ * @returns the `missingRefs` object.
33
+ */
34
+ run(): Promise<Record<string, any>>;
35
+ validateFieldRules(schema: Record<string, unknown>): void;
36
+ fixFieldRules(schema: Record<string, unknown>): void;
37
+ addMissingReferences(actions: Record<string, unknown>, fixStatus?: string): void;
38
+ /**
39
+ * @method prerequisiteData
40
+ * The `prerequisiteData` function reads and parses JSON files to retrieve extension and marketplace
41
+ * app data, and stores them in the `extensions` array.
42
+ */
43
+ prerequisiteData(): Promise<void>;
44
+ /**
45
+ * The function checks if it can write the fix content to a file and if so, it writes the content as
46
+ * JSON to the specified file path.
47
+ */
48
+ writeFixContent(): Promise<void>;
49
+ lookForReference(tree: Record<string, unknown>[], field: ContentTypeStruct | GlobalFieldDataType | ModularBlockType | GroupFieldDataType, parent?: string | null): Promise<void>;
50
+ validateGlobalField(tree: Record<string, unknown>[], field: GlobalFieldDataType, parent: string | null): Promise<void>;
51
+ validateModularBlocksField(tree: Record<string, unknown>[], field: ModularBlocksDataType, parent: string | null): Promise<void>;
52
+ validateGroupField(tree: Record<string, unknown>[], field: GroupFieldDataType, parent: string | null): Promise<void>;
53
+ prepareEntryMetaData(): Promise<void>;
54
+ }
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const map_1 = tslib_1.__importDefault(require("lodash/map"));
5
+ const path_1 = require("path");
6
+ const fs_1 = require("fs");
7
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
8
+ const messages_1 = require("../messages");
9
+ const lodash_1 = require("lodash");
10
+ /* The `ContentType` class is responsible for scanning content types, looking for references, and
11
+ generating a report in JSON and CSV formats. */
12
+ class FieldRule {
13
+ constructor({ log, fix, config, moduleName, ctSchema, gfSchema }) {
14
+ this.extensions = [];
15
+ this.inMemoryFix = false;
16
+ this.schema = [];
17
+ this.missingRefs = {};
18
+ this.schemaMap = [];
19
+ this.missingSelectFeild = {};
20
+ this.missingMandatoryFields = {};
21
+ this.missingEnvLocale = {};
22
+ this.entryMetaData = [];
23
+ this.action = ['show', 'hide'];
24
+ this.log = log;
25
+ this.config = config;
26
+ this.fix = fix !== null && fix !== void 0 ? fix : false;
27
+ this.ctSchema = ctSchema;
28
+ this.gfSchema = gfSchema;
29
+ this.moduleName = this.validateModules(moduleName, this.config.moduleConfig);
30
+ this.fileName = config.moduleConfig[this.moduleName].fileName;
31
+ this.folderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.basePath), (0, cli_utilities_1.sanitizePath)(config.moduleConfig[this.moduleName].dirName));
32
+ }
33
+ validateModules(moduleName, moduleConfig) {
34
+ if (Object.keys(moduleConfig).includes(moduleName)) {
35
+ return moduleName;
36
+ }
37
+ return 'content-types';
38
+ }
39
+ /**
40
+ * The `run` function checks if a folder path exists, sets the schema based on the module name,
41
+ * iterates over the schema and looks for references, and returns a list of missing references.
42
+ * @returns the `missingRefs` object.
43
+ */
44
+ async run() {
45
+ var _a;
46
+ if (!(0, fs_1.existsSync)(this.folderPath)) {
47
+ this.log(`Skipping ${this.moduleName} audit`, 'warn');
48
+ this.log((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
49
+ return {};
50
+ }
51
+ this.schema = this.moduleName === 'content-types' ? this.ctSchema : this.gfSchema;
52
+ await this.prerequisiteData();
53
+ await this.prepareEntryMetaData();
54
+ for (const schema of (_a = this.schema) !== null && _a !== void 0 ? _a : []) {
55
+ this.currentUid = schema.uid;
56
+ this.currentTitle = schema.title;
57
+ this.missingRefs[this.currentUid] = [];
58
+ const { uid, title } = schema;
59
+ await this.lookForReference([{ uid, name: title }], schema, null);
60
+ this.missingRefs[this.currentUid] = [];
61
+ if (this.fix) {
62
+ this.fixFieldRules(schema);
63
+ }
64
+ else {
65
+ this.validateFieldRules(schema);
66
+ }
67
+ this.schemaMap = [];
68
+ this.log((0, messages_1.$t)(messages_1.auditMsg.SCAN_CT_SUCCESS_MSG, { title, module: this.config.moduleConfig[this.moduleName].name }), 'info');
69
+ }
70
+ if (this.fix) {
71
+ await this.writeFixContent();
72
+ }
73
+ for (let propName in this.missingRefs) {
74
+ if (!this.missingRefs[propName].length) {
75
+ delete this.missingRefs[propName];
76
+ }
77
+ }
78
+ return this.missingRefs;
79
+ }
80
+ validateFieldRules(schema) {
81
+ if (Array.isArray(schema.field_rules)) {
82
+ let count = 0;
83
+ schema.field_rules.forEach((fr) => {
84
+ fr.actions.forEach((actions) => {
85
+ if (!this.schemaMap.includes(actions.target_field)) {
86
+ this.log((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_TARGET_ABSENT, {
87
+ target_field: actions.target_field,
88
+ ctUid: schema.uid,
89
+ }), 'error');
90
+ this.addMissingReferences(actions);
91
+ }
92
+ this.log((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_TARGET_SCAN_MESSAGE, { num: count.toString(), ctUid: schema.uid }), 'info');
93
+ });
94
+ fr.conditions.forEach((actions) => {
95
+ if (!this.schemaMap.includes(actions.operand_field)) {
96
+ this.addMissingReferences(actions);
97
+ this.log((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_CONDITION_ABSENT, { condition_field: actions.operand_field }), 'error');
98
+ }
99
+ this.log((0, messages_1.$t)(messages_1.auditMsg.FIELD_RULE_CONDITION_SCAN_MESSAGE, { num: count.toString(), ctUid: schema.uid }), 'info');
100
+ });
101
+ count = count + 1;
102
+ });
103
+ }
104
+ }
105
+ fixFieldRules(schema) {
106
+ if (!Array.isArray(schema.field_rules))
107
+ return;
108
+ schema.field_rules = schema.field_rules
109
+ .map((fr, index) => {
110
+ var _a, _b, _c, _d;
111
+ const validActions = (_b = (_a = fr.actions) === null || _a === void 0 ? void 0 : _a.filter(action => {
112
+ const isValid = this.schemaMap.includes(action.target_field);
113
+ const logMsg = isValid
114
+ ? messages_1.auditMsg.FIELD_RULE_TARGET_SCAN_MESSAGE
115
+ : messages_1.auditMsg.FIELD_RULE_TARGET_ABSENT;
116
+ this.log((0, messages_1.$t)(logMsg, Object.assign({ num: index.toString(), ctUid: schema.uid }, (action.target_field && { target_field: action.target_field }))), isValid ? 'info' : 'error');
117
+ if (!isValid) {
118
+ this.addMissingReferences(action, 'Fixed');
119
+ this.log((0, messages_1.$t)(messages_1.auditFixMsg.FIELD_RULE_FIX_MESSAGE, {
120
+ num: index.toString(),
121
+ ctUid: schema.uid
122
+ }), 'info');
123
+ }
124
+ return isValid;
125
+ })) !== null && _b !== void 0 ? _b : [];
126
+ const validConditions = (_d = (_c = fr.conditions) === null || _c === void 0 ? void 0 : _c.filter(condition => {
127
+ const isValid = this.schemaMap.includes(condition.operand_field);
128
+ const logMsg = isValid
129
+ ? messages_1.auditMsg.FIELD_RULE_CONDITION_SCAN_MESSAGE
130
+ : messages_1.auditMsg.FIELD_RULE_CONDITION_ABSENT;
131
+ this.log((0, messages_1.$t)(logMsg, Object.assign({ num: index.toString(), ctUid: schema.uid }, (condition.operand_field && { condition_field: condition.operand_field }))), isValid ? 'info' : 'error');
132
+ if (!isValid) {
133
+ this.addMissingReferences(condition, 'Fixed');
134
+ this.log((0, messages_1.$t)(messages_1.auditFixMsg.FIELD_RULE_FIX_MESSAGE, {
135
+ num: index.toString(),
136
+ ctUid: schema.uid
137
+ }), 'info');
138
+ }
139
+ return isValid;
140
+ })) !== null && _d !== void 0 ? _d : [];
141
+ return (validActions.length && validConditions.length) ? Object.assign(Object.assign({}, fr), { actions: validActions, conditions: validConditions }) : null;
142
+ })
143
+ .filter(Boolean);
144
+ }
145
+ addMissingReferences(actions, fixStatus) {
146
+ if (fixStatus) {
147
+ this.missingRefs[this.currentUid].push({
148
+ ctUid: this.currentUid,
149
+ action: actions,
150
+ fixStatus: 'Fixed',
151
+ });
152
+ }
153
+ else {
154
+ this.missingRefs[this.currentUid].push({ ctUid: this.currentUid, action: actions });
155
+ }
156
+ }
157
+ /**
158
+ * @method prerequisiteData
159
+ * The `prerequisiteData` function reads and parses JSON files to retrieve extension and marketplace
160
+ * app data, and stores them in the `extensions` array.
161
+ */
162
+ async prerequisiteData() {
163
+ var _a;
164
+ const extensionPath = (0, path_1.resolve)(this.config.basePath, 'extensions', 'extensions.json');
165
+ const marketplacePath = (0, path_1.resolve)(this.config.basePath, 'marketplace_apps', 'marketplace_apps.json');
166
+ if ((0, fs_1.existsSync)(extensionPath)) {
167
+ try {
168
+ this.extensions = Object.keys(JSON.parse((0, fs_1.readFileSync)(extensionPath, 'utf8')));
169
+ }
170
+ catch (error) { }
171
+ }
172
+ if ((0, fs_1.existsSync)(marketplacePath)) {
173
+ try {
174
+ const marketplaceApps = JSON.parse((0, fs_1.readFileSync)(marketplacePath, 'utf8'));
175
+ for (const app of marketplaceApps) {
176
+ 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);
177
+ this.extensions.push(...metaData);
178
+ }
179
+ }
180
+ catch (error) { }
181
+ }
182
+ }
183
+ /**
184
+ * The function checks if it can write the fix content to a file and if so, it writes the content as
185
+ * JSON to the specified file path.
186
+ */
187
+ async writeFixContent() {
188
+ var _a, _b;
189
+ let canWrite = true;
190
+ if (this.fix) {
191
+ if (!this.config.flags['copy-dir'] && !((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm)) {
192
+ canWrite = (_b = this.config.flags.yes) !== null && _b !== void 0 ? _b : (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
193
+ }
194
+ if (canWrite) {
195
+ (0, fs_1.writeFileSync)((0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName), JSON.stringify(this.schema));
196
+ }
197
+ }
198
+ }
199
+ async lookForReference(tree, field, parent = null) {
200
+ var _a, _b;
201
+ const fixTypes = (_a = this.config.flags['fix-only']) !== null && _a !== void 0 ? _a : this.config['fix-fields'];
202
+ for (let child of (_b = field.schema) !== null && _b !== void 0 ? _b : []) {
203
+ if (parent !== null) {
204
+ this.schemaMap.push(`${parent}.${child === null || child === void 0 ? void 0 : child.uid}`);
205
+ }
206
+ else {
207
+ this.schemaMap.push(child.uid);
208
+ }
209
+ if (!fixTypes.includes(child.data_type) && child.data_type !== 'json')
210
+ continue;
211
+ switch (child.data_type) {
212
+ case 'global_field':
213
+ 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
+ break;
215
+ case 'blocks':
216
+ 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
+ break;
218
+ case 'group':
219
+ 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
+ break;
221
+ }
222
+ }
223
+ }
224
+ async validateGlobalField(tree, field, parent) {
225
+ await this.lookForReference(tree, field, parent);
226
+ }
227
+ async validateModularBlocksField(tree, field, parent) {
228
+ const { blocks } = field;
229
+ for (const block of blocks) {
230
+ const { uid, title } = block;
231
+ await this.lookForReference([...tree, { uid, name: title }], block, parent + '.' + block.uid);
232
+ }
233
+ }
234
+ async validateGroupField(tree, field, parent) {
235
+ // NOTE Any Group Field related logic can be added here (Ex data serialization or picking any metadata for report etc.,)
236
+ await this.lookForReference(tree, field, parent);
237
+ }
238
+ async prepareEntryMetaData() {
239
+ var _a;
240
+ this.log(messages_1.auditMsg.PREPARING_ENTRY_METADATA, 'info');
241
+ const localesFolderPath = (0, path_1.resolve)(this.config.basePath, this.config.moduleConfig.locales.dirName);
242
+ const localesPath = (0, path_1.join)(localesFolderPath, this.config.moduleConfig.locales.fileName);
243
+ const masterLocalesPath = (0, path_1.join)(localesFolderPath, 'master-locale.json');
244
+ this.locales = (0, fs_1.existsSync)(masterLocalesPath) ? (0, lodash_1.values)(JSON.parse((0, fs_1.readFileSync)(masterLocalesPath, 'utf8'))) : [];
245
+ if ((0, fs_1.existsSync)(localesPath)) {
246
+ this.locales.push(...(0, lodash_1.values)(JSON.parse((0, fs_1.readFileSync)(localesPath, 'utf8'))));
247
+ }
248
+ const entriesFolderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.basePath), 'entries');
249
+ for (const { code } of this.locales) {
250
+ for (const { uid } of (_a = this.ctSchema) !== null && _a !== void 0 ? _a : []) {
251
+ let basePath = (0, path_1.join)(entriesFolderPath, uid, code);
252
+ let fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: 'index.json' });
253
+ let indexer = fsUtility.indexFileContent;
254
+ for (const _ in indexer) {
255
+ const entries = (await fsUtility.readChunkFiles.next());
256
+ for (const entryUid in entries) {
257
+ let { title } = entries[entryUid];
258
+ this.entryMetaData.push({ uid: entryUid, title, ctUid: uid });
259
+ }
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
265
+ exports.default = FieldRule;
@@ -6,7 +6,7 @@ export default class GlobalField extends ContentType {
6
6
  * references.
7
7
  * @returns the value of the variable `missingRefs`.
8
8
  */
9
- run(returnFixSchema?: boolean): Promise<Record<string, any>>;
9
+ run(returnFixSchema?: boolean): Promise<Record<string, any> | import("../types").ContentTypeStruct[]>;
10
10
  /**
11
11
  * The function validates a field containing modular blocks by traversing each block and checking for
12
12
  * references in a given tree.
@@ -5,4 +5,6 @@ import Workflows from './workflows';
5
5
  import Extensions from './extensions';
6
6
  import CustomRoles from './custom-roles';
7
7
  import Assets from './assets';
8
- export { Entries, GlobalField, ContentType, Workflows, Extensions, Assets, CustomRoles };
8
+ import FieldRule from './field_rules';
9
+ import ModuleDataReader from './modulesData';
10
+ export { Entries, GlobalField, ContentType, Workflows, Extensions, Assets, CustomRoles, FieldRule, ModuleDataReader };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CustomRoles = exports.Assets = exports.Extensions = exports.Workflows = exports.ContentType = exports.GlobalField = exports.Entries = void 0;
3
+ exports.ModuleDataReader = exports.FieldRule = exports.CustomRoles = exports.Assets = exports.Extensions = exports.Workflows = exports.ContentType = exports.GlobalField = exports.Entries = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const entries_1 = tslib_1.__importDefault(require("./entries"));
6
6
  exports.Entries = entries_1.default;
@@ -16,3 +16,7 @@ const custom_roles_1 = tslib_1.__importDefault(require("./custom-roles"));
16
16
  exports.CustomRoles = custom_roles_1.default;
17
17
  const assets_1 = tslib_1.__importDefault(require("./assets"));
18
18
  exports.Assets = assets_1.default;
19
+ const field_rules_1 = tslib_1.__importDefault(require("./field_rules"));
20
+ exports.FieldRule = field_rules_1.default;
21
+ const modulesData_1 = tslib_1.__importDefault(require("./modulesData"));
22
+ exports.ModuleDataReader = modulesData_1.default;
@@ -0,0 +1,18 @@
1
+ import { LogFn, ConfigType, ContentTypeStruct, CtConstructorParam, ModuleConstructorParam } from '../types';
2
+ export default class ModuleDataReader {
3
+ log: LogFn;
4
+ config: ConfigType;
5
+ folderPath: string;
6
+ assets: Record<string, any>;
7
+ locales: any[];
8
+ gfSchema: ContentTypeStruct[];
9
+ ctSchema: ContentTypeStruct[];
10
+ environments: string[];
11
+ auditData: Record<string, unknown>;
12
+ protected schema: ContentTypeStruct[];
13
+ constructor({ log, config, ctSchema, gfSchema }: ModuleConstructorParam & CtConstructorParam);
14
+ getModuleItemCount(moduleName: string): Promise<number>;
15
+ readUsingFsModule(path: string): Promise<Record<string, any>>;
16
+ readEntryAssetsModule(basePath: string, module: string): Promise<number>;
17
+ run(): Promise<Object>;
18
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const path_1 = require("path");
4
+ const fs_1 = require("fs");
5
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
6
+ const lodash_1 = require("lodash");
7
+ class ModuleDataReader {
8
+ constructor({ log, config, ctSchema, gfSchema }) {
9
+ this.locales = [];
10
+ this.environments = [];
11
+ this.auditData = {};
12
+ this.schema = [];
13
+ this.log = log;
14
+ this.config = config;
15
+ this.ctSchema = ctSchema;
16
+ this.gfSchema = gfSchema;
17
+ this.folderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.basePath));
18
+ }
19
+ async getModuleItemCount(moduleName) {
20
+ let count = 0;
21
+ switch (moduleName) {
22
+ case "content-types":
23
+ count = this.ctSchema.length;
24
+ break;
25
+ case 'global-fields':
26
+ count = this.gfSchema.length;
27
+ break;
28
+ case 'assets':
29
+ count = await this.readEntryAssetsModule((0, path_1.join)(this.folderPath, 'assets'), 'assets') || 0;
30
+ break;
31
+ case 'entries':
32
+ {
33
+ const localesFolderPath = (0, path_1.resolve)(this.config.basePath, this.config.moduleConfig.locales.dirName);
34
+ const localesPath = (0, path_1.join)(localesFolderPath, this.config.moduleConfig.locales.fileName);
35
+ const masterLocalesPath = (0, path_1.join)(localesFolderPath, 'master-locale.json');
36
+ this.locales = (0, lodash_1.values)(await this.readUsingFsModule(masterLocalesPath));
37
+ if ((0, fs_1.existsSync)(localesPath)) {
38
+ this.locales.push(...(0, lodash_1.values)(JSON.parse((0, fs_1.readFileSync)(localesPath, 'utf8'))));
39
+ }
40
+ for (const { code } of this.locales) {
41
+ for (const ctSchema of this.ctSchema) {
42
+ const basePath = (0, path_1.join)(this.folderPath, 'entries', ctSchema.uid, code);
43
+ count = count + await this.readEntryAssetsModule(basePath, 'index') || 0;
44
+ }
45
+ }
46
+ }
47
+ break;
48
+ case 'custom-roles':
49
+ case 'extensions':
50
+ case 'workflows':
51
+ count = (0, lodash_1.keys)(await (this.readUsingFsModule((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))))).length;
52
+ break;
53
+ }
54
+ return count;
55
+ }
56
+ async readUsingFsModule(path) {
57
+ const data = (0, fs_1.existsSync)(path) ? (JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'))) : [];
58
+ return data;
59
+ }
60
+ async readEntryAssetsModule(basePath, module) {
61
+ let fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: `${module}.json` });
62
+ let indexer = fsUtility.indexFileContent;
63
+ let count = 0;
64
+ for (const _ in indexer) {
65
+ const entries = (await fsUtility.readChunkFiles.next());
66
+ count = count + Object.keys(entries).length;
67
+ }
68
+ return count;
69
+ }
70
+ async run() {
71
+ await Promise.allSettled(Object.keys(this.config.moduleConfig).map(async (module) => {
72
+ this.auditData[module] = { Total: await this.getModuleItemCount(module) };
73
+ }));
74
+ return this.auditData;
75
+ }
76
+ }
77
+ exports.default = ModuleDataReader;
@@ -106,7 +106,7 @@ class Workflows {
106
106
  const { name, uid } = workflow;
107
107
  const warningMessage = (0, messages_1.$t)(messages_1.commonMsg.WORKFLOW_FIX_WARN, { name, uid });
108
108
  this.log(warningMessage, { color: 'yellow' });
109
- if (this.config.flags.yes || (await cli_utilities_1.ux.confirm(messages_1.commonMsg.WORKFLOW_FIX_CONFIRMATION))) {
109
+ if (this.config.flags.yes || (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.WORKFLOW_FIX_CONFIRMATION))) {
110
110
  delete newWorkflowSchema[workflow.uid];
111
111
  }
112
112
  }
@@ -120,7 +120,7 @@ class Workflows {
120
120
  (this.config.flags['copy-dir'] ||
121
121
  ((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm) ||
122
122
  this.config.flags.yes ||
123
- (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
123
+ (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
124
124
  (0, fs_1.writeFileSync)((0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName), JSON.stringify(newWorkflowSchema));
125
125
  }
126
126
  }
@@ -1,8 +1,6 @@
1
- import { ux } from "@contentstack/cli-utilities";
2
- type IFlags = typeof ux.table.Flags;
3
1
  type IncludeFlags<T, K extends keyof T> = Pick<T, K>;
4
2
  type CommandNames = 'cm:stacks:audit' | 'cm:stacks:audit:fix';
5
3
  interface AnyProperty {
6
4
  [propName: string]: any;
7
5
  }
8
- export { IFlags, IncludeFlags, CommandNames, AnyProperty };
6
+ export { IncludeFlags, CommandNames, AnyProperty };
@@ -1,8 +1,9 @@
1
1
  import config from '../config';
2
2
  import { AnyProperty } from './common';
3
3
  import { ConfigType, LogFn } from './utils';
4
- type ContentTypeSchemaType = ReferenceFieldDataType | GlobalFieldDataType | ExtensionOrAppFieldDataType | JsonRTEFieldDataType | GroupFieldDataType | ModularBlocksDataType | SelectFeildStruct;
4
+ type ContentTypeSchemaType = ReferenceFieldDataType | GlobalFieldDataType | ExtensionOrAppFieldDataType | JsonRTEFieldDataType | GroupFieldDataType | ModularBlocksDataType | SelectFeildStruct | any;
5
5
  type ContentTypeStruct = {
6
+ field_rules: any;
6
7
  uid: string;
7
8
  title: string;
8
9
  description: string;
@@ -117,7 +118,28 @@ declare enum OutputColumn {
117
118
  'asset_uid' = "asset_uid",
118
119
  'selectedValue' = "selectedValue",
119
120
  'fixStatus' = "fixStatus",
121
+ 'Content_type_uid' = "ct_uid",
122
+ 'action' = "action",
120
123
  'field_uid' = "field_uid",
121
- 'multiple' = "multiple"
124
+ 'multiple' = "multiple",
125
+ Module = "Module",
126
+ "Total" = "Total",
127
+ "Passed" = "Passed",
128
+ "Fixable" = "Fixable",
129
+ "Non-Fixable" = "Non-Fixable",
130
+ "Fixed" = "Fixed",
131
+ "Not-Fixed" = "Not-Fixed"
122
132
  }
123
- export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, ExtensionOrAppFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, ContentTypeSchemaType, GlobalFieldSchemaTypes, WorkflowExtensionsRefErrorReturnType, SelectFeildStruct, };
133
+ export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, ExtensionOrAppFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, ContentTypeSchemaType, GlobalFieldSchemaTypes, WorkflowExtensionsRefErrorReturnType, SelectFeildStruct, FieldRuleStruct, };
134
+ type FieldRuleStruct = {
135
+ match_type: string;
136
+ actions: Array<{
137
+ action: string;
138
+ target_field: string;
139
+ }> | undefined;
140
+ conditions: Array<{
141
+ value: string;
142
+ operand_field: string;
143
+ operator: string;
144
+ }> | undefined;
145
+ };
@@ -31,7 +31,15 @@ var OutputColumn;
31
31
  OutputColumn["asset_uid"] = "asset_uid";
32
32
  OutputColumn["selectedValue"] = "selectedValue";
33
33
  OutputColumn["fixStatus"] = "fixStatus";
34
+ OutputColumn["Content_type_uid"] = "ct_uid";
35
+ OutputColumn["action"] = "action";
34
36
  OutputColumn["field_uid"] = "field_uid";
35
37
  OutputColumn["multiple"] = "multiple";
36
- })(OutputColumn || (OutputColumn = {}));
37
- exports.OutputColumn = OutputColumn;
38
+ OutputColumn["Module"] = "Module";
39
+ OutputColumn["Total"] = "Total";
40
+ OutputColumn["Passed"] = "Passed";
41
+ OutputColumn["Fixable"] = "Fixable";
42
+ OutputColumn["Non-Fixable"] = "Non-Fixable";
43
+ OutputColumn["Fixed"] = "Fixed";
44
+ OutputColumn["Not-Fixed"] = "Not-Fixed";
45
+ })(OutputColumn || (exports.OutputColumn = OutputColumn = {}));
@@ -1,13 +1,5 @@
1
1
  import { FlagDefinition } from '@contentstack/cli-utilities';
2
- import { IFlags, IncludeFlags, JSONFlagOptions } from '../types';
3
- /**
4
- * The function `getTableFlags` returns a set of table flags based on the specified columns, with
5
- * updated descriptions and help groups.
6
- * @param {(keyof IFlags)[]} columns - An optional array of column keys from the IFlags interface. The
7
- * default value is ['columns', 'sort', 'filter', 'csv', 'no-truncate'].
8
- * @returns an object of type `IncludeFlags<IFlags, keyof IFlags>`.
9
- */
10
- declare function getTableFlags(columns?: (keyof IFlags)[]): IncludeFlags<IFlags, keyof IFlags>;
2
+ import { JSONFlagOptions } from '../types';
11
3
  /**
12
4
  * The function `getJsonInputFlags` returns a flag definition for parsing JSON input.
13
5
  * @param {JSONFlagOptions} options - The `options` parameter is an object that contains the following
@@ -15,4 +7,5 @@ declare function getTableFlags(columns?: (keyof IFlags)[]): IncludeFlags<IFlags,
15
7
  * @returns a `FlagDefinition` object.
16
8
  */
17
9
  declare function getJsonInputFlags(options?: JSONFlagOptions): FlagDefinition<Record<string, unknown>, Record<string, unknown>>;
18
- export { getTableFlags, getJsonInputFlags };
10
+ declare const tableFlags: import("@contentstack/cli-utilities").FlagInput<import("@contentstack/cli-utilities").TableFlags>;
11
+ export { getJsonInputFlags, tableFlags };