@contentstack/cli-audit 1.4.1 → 1.5.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 CHANGED
@@ -19,7 +19,7 @@ $ npm install -g @contentstack/cli-audit
19
19
  $ csdx COMMAND
20
20
  running command...
21
21
  $ csdx (--version|-v)
22
- @contentstack/cli-audit/1.4.1 linux-x64 node-v18.19.1
22
+ @contentstack/cli-audit/1.5.0 linux-x64 node-v18.19.1
23
23
  $ csdx --help [COMMAND]
24
24
  USAGE
25
25
  $ csdx COMMAND
@@ -53,12 +53,12 @@ Perform audits and find possible errors in the exported Contentstack data
53
53
  ```
54
54
  USAGE
55
55
  $ csdx audit [-c <value>] [-d <value>] [--report-path <value>] [--modules
56
- content-types|global-fields|entries] [--columns <value> | ] [--sort <value>] [--filter <value>] [--csv |
57
- --no-truncate]
56
+ content-types|global-fields|entries|extensions|workflows] [--columns <value> | ] [--sort <value>] [--filter <value>]
57
+ [--csv | --no-truncate]
58
58
 
59
59
  FLAGS
60
60
  --modules=<option>... Provide the list of modules to be audited
61
- <options: content-types|global-fields|entries>
61
+ <options: content-types|global-fields|entries|extensions|workflows>
62
62
  --report-path=<value> Path to store the audit reports
63
63
 
64
64
  COMMON FLAGS
@@ -98,17 +98,17 @@ Perform audits and fix possible errors in the exported Contentstack data.
98
98
  ```
99
99
  USAGE
100
100
  $ csdx audit:fix [-c <value>] [-d <value>] [--report-path <value>] [--modules
101
- content-types|global-fields|entries] [--copy-path <value> --copy-dir] [--fix-only
102
- reference|global_field|json:rte|json:extension|blocks|group] [--columns <value> | ] [--sort <value>] [--filter
103
- <value>] [--csv | --no-truncate]
101
+ content-types|global-fields|entries|extensions|workflows] [--copy-path <value> --copy-dir] [--fix-only
102
+ reference|global_field|json:rte|json:extension|blocks|group|content_types] [--columns <value> | ] [--sort <value>]
103
+ [--filter <value>] [--csv | --no-truncate]
104
104
 
105
105
  FLAGS
106
106
  --copy-dir Create backup from the original data.
107
107
  --copy-path=<value> Provide the path to backup the copied data
108
108
  --fix-only=<option>... Provide the list of fix options
109
- <options: reference|global_field|json:rte|json:extension|blocks|group>
109
+ <options: reference|global_field|json:rte|json:extension|blocks|group|content_types>
110
110
  --modules=<option>... Provide the list of modules to be audited
111
- <options: content-types|global-fields|entries>
111
+ <options: content-types|global-fields|entries|extensions|workflows>
112
112
  --report-path=<value> Path to store the audit reports
113
113
 
114
114
  COMMON FLAGS
@@ -150,12 +150,12 @@ Perform audits and find possible errors in the exported Contentstack data
150
150
  ```
151
151
  USAGE
152
152
  $ csdx cm:stacks:audit [-c <value>] [-d <value>] [--report-path <value>] [--modules
153
- content-types|global-fields|entries] [--columns <value> | ] [--sort <value>] [--filter <value>] [--csv |
154
- --no-truncate]
153
+ content-types|global-fields|entries|extensions|workflows] [--columns <value> | ] [--sort <value>] [--filter <value>]
154
+ [--csv | --no-truncate]
155
155
 
156
156
  FLAGS
157
157
  --modules=<option>... Provide the list of modules to be audited
158
- <options: content-types|global-fields|entries>
158
+ <options: content-types|global-fields|entries|extensions|workflows>
159
159
  --report-path=<value> Path to store the audit reports
160
160
 
161
161
  COMMON FLAGS
@@ -197,17 +197,17 @@ Perform audits and fix possible errors in the exported Contentstack data.
197
197
  ```
198
198
  USAGE
199
199
  $ csdx cm:stacks:audit:fix [-c <value>] [-d <value>] [--report-path <value>] [--modules
200
- content-types|global-fields|entries] [--copy-path <value> --copy-dir] [--fix-only
201
- reference|global_field|json:rte|json:extension|blocks|group] [--columns <value> | ] [--sort <value>] [--filter
202
- <value>] [--csv | --no-truncate]
200
+ content-types|global-fields|entries|extensions|workflows] [--copy-path <value> --copy-dir] [--fix-only
201
+ reference|global_field|json:rte|json:extension|blocks|group|content_types] [--columns <value> | ] [--sort <value>]
202
+ [--filter <value>] [--csv | --no-truncate]
203
203
 
204
204
  FLAGS
205
205
  --copy-dir Create backup from the original data.
206
206
  --copy-path=<value> Provide the path to backup the copied data
207
207
  --fix-only=<option>... Provide the list of fix options
208
- <options: reference|global_field|json:rte|json:extension|blocks|group>
208
+ <options: reference|global_field|json:rte|json:extension|blocks|group|content_types>
209
209
  --modules=<option>... Provide the list of modules to be audited
210
- <options: content-types|global-fields|entries>
210
+ <options: content-types|global-fields|entries|extensions|workflows>
211
211
  --report-path=<value> Path to store the audit reports
212
212
 
213
213
  COMMON FLAGS
@@ -285,7 +285,7 @@ EXAMPLES
285
285
  $ csdx plugins
286
286
  ```
287
287
 
288
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.6/src/commands/plugins/index.ts)_
288
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/index.ts)_
289
289
 
290
290
  ## `csdx plugins:install PLUGIN...`
291
291
 
@@ -354,7 +354,7 @@ EXAMPLES
354
354
  $ csdx plugins:inspect myplugin
355
355
  ```
356
356
 
357
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.6/src/commands/plugins/inspect.ts)_
357
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/inspect.ts)_
358
358
 
359
359
  ## `csdx plugins:install PLUGIN...`
360
360
 
@@ -398,7 +398,7 @@ EXAMPLES
398
398
  $ csdx plugins:install someuser/someplugin
399
399
  ```
400
400
 
401
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.6/src/commands/plugins/install.ts)_
401
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/install.ts)_
402
402
 
403
403
  ## `csdx plugins:link PLUGIN`
404
404
 
@@ -428,7 +428,7 @@ EXAMPLES
428
428
  $ csdx plugins:link myplugin
429
429
  ```
430
430
 
431
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.6/src/commands/plugins/link.ts)_
431
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/link.ts)_
432
432
 
433
433
  ## `csdx plugins:uninstall PLUGIN...`
434
434
 
@@ -469,7 +469,7 @@ FLAGS
469
469
  --reinstall Reinstall all plugins after uninstalling.
470
470
  ```
471
471
 
472
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.6/src/commands/plugins/reset.ts)_
472
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/reset.ts)_
473
473
 
474
474
  ## `csdx plugins:uninstall PLUGIN...`
475
475
 
@@ -497,7 +497,7 @@ EXAMPLES
497
497
  $ csdx plugins:uninstall myplugin
498
498
  ```
499
499
 
500
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.6/src/commands/plugins/uninstall.ts)_
500
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/uninstall.ts)_
501
501
 
502
502
  ## `csdx plugins:uninstall PLUGIN...`
503
503
 
@@ -541,5 +541,5 @@ DESCRIPTION
541
541
  Update installed plugins.
542
542
  ```
543
543
 
544
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.6/src/commands/plugins/update.ts)_
544
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/update.ts)_
545
545
  <!-- commandsstop -->
@@ -11,7 +11,7 @@ export declare abstract class AuditBaseCommand extends BaseCommand<typeof AuditB
11
11
  };
12
12
  };
13
13
  /**
14
- * The `start` function performs an audit on content types, global fields, and entries, and displays
14
+ * The `start` function performs an audit on content types, global fields, entries, and workflows and displays
15
15
  * any missing references.
16
16
  * @param {string} command - The `command` parameter is a string that represents the current command
17
17
  * being executed.
@@ -27,6 +27,8 @@ export declare abstract class AuditBaseCommand extends BaseCommand<typeof AuditB
27
27
  missingCtRefs: Record<string, any> | undefined;
28
28
  missingGfRefs: Record<string, any> | undefined;
29
29
  missingEntryRefs: Record<string, any> | undefined;
30
+ missingCtRefsInExtensions: {} | undefined;
31
+ missingCtRefsInWorkflow: {} | undefined;
30
32
  }>;
31
33
  /**
32
34
  * The `promptQueue` function prompts the user to enter a data directory path if the `data-dir` flag
@@ -58,6 +60,10 @@ export declare abstract class AuditBaseCommand extends BaseCommand<typeof AuditB
58
60
  module: string;
59
61
  missingRefs?: Record<string, any>;
60
62
  }[]): void;
63
+ showOutputOnScreenWorkflowsAndExtension(allMissingRefs: {
64
+ module: string;
65
+ missingRefs?: Record<string, any>;
66
+ }[]): void;
61
67
  /**
62
68
  * The function prepares a report by writing a JSON file and a CSV file with a list of missing
63
69
  * references for a given module.
@@ -29,7 +29,7 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
29
29
  };
30
30
  }
31
31
  /**
32
- * The `start` function performs an audit on content types, global fields, and entries, and displays
32
+ * The `start` function performs an audit on content types, global fields, entries, and workflows and displays
33
33
  * any missing references.
34
34
  * @param {string} command - The `command` parameter is a string that represents the current command
35
35
  * being executed.
@@ -39,13 +39,19 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
39
39
  await this.promptQueue();
40
40
  await this.createBackUp();
41
41
  this.sharedConfig.reportPath = (0, path_1.resolve)(this.flags['report-path'] || process.cwd(), 'audit-report');
42
- const { missingCtRefs, missingGfRefs, missingEntryRefs } = await this.scanAndFix();
42
+ const { missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow } = await this.scanAndFix();
43
43
  this.showOutputOnScreen([
44
44
  { module: 'Content types', missingRefs: missingCtRefs },
45
45
  { module: 'Global Fields', missingRefs: missingGfRefs },
46
46
  { module: 'Entries', missingRefs: missingEntryRefs },
47
47
  ]);
48
- if (!(0, isEmpty_1.default)(missingCtRefs) || !(0, isEmpty_1.default)(missingGfRefs) || !(0, isEmpty_1.default)(missingEntryRefs)) {
48
+ this.showOutputOnScreenWorkflowsAndExtension([{ module: 'Extensions', missingRefs: missingCtRefsInExtensions }]);
49
+ this.showOutputOnScreenWorkflowsAndExtension([{ module: 'Workflows', missingRefs: missingCtRefsInWorkflow }]);
50
+ if (!(0, isEmpty_1.default)(missingCtRefs) ||
51
+ !(0, isEmpty_1.default)(missingGfRefs) ||
52
+ !(0, isEmpty_1.default)(missingEntryRefs) ||
53
+ !(0, isEmpty_1.default)(missingCtRefsInWorkflow) ||
54
+ !(0, isEmpty_1.default)(missingCtRefsInExtensions)) {
49
55
  if (this.currentCommand === 'cm:stacks:audit') {
50
56
  this.log(this.$t(messages_1.auditMsg.FINAL_REPORT_PATH, { path: this.sharedConfig.reportPath }), 'warn');
51
57
  }
@@ -63,7 +69,11 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
63
69
  (0, fs_1.rmSync)(this.sharedConfig.basePath, { recursive: true });
64
70
  }
65
71
  }
66
- return !(0, isEmpty_1.default)(missingCtRefs) || !(0, isEmpty_1.default)(missingGfRefs) || !(0, isEmpty_1.default)(missingEntryRefs);
72
+ return (!(0, isEmpty_1.default)(missingCtRefs) ||
73
+ !(0, isEmpty_1.default)(missingGfRefs) ||
74
+ !(0, isEmpty_1.default)(missingEntryRefs) ||
75
+ !(0, isEmpty_1.default)(missingCtRefsInWorkflow) ||
76
+ !(0, isEmpty_1.default)(missingCtRefsInExtensions));
67
77
  }
68
78
  /**
69
79
  * The `scan` function performs an audit on different modules (content-types, global-fields, and
@@ -73,7 +83,7 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
73
83
  */
74
84
  async scanAndFix() {
75
85
  let { ctSchema, gfSchema } = this.getCtAndGfSchema();
76
- let missingCtRefs, missingGfRefs, missingEntryRefs;
86
+ let missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow;
77
87
  for (const module of this.sharedConfig.flags.modules || this.sharedConfig.modules) {
78
88
  (0, log_1.print)([
79
89
  {
@@ -103,6 +113,20 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
103
113
  missingEntryRefs = await new modules_1.Entries((0, cloneDeep_1.default)(constructorParam)).run();
104
114
  await this.prepareReport(module, missingEntryRefs);
105
115
  break;
116
+ case 'workflows':
117
+ missingCtRefsInWorkflow = await new modules_1.Workflows({
118
+ ctSchema,
119
+ log: this.log,
120
+ moduleName: module,
121
+ config: this.sharedConfig,
122
+ fix: this.currentCommand === 'cm:stacks:audit:fix',
123
+ }).run();
124
+ await this.prepareReport(module, missingCtRefsInWorkflow);
125
+ break;
126
+ case 'extensions':
127
+ missingCtRefsInExtensions = await new modules_1.Extensions((0, cloneDeep_1.default)(constructorParam)).run();
128
+ await this.prepareReport(module, missingCtRefsInExtensions);
129
+ break;
106
130
  }
107
131
  (0, log_1.print)([
108
132
  {
@@ -117,7 +141,7 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
117
141
  },
118
142
  ]);
119
143
  }
120
- return { missingCtRefs, missingGfRefs, missingEntryRefs };
144
+ return { missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow };
121
145
  }
122
146
  /**
123
147
  * The `promptQueue` function prompts the user to enter a data directory path if the `data-dir` flag
@@ -210,6 +234,47 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
210
234
  }
211
235
  }
212
236
  }
237
+ // Make it generic it takes the column header as param
238
+ showOutputOnScreenWorkflowsAndExtension(allMissingRefs) {
239
+ var _a;
240
+ if (!this.sharedConfig.showTerminalOutput || ((_a = this.flags['external-config']) === null || _a === void 0 ? void 0 : _a.noTerminalOutput)) {
241
+ return;
242
+ }
243
+ this.log(''); // Adding a new line
244
+ for (const { module, missingRefs } of allMissingRefs) {
245
+ if ((0, isEmpty_1.default)(missingRefs)) {
246
+ continue;
247
+ }
248
+ (0, log_1.print)([{ bold: true, color: 'cyan', message: ` ${module}` }]);
249
+ const tableValues = Object.values(missingRefs).flat();
250
+ const tableKeys = Object.keys(missingRefs[0]);
251
+ const arrayOfObjects = tableKeys.map((key) => {
252
+ if (['title', 'name', 'uid', 'content_types', 'fixStatus'].includes(key)) {
253
+ return {
254
+ [key]: {
255
+ minWidth: 7,
256
+ header: key,
257
+ get: (row) => {
258
+ if (key === 'fixStatus') {
259
+ return chalk_1.default.green(typeof row[key] === 'object' ? JSON.stringify(row[key]) : row[key]);
260
+ }
261
+ else if (key === 'content_types') {
262
+ return chalk_1.default.red(typeof row[key] === 'object' ? JSON.stringify(row[key]) : row[key]);
263
+ }
264
+ else {
265
+ return chalk_1.default.white(typeof row[key] === 'object' ? JSON.stringify(row[key]) : row[key]);
266
+ }
267
+ },
268
+ },
269
+ };
270
+ }
271
+ return {};
272
+ });
273
+ const mergedObject = Object.assign({}, ...arrayOfObjects);
274
+ cli_utilities_1.ux.table(tableValues, mergedObject, Object.assign({}, this.flags));
275
+ this.log(''); // Adding a new line
276
+ }
277
+ }
213
278
  /**
214
279
  * The function prepares a report by writing a JSON file and a CSV file with a list of missing
215
280
  * references for a given module.
@@ -260,8 +325,10 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
260
325
  for (const issue of missingRefs) {
261
326
  let row = {};
262
327
  for (const column of columns) {
263
- row[column] = issue[types_1.OutputColumn[column]];
264
- row[column] = typeof row[column] === 'object' ? JSON.stringify(row[column]) : row[column];
328
+ if (Object.keys(issue).includes(types_1.OutputColumn[column])) {
329
+ row[column] = issue[types_1.OutputColumn[column]];
330
+ row[column] = typeof row[column] === 'object' ? JSON.stringify(row[column]) : row[column];
331
+ }
265
332
  }
266
333
  if (this.currentCommand === 'cm:stacks:audit:fix') {
267
334
  row['Fix status'] = row.fixStatus;
@@ -7,7 +7,7 @@ export default class Audit extends AuditBaseCommand {
7
7
  static flags: FlagInput;
8
8
  /**
9
9
  * The `run` function is an asynchronous function that performs an audit on different modules
10
- * (content-types, global-fields, entries) and generates a report.
10
+ * (content-types, global-fields, entries, workflows) and generates a report.
11
11
  */
12
12
  run(): Promise<void>;
13
13
  }
@@ -9,7 +9,7 @@ const util_1 = require("../../../../util");
9
9
  class Audit extends audit_base_command_1.AuditBaseCommand {
10
10
  /**
11
11
  * The `run` function is an asynchronous function that performs an audit on different modules
12
- * (content-types, global-fields, entries) and generates a report.
12
+ * (content-types, global-fields, entries, workflows) and generates a report.
13
13
  */
14
14
  async run() {
15
15
  try {
@@ -25,6 +25,16 @@ declare const config: {
25
25
  dirName: string;
26
26
  fileName: string;
27
27
  };
28
+ workflows: {
29
+ name: string;
30
+ dirName: string;
31
+ fileName: string;
32
+ };
33
+ extensions: {
34
+ name: string;
35
+ dirName: string;
36
+ fileName: string;
37
+ };
28
38
  };
29
39
  entries: {
30
40
  systemKeys: string[];
@@ -4,8 +4,8 @@ const config = {
4
4
  showTerminalOutput: true,
5
5
  skipRefs: ['sys_assets'],
6
6
  skipFieldTypes: ['taxonomy', 'group'],
7
- modules: ['content-types', 'global-fields', 'entries'],
8
- 'fix-fields': ['reference', 'global_field', 'json:rte', 'json:extension', 'blocks', 'group'],
7
+ modules: ['content-types', 'global-fields', 'entries', 'extensions', 'workflows'],
8
+ 'fix-fields': ['reference', 'global_field', 'json:rte', 'json:extension', 'blocks', 'group', 'content_types'],
9
9
  moduleConfig: {
10
10
  'content-types': {
11
11
  name: 'content type',
@@ -27,6 +27,16 @@ const config = {
27
27
  dirName: 'locales',
28
28
  fileName: 'locales.json',
29
29
  },
30
+ workflows: {
31
+ name: 'workflows',
32
+ dirName: 'workflows',
33
+ fileName: 'workflows.json',
34
+ },
35
+ extensions: {
36
+ name: 'extensions',
37
+ dirName: 'extensions',
38
+ fileName: 'extensions.json',
39
+ },
30
40
  },
31
41
  entries: {
32
42
  systemKeys: [
@@ -10,6 +10,10 @@ declare const commonMsg: {
10
10
  CONFIG: string;
11
11
  DATA_DIR: string;
12
12
  FIX_CONFIRMATION: string;
13
+ WORKFLOW_FIX_WARN: string;
14
+ WORKFLOW_FIX_CONFIRMATION: string;
15
+ EXTENSION_FIX_WARN: string;
16
+ EXTENSION_FIX_CONFIRMATION: string;
13
17
  };
14
18
  declare const auditMsg: {
15
19
  REPORT_PATH: string;
@@ -22,7 +26,9 @@ declare const auditMsg: {
22
26
  FINAL_REPORT_PATH: string;
23
27
  SCAN_CT_SUCCESS_MSG: string;
24
28
  SCAN_ENTRY_SUCCESS_MSG: string;
29
+ SCAN_EXT_SUCCESS_MSG: string;
25
30
  AUDIT_CMD_DESCRIPTION: string;
31
+ SCAN_WF_SUCCESS_MSG: string;
26
32
  };
27
33
  declare const auditFixMsg: {
28
34
  COPY_DATA: string;
@@ -31,6 +37,7 @@ declare const auditFixMsg: {
31
37
  FIXED_CONTENT_PATH_MAG: string;
32
38
  EMPTY_FIX_MSG: string;
33
39
  AUDIT_FIX_CMD_DESCRIPTION: string;
40
+ WF_FIX_MSG: string;
34
41
  };
35
42
  declare const messages: typeof errors & typeof commonMsg & typeof auditMsg & typeof auditFixMsg & typeof tableColumnDescriptions;
36
43
  /**
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.tableColumnDescriptions = exports.auditFixMsg = exports.auditMsg = exports.commonMsg = exports.errors = exports.$t = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const memoize_1 = tslib_1.__importDefault(require("lodash/memoize"));
6
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
6
7
  const errors = {};
7
8
  exports.errors = errors;
8
9
  const tableColumnDescriptions = {
@@ -17,6 +18,10 @@ const commonMsg = {
17
18
  CONFIG: 'Path of the external config',
18
19
  DATA_DIR: 'Path where the data is stored',
19
20
  FIX_CONFIRMATION: 'Would you like to overwrite existing file.?',
21
+ WORKFLOW_FIX_WARN: `The workflow associated with UID {uid} and name {name} will be removed.`,
22
+ WORKFLOW_FIX_CONFIRMATION: 'Would you like to overwrite existing file?',
23
+ EXTENSION_FIX_WARN: `The extension associated with UID {uid} and title '{title}' will be removed.`,
24
+ EXTENSION_FIX_CONFIRMATION: `Would you like to overwrite existing file?`,
20
25
  };
21
26
  exports.commonMsg = commonMsg;
22
27
  const auditMsg = {
@@ -30,7 +35,9 @@ const auditMsg = {
30
35
  FINAL_REPORT_PATH: "Reports ready. Please find the reports at '{path}'.",
31
36
  SCAN_CT_SUCCESS_MSG: "Successfully completed the scanning of {module} '{title}'.",
32
37
  SCAN_ENTRY_SUCCESS_MSG: "Successfully completed the scanning of {module} ({local}) '{title}'.",
38
+ SCAN_EXT_SUCCESS_MSG: "Successfully completed scanning the {module} titled '{title}' with UID '{uid}'",
33
39
  AUDIT_CMD_DESCRIPTION: 'Perform audits and find possible errors in the exported Contentstack data',
40
+ SCAN_WF_SUCCESS_MSG: 'Successfully completed the scanning of workflow with UID {uid} and name {name}.',
34
41
  };
35
42
  exports.auditMsg = auditMsg;
36
43
  const auditFixMsg = {
@@ -40,6 +47,7 @@ const auditFixMsg = {
40
47
  FIXED_CONTENT_PATH_MAG: 'You can locate the fixed content at {path}.',
41
48
  EMPTY_FIX_MSG: 'Successfully removed the empty field/block found at {path} from the schema.',
42
49
  AUDIT_FIX_CMD_DESCRIPTION: 'Perform audits and fix possible errors in the exported Contentstack data.',
50
+ WF_FIX_MSG: 'Successfully removed the workflow {uid} named {name}.',
43
51
  };
44
52
  exports.auditFixMsg = auditFixMsg;
45
53
  const messages = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, errors), commonMsg), auditMsg), auditFixMsg), tableColumnDescriptions);
@@ -57,8 +65,8 @@ function $t(msg, args) {
57
65
  if (!msg)
58
66
  return '';
59
67
  for (const key of Object.keys(args)) {
60
- const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
61
- msg = msg.replace(new RegExp(`{${escapedKey}}`, 'g'), args[key] || escapedKey);
68
+ const escapedKey = (0, cli_utilities_1.escapeRegExp)(key);
69
+ msg = msg.replace(new RegExp(`{${escapedKey}}`, 'g'), (0, cli_utilities_1.escapeRegExp)(args[key]) || escapedKey);
62
70
  }
63
71
  return msg;
64
72
  });
@@ -0,0 +1,20 @@
1
+ import { LogFn, ConfigType, ContentTypeStruct, CtConstructorParam, ModuleConstructorParam, Extension } from '../types';
2
+ import auditConfig from '../config';
3
+ export default class Extensions {
4
+ log: LogFn;
5
+ protected fix: boolean;
6
+ fileName: any;
7
+ config: ConfigType;
8
+ folderPath: string;
9
+ extensionsSchema: Extension[];
10
+ ctSchema: ContentTypeStruct[];
11
+ moduleName: keyof typeof auditConfig.moduleConfig;
12
+ ctUidSet: Set<string>;
13
+ missingCtInExtensions: Extension[];
14
+ missingCts: Set<string>;
15
+ extensionsPath: string;
16
+ constructor({ log, fix, config, moduleName, ctSchema, }: ModuleConstructorParam & Pick<CtConstructorParam, 'ctSchema'>);
17
+ run(): Promise<{}>;
18
+ fixExtensionsScope(missingCtInExtensions: Extension[]): Promise<void>;
19
+ writeFixContent(fixedExtensions: Record<string, Extension>): Promise<void>;
20
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const path_1 = tslib_1.__importStar(require("path"));
5
+ const fs_1 = require("fs");
6
+ const lodash_1 = require("lodash");
7
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
8
+ const messages_1 = require("../messages");
9
+ const lodash_2 = require("lodash");
10
+ class Extensions {
11
+ constructor({ log, fix, config, moduleName, ctSchema, }) {
12
+ this.log = log;
13
+ this.config = config;
14
+ this.fix = fix !== null && fix !== void 0 ? fix : false;
15
+ this.ctSchema = ctSchema;
16
+ this.extensionsSchema = [];
17
+ this.moduleName = moduleName !== null && moduleName !== void 0 ? moduleName : 'extensions';
18
+ this.fileName = config.moduleConfig[this.moduleName].fileName;
19
+ this.folderPath = (0, path_1.resolve)(config.basePath, config.moduleConfig[this.moduleName].dirName);
20
+ this.ctUidSet = new Set(['$all']);
21
+ this.missingCtInExtensions = [];
22
+ this.missingCts = new Set();
23
+ this.extensionsPath = '';
24
+ }
25
+ async run() {
26
+ if (!(0, fs_1.existsSync)(this.folderPath)) {
27
+ this.log(`Skipping ${this.moduleName} audit`, 'warn');
28
+ this.log((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
29
+ return {};
30
+ }
31
+ this.extensionsPath = path_1.default.join(this.folderPath, this.fileName);
32
+ this.extensionsSchema = (0, fs_1.existsSync)(this.extensionsPath)
33
+ ? (0, lodash_2.values)(JSON.parse((0, fs_1.readFileSync)(this.extensionsPath, 'utf-8')))
34
+ : [];
35
+ this.ctSchema.map((ct) => this.ctUidSet.add(ct.uid));
36
+ for (const ext of this.extensionsSchema) {
37
+ const { title, uid, scope } = ext;
38
+ const ctNotPresent = scope === null || scope === void 0 ? void 0 : scope.content_types.filter((ct) => !this.ctUidSet.has(ct));
39
+ if ((ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.length) && ext.scope) {
40
+ ext.content_types = ctNotPresent;
41
+ ctNotPresent.forEach((ct) => this.missingCts.add(ct));
42
+ this.missingCtInExtensions.push((0, lodash_1.cloneDeep)(ext));
43
+ }
44
+ this.log((0, messages_1.$t)(messages_1.auditMsg.SCAN_EXT_SUCCESS_MSG, {
45
+ title,
46
+ module: this.config.moduleConfig[this.moduleName].name,
47
+ uid,
48
+ }), 'info');
49
+ }
50
+ if (this.fix && this.missingCtInExtensions.length) {
51
+ await this.fixExtensionsScope((0, lodash_1.cloneDeep)(this.missingCtInExtensions));
52
+ this.missingCtInExtensions.forEach((ext) => (ext.fixStatus = 'Fixed'));
53
+ return this.missingCtInExtensions;
54
+ }
55
+ return this.missingCtInExtensions;
56
+ }
57
+ async fixExtensionsScope(missingCtInExtensions) {
58
+ var _a, _b;
59
+ let newExtensionSchema = (0, fs_1.existsSync)(this.extensionsPath)
60
+ ? JSON.parse((0, fs_1.readFileSync)(this.extensionsPath, 'utf8'))
61
+ : {};
62
+ for (const ext of missingCtInExtensions) {
63
+ const { uid, title } = ext;
64
+ const fixedCts = (_a = ext === null || ext === void 0 ? void 0 : ext.scope) === null || _a === void 0 ? void 0 : _a.content_types.filter((ct) => !this.missingCts.has(ct));
65
+ if ((fixedCts === null || fixedCts === void 0 ? void 0 : fixedCts.length) && ((_b = newExtensionSchema[uid]) === null || _b === void 0 ? void 0 : _b.scope)) {
66
+ newExtensionSchema[uid].scope.content_types = fixedCts;
67
+ }
68
+ else {
69
+ this.log((0, messages_1.$t)(messages_1.commonMsg.EXTENSION_FIX_WARN, { title: title, uid }), { color: 'yellow' });
70
+ const shouldDelete = this.config.flags.yes || (await cli_utilities_1.ux.confirm(messages_1.commonMsg.EXTENSION_FIX_CONFIRMATION));
71
+ if (shouldDelete) {
72
+ delete newExtensionSchema[uid];
73
+ }
74
+ }
75
+ }
76
+ await this.writeFixContent(newExtensionSchema);
77
+ }
78
+ async writeFixContent(fixedExtensions) {
79
+ var _a;
80
+ if (this.fix &&
81
+ (this.config.flags['copy-dir'] ||
82
+ ((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm) ||
83
+ (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
84
+ (0, fs_1.writeFileSync)((0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName), JSON.stringify(fixedExtensions));
85
+ }
86
+ }
87
+ }
88
+ exports.default = Extensions;
@@ -1,4 +1,6 @@
1
- import Entries from "./entries";
2
- import GlobalField from "./global-fields";
3
- import ContentType from "./content-types";
4
- export { Entries, GlobalField, ContentType };
1
+ import Entries from './entries';
2
+ import GlobalField from './global-fields';
3
+ import ContentType from './content-types';
4
+ import Workflows from './workflows';
5
+ import Extensions from './extensions';
6
+ export { Entries, GlobalField, ContentType, Workflows, Extensions };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ContentType = exports.GlobalField = exports.Entries = void 0;
3
+ 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;
@@ -8,3 +8,7 @@ const global_fields_1 = tslib_1.__importDefault(require("./global-fields"));
8
8
  exports.GlobalField = global_fields_1.default;
9
9
  const content_types_1 = tslib_1.__importDefault(require("./content-types"));
10
10
  exports.ContentType = content_types_1.default;
11
+ const workflows_1 = tslib_1.__importDefault(require("./workflows"));
12
+ exports.Workflows = workflows_1.default;
13
+ const extensions_1 = tslib_1.__importDefault(require("./extensions"));
14
+ exports.Extensions = extensions_1.default;
@@ -0,0 +1,26 @@
1
+ import { LogFn, ConfigType, ContentTypeStruct, CtConstructorParam, ModuleConstructorParam, Workflow } from '../types';
2
+ import auditConfig from '../config';
3
+ export default class Workflows {
4
+ log: LogFn;
5
+ protected fix: boolean;
6
+ fileName: any;
7
+ config: ConfigType;
8
+ folderPath: string;
9
+ workflowSchema: Workflow[];
10
+ ctSchema: ContentTypeStruct[];
11
+ moduleName: keyof typeof auditConfig.moduleConfig;
12
+ ctUidSet: Set<string>;
13
+ missingCtInWorkflows: Workflow[];
14
+ missingCts: Set<string>;
15
+ workflowPath: string;
16
+ constructor({ log, fix, config, moduleName, ctSchema, }: ModuleConstructorParam & Pick<CtConstructorParam, 'ctSchema'>);
17
+ /**
18
+ * Check whether the given path for the workflow exists or not
19
+ * If path exist read
20
+ * From the ctSchema add all the content type UID into ctUidSet to check whether the content-type is present or not
21
+ * @returns Array of object containing the workflow name, uid and content_types that are missing
22
+ */
23
+ run(): Promise<{}>;
24
+ fixWorkflowSchema(): Promise<void>;
25
+ writeFixContent(newWorkflowSchema: Record<string, Workflow>): Promise<void>;
26
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const path_1 = require("path");
4
+ const fs_1 = require("fs");
5
+ const lodash_1 = require("lodash");
6
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
7
+ const messages_1 = require("../messages");
8
+ const lodash_2 = require("lodash");
9
+ class Workflows {
10
+ constructor({ log, fix, config, moduleName, ctSchema, }) {
11
+ this.log = log;
12
+ this.config = config;
13
+ this.fix = fix !== null && fix !== void 0 ? fix : false;
14
+ this.ctSchema = ctSchema;
15
+ this.workflowSchema = [];
16
+ this.moduleName = moduleName !== null && moduleName !== void 0 ? moduleName : 'workflows';
17
+ this.fileName = config.moduleConfig[this.moduleName].fileName;
18
+ this.folderPath = (0, path_1.resolve)(config.basePath, config.moduleConfig[this.moduleName].dirName);
19
+ this.ctUidSet = new Set(['$all']);
20
+ this.missingCtInWorkflows = [];
21
+ this.missingCts = new Set();
22
+ this.workflowPath = '';
23
+ }
24
+ /**
25
+ * Check whether the given path for the workflow exists or not
26
+ * If path exist read
27
+ * From the ctSchema add all the content type UID into ctUidSet to check whether the content-type is present or not
28
+ * @returns Array of object containing the workflow name, uid and content_types that are missing
29
+ */
30
+ async run() {
31
+ if (!(0, fs_1.existsSync)(this.folderPath)) {
32
+ this.log(`Skipping ${this.moduleName} audit`, 'warn');
33
+ this.log((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
34
+ return {};
35
+ }
36
+ this.workflowPath = (0, path_1.join)(this.folderPath, this.fileName);
37
+ this.workflowSchema = (0, fs_1.existsSync)(this.workflowPath)
38
+ ? (0, lodash_2.values)(JSON.parse((0, fs_1.readFileSync)(this.workflowPath, 'utf8')))
39
+ : [];
40
+ this.ctSchema.forEach((ct) => this.ctUidSet.add(ct.uid));
41
+ for (const workflow of this.workflowSchema) {
42
+ const ctNotPresent = workflow.content_types.filter((ct) => !this.ctUidSet.has(ct));
43
+ if (ctNotPresent.length) {
44
+ const tempwf = (0, lodash_1.cloneDeep)(workflow);
45
+ tempwf.content_types = ctNotPresent;
46
+ ctNotPresent.forEach((ct) => this.missingCts.add(ct));
47
+ this.missingCtInWorkflows.push(tempwf);
48
+ }
49
+ this.log((0, messages_1.$t)(messages_1.auditMsg.SCAN_WF_SUCCESS_MSG, {
50
+ name: workflow.name,
51
+ uid: workflow.uid,
52
+ }), 'info');
53
+ }
54
+ if (this.fix && this.missingCtInWorkflows.length) {
55
+ await this.fixWorkflowSchema();
56
+ this.missingCtInWorkflows.forEach((wf) => (wf.fixStatus = 'Fixed'));
57
+ }
58
+ return this.missingCtInWorkflows;
59
+ }
60
+ async fixWorkflowSchema() {
61
+ const newWorkflowSchema = (0, fs_1.existsSync)(this.workflowPath)
62
+ ? JSON.parse((0, fs_1.readFileSync)(this.workflowPath, 'utf8'))
63
+ : {};
64
+ if (Object.keys(newWorkflowSchema).length !== 0) {
65
+ for (const workflow of this.workflowSchema) {
66
+ const fixedCts = workflow.content_types.filter((ct) => !this.missingCts.has(ct));
67
+ if (fixedCts.length) {
68
+ newWorkflowSchema[workflow.uid].content_types = fixedCts;
69
+ }
70
+ else {
71
+ const { name, uid } = workflow;
72
+ const warningMessage = (0, messages_1.$t)(messages_1.commonMsg.WORKFLOW_FIX_WARN, { name, uid });
73
+ this.log(warningMessage, { color: 'yellow' });
74
+ if (this.config.flags.yes || (await cli_utilities_1.ux.confirm(messages_1.commonMsg.WORKFLOW_FIX_CONFIRMATION))) {
75
+ delete newWorkflowSchema[workflow.uid];
76
+ }
77
+ }
78
+ }
79
+ }
80
+ await this.writeFixContent(newWorkflowSchema);
81
+ }
82
+ async writeFixContent(newWorkflowSchema) {
83
+ var _a;
84
+ if (this.fix &&
85
+ !(this.config.flags['copy-dir'] || ((_a = this.config.flags['external-config']) === null || _a === void 0 ? void 0 : _a.skipConfirm)) &&
86
+ (this.config.flags.yes || (await cli_utilities_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION)))) {
87
+ (0, fs_1.writeFileSync)((0, path_1.join)(this.folderPath, this.config.moduleConfig[this.moduleName].fileName), JSON.stringify(newWorkflowSchema));
88
+ }
89
+ }
90
+ }
91
+ exports.default = Workflows;
@@ -36,6 +36,9 @@ type RefErrorReturnType = {
36
36
  missingRefs: string[];
37
37
  display_name: string;
38
38
  tree: Record<string, unknown>[];
39
+ uid?: string;
40
+ content_types?: string[];
41
+ title?: string;
39
42
  };
40
43
  type ReferenceFieldDataType = CommonDataTypeStruct & {
41
44
  reference_to: string[];
@@ -73,6 +76,9 @@ declare enum OutputColumn {
73
76
  'Field name' = "display_name",
74
77
  'Field type' = "data_type",
75
78
  'Missing references' = "missingRefs",
76
- Path = "treeStr"
79
+ Path = "treeStr",
80
+ title = "title",
81
+ 'uid' = "uid",
82
+ 'missingCts' = "content_types"
77
83
  }
78
84
  export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, ExtensionOrAppFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, ContentTypeSchemaType, GlobalFieldSchemaTypes, };
@@ -8,5 +8,8 @@ var OutputColumn;
8
8
  OutputColumn["Field type"] = "data_type";
9
9
  OutputColumn["Missing references"] = "missingRefs";
10
10
  OutputColumn["Path"] = "treeStr";
11
+ OutputColumn["title"] = "title";
12
+ OutputColumn["uid"] = "uid";
13
+ OutputColumn["missingCts"] = "content_types";
11
14
  })(OutputColumn || (OutputColumn = {}));
12
15
  exports.OutputColumn = OutputColumn;
@@ -0,0 +1,24 @@
1
+ export interface Extension {
2
+ stackHeaders: {
3
+ api_key: string;
4
+ };
5
+ urlPath: string;
6
+ uid: string;
7
+ created_at: string;
8
+ updated_at: string;
9
+ created_by: string;
10
+ updated_by: string;
11
+ tags?: [];
12
+ _version: number;
13
+ title: string;
14
+ config: {};
15
+ type: 'field';
16
+ data_type: string;
17
+ multiple: boolean;
18
+ srcdoc?: string;
19
+ scope: {
20
+ content_types: string[];
21
+ };
22
+ content_types?: string[];
23
+ fixStatus?: string;
24
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -2,3 +2,5 @@ export * from './utils';
2
2
  export * from './common';
3
3
  export * from './entries';
4
4
  export * from './content-types';
5
+ export * from './workflow';
6
+ export * from './extensions';
@@ -5,3 +5,5 @@ tslib_1.__exportStar(require("./utils"), exports);
5
5
  tslib_1.__exportStar(require("./common"), exports);
6
6
  tslib_1.__exportStar(require("./entries"), exports);
7
7
  tslib_1.__exportStar(require("./content-types"), exports);
8
+ tslib_1.__exportStar(require("./workflow"), exports);
9
+ tslib_1.__exportStar(require("./extensions"), exports);
@@ -0,0 +1,13 @@
1
+ export interface Workflow {
2
+ uid: string;
3
+ name: string;
4
+ content_types: string[];
5
+ org_uid?: string;
6
+ api_key?: string;
7
+ workflow_stages?: Record<string, unknown>;
8
+ admin_users?: any;
9
+ enabled?: boolean;
10
+ deleted_at?: any;
11
+ missingRefs?: any;
12
+ fixStatus?: string;
13
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.4.1",
2
+ "version": "1.5.0",
3
3
  "commands": {
4
4
  "cm:stacks:audit:fix": {
5
5
  "id": "cm:stacks:audit:fix",
@@ -58,7 +58,9 @@
58
58
  "options": [
59
59
  "content-types",
60
60
  "global-fields",
61
- "entries"
61
+ "entries",
62
+ "extensions",
63
+ "workflows"
62
64
  ]
63
65
  },
64
66
  "copy-dir": {
@@ -87,7 +89,8 @@
87
89
  "json:rte",
88
90
  "json:extension",
89
91
  "blocks",
90
- "group"
92
+ "group",
93
+ "content_types"
91
94
  ]
92
95
  },
93
96
  "yes": {
@@ -208,7 +211,9 @@
208
211
  "options": [
209
212
  "content-types",
210
213
  "global-fields",
211
- "entries"
214
+ "entries",
215
+ "extensions",
216
+ "workflows"
212
217
  ]
213
218
  },
214
219
  "columns": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentstack/cli-audit",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Contentstack audit plugin",
5
5
  "author": "Contentstack CLI",
6
6
  "homepage": "https://github.com/contentstack/cli",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "@contentstack/cli-command": "~1.2.16",
22
- "@contentstack/cli-utilities": "~1.5.12",
22
+ "@contentstack/cli-utilities": "~1.6.0",
23
23
  "@oclif/plugin-help": "^5",
24
24
  "@oclif/plugin-plugins": "^4.1.9",
25
25
  "chalk": "^4.1.2",