@contentstack/cli-audit 1.10.0 → 1.11.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.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.tableColumnDescriptions = exports.auditFixMsg = exports.auditMsg = exports.commonMsg = exports.errors = exports.$t = void 0;
3
+ exports.tableColumnDescriptions = exports.auditFixMsg = exports.auditMsg = exports.commonMsg = exports.errors = void 0;
4
+ exports.$t = $t;
4
5
  const tslib_1 = require("tslib");
5
6
  const memoize_1 = tslib_1.__importDefault(require("lodash/memoize"));
6
7
  const errors = {};
@@ -46,6 +47,10 @@ const auditMsg = {
46
47
  CT_REFERENCE_FIELD: `The mentioned Reference field is not Array field reference is '{reference_to}' having display name '{display_name}''`,
47
48
  ASSET_NOT_EXIST: `The publish_details either does not exist or is not an array for asset uid '{uid}'`,
48
49
  ENTRY_PUBLISH_DETAILS_NOT_EXIST: `The publish_details either does not exist or is not an array for entry uid '{uid}'`,
50
+ FIELD_RULE_CONDITION_ABSENT: `The operand field '{condition_field}' is not present in the schema of the content-type {ctUid}`,
51
+ FIELD_RULE_TARGET_ABSENT: `The target field '{target_field}' is not present in the schema of the content-type {ctUid}`,
52
+ FIELD_RULE_CONDITION_SCAN_MESSAGE: `Completed Scanning of Field Rule '{num}' condition of Content-type '{ctUid}'`,
53
+ FIELD_RULE_TARGET_SCAN_MESSAGE: `Completed Scanning of Field Rule '{num}' target of Content-type '{ctUid}'`
49
54
  };
50
55
  exports.auditMsg = auditMsg;
51
56
  const auditFixMsg = {
@@ -59,6 +64,7 @@ const auditFixMsg = {
59
64
  ENTRY_MANDATORY_FIELD_FIX: `Removing the publish details from the entry with UID '{uid}' in Locale '{locale}'...`,
60
65
  ENTRY_SELECT_FIELD_FIX: `Adding the value '{value}' in the select field of entry UID '{uid}'...`,
61
66
  ASSET_FIX: `Fixed publish detials for Asset with UID '{uid}'`,
67
+ FIELD_RULE_FIX_MESSAGE: `Fixed Field Rule '{num}' target of Content-type '{ctUid}`,
62
68
  };
63
69
  exports.auditFixMsg = auditFixMsg;
64
70
  const messages = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, errors), commonMsg), auditMsg), auditFixMsg), tableColumnDescriptions);
@@ -84,5 +90,4 @@ function $t(msg, args) {
84
90
  });
85
91
  return transfer(msg, args);
86
92
  }
87
- exports.$t = $t;
88
93
  exports.default = messages;
@@ -21,7 +21,7 @@ export default class Assets {
21
21
  * iterates over the schema and looks for references, and returns a list of missing references.
22
22
  * @returns the `missingEnvLocales` object.
23
23
  */
24
- run(returnFixSchema?: boolean): Promise<Record<string, any>>;
24
+ run(returnFixSchema?: boolean): Promise<Record<string, any> | ContentTypeStruct[]>;
25
25
  /**
26
26
  * @method prerequisiteData
27
27
  * The `prerequisiteData` function reads and parses JSON files to retrieve extension and marketplace
@@ -80,7 +80,7 @@ class Assets {
80
80
  let canWrite = true;
81
81
  if (this.fix) {
82
82
  if (!this.config.flags['copy-dir'] && !((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm)) {
83
- canWrite = this.config.flags.yes || (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
83
+ canWrite = this.config.flags.yes || (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
84
84
  }
85
85
  if (canWrite) {
86
86
  (0, fs_1.writeFileSync)(filePath, JSON.stringify(schema));
@@ -22,7 +22,7 @@ export default class ContentType {
22
22
  * iterates over the schema and looks for references, and returns a list of missing references.
23
23
  * @returns the `missingRefs` object.
24
24
  */
25
- run(returnFixSchema?: boolean): Promise<Record<string, any>>;
25
+ run(returnFixSchema?: boolean): Promise<Record<string, any> | ContentTypeStruct[]>;
26
26
  /**
27
27
  * @method prerequisiteData
28
28
  * The `prerequisiteData` function reads and parses JSON files to retrieve extension and marketplace
@@ -102,7 +102,7 @@ class ContentType {
102
102
  let canWrite = true;
103
103
  if (!this.inMemoryFix && this.fix) {
104
104
  if (!this.config.flags['copy-dir'] && !((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm)) {
105
- canWrite = (_b = this.config.flags.yes) !== null && _b !== void 0 ? _b : (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
105
+ canWrite = (_b = this.config.flags.yes) !== null && _b !== void 0 ? _b : (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
106
106
  }
107
107
  if (canWrite) {
108
108
  (0, fs_1.writeFileSync)((0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName), JSON.stringify(this.schema));
@@ -117,7 +117,7 @@ class CustomRoles {
117
117
  (this.config.flags['copy-dir'] ||
118
118
  ((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm) ||
119
119
  this.config.flags.yes ||
120
- (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
120
+ (await cli_utilities_1.cliux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
121
121
  (0, fs_1.writeFileSync)((0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName), JSON.stringify(newCustomRoleSchema));
122
122
  }
123
123
  }
@@ -198,6 +198,7 @@ export default class Entries {
198
198
  * @returns if there is missing field returns field and path
199
199
  * Else empty array
200
200
  */
201
+ removeEmojiAndImages(str: string): string;
201
202
  validateSelectField(tree: Record<string, unknown>[], fieldStructure: SelectFeildStruct, field: any): {
202
203
  uid: string;
203
204
  name: string;
@@ -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({ action: actions, ctUid: this.currentUid });
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,5 @@ 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
+ export { Entries, GlobalField, ContentType, Workflows, Extensions, Assets, CustomRoles, FieldRule };
@@ -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.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,5 @@ 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;
@@ -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,21 @@ 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
124
  'multiple' = "multiple"
122
125
  }
123
- export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, ExtensionOrAppFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, ContentTypeSchemaType, GlobalFieldSchemaTypes, WorkflowExtensionsRefErrorReturnType, SelectFeildStruct, };
126
+ export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, ExtensionOrAppFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, ContentTypeSchemaType, GlobalFieldSchemaTypes, WorkflowExtensionsRefErrorReturnType, SelectFeildStruct, FieldRuleStruct, };
127
+ type FieldRuleStruct = {
128
+ match_type: string;
129
+ actions: Array<{
130
+ action: string;
131
+ target_field: string;
132
+ }> | undefined;
133
+ conditions: Array<{
134
+ value: string;
135
+ operand_field: string;
136
+ operator: string;
137
+ }> | undefined;
138
+ };
@@ -31,7 +31,8 @@ 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 || (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 };
package/lib/util/flags.js CHANGED
@@ -1,30 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getJsonInputFlags = exports.getTableFlags = void 0;
3
+ exports.tableFlags = void 0;
4
+ exports.getJsonInputFlags = getJsonInputFlags;
4
5
  const cli_utilities_1 = require("@contentstack/cli-utilities");
5
- const messages_1 = require("../messages");
6
6
  const defaultJSONOptions = { description: 'Provide JSON input' };
7
- /**
8
- * The function `getTableFlags` returns a set of table flags based on the specified columns, with
9
- * updated descriptions and help groups.
10
- * @param {(keyof IFlags)[]} columns - An optional array of column keys from the IFlags interface. The
11
- * default value is ['columns', 'sort', 'filter', 'csv', 'no-truncate'].
12
- * @returns an object of type `IncludeFlags<IFlags, keyof IFlags>`.
13
- */
14
- function getTableFlags(columns = ['columns', 'sort', 'filter', 'csv', 'no-truncate']) {
15
- const flags = cli_utilities_1.ux.table.flags({
16
- only: columns,
17
- });
18
- // NOTE Assign group and update Descriptions
19
- columns.forEach((element) => {
20
- var _a;
21
- flags[element].helpGroup = 'TABLE';
22
- const descriptionKey = `TABLE_${element.toUpperCase()}`;
23
- flags[element].description = (_a = messages_1.tableColumnDescriptions[descriptionKey]) !== null && _a !== void 0 ? _a : flags[element].description;
24
- });
25
- return flags;
26
- }
27
- exports.getTableFlags = getTableFlags;
28
7
  /**
29
8
  * The function `getJsonInputFlags` returns a flag definition for parsing JSON input.
30
9
  * @param {JSONFlagOptions} options - The `options` parameter is an object that contains the following
@@ -46,4 +25,5 @@ function getJsonInputFlags(options = defaultJSONOptions) {
46
25
  },
47
26
  });
48
27
  }
49
- exports.getJsonInputFlags = getJsonInputFlags;
28
+ const tableFlags = cli_utilities_1.CLITable.getTableFlags(['columns', 'sort', 'filter', 'csv', 'no-truncate', 'no-header', 'output']);
29
+ exports.tableFlags = tableFlags;