@contentstack/cli-audit 1.4.0 → 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 +29 -25
- package/lib/audit-base-command.d.ts +7 -1
- package/lib/audit-base-command.js +94 -10
- package/lib/commands/cm/stacks/audit/index.d.ts +1 -1
- package/lib/commands/cm/stacks/audit/index.js +1 -1
- package/lib/config/index.d.ts +10 -0
- package/lib/config/index.js +13 -3
- package/lib/messages/index.d.ts +7 -0
- package/lib/messages/index.js +20 -7
- package/lib/modules/entries.js +6 -3
- package/lib/modules/extensions.d.ts +20 -0
- package/lib/modules/extensions.js +88 -0
- package/lib/modules/index.d.ts +6 -4
- package/lib/modules/index.js +5 -1
- package/lib/modules/workflows.d.ts +26 -0
- package/lib/modules/workflows.js +91 -0
- package/lib/types/content-types.d.ts +7 -1
- package/lib/types/content-types.js +3 -0
- package/lib/types/extensions.d.ts +24 -0
- package/lib/types/extensions.js +2 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +2 -0
- package/lib/types/utils.d.ts +2 -2
- package/lib/types/workflow.d.ts +13 -0
- package/lib/types/workflow.js +2 -0
- package/lib/util/log.d.ts +2 -1
- package/lib/util/log.js +15 -6
- package/oclif.manifest.json +9 -4
- package/package.json +2 -2
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.
|
|
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>]
|
|
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>]
|
|
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>]
|
|
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>]
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
|
@@ -462,10 +462,14 @@ Remove all user-installed and linked plugins.
|
|
|
462
462
|
|
|
463
463
|
```
|
|
464
464
|
USAGE
|
|
465
|
-
$ csdx plugins:reset
|
|
465
|
+
$ csdx plugins:reset [--hard] [--reinstall]
|
|
466
|
+
|
|
467
|
+
FLAGS
|
|
468
|
+
--hard Delete node_modules and package manager related files in addition to uninstalling plugins.
|
|
469
|
+
--reinstall Reinstall all plugins after uninstalling.
|
|
466
470
|
```
|
|
467
471
|
|
|
468
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
472
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/reset.ts)_
|
|
469
473
|
|
|
470
474
|
## `csdx plugins:uninstall PLUGIN...`
|
|
471
475
|
|
|
@@ -493,7 +497,7 @@ EXAMPLES
|
|
|
493
497
|
$ csdx plugins:uninstall myplugin
|
|
494
498
|
```
|
|
495
499
|
|
|
496
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
500
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/uninstall.ts)_
|
|
497
501
|
|
|
498
502
|
## `csdx plugins:uninstall PLUGIN...`
|
|
499
503
|
|
|
@@ -537,5 +541,5 @@ DESCRIPTION
|
|
|
537
541
|
Update installed plugins.
|
|
538
542
|
```
|
|
539
543
|
|
|
540
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
544
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.3.2/src/commands/plugins/update.ts)_
|
|
541
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,
|
|
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,
|
|
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
|
-
|
|
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) ||
|
|
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,9 +83,15 @@ 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)([
|
|
89
|
+
{
|
|
90
|
+
bold: true,
|
|
91
|
+
color: 'whiteBright',
|
|
92
|
+
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
|
|
93
|
+
},
|
|
94
|
+
]);
|
|
79
95
|
const constructorParam = {
|
|
80
96
|
ctSchema,
|
|
81
97
|
gfSchema,
|
|
@@ -97,10 +113,35 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
97
113
|
missingEntryRefs = await new modules_1.Entries((0, cloneDeep_1.default)(constructorParam)).run();
|
|
98
114
|
await this.prepareReport(module, missingEntryRefs);
|
|
99
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;
|
|
100
130
|
}
|
|
101
|
-
|
|
131
|
+
(0, log_1.print)([
|
|
132
|
+
{
|
|
133
|
+
bold: true,
|
|
134
|
+
color: 'whiteBright',
|
|
135
|
+
message: this.$t(this.messages.AUDIT_START_SPINNER, { module }),
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
bold: true,
|
|
139
|
+
message: ' done',
|
|
140
|
+
color: 'whiteBright',
|
|
141
|
+
},
|
|
142
|
+
]);
|
|
102
143
|
}
|
|
103
|
-
return { missingCtRefs, missingGfRefs, missingEntryRefs };
|
|
144
|
+
return { missingCtRefs, missingGfRefs, missingEntryRefs, missingCtRefsInExtensions, missingCtRefsInWorkflow };
|
|
104
145
|
}
|
|
105
146
|
/**
|
|
106
147
|
* The `promptQueue` function prompts the user to enter a data directory path if the `data-dir` flag
|
|
@@ -193,6 +234,47 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
193
234
|
}
|
|
194
235
|
}
|
|
195
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
|
+
}
|
|
196
278
|
/**
|
|
197
279
|
* The function prepares a report by writing a JSON file and a CSV file with a list of missing
|
|
198
280
|
* references for a given module.
|
|
@@ -243,8 +325,10 @@ class AuditBaseCommand extends base_command_1.BaseCommand {
|
|
|
243
325
|
for (const issue of missingRefs) {
|
|
244
326
|
let row = {};
|
|
245
327
|
for (const column of columns) {
|
|
246
|
-
|
|
247
|
-
|
|
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
|
+
}
|
|
248
332
|
}
|
|
249
333
|
if (this.currentCommand === 'cm:stacks:audit:fix') {
|
|
250
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 {
|
package/lib/config/index.d.ts
CHANGED
|
@@ -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[];
|
package/lib/config/index.js
CHANGED
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const config = {
|
|
4
4
|
showTerminalOutput: true,
|
|
5
5
|
skipRefs: ['sys_assets'],
|
|
6
|
-
skipFieldTypes: ['taxonomy'],
|
|
7
|
-
modules: ['content-types', 'global-fields', 'entries'],
|
|
8
|
-
'fix-fields': ['reference', 'global_field', 'json:rte', 'json:extension', 'blocks', 'group'],
|
|
6
|
+
skipFieldTypes: ['taxonomy', '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: [
|
package/lib/messages/index.d.ts
CHANGED
|
@@ -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
|
/**
|
package/lib/messages/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.tableColumnDescriptions = exports.auditFixMsg = exports.auditMsg = exports.commonMsg = exports.errors = exports.$t = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const memoize_1 = tslib_1.__importDefault(require("lodash/memoize"));
|
|
6
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
4
7
|
const errors = {};
|
|
5
8
|
exports.errors = errors;
|
|
6
9
|
const tableColumnDescriptions = {
|
|
@@ -15,6 +18,10 @@ const commonMsg = {
|
|
|
15
18
|
CONFIG: 'Path of the external config',
|
|
16
19
|
DATA_DIR: 'Path where the data is stored',
|
|
17
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?`,
|
|
18
25
|
};
|
|
19
26
|
exports.commonMsg = commonMsg;
|
|
20
27
|
const auditMsg = {
|
|
@@ -28,7 +35,9 @@ const auditMsg = {
|
|
|
28
35
|
FINAL_REPORT_PATH: "Reports ready. Please find the reports at '{path}'.",
|
|
29
36
|
SCAN_CT_SUCCESS_MSG: "Successfully completed the scanning of {module} '{title}'.",
|
|
30
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}'",
|
|
31
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}.',
|
|
32
41
|
};
|
|
33
42
|
exports.auditMsg = auditMsg;
|
|
34
43
|
const auditFixMsg = {
|
|
@@ -38,6 +47,7 @@ const auditFixMsg = {
|
|
|
38
47
|
FIXED_CONTENT_PATH_MAG: 'You can locate the fixed content at {path}.',
|
|
39
48
|
EMPTY_FIX_MSG: 'Successfully removed the empty field/block found at {path} from the schema.',
|
|
40
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}.',
|
|
41
51
|
};
|
|
42
52
|
exports.auditFixMsg = auditFixMsg;
|
|
43
53
|
const messages = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, errors), commonMsg), auditMsg), auditFixMsg), tableColumnDescriptions);
|
|
@@ -51,13 +61,16 @@ const messages = Object.assign(Object.assign(Object.assign(Object.assign(Object.
|
|
|
51
61
|
* @returns a string.
|
|
52
62
|
*/
|
|
53
63
|
function $t(msg, args) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
const transfer = (0, memoize_1.default)(function (msg, args) {
|
|
65
|
+
if (!msg)
|
|
66
|
+
return '';
|
|
67
|
+
for (const key of Object.keys(args)) {
|
|
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);
|
|
70
|
+
}
|
|
71
|
+
return msg;
|
|
72
|
+
});
|
|
73
|
+
return transfer(msg, args);
|
|
61
74
|
}
|
|
62
75
|
exports.$t = $t;
|
|
63
76
|
exports.default = messages;
|
package/lib/modules/entries.js
CHANGED
|
@@ -10,6 +10,7 @@ const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
|
10
10
|
const fs_1 = require("fs");
|
|
11
11
|
const content_types_1 = tslib_1.__importDefault(require("./content-types"));
|
|
12
12
|
const messages_1 = require("../messages");
|
|
13
|
+
const util_1 = require("../util");
|
|
13
14
|
const global_fields_1 = tslib_1.__importDefault(require("./global-fields"));
|
|
14
15
|
class Entries {
|
|
15
16
|
constructor({ log, fix, config, moduleName, ctSchema, gfSchema }) {
|
|
@@ -59,11 +60,13 @@ class Entries {
|
|
|
59
60
|
this.removeMissingKeysOnEntry(ctSchema.schema, this.entries[entryUid]);
|
|
60
61
|
}
|
|
61
62
|
this.lookForReference([{ locale: code, uid, name: title }], ctSchema, this.entries[entryUid]);
|
|
62
|
-
|
|
63
|
+
const message = (0, messages_1.$t)(messages_1.auditMsg.SCAN_ENTRY_SUCCESS_MSG, {
|
|
63
64
|
title,
|
|
64
65
|
local: code,
|
|
65
66
|
module: this.config.moduleConfig.entries.name,
|
|
66
|
-
})
|
|
67
|
+
});
|
|
68
|
+
this.log(message, 'hidden');
|
|
69
|
+
(0, util_1.print)([{ message: `info: ${message}`, color: 'green' }]);
|
|
67
70
|
}
|
|
68
71
|
if (this.fix) {
|
|
69
72
|
await this.writeFixContent(`${basePath}/${indexer[fileIndex]}`, this.entries);
|
|
@@ -71,7 +74,7 @@ class Entries {
|
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
|
-
this.log('', 'info'); // Adding empty line
|
|
77
|
+
// this.log('', 'info'); // Adding empty line
|
|
75
78
|
this.removeEmptyVal();
|
|
76
79
|
return this.missingRefs;
|
|
77
80
|
}
|
|
@@ -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;
|
package/lib/modules/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import Entries from
|
|
2
|
-
import GlobalField from
|
|
3
|
-
import ContentType from
|
|
4
|
-
|
|
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 };
|
package/lib/modules/index.js
CHANGED
|
@@ -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
|
+
}
|
package/lib/types/index.d.ts
CHANGED
package/lib/types/index.js
CHANGED
|
@@ -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);
|
package/lib/types/utils.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Color } from "chalk";
|
|
2
2
|
import { PrintOptions } from "@contentstack/cli-utilities";
|
|
3
3
|
import config from "../config";
|
|
4
|
-
type LogFn = (message: string | any, logType?: LoggerType | PrintOptions | undefined) => void;
|
|
4
|
+
type LogFn = (message: string | any, logType?: LoggerType | PrintOptions | undefined, skipCredentialCheck?: boolean) => void;
|
|
5
5
|
type ExitFn = (code?: number | undefined) => void;
|
|
6
6
|
type Partial<T> = {
|
|
7
7
|
[P in keyof T]?: T[P];
|
|
@@ -10,7 +10,7 @@ type ConfigType = {
|
|
|
10
10
|
config?: string;
|
|
11
11
|
} & typeof config & Record<string, any>;
|
|
12
12
|
export { LogFn, ExitFn, Partial, ConfigType };
|
|
13
|
-
export type LoggerType = "info" | "warn" | "error" | "debug";
|
|
13
|
+
export type LoggerType = "info" | "warn" | "error" | "debug" | 'hidden';
|
|
14
14
|
export type PrintType = {
|
|
15
15
|
message: string;
|
|
16
16
|
bold?: boolean;
|
|
@@ -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
|
+
}
|
package/lib/util/log.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export default class Logger {
|
|
|
5
5
|
private infoLogger;
|
|
6
6
|
private errorLogger;
|
|
7
7
|
private config;
|
|
8
|
+
private hiddenInfoLogger;
|
|
8
9
|
get loggerOptions(): winston.transports.FileTransportOptions;
|
|
9
10
|
constructor(config: Record<string, any>);
|
|
10
11
|
/**
|
|
@@ -24,7 +25,7 @@ export default class Logger {
|
|
|
24
25
|
* @param {LoggerType | PrintOptions | undefined} [logType] - The `logType` parameter is an optional
|
|
25
26
|
* parameter that specifies the type of log. It can be one of the following values:
|
|
26
27
|
*/
|
|
27
|
-
log(message: string | any, logType?: LoggerType | PrintOptions | undefined): void;
|
|
28
|
+
log(message: string | any, logType?: LoggerType | PrintOptions | undefined, skipCredentialCheck?: boolean): void;
|
|
28
29
|
/**
|
|
29
30
|
* The function `returnString` takes a message as input and returns a modified version of the message
|
|
30
31
|
* with sensitive credentials replaced and any ANSI escape codes removed.
|
package/lib/util/log.js
CHANGED
|
@@ -35,6 +35,7 @@ class Logger {
|
|
|
35
35
|
this.config = config;
|
|
36
36
|
this.infoLogger = this.getLoggerInstance('info');
|
|
37
37
|
this.errorLogger = this.getLoggerInstance('error');
|
|
38
|
+
this.hiddenInfoLogger = this.getLoggerInstance('hidden');
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* The function getLoggerInstance creates and returns a winston logger instance based on the provided
|
|
@@ -48,15 +49,20 @@ class Logger {
|
|
|
48
49
|
const consoleOptions = {
|
|
49
50
|
format: winston_1.default.format.combine(winston_1.default.format.simple(), winston_1.default.format.colorize({ all: true })),
|
|
50
51
|
};
|
|
52
|
+
const isHidden = logType === 'hidden';
|
|
53
|
+
logType = logType === 'hidden' ? 'info' : logType;
|
|
51
54
|
if (logType === 'error') {
|
|
52
55
|
consoleOptions.level = logType;
|
|
53
56
|
}
|
|
54
57
|
const filename = (0, path_1.normalize)((0, path_1.resolve)(this.config.basePath, 'logs', `${logType}.log`)).replace(/^(\.\.(\/|\\|$))+/, '');
|
|
58
|
+
const transports = [
|
|
59
|
+
new winston_1.default.transports.File(Object.assign(Object.assign({}, this.loggerOptions), { level: logType, filename })),
|
|
60
|
+
];
|
|
61
|
+
if (!isHidden) {
|
|
62
|
+
transports.push(new winston_1.default.transports.Console(consoleOptions));
|
|
63
|
+
}
|
|
55
64
|
const loggerOptions = {
|
|
56
|
-
transports
|
|
57
|
-
new winston_1.default.transports.File(Object.assign(Object.assign({}, this.loggerOptions), { level: logType, filename })),
|
|
58
|
-
new winston_1.default.transports.Console(consoleOptions),
|
|
59
|
-
],
|
|
65
|
+
transports,
|
|
60
66
|
levels: customLevels.levels,
|
|
61
67
|
};
|
|
62
68
|
if (logType === 'error') {
|
|
@@ -72,8 +78,8 @@ class Logger {
|
|
|
72
78
|
* @param {LoggerType | PrintOptions | undefined} [logType] - The `logType` parameter is an optional
|
|
73
79
|
* parameter that specifies the type of log. It can be one of the following values:
|
|
74
80
|
*/
|
|
75
|
-
log(message, logType) {
|
|
76
|
-
const logString = this.returnString(message);
|
|
81
|
+
log(message, logType, skipCredentialCheck = false) {
|
|
82
|
+
const logString = skipCredentialCheck ? message : this.returnString(message);
|
|
77
83
|
switch (logType) {
|
|
78
84
|
case 'info':
|
|
79
85
|
case 'debug':
|
|
@@ -83,6 +89,9 @@ class Logger {
|
|
|
83
89
|
case 'error':
|
|
84
90
|
this.errorLogger.error(logString);
|
|
85
91
|
break;
|
|
92
|
+
case 'hidden':
|
|
93
|
+
this.hiddenInfoLogger.log('info', logString);
|
|
94
|
+
break;
|
|
86
95
|
default:
|
|
87
96
|
cli_utilities_1.cliux.print(logString, logType || {});
|
|
88
97
|
break;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "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.
|
|
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.
|
|
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",
|