@contentstack/cli-audit 1.0.0 → 1.2.1

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
@@ -2,6 +2,7 @@
2
2
  <!-- Insert Audit version here -->
3
3
 
4
4
  # @contentstack/cli-audit
5
+
5
6
  Audit plugin
6
7
 
7
8
  ## How to install this plugin
@@ -12,15 +13,13 @@ $ csdx plugins:install @contentstack/cli-audit
12
13
 
13
14
  ## How to use this plugin
14
15
 
15
- This plugin requires you to be authenticated using [csdx auth:login](https://www.contentstack.com/docs/developers/cli/authenticate-with-the-cli/).
16
-
17
16
  <!-- usage -->
18
17
  ```sh-session
19
18
  $ npm install -g @contentstack/cli-audit
20
19
  $ csdx COMMAND
21
20
  running command...
22
21
  $ csdx (--version|-v)
23
- @contentstack/cli-audit/1.0.0 linux-x64 node-v18.18.0
22
+ @contentstack/cli-audit/1.2.1 linux-x64 node-v18.18.2
24
23
  $ csdx --help [COMMAND]
25
24
  USAGE
26
25
  $ csdx COMMAND
@@ -29,10 +28,12 @@ USAGE
29
28
  <!-- usagestop -->
30
29
 
31
30
  # Commands
31
+
32
32
  <!-- commands -->
33
- * [`csdx cm::stacks:audit:fix`](#csdx-cmstacksauditfix)
33
+ * [`csdx audit`](#csdx-audit)
34
+ * [`csdx audit:fix`](#csdx-auditfix)
34
35
  * [`csdx cm:stacks:audit`](#csdx-cmstacksaudit)
35
- * [`csdx cm:stacks:audit:fix`](#csdx-cmstacksauditfix-1)
36
+ * [`csdx cm:stacks:audit:fix`](#csdx-cmstacksauditfix)
36
37
  * [`csdx help [COMMANDS]`](#csdx-help-commands)
37
38
  * [`csdx plugins`](#csdx-plugins)
38
39
  * [`csdx plugins:install PLUGIN...`](#csdx-pluginsinstall-plugin)
@@ -44,29 +45,89 @@ USAGE
44
45
  * [`csdx plugins:uninstall PLUGIN...`](#csdx-pluginsuninstall-plugin-2)
45
46
  * [`csdx plugins:update`](#csdx-pluginsupdate)
46
47
 
47
- ## `csdx cm::stacks:audit:fix`
48
+ ## `csdx audit`
48
49
 
49
- Audit fix command
50
+ Perform audits and find possible errors in the exported Contentstack data
50
51
 
51
52
  ```
52
53
  USAGE
53
- $ csdx cm::stacks:audit:fix [-c <value>] [-d <value>]
54
+ $ csdx audit [-c <value>] [-d <value>] [--report-path <value>] [--modules
55
+ content-types|global-fields|entries] [--columns <value> | ] [--sort <value>] [--filter <value>] [--csv |
56
+ --no-truncate]
54
57
 
55
58
  FLAGS
56
- -c, --config=<value> Path of the external config.
57
- -d, --data-dir=<value> Path where the data is stored.
59
+ -c, --config=<value> Path of the external config
60
+ -d, --data-dir=<value> Path where the data is stored
61
+ --columns=<value> only show provided columns (comma-separated)
62
+ --csv output is csv format [alias: --output=csv]
63
+ --filter=<value> filter property by partial string matching, ex: name=foo
64
+ --modules=<option>... Provide the list of modules to be audited
65
+ <options: content-types|global-fields|entries>
66
+ --no-truncate do not truncate output to fit screen
67
+ --report-path=<value> Path to store the audit reports
68
+ --sort=<value> property to sort by (prepend '-' for descending)
58
69
 
59
70
  DESCRIPTION
60
- Audit fix command
71
+ Perform audits and find possible errors in the exported Contentstack data
61
72
 
62
73
  ALIASES
63
- $ csdx cm::stacks:audit:fix
74
+ $ csdx audit
75
+ $ csdx cm:stacks:audit
64
76
 
65
77
  EXAMPLES
66
- $ csdx cm::stacks:audit:fix
78
+ $ csdx audit
79
+
80
+ $ csdx audit --report-path=<path>
81
+
82
+ $ csdx audit --report-path=<path> --csv
83
+
84
+ $ csdx audit --report-path=<path> --filter="name=<filter-value>"
85
+
86
+ $ csdx audit --report-path=<path> --modules=content-types --filter="name="<filter-value>"
67
87
  ```
68
88
 
69
- _See code: [src/commands/cm/stacks/audit/fix.ts](https://github.com/contentstack/audit/blob/main/packages/contentstack-audit/src/commands/cm/stacks/audit/fix.ts)_
89
+ ## `csdx audit:fix`
90
+
91
+ Perform audits and fix possible errors in the exported Contentstack data.
92
+
93
+ ```
94
+ USAGE
95
+ $ csdx audit:fix [-c <value>] [-d <value>] [--report-path <value>] [--modules
96
+ content-types|global-fields|entries] [--copy-path <value> --copy-dir] [--columns <value> | ] [--sort <value>]
97
+ [--filter <value>] [--csv | --no-truncate]
98
+
99
+ FLAGS
100
+ -c, --config=<value> Path of the external config
101
+ -d, --data-dir=<value> Path where the data is stored
102
+ --columns=<value> only show provided columns (comma-separated)
103
+ --copy-dir Create backup from the original data.
104
+ --copy-path=<value> Provide the path to backup the copied data
105
+ --csv output is csv format [alias: --output=csv]
106
+ --filter=<value> filter property by partial string matching, ex: name=foo
107
+ --modules=<option>... Provide the list of modules to be audited
108
+ <options: content-types|global-fields|entries>
109
+ --no-truncate do not truncate output to fit screen
110
+ --report-path=<value> Path to store the audit reports
111
+ --sort=<value> property to sort by (prepend '-' for descending)
112
+
113
+ DESCRIPTION
114
+ Perform audits and fix possible errors in the exported Contentstack data.
115
+
116
+ ALIASES
117
+ $ csdx audit:fix
118
+ $ csdx cm:stacks:audit:fix
119
+
120
+ EXAMPLES
121
+ $ csdx audit:fix --copy-dir
122
+
123
+ $ csdx audit:fix --report-path=<path> --copy-dir
124
+
125
+ $ csdx audit:fix --report-path=<path> --copy-dir --csv
126
+
127
+ $ csdx audit:fix --report-path=<path> --filter="name=<filter-value>"
128
+
129
+ $ csdx audit:fix --report-path=<path> --modules=content-types --filter="name="<filter-value>" --copy-dir --copy-path=<path>
130
+ ```
70
131
 
71
132
  ## `csdx cm:stacks:audit`
72
133
 
@@ -79,21 +140,22 @@ USAGE
79
140
  --no-truncate]
80
141
 
81
142
  FLAGS
82
- -c, --config=<value> Path of the external config.
83
- -d, --data-dir=<value> Path where the data is stored.
143
+ -c, --config=<value> Path of the external config
144
+ -d, --data-dir=<value> Path where the data is stored
84
145
  --columns=<value> only show provided columns (comma-separated)
85
146
  --csv output is csv format [alias: --output=csv]
86
147
  --filter=<value> filter property by partial string matching, ex: name=foo
87
- --modules=<option>... Provide the list of modules to be audited.
148
+ --modules=<option>... Provide the list of modules to be audited
88
149
  <options: content-types|global-fields|entries>
89
150
  --no-truncate do not truncate output to fit screen
90
- --report-path=<value> Path to store the audit reports.
151
+ --report-path=<value> Path to store the audit reports
91
152
  --sort=<value> property to sort by (prepend '-' for descending)
92
153
 
93
154
  DESCRIPTION
94
155
  Perform audits and find possible errors in the exported Contentstack data
95
156
 
96
157
  ALIASES
158
+ $ csdx audit
97
159
  $ csdx cm:stacks:audit
98
160
 
99
161
  EXAMPLES
@@ -112,24 +174,45 @@ _See code: [src/commands/cm/stacks/audit/index.ts](https://github.com/contentsta
112
174
 
113
175
  ## `csdx cm:stacks:audit:fix`
114
176
 
115
- Audit fix command
177
+ Perform audits and fix possible errors in the exported Contentstack data.
116
178
 
117
179
  ```
118
180
  USAGE
119
- $ csdx cm:stacks:audit:fix [-c <value>] [-d <value>]
181
+ $ csdx cm:stacks:audit:fix [-c <value>] [-d <value>] [--report-path <value>] [--modules
182
+ content-types|global-fields|entries] [--copy-path <value> --copy-dir] [--columns <value> | ] [--sort <value>]
183
+ [--filter <value>] [--csv | --no-truncate]
120
184
 
121
185
  FLAGS
122
- -c, --config=<value> Path of the external config.
123
- -d, --data-dir=<value> Path where the data is stored.
186
+ -c, --config=<value> Path of the external config
187
+ -d, --data-dir=<value> Path where the data is stored
188
+ --columns=<value> only show provided columns (comma-separated)
189
+ --copy-dir Create backup from the original data.
190
+ --copy-path=<value> Provide the path to backup the copied data
191
+ --csv output is csv format [alias: --output=csv]
192
+ --filter=<value> filter property by partial string matching, ex: name=foo
193
+ --modules=<option>... Provide the list of modules to be audited
194
+ <options: content-types|global-fields|entries>
195
+ --no-truncate do not truncate output to fit screen
196
+ --report-path=<value> Path to store the audit reports
197
+ --sort=<value> property to sort by (prepend '-' for descending)
124
198
 
125
199
  DESCRIPTION
126
- Audit fix command
200
+ Perform audits and fix possible errors in the exported Contentstack data.
127
201
 
128
202
  ALIASES
129
- $ csdx cm::stacks:audit:fix
203
+ $ csdx audit:fix
204
+ $ csdx cm:stacks:audit:fix
130
205
 
131
206
  EXAMPLES
132
- $ csdx cm:stacks:audit:fix
207
+ $ csdx cm:stacks:audit:fix --copy-dir
208
+
209
+ $ csdx cm:stacks:audit:fix --report-path=<path> --copy-dir
210
+
211
+ $ csdx cm:stacks:audit:fix --report-path=<path> --copy-dir --csv
212
+
213
+ $ csdx cm:stacks:audit:fix --report-path=<path> --filter="name=<filter-value>"
214
+
215
+ $ csdx cm:stacks:audit:fix --report-path=<path> --modules=content-types --filter="name="<filter-value>" --copy-dir --copy-path=<path>
133
216
  ```
134
217
 
135
218
  _See code: [src/commands/cm/stacks/audit/fix.ts](https://github.com/contentstack/audit/blob/main/packages/contentstack-audit/src/commands/cm/stacks/audit/fix.ts)_
@@ -0,0 +1,83 @@
1
+ import config from './config';
2
+ import { BaseCommand } from './base-command';
3
+ import { ContentTypeStruct } from './types';
4
+ export declare abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseCommand> {
5
+ private currentCommand;
6
+ get fixStatus(): {
7
+ fixStatus: {
8
+ minWidth: number;
9
+ header: string;
10
+ get: (row: any) => string;
11
+ };
12
+ };
13
+ /**
14
+ * The `start` function performs an audit on content types, global fields, and entries, and displays
15
+ * any missing references.
16
+ * @param {string} command - The `command` parameter is a string that represents the current command
17
+ * being executed.
18
+ */
19
+ start(command: string): Promise<void>;
20
+ /**
21
+ * The `scan` function performs an audit on different modules (content-types, global-fields, and
22
+ * entries) and returns the missing references for each module.
23
+ * @returns The function `scan()` returns an object with properties `missingCtRefs`, `missingGfRefs`,
24
+ * and `missingEntryRefs`.
25
+ */
26
+ scanAndFix(): Promise<{
27
+ missingCtRefs: Record<string, any> | undefined;
28
+ missingGfRefs: Record<string, any> | undefined;
29
+ missingEntryRefs: Record<string, any> | undefined;
30
+ }>;
31
+ /**
32
+ * The `promptQueue` function prompts the user to enter a data directory path if the `data-dir` flag
33
+ * is missing, and sets the `basePath` property of the `sharedConfig` object to the entered path.
34
+ */
35
+ promptQueue(): Promise<void>;
36
+ /**
37
+ * The function `createBackUp` creates a backup of data if the `copy-dir` flag is set, and throws
38
+ * an error if the specified path does not exist.
39
+ */
40
+ createBackUp(): Promise<void>;
41
+ /**
42
+ * The function `getCtAndGfSchema` reads and parses JSON files containing content type and global
43
+ * field schemas, and returns them as an object.
44
+ * @returns The function `getCtAndGfSchema()` returns an object with two properties: `ctSchema` and
45
+ * `gfSchema`. The values of these properties are the parsed JSON data from two different files.
46
+ */
47
+ getCtAndGfSchema(): {
48
+ ctSchema: ContentTypeStruct[];
49
+ gfSchema: ContentTypeStruct[];
50
+ };
51
+ /**
52
+ * The function `showOutputOnScreen` displays missing references on the terminal screen if the
53
+ * `showTerminalOutput` flag is set to true.
54
+ * @param {{ module: string; missingRefs?: Record<string, any> }[]} allMissingRefs - An array of
55
+ * objects, where each object has two properties:
56
+ */
57
+ showOutputOnScreen(allMissingRefs: {
58
+ module: string;
59
+ missingRefs?: Record<string, any>;
60
+ }[]): void;
61
+ /**
62
+ * The function prepares a report by writing a JSON file and a CSV file with a list of missing
63
+ * references for a given module.
64
+ * @param moduleName - The `moduleName` parameter is a string that represents the name of a module.
65
+ * It is used to generate the filename for the report.
66
+ * @param listOfMissingRefs - The `listOfMissingRefs` parameter is a record object that contains
67
+ * information about missing references. It is a key-value pair where the key represents the
68
+ * reference name and the value represents additional information about the missing reference.
69
+ * @returns The function `prepareReport` returns a Promise that resolves to `void`.
70
+ */
71
+ prepareReport(moduleName: keyof typeof config.moduleConfig, listOfMissingRefs: Record<string, any>): Promise<void>;
72
+ /**
73
+ * The function `prepareCSV` takes a module name and a list of missing references, and generates a
74
+ * CSV file with the specified columns and filtered rows.
75
+ * @param moduleName - The `moduleName` parameter is a string that represents the name of a module.
76
+ * It is used to generate the name of the CSV file that will be created.
77
+ * @param listOfMissingRefs - The `listOfMissingRefs` parameter is a record object that contains
78
+ * information about missing references. Each key in the record represents a reference, and the
79
+ * corresponding value is an array of objects that contain details about the missing reference.
80
+ * @returns The function `prepareCSV` returns a Promise that resolves to `void`.
81
+ */
82
+ prepareCSV(moduleName: keyof typeof config.moduleConfig, listOfMissingRefs: Record<string, any>): Promise<void>;
83
+ }
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuditBaseCommand = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const csv = tslib_1.__importStar(require("fast-csv"));
7
+ const fs_extra_1 = require("fs-extra");
8
+ const uuid_1 = require("uuid");
9
+ const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
10
+ const path_1 = require("path");
11
+ const cloneDeep_1 = tslib_1.__importDefault(require("lodash/cloneDeep"));
12
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
13
+ const fs_1 = require("fs");
14
+ const log_1 = require("./util/log");
15
+ const messages_1 = require("./messages");
16
+ const base_command_1 = require("./base-command");
17
+ const modules_1 = require("./modules");
18
+ const types_1 = require("./types");
19
+ class AuditBaseCommand extends base_command_1.BaseCommand {
20
+ get fixStatus() {
21
+ return {
22
+ fixStatus: {
23
+ minWidth: 7,
24
+ header: 'Fix Status',
25
+ get: (row) => {
26
+ return row.fixStatus === 'Fixed' ? chalk_1.default.greenBright(row.fixStatus) : chalk_1.default.redBright(row.fixStatus);
27
+ },
28
+ },
29
+ };
30
+ }
31
+ /**
32
+ * The `start` function performs an audit on content types, global fields, and entries, and displays
33
+ * any missing references.
34
+ * @param {string} command - The `command` parameter is a string that represents the current command
35
+ * being executed.
36
+ */
37
+ async start(command) {
38
+ this.currentCommand = command;
39
+ await this.promptQueue();
40
+ await this.createBackUp();
41
+ this.sharedConfig.reportPath = (0, path_1.resolve)(this.flags['report-path'] || process.cwd(), 'audit-report');
42
+ const { missingCtRefs, missingGfRefs, missingEntryRefs } = await this.scanAndFix();
43
+ this.showOutputOnScreen([
44
+ { module: 'Content types', missingRefs: missingCtRefs },
45
+ { module: 'Global Fields', missingRefs: missingGfRefs },
46
+ { module: 'Entries', missingRefs: missingEntryRefs },
47
+ ]);
48
+ if (!(0, isEmpty_1.default)(missingCtRefs) || !(0, isEmpty_1.default)(missingGfRefs) || !(0, isEmpty_1.default)(missingEntryRefs)) {
49
+ if (this.currentCommand === 'cm:stacks:audit') {
50
+ this.log(this.$t(messages_1.auditMsg.FINAL_REPORT_PATH, { path: this.sharedConfig.reportPath }), 'warn');
51
+ }
52
+ else {
53
+ this.log(this.$t(this.messages.FIXED_CONTENT_PATH_MAG, { path: this.sharedConfig.basePath }), 'warn');
54
+ }
55
+ }
56
+ else {
57
+ this.log(this.messages.NO_MISSING_REF_FOUND, 'info');
58
+ this.log('');
59
+ }
60
+ }
61
+ /**
62
+ * The `scan` function performs an audit on different modules (content-types, global-fields, and
63
+ * entries) and returns the missing references for each module.
64
+ * @returns The function `scan()` returns an object with properties `missingCtRefs`, `missingGfRefs`,
65
+ * and `missingEntryRefs`.
66
+ */
67
+ async scanAndFix() {
68
+ let { ctSchema, gfSchema } = this.getCtAndGfSchema();
69
+ let missingCtRefs, missingGfRefs, missingEntryRefs;
70
+ for (const module of this.sharedConfig.flags.modules || this.sharedConfig.modules) {
71
+ cli_utilities_1.ux.action.start(this.$t(this.messages.AUDIT_START_SPINNER, { module }));
72
+ const constructorParam = {
73
+ ctSchema,
74
+ gfSchema,
75
+ log: this.log,
76
+ moduleName: module,
77
+ config: this.sharedConfig,
78
+ fix: this.currentCommand === 'cm:stacks:audit:fix',
79
+ };
80
+ switch (module) {
81
+ case 'content-types':
82
+ missingCtRefs = await new modules_1.ContentType((0, cloneDeep_1.default)(constructorParam)).run();
83
+ await this.prepareReport(module, missingCtRefs);
84
+ break;
85
+ case 'global-fields':
86
+ missingGfRefs = await new modules_1.GlobalField((0, cloneDeep_1.default)(constructorParam)).run();
87
+ await this.prepareReport(module, missingGfRefs);
88
+ break;
89
+ case 'entries':
90
+ missingEntryRefs = await new modules_1.Entries((0, cloneDeep_1.default)(constructorParam)).run();
91
+ await this.prepareReport(module, missingEntryRefs);
92
+ break;
93
+ }
94
+ cli_utilities_1.ux.action.stop();
95
+ }
96
+ return { missingCtRefs, missingGfRefs, missingEntryRefs };
97
+ }
98
+ /**
99
+ * The `promptQueue` function prompts the user to enter a data directory path if the `data-dir` flag
100
+ * is missing, and sets the `basePath` property of the `sharedConfig` object to the entered path.
101
+ */
102
+ async promptQueue() {
103
+ // NOTE get content path if data-dir flag is missing
104
+ this.sharedConfig.basePath =
105
+ this.flags['data-dir'] ||
106
+ (await cli_utilities_1.cliux.inquire({
107
+ type: 'input',
108
+ name: 'data-dir',
109
+ message: this.messages.DATA_DIR,
110
+ }));
111
+ }
112
+ /**
113
+ * The function `createBackUp` creates a backup of data if the `copy-dir` flag is set, and throws
114
+ * an error if the specified path does not exist.
115
+ */
116
+ async createBackUp() {
117
+ if (this.currentCommand === 'cm:stacks:audit:fix' && this.flags['copy-dir']) {
118
+ if (!(0, fs_1.existsSync)(this.sharedConfig.basePath)) {
119
+ throw Error(this.$t(this.messages.NOT_VALID_PATH, { path: this.sharedConfig.basePath }));
120
+ }
121
+ // NOTE create bkp directory
122
+ const backupDirPath = `${(this.flags['copy-path'] || this.flags['data-dir']).replace(/\/+$/, '')}_backup_${(0, uuid_1.v4)()}`;
123
+ if (!(0, fs_1.existsSync)(backupDirPath)) {
124
+ (0, fs_1.mkdirSync)(backupDirPath, { recursive: true });
125
+ }
126
+ await (0, fs_extra_1.copy)(this.sharedConfig.basePath, backupDirPath);
127
+ this.sharedConfig.basePath = backupDirPath;
128
+ }
129
+ }
130
+ /**
131
+ * The function `getCtAndGfSchema` reads and parses JSON files containing content type and global
132
+ * field schemas, and returns them as an object.
133
+ * @returns The function `getCtAndGfSchema()` returns an object with two properties: `ctSchema` and
134
+ * `gfSchema`. The values of these properties are the parsed JSON data from two different files.
135
+ */
136
+ getCtAndGfSchema() {
137
+ const modules = this.sharedConfig.flags.modules || this.sharedConfig.modules;
138
+ const ctPath = (0, path_1.join)(this.sharedConfig.basePath, this.sharedConfig.moduleConfig['content-types'].dirName, this.sharedConfig.moduleConfig['content-types'].fileName);
139
+ const gfPath = (0, path_1.join)(this.sharedConfig.basePath, this.sharedConfig.moduleConfig['global-fields'].dirName, this.sharedConfig.moduleConfig['global-fields'].fileName);
140
+ if (modules.includes('content-types')) {
141
+ if (!(0, fs_1.existsSync)(ctPath)) {
142
+ this.log(this.$t(messages_1.auditMsg.NOT_VALID_PATH, { path: ctPath }), 'error');
143
+ }
144
+ }
145
+ if (modules.includes('global-fields')) {
146
+ if (!(0, fs_1.existsSync)(gfPath)) {
147
+ this.log(this.$t(messages_1.auditMsg.NOT_VALID_PATH, { path: ctPath }), 'error');
148
+ }
149
+ }
150
+ const gfSchema = (0, fs_1.existsSync)(gfPath) ? JSON.parse((0, fs_1.readFileSync)(gfPath, 'utf8')) : [];
151
+ const ctSchema = (0, fs_1.existsSync)(ctPath) ? JSON.parse((0, fs_1.readFileSync)(ctPath, 'utf8')) : [];
152
+ return { ctSchema, gfSchema };
153
+ }
154
+ /**
155
+ * The function `showOutputOnScreen` displays missing references on the terminal screen if the
156
+ * `showTerminalOutput` flag is set to true.
157
+ * @param {{ module: string; missingRefs?: Record<string, any> }[]} allMissingRefs - An array of
158
+ * objects, where each object has two properties:
159
+ */
160
+ showOutputOnScreen(allMissingRefs) {
161
+ var _a;
162
+ if (this.sharedConfig.showTerminalOutput) {
163
+ this.log(''); // NOTE adding new line
164
+ for (const { module, missingRefs } of allMissingRefs) {
165
+ if (!(0, isEmpty_1.default)(missingRefs)) {
166
+ (0, log_1.print)([
167
+ {
168
+ bold: true,
169
+ color: 'cyan',
170
+ message: ` ${module}`,
171
+ },
172
+ ]);
173
+ const tableValues = Object.values(missingRefs).flat();
174
+ cli_utilities_1.ux.table(tableValues, Object.assign(Object.assign({ name: {
175
+ minWidth: 7,
176
+ header: 'Title',
177
+ }, display_name: {
178
+ minWidth: 7,
179
+ header: 'Field name',
180
+ }, data_type: {
181
+ minWidth: 7,
182
+ header: 'Field type',
183
+ }, missingRefs: {
184
+ minWidth: 7,
185
+ header: 'Missing references',
186
+ get: (row) => {
187
+ return chalk_1.default.red(typeof row.missingRefs === 'object' ? JSON.stringify(row.missingRefs) : row.missingRefs);
188
+ },
189
+ } }, (((_a = tableValues[0]) === null || _a === void 0 ? void 0 : _a.fixStatus) ? this.fixStatus : {})), { treeStr: {
190
+ minWidth: 7,
191
+ header: 'Path',
192
+ } }), Object.assign({}, this.flags));
193
+ this.log(''); // NOTE adding new line
194
+ }
195
+ }
196
+ }
197
+ }
198
+ /**
199
+ * The function prepares a report by writing a JSON file and a CSV file with a list of missing
200
+ * references for a given module.
201
+ * @param moduleName - The `moduleName` parameter is a string that represents the name of a module.
202
+ * It is used to generate the filename for the report.
203
+ * @param listOfMissingRefs - The `listOfMissingRefs` parameter is a record object that contains
204
+ * information about missing references. It is a key-value pair where the key represents the
205
+ * reference name and the value represents additional information about the missing reference.
206
+ * @returns The function `prepareReport` returns a Promise that resolves to `void`.
207
+ */
208
+ prepareReport(moduleName, listOfMissingRefs) {
209
+ if ((0, isEmpty_1.default)(listOfMissingRefs))
210
+ return Promise.resolve(void 0);
211
+ if (!(0, fs_1.existsSync)(this.sharedConfig.reportPath)) {
212
+ (0, fs_1.mkdirSync)(this.sharedConfig.reportPath, { recursive: true });
213
+ }
214
+ // NOTE write int json
215
+ (0, fs_1.writeFileSync)((0, path_1.join)(this.sharedConfig.reportPath, `${moduleName}.json`), JSON.stringify(listOfMissingRefs));
216
+ // NOTE write into CSV
217
+ return this.prepareCSV(moduleName, listOfMissingRefs);
218
+ }
219
+ /**
220
+ * The function `prepareCSV` takes a module name and a list of missing references, and generates a
221
+ * CSV file with the specified columns and filtered rows.
222
+ * @param moduleName - The `moduleName` parameter is a string that represents the name of a module.
223
+ * It is used to generate the name of the CSV file that will be created.
224
+ * @param listOfMissingRefs - The `listOfMissingRefs` parameter is a record object that contains
225
+ * information about missing references. Each key in the record represents a reference, and the
226
+ * corresponding value is an array of objects that contain details about the missing reference.
227
+ * @returns The function `prepareCSV` returns a Promise that resolves to `void`.
228
+ */
229
+ prepareCSV(moduleName, listOfMissingRefs) {
230
+ const csvStream = csv.format({ headers: true });
231
+ const csvPath = (0, path_1.join)(this.sharedConfig.reportPath, `${moduleName}.csv`);
232
+ const assetFileStream = (0, fs_1.createWriteStream)(csvPath);
233
+ assetFileStream.on('error', (error) => {
234
+ throw error;
235
+ });
236
+ return new Promise((resolve, reject) => {
237
+ csvStream.pipe(assetFileStream).on('close', resolve).on('error', reject);
238
+ const defaultColumns = Object.keys(types_1.OutputColumn);
239
+ const userDefinedColumns = this.sharedConfig.flags.columns ? this.sharedConfig.flags.columns.split(',') : null;
240
+ let missingRefs = Object.values(listOfMissingRefs).flat();
241
+ const columns = userDefinedColumns
242
+ ? [...userDefinedColumns, ...defaultColumns.filter((val) => !userDefinedColumns.includes(val))]
243
+ : defaultColumns;
244
+ if (this.sharedConfig.flags.filter) {
245
+ const [column, value] = this.sharedConfig.flags.filter.split('=');
246
+ missingRefs = missingRefs.filter((row) => row[types_1.OutputColumn[column]] === value);
247
+ }
248
+ for (const issue of missingRefs) {
249
+ let row = {};
250
+ for (const column of columns) {
251
+ row[column] = issue[types_1.OutputColumn[column]];
252
+ row[column] = typeof row[column] === 'object' ? JSON.stringify(row[column]) : row[column];
253
+ }
254
+ if (this.currentCommand === 'cm:stacks:audit:fix') {
255
+ row['Fix status'] = row.fixStatus;
256
+ }
257
+ csvStream.write(row);
258
+ }
259
+ csvStream.end();
260
+ });
261
+ }
262
+ }
263
+ exports.AuditBaseCommand = AuditBaseCommand;
@@ -1,8 +1,13 @@
1
- import { BaseCommand } from '../../../../base-command';
2
- export default class AuditFix extends BaseCommand<typeof AuditFix> {
3
- static description: string;
1
+ import { FlagInput } from '@contentstack/cli-utilities';
2
+ import { AuditBaseCommand } from '../../../../audit-base-command';
3
+ export default class AuditFix extends AuditBaseCommand {
4
4
  static aliases: string[];
5
+ static description: string;
5
6
  static examples: string[];
6
- static flags: {};
7
+ static flags: FlagInput;
8
+ /**
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.
11
+ */
7
12
  run(): Promise<void>;
8
13
  }
@@ -1,11 +1,55 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const base_command_1 = require("../../../../base-command");
4
- class AuditFix extends base_command_1.BaseCommand {
5
- async run() { }
3
+ const tslib_1 = require("tslib");
4
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
5
+ const config_1 = tslib_1.__importDefault(require("../../../../config"));
6
+ const messages_1 = require("../../../../messages");
7
+ const audit_base_command_1 = require("../../../../audit-base-command");
8
+ class AuditFix extends audit_base_command_1.AuditBaseCommand {
9
+ /**
10
+ * The `run` function is an asynchronous function that performs an audit on different modules
11
+ * (content-types, global-fields, entries) and generates a report.
12
+ */
13
+ async run() {
14
+ try {
15
+ await this.start('cm:stacks:audit:fix');
16
+ }
17
+ catch (error) {
18
+ this.log(error instanceof Error ? error.message : error, 'error');
19
+ console.trace(error);
20
+ cli_utilities_1.ux.action.stop('Process failed.!');
21
+ this.exit(1);
22
+ }
23
+ }
6
24
  }
7
25
  exports.default = AuditFix;
8
- AuditFix.description = 'Audit fix command';
9
- AuditFix.aliases = ['cm::stacks:audit:fix'];
10
- AuditFix.examples = ['$ <%= config.bin %> <%= command.id %>'];
11
- AuditFix.flags = {};
26
+ AuditFix.aliases = ['audit:fix', 'cm:stacks:audit:fix'];
27
+ AuditFix.description = messages_1.auditFixMsg.AUDIT_FIX_CMD_DESCRIPTION;
28
+ AuditFix.examples = [
29
+ '$ <%= config.bin %> <%= command.id %> --copy-dir',
30
+ '$ <%= config.bin %> <%= command.id %> --report-path=<path> --copy-dir',
31
+ '$ <%= config.bin %> <%= command.id %> --report-path=<path> --copy-dir --csv',
32
+ '$ <%= config.bin %> <%= command.id %> --report-path=<path> --filter="name=<filter-value>"',
33
+ '$ <%= config.bin %> <%= command.id %> --report-path=<path> --modules=content-types --filter="name="<filter-value>" --copy-dir --copy-path=<path>',
34
+ ];
35
+ AuditFix.flags = Object.assign({ 'report-path': cli_utilities_1.Flags.string({
36
+ description: messages_1.auditMsg.REPORT_PATH,
37
+ }), 'reference-only': cli_utilities_1.Flags.boolean({
38
+ hidden: true,
39
+ description: messages_1.auditMsg.REFERENCE_ONLY,
40
+ }), modules: cli_utilities_1.Flags.string({
41
+ multiple: true,
42
+ options: config_1.default.modules,
43
+ description: messages_1.auditMsg.MODULES,
44
+ }), 'copy-dir': cli_utilities_1.Flags.boolean({
45
+ description: messages_1.auditFixMsg.COPY_DATA,
46
+ }), 'copy-path': cli_utilities_1.Flags.string({
47
+ dependsOn: ['copy-dir'],
48
+ description: messages_1.auditFixMsg.BKP_PATH,
49
+ }), yes: cli_utilities_1.Flags.boolean({
50
+ char: 'y',
51
+ hidden: true,
52
+ description: 'Use this flag to skip confirmation',
53
+ }) }, cli_utilities_1.ux.table.flags({
54
+ only: ['columns', 'sort', 'filter', 'csv', 'no-truncate'],
55
+ }));