@contentstack/cli-audit 1.17.0 → 2.0.0-beta

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.
Files changed (38) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +19 -23
  3. package/lib/audit-base-command.d.ts +4 -1
  4. package/lib/audit-base-command.js +85 -54
  5. package/lib/config/index.d.ts +0 -5
  6. package/lib/config/index.js +9 -16
  7. package/lib/messages/index.d.ts +0 -1
  8. package/lib/messages/index.js +1 -2
  9. package/lib/modules/assets.d.ts +6 -4
  10. package/lib/modules/assets.js +51 -30
  11. package/lib/modules/base-class.d.ts +24 -0
  12. package/lib/modules/base-class.js +54 -0
  13. package/lib/modules/content-types.d.ts +6 -4
  14. package/lib/modules/content-types.js +62 -40
  15. package/lib/modules/custom-roles.d.ts +4 -4
  16. package/lib/modules/custom-roles.js +82 -61
  17. package/lib/modules/entries.d.ts +5 -4
  18. package/lib/modules/entries.js +190 -168
  19. package/lib/modules/extensions.d.ts +4 -4
  20. package/lib/modules/extensions.js +78 -58
  21. package/lib/modules/field_rules.d.ts +4 -4
  22. package/lib/modules/field_rules.js +69 -52
  23. package/lib/modules/global-fields.d.ts +3 -1
  24. package/lib/modules/global-fields.js +4 -2
  25. package/lib/modules/index.d.ts +2 -2
  26. package/lib/modules/index.js +3 -3
  27. package/lib/modules/modulesData.js +8 -17
  28. package/lib/modules/workflows.d.ts +4 -4
  29. package/lib/modules/workflows.js +85 -68
  30. package/lib/types/content-types.d.ts +1 -2
  31. package/lib/types/content-types.js +0 -1
  32. package/lib/types/context.d.ts +5 -0
  33. package/oclif.manifest.json +3 -5
  34. package/package.json +4 -4
  35. package/lib/modules/composable-studio.d.ts +0 -40
  36. package/lib/modules/composable-studio.js +0 -307
  37. package/lib/types/composable-studio.d.ts +0 -25
  38. package/lib/types/composable-studio.js +0 -2
@@ -1,10 +1,10 @@
1
1
  import { Locale } from '@contentstack/cli-utilities';
2
- import { ConfigType, ModularBlockType, ContentTypeStruct, GroupFieldDataType, CtConstructorParam, GlobalFieldDataType, ModularBlocksDataType, ModuleConstructorParam, EntryStruct } from '../types';
2
+ import { ModularBlockType, ContentTypeStruct, GroupFieldDataType, CtConstructorParam, GlobalFieldDataType, ModularBlocksDataType, ModuleConstructorParam, EntryStruct } from '../types';
3
3
  import auditConfig from '../config';
4
- export default class FieldRule {
4
+ import BaseClass from './base-class';
5
+ export default class FieldRule extends BaseClass {
5
6
  protected fix: boolean;
6
7
  fileName: string;
7
- config: ConfigType;
8
8
  folderPath: string;
9
9
  currentUid: string;
10
10
  currentTitle: string;
@@ -30,7 +30,7 @@ export default class FieldRule {
30
30
  * iterates over the schema and looks for references, and returns a list of missing references.
31
31
  * @returns the `missingRefs` object.
32
32
  */
33
- run(): Promise<Record<string, any>>;
33
+ run(totalCount?: number): Promise<Record<string, any>>;
34
34
  validateFieldRules(schema: Record<string, unknown>): void;
35
35
  fixFieldRules(schema: Record<string, unknown>): void;
36
36
  addMissingReferences(actions: Record<string, unknown>, fixStatus?: string): void;
@@ -7,10 +7,12 @@ const fs_1 = require("fs");
7
7
  const cli_utilities_1 = require("@contentstack/cli-utilities");
8
8
  const messages_1 = require("../messages");
9
9
  const lodash_1 = require("lodash");
10
- /* The `ContentType` class is responsible for scanning content types, looking for references, and
10
+ const base_class_1 = tslib_1.__importDefault(require("./base-class"));
11
+ /* The `FieldRule` class is responsible for scanning field rules, looking for references, and
11
12
  generating a report in JSON and CSV formats. */
12
- class FieldRule {
13
+ class FieldRule extends base_class_1.default {
13
14
  constructor({ fix, config, moduleName, ctSchema, gfSchema }) {
15
+ super({ config });
14
16
  this.extensions = [];
15
17
  this.inMemoryFix = false;
16
18
  this.schema = [];
@@ -21,7 +23,6 @@ class FieldRule {
21
23
  this.missingEnvLocale = {};
22
24
  this.entryMetaData = [];
23
25
  this.action = ['show', 'hide'];
24
- this.config = config;
25
26
  this.fix = fix !== null && fix !== void 0 ? fix : false;
26
27
  this.ctSchema = ctSchema;
27
28
  this.gfSchema = gfSchema;
@@ -52,61 +53,77 @@ class FieldRule {
52
53
  * iterates over the schema and looks for references, and returns a list of missing references.
53
54
  * @returns the `missingRefs` object.
54
55
  */
55
- async run() {
56
+ async run(totalCount) {
56
57
  var _a, _b, _c;
57
- cli_utilities_1.log.debug(`Starting ${this.moduleName} field rules audit process`, this.config.auditContext);
58
- cli_utilities_1.log.debug(`Field rules folder path: ${this.folderPath}`, this.config.auditContext);
59
- cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
60
- if (!(0, fs_1.existsSync)(this.folderPath)) {
61
- cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
62
- cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
63
- cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
64
- return {};
65
- }
66
- this.schema = this.moduleName === 'content-types' ? this.ctSchema : this.gfSchema;
67
- cli_utilities_1.log.debug(`Using ${this.moduleName} schema with ${((_a = this.schema) === null || _a === void 0 ? void 0 : _a.length) || 0} items`, this.config.auditContext);
68
- cli_utilities_1.log.debug(`Loading prerequisite data`, this.config.auditContext);
69
- await this.prerequisiteData();
70
- cli_utilities_1.log.debug(`Loaded ${this.extensions.length} extensions`, this.config.auditContext);
71
- cli_utilities_1.log.debug(`Preparing entry metadata`, this.config.auditContext);
72
- await this.prepareEntryMetaData();
73
- cli_utilities_1.log.debug(`Prepared metadata for ${this.entryMetaData.length} entries`, this.config.auditContext);
74
- cli_utilities_1.log.debug(`Processing ${((_b = this.schema) === null || _b === void 0 ? void 0 : _b.length) || 0} schemas for field rules`, this.config.auditContext);
75
- for (const schema of (_c = this.schema) !== null && _c !== void 0 ? _c : []) {
76
- this.currentUid = schema.uid;
77
- this.currentTitle = schema.title;
78
- this.missingRefs[this.currentUid] = [];
79
- const { uid, title } = schema;
80
- cli_utilities_1.log.debug(`Processing schema: ${title} (${uid})`, this.config.auditContext);
81
- cli_utilities_1.log.debug(`Field rules count: ${Array.isArray(schema.field_rules) ? schema.field_rules.length : 0}`, this.config.auditContext);
82
- cli_utilities_1.log.debug(`Looking for references in schema: ${title}`, this.config.auditContext);
83
- await this.lookForReference([{ uid, name: title }], schema, null);
84
- cli_utilities_1.log.debug(`Schema map contains ${this.schemaMap.length} field references`, this.config.auditContext);
85
- this.missingRefs[this.currentUid] = [];
58
+ try {
59
+ cli_utilities_1.log.debug(`Starting ${this.moduleName} field rules audit process`, this.config.auditContext);
60
+ cli_utilities_1.log.debug(`Field rules folder path: ${this.folderPath}`, this.config.auditContext);
61
+ cli_utilities_1.log.debug(`Fix mode: ${this.fix}`, this.config.auditContext);
62
+ if (!(0, fs_1.existsSync)(this.folderPath)) {
63
+ cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
64
+ cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
65
+ cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
66
+ return {};
67
+ }
68
+ this.schema = this.moduleName === 'content-types' ? this.ctSchema : this.gfSchema;
69
+ cli_utilities_1.log.debug(`Using ${this.moduleName} schema with ${((_a = this.schema) === null || _a === void 0 ? void 0 : _a.length) || 0} items`, this.config.auditContext);
70
+ // Load prerequisite data with loading spinner
71
+ await this.withLoadingSpinner('FIELD-RULES: Loading prerequisite data...', async () => {
72
+ await this.prerequisiteData();
73
+ });
74
+ cli_utilities_1.log.debug(`Loaded ${this.extensions.length} extensions`, this.config.auditContext);
75
+ // Prepare entry metadata with loading spinner
76
+ await this.withLoadingSpinner('FIELD-RULES: Preparing entry metadata...', async () => {
77
+ await this.prepareEntryMetaData();
78
+ });
79
+ cli_utilities_1.log.debug(`Prepared metadata for ${this.entryMetaData.length} entries`, this.config.auditContext);
80
+ // Create progress manager if we have a total count
81
+ if (totalCount && totalCount > 0) {
82
+ const progress = this.createSimpleProgress(this.moduleName, totalCount);
83
+ progress.updateStatus('Validating field rules...');
84
+ }
85
+ cli_utilities_1.log.debug(`Processing ${((_b = this.schema) === null || _b === void 0 ? void 0 : _b.length) || 0} schemas for field rules`, this.config.auditContext);
86
+ for (const schema of (_c = this.schema) !== null && _c !== void 0 ? _c : []) {
87
+ this.currentUid = schema.uid;
88
+ this.currentTitle = schema.title;
89
+ this.missingRefs[this.currentUid] = [];
90
+ const { uid, title } = schema;
91
+ cli_utilities_1.log.debug(`Processing schema: ${title} (${uid})`, this.config.auditContext);
92
+ cli_utilities_1.log.debug(`Field rules count: ${Array.isArray(schema.field_rules) ? schema.field_rules.length : 0}`, this.config.auditContext);
93
+ cli_utilities_1.log.debug(`Looking for references in schema: ${title}`, this.config.auditContext);
94
+ await this.lookForReference([{ uid, name: title }], schema, null);
95
+ cli_utilities_1.log.debug(`Schema map contains ${this.schemaMap.length} field references`, this.config.auditContext);
96
+ this.missingRefs[this.currentUid] = [];
97
+ if (this.fix) {
98
+ cli_utilities_1.log.debug(`Fixing field rules for schema: ${title}`, this.config.auditContext);
99
+ this.fixFieldRules(schema);
100
+ }
101
+ else {
102
+ cli_utilities_1.log.debug(`Validating field rules for schema: ${title}`, this.config.auditContext);
103
+ this.validateFieldRules(schema);
104
+ }
105
+ this.schemaMap = [];
106
+ cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_CT_SUCCESS_MSG, { title, module: this.config.moduleConfig[this.moduleName].name }), this.config.auditContext);
107
+ }
86
108
  if (this.fix) {
87
- cli_utilities_1.log.debug(`Fixing field rules for schema: ${title}`, this.config.auditContext);
88
- this.fixFieldRules(schema);
109
+ cli_utilities_1.log.debug(`Fix mode enabled, writing fix content`, this.config.auditContext);
110
+ await this.writeFixContent();
89
111
  }
90
- else {
91
- cli_utilities_1.log.debug(`Validating field rules for schema: ${title}`, this.config.auditContext);
92
- this.validateFieldRules(schema);
112
+ cli_utilities_1.log.debug(`Cleaning up empty missing references`, this.config.auditContext);
113
+ for (let propName in this.missingRefs) {
114
+ if (!this.missingRefs[propName].length) {
115
+ cli_utilities_1.log.debug(`Removing empty missing references for: ${propName}`, this.config.auditContext);
116
+ delete this.missingRefs[propName];
117
+ }
93
118
  }
94
- this.schemaMap = [];
95
- cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_CT_SUCCESS_MSG, { title, module: this.config.moduleConfig[this.moduleName].name }), this.config.auditContext);
96
- }
97
- if (this.fix) {
98
- cli_utilities_1.log.debug(`Fix mode enabled, writing fix content`, this.config.auditContext);
99
- await this.writeFixContent();
119
+ cli_utilities_1.log.debug(`Field rules audit completed. Found ${Object.keys(this.missingRefs).length} schemas with issues`, this.config.auditContext);
120
+ this.completeProgress(true);
121
+ return this.missingRefs;
100
122
  }
101
- cli_utilities_1.log.debug(`Cleaning up empty missing references`, this.config.auditContext);
102
- for (let propName in this.missingRefs) {
103
- if (!this.missingRefs[propName].length) {
104
- cli_utilities_1.log.debug(`Removing empty missing references for: ${propName}`, this.config.auditContext);
105
- delete this.missingRefs[propName];
106
- }
123
+ catch (error) {
124
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Field rules audit failed');
125
+ throw error;
107
126
  }
108
- cli_utilities_1.log.debug(`Field rules audit completed. Found ${Object.keys(this.missingRefs).length} schemas with issues`, this.config.auditContext);
109
- return this.missingRefs;
110
127
  }
111
128
  validateFieldRules(schema) {
112
129
  cli_utilities_1.log.debug(`Validating field rules for schema: ${schema.uid}`, this.config.auditContext);
@@ -4,9 +4,11 @@ export default class GlobalField extends ContentType {
4
4
  /**
5
5
  * The above function is an asynchronous function that runs a validation and returns any missing
6
6
  * references.
7
+ * @param returnFixSchema - If true, returns the fixed schema instead of missing references
8
+ * @param totalCount - Total number of items to process (for progress tracking)
7
9
  * @returns the value of the variable `missingRefs`.
8
10
  */
9
- run(returnFixSchema?: boolean): Promise<Record<string, any> | import("../types").ContentTypeStruct[]>;
11
+ run(returnFixSchema?: boolean, totalCount?: number): Promise<Record<string, any> | import("../types").ContentTypeStruct[]>;
10
12
  /**
11
13
  * The function validates a field containing modular blocks by traversing each block and checking for
12
14
  * references in a given tree.
@@ -7,14 +7,16 @@ class GlobalField extends content_types_1.default {
7
7
  /**
8
8
  * The above function is an asynchronous function that runs a validation and returns any missing
9
9
  * references.
10
+ * @param returnFixSchema - If true, returns the fixed schema instead of missing references
11
+ * @param totalCount - Total number of items to process (for progress tracking)
10
12
  * @returns the value of the variable `missingRefs`.
11
13
  */
12
- async run(returnFixSchema = false) {
14
+ async run(returnFixSchema = false, totalCount) {
13
15
  cli_utilities_1.log.debug(`Starting GlobalField audit process`, this.config.auditContext);
14
16
  cli_utilities_1.log.debug(`Return fix schema: ${returnFixSchema}`, this.config.auditContext);
15
17
  // NOTE add any validation if required
16
18
  cli_utilities_1.log.debug(`Calling parent ContentType.run() method`, this.config.auditContext);
17
- const missingRefs = await super.run(returnFixSchema);
19
+ const missingRefs = await super.run(returnFixSchema, totalCount);
18
20
  cli_utilities_1.log.debug(`Parent method completed, found ${Object.keys(missingRefs || {}).length} missing references`, this.config.auditContext);
19
21
  cli_utilities_1.log.debug(`GlobalField audit completed`, this.config.auditContext);
20
22
  return missingRefs;
@@ -7,5 +7,5 @@ import CustomRoles from './custom-roles';
7
7
  import Assets from './assets';
8
8
  import FieldRule from './field_rules';
9
9
  import ModuleDataReader from './modulesData';
10
- import ComposableStudio from './composable-studio';
11
- export { Entries, GlobalField, ContentType, Workflows, Extensions, Assets, CustomRoles, FieldRule, ModuleDataReader, ComposableStudio };
10
+ import BaseClass from './base-class';
11
+ export { Entries, GlobalField, ContentType, Workflows, Extensions, Assets, CustomRoles, FieldRule, ModuleDataReader, BaseClass };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ComposableStudio = exports.ModuleDataReader = exports.FieldRule = exports.CustomRoles = exports.Assets = exports.Extensions = exports.Workflows = exports.ContentType = exports.GlobalField = exports.Entries = void 0;
3
+ exports.BaseClass = exports.ModuleDataReader = exports.FieldRule = exports.CustomRoles = exports.Assets = exports.Extensions = exports.Workflows = exports.ContentType = exports.GlobalField = exports.Entries = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const entries_1 = tslib_1.__importDefault(require("./entries"));
6
6
  exports.Entries = entries_1.default;
@@ -20,5 +20,5 @@ const field_rules_1 = tslib_1.__importDefault(require("./field_rules"));
20
20
  exports.FieldRule = field_rules_1.default;
21
21
  const modulesData_1 = tslib_1.__importDefault(require("./modulesData"));
22
22
  exports.ModuleDataReader = modulesData_1.default;
23
- const composable_studio_1 = tslib_1.__importDefault(require("./composable-studio"));
24
- exports.ComposableStudio = composable_studio_1.default;
23
+ const base_class_1 = tslib_1.__importDefault(require("./base-class"));
24
+ exports.BaseClass = base_class_1.default;
@@ -24,7 +24,7 @@ class ModuleDataReader {
24
24
  cli_utilities_1.log.debug(`Getting item count for module: ${moduleName}`, this.config.auditContext);
25
25
  let count = 0;
26
26
  switch (moduleName) {
27
- case 'content-types':
27
+ case "content-types":
28
28
  cli_utilities_1.log.debug(`Counting content types`, this.config.auditContext);
29
29
  count = this.ctSchema.length;
30
30
  cli_utilities_1.log.debug(`Content types count: ${count}`, this.config.auditContext);
@@ -38,7 +38,7 @@ class ModuleDataReader {
38
38
  cli_utilities_1.log.debug(`Counting assets`, this.config.auditContext);
39
39
  const assetsPath = (0, path_1.join)(this.folderPath, 'assets');
40
40
  cli_utilities_1.log.debug(`Assets path: ${assetsPath}`, this.config.auditContext);
41
- count = (await this.readEntryAssetsModule(assetsPath, 'assets')) || 0;
41
+ count = await this.readEntryAssetsModule(assetsPath, 'assets') || 0;
42
42
  cli_utilities_1.log.debug(`Assets count: ${count}`, this.config.auditContext);
43
43
  break;
44
44
  }
@@ -53,13 +53,11 @@ class ModuleDataReader {
53
53
  cli_utilities_1.log.debug(`Master locales path: ${masterLocalesPath}`, this.config.auditContext);
54
54
  cli_utilities_1.log.debug(`Loading master locales`, this.config.auditContext);
55
55
  this.locales = (0, lodash_1.values)(await this.readUsingFsModule(masterLocalesPath));
56
- cli_utilities_1.log.debug(`Loaded ${this.locales.length} master locales: ${this.locales.map((locale) => locale.code).join(', ')}`, this.config.auditContext);
56
+ cli_utilities_1.log.debug(`Loaded ${this.locales.length} master locales: ${this.locales.map(locale => locale.code).join(', ')}`, this.config.auditContext);
57
57
  if ((0, fs_1.existsSync)(localesPath)) {
58
58
  cli_utilities_1.log.debug(`Loading additional locales from file`, this.config.auditContext);
59
59
  this.locales.push(...(0, lodash_1.values)(JSON.parse((0, fs_1.readFileSync)(localesPath, 'utf8'))));
60
- cli_utilities_1.log.debug(`Total locales after loading: ${this.locales.length} - ${this.locales
61
- .map((locale) => locale.code)
62
- .join(', ')}`, this.config.auditContext);
60
+ cli_utilities_1.log.debug(`Total locales after loading: ${this.locales.length} - ${this.locales.map(locale => locale.code).join(', ')}`, this.config.auditContext);
63
61
  }
64
62
  else {
65
63
  cli_utilities_1.log.debug(`Additional locales file not found`, this.config.auditContext);
@@ -71,7 +69,7 @@ class ModuleDataReader {
71
69
  cli_utilities_1.log.debug(`Processing content type: ${ctSchema.uid}`, this.config.auditContext);
72
70
  const basePath = (0, path_1.join)(this.folderPath, 'entries', ctSchema.uid, code);
73
71
  cli_utilities_1.log.debug(`Base path: ${basePath}`, this.config.auditContext);
74
- const entryCount = (await this.readEntryAssetsModule(basePath, 'index')) || 0;
72
+ const entryCount = await this.readEntryAssetsModule(basePath, 'index') || 0;
75
73
  cli_utilities_1.log.debug(`Found ${entryCount} entries for ${ctSchema.uid} in ${code}`, this.config.auditContext);
76
74
  count = count + entryCount;
77
75
  }
@@ -81,19 +79,12 @@ class ModuleDataReader {
81
79
  break;
82
80
  case 'custom-roles':
83
81
  case 'extensions':
84
- case 'workflows':
85
- case 'composable-studio': {
82
+ case 'workflows': {
86
83
  cli_utilities_1.log.debug(`Counting ${moduleName}`, this.config.auditContext);
87
84
  const modulePath = (0, path_1.resolve)(this.folderPath, (0, cli_utilities_1.sanitizePath)(this.config.moduleConfig[moduleName].dirName), (0, cli_utilities_1.sanitizePath)(this.config.moduleConfig[moduleName].fileName));
88
85
  cli_utilities_1.log.debug(`Reading module: ${moduleName} from file: ${modulePath}`, this.config.auditContext);
89
86
  const moduleData = await this.readUsingFsModule(modulePath);
90
- // For composable-studio, it could be a single object or an array
91
- if (moduleName === 'composable-studio') {
92
- count = Array.isArray(moduleData) ? moduleData.length : Object.keys(moduleData).length > 0 ? 1 : 0;
93
- }
94
- else {
95
- count = (0, lodash_1.keys)(moduleData).length;
96
- }
87
+ count = (0, lodash_1.keys)(moduleData).length;
97
88
  cli_utilities_1.log.debug(`module:${moduleName} count: ${count}`, this.config.auditContext);
98
89
  break;
99
90
  }
@@ -103,7 +94,7 @@ class ModuleDataReader {
103
94
  }
104
95
  async readUsingFsModule(path) {
105
96
  cli_utilities_1.log.debug(`Reading file: ${path}`, this.config.auditContext);
106
- const data = (0, fs_1.existsSync)(path) ? JSON.parse((0, fs_1.readFileSync)(path, 'utf-8')) : [];
97
+ const data = (0, fs_1.existsSync)(path) ? (JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'))) : [];
107
98
  cli_utilities_1.log.debug(`File ${(0, fs_1.existsSync)(path) ? 'exists' : 'not found'}, data type: ${Array.isArray(data) ? 'array' : 'object'}`, this.config.auditContext);
108
99
  if ((0, fs_1.existsSync)(path)) {
109
100
  const dataSize = Array.isArray(data) ? data.length : Object.keys(data).length;
@@ -1,9 +1,9 @@
1
- import { ConfigType, ContentTypeStruct, CtConstructorParam, ModuleConstructorParam, Workflow } from '../types';
1
+ import { ContentTypeStruct, CtConstructorParam, ModuleConstructorParam, Workflow } from '../types';
2
2
  import auditConfig from '../config';
3
- export default class Workflows {
3
+ import BaseClass from './base-class';
4
+ export default class Workflows extends BaseClass {
4
5
  protected fix: boolean;
5
6
  fileName: any;
6
- config: ConfigType;
7
7
  folderPath: string;
8
8
  workflowSchema: Workflow[];
9
9
  ctSchema: ContentTypeStruct[];
@@ -21,7 +21,7 @@ export default class Workflows {
21
21
  * From the ctSchema add all the content type UID into ctUidSet to check whether the content-type is present or not
22
22
  * @returns Array of object containing the workflow name, uid and content_types that are missing
23
23
  */
24
- run(): Promise<{}>;
24
+ run(totalCount?: number): Promise<{}>;
25
25
  fixWorkflowSchema(): Promise<void>;
26
26
  writeFixContent(newWorkflowSchema: Record<string, Workflow>): Promise<void>;
27
27
  }
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
3
4
  const path_1 = require("path");
4
5
  const fs_1 = require("fs");
5
6
  const lodash_1 = require("lodash");
6
7
  const cli_utilities_1 = require("@contentstack/cli-utilities");
7
8
  const messages_1 = require("../messages");
8
9
  const lodash_2 = require("lodash");
9
- class Workflows {
10
+ const base_class_1 = tslib_1.__importDefault(require("./base-class"));
11
+ class Workflows extends base_class_1.default {
10
12
  constructor({ fix, config, moduleName, ctSchema, }) {
11
- this.config = config;
13
+ super({ config });
12
14
  this.fix = fix !== null && fix !== void 0 ? fix : false;
13
15
  this.ctSchema = ctSchema;
14
16
  this.workflowSchema = [];
@@ -44,81 +46,96 @@ class Workflows {
44
46
  * From the ctSchema add all the content type UID into ctUidSet to check whether the content-type is present or not
45
47
  * @returns Array of object containing the workflow name, uid and content_types that are missing
46
48
  */
47
- async run() {
49
+ async run(totalCount) {
48
50
  var _a, _b, _c, _d, _e;
49
- if (!(0, fs_1.existsSync)(this.folderPath)) {
50
- cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
51
- cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
52
- cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
53
- return {};
54
- }
55
- this.workflowPath = (0, path_1.join)(this.folderPath, this.fileName);
56
- cli_utilities_1.log.debug(`Workflows file path: ${this.workflowPath}`, this.config.auditContext);
57
- cli_utilities_1.log.debug(`Loading workflows schema from file`, this.config.auditContext);
58
- this.workflowSchema = (0, fs_1.existsSync)(this.workflowPath)
59
- ? (0, lodash_2.values)(JSON.parse((0, fs_1.readFileSync)(this.workflowPath, 'utf8')))
60
- : [];
61
- cli_utilities_1.log.debug(`Loaded ${this.workflowSchema.length} workflows`, this.config.auditContext);
62
- cli_utilities_1.log.debug(`Building content type UID set from ${this.ctSchema.length} content types`, this.config.auditContext);
63
- this.ctSchema.forEach((ct) => this.ctUidSet.add(ct.uid));
64
- cli_utilities_1.log.debug(`Content type UID set contains: ${Array.from(this.ctUidSet).join(', ')}`, this.config.auditContext);
65
- cli_utilities_1.log.debug(`Processing ${this.workflowSchema.length} workflows`, this.config.auditContext);
66
- for (const workflow of this.workflowSchema) {
67
- const { name, uid } = workflow;
68
- cli_utilities_1.log.debug(`Processing workflow: ${name} (${uid})`, this.config.auditContext);
69
- cli_utilities_1.log.debug(`Workflow content types: ${((_a = workflow.content_types) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'none'}`, this.config.auditContext);
70
- cli_utilities_1.log.debug(`Workflow branches: ${((_b = workflow.branches) === null || _b === void 0 ? void 0 : _b.join(', ')) || 'none'}`, this.config.auditContext);
71
- const ctNotPresent = workflow.content_types.filter((ct) => !this.ctUidSet.has(ct));
72
- cli_utilities_1.log.debug(`Missing content types in workflow: ${(ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.join(', ')) || 'none'}`, this.config.auditContext);
73
- cli_utilities_1.log.debug(`Config branch : ${this.config.branch}`, this.config.auditContext);
74
- let branchesToBeRemoved = [];
75
- if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.branch) {
76
- branchesToBeRemoved = ((_d = workflow === null || workflow === void 0 ? void 0 : workflow.branches) === null || _d === void 0 ? void 0 : _d.filter((branch) => { var _a; return branch !== ((_a = this.config) === null || _a === void 0 ? void 0 : _a.branch); })) || [];
77
- cli_utilities_1.log.debug(`Branches to be removed: ${(branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.join(', ')) || 'none'}`, this.config.auditContext);
51
+ try {
52
+ if (!(0, fs_1.existsSync)(this.folderPath)) {
53
+ cli_utilities_1.log.debug(`Skipping ${this.moduleName} audit - path does not exist`, this.config.auditContext);
54
+ cli_utilities_1.log.warn(`Skipping ${this.moduleName} audit`, this.config.auditContext);
55
+ cli_utilities_1.cliux.print((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }), { color: 'yellow' });
56
+ return {};
78
57
  }
79
- else {
80
- cli_utilities_1.log.debug(`No branch configuration found`, this.config.auditContext);
58
+ this.workflowPath = (0, path_1.join)(this.folderPath, this.fileName);
59
+ cli_utilities_1.log.debug(`Workflows file path: ${this.workflowPath}`, this.config.auditContext);
60
+ // Load workflows schema with loading spinner
61
+ await this.withLoadingSpinner('WORKFLOWS: Loading workflows schema...', async () => {
62
+ this.workflowSchema = (0, fs_1.existsSync)(this.workflowPath)
63
+ ? (0, lodash_2.values)(JSON.parse((0, fs_1.readFileSync)(this.workflowPath, 'utf8')))
64
+ : [];
65
+ });
66
+ cli_utilities_1.log.debug(`Loaded ${this.workflowSchema.length} workflows`, this.config.auditContext);
67
+ cli_utilities_1.log.debug(`Building content type UID set from ${this.ctSchema.length} content types`, this.config.auditContext);
68
+ this.ctSchema.forEach((ct) => this.ctUidSet.add(ct.uid));
69
+ cli_utilities_1.log.debug(`Content type UID set contains: ${Array.from(this.ctUidSet).join(', ')}`, this.config.auditContext);
70
+ // Create progress manager if we have a total count
71
+ if (totalCount && totalCount > 0) {
72
+ const progress = this.createSimpleProgress(this.moduleName, totalCount);
73
+ progress.updateStatus('Validating workflows...');
81
74
  }
82
- if (ctNotPresent.length || (branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.length)) {
83
- cli_utilities_1.log.debug(`Workflow ${name} has issues - missing content types: ${ctNotPresent.length}, branches to remove: ${branchesToBeRemoved.length}`, this.config.auditContext);
84
- const tempwf = (0, lodash_1.cloneDeep)(workflow);
85
- tempwf.content_types = ctNotPresent || [];
86
- if ((workflow === null || workflow === void 0 ? void 0 : workflow.branches) && ((_e = this.config) === null || _e === void 0 ? void 0 : _e.branch)) {
87
- tempwf.branches = branchesToBeRemoved;
75
+ cli_utilities_1.log.debug(`Processing ${this.workflowSchema.length} workflows`, this.config.auditContext);
76
+ for (const workflow of this.workflowSchema) {
77
+ const { name, uid } = workflow;
78
+ cli_utilities_1.log.debug(`Processing workflow: ${name} (${uid})`, this.config.auditContext);
79
+ cli_utilities_1.log.debug(`Workflow content types: ${((_a = workflow.content_types) === null || _a === void 0 ? void 0 : _a.join(', ')) || 'none'}`, this.config.auditContext);
80
+ cli_utilities_1.log.debug(`Workflow branches: ${((_b = workflow.branches) === null || _b === void 0 ? void 0 : _b.join(', ')) || 'none'}`, this.config.auditContext);
81
+ const ctNotPresent = workflow.content_types.filter((ct) => !this.ctUidSet.has(ct));
82
+ cli_utilities_1.log.debug(`Missing content types in workflow: ${(ctNotPresent === null || ctNotPresent === void 0 ? void 0 : ctNotPresent.join(', ')) || 'none'}`, this.config.auditContext);
83
+ cli_utilities_1.log.debug(`Config branch : ${this.config.branch}`, this.config.auditContext);
84
+ let branchesToBeRemoved = [];
85
+ if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.branch) {
86
+ branchesToBeRemoved = ((_d = workflow === null || workflow === void 0 ? void 0 : workflow.branches) === null || _d === void 0 ? void 0 : _d.filter((branch) => { var _a; return branch !== ((_a = this.config) === null || _a === void 0 ? void 0 : _a.branch); })) || [];
87
+ cli_utilities_1.log.debug(`Branches to be removed: ${(branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.join(', ')) || 'none'}`, this.config.auditContext);
88
88
  }
89
- if (branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.length) {
90
- cli_utilities_1.log.debug(`Branch fix will be needed`, this.config.auditContext);
91
- this.isBranchFixDone = true;
89
+ else {
90
+ cli_utilities_1.log.debug(`No branch configuration found`, this.config.auditContext);
92
91
  }
93
- ctNotPresent.forEach((ct) => {
94
- cli_utilities_1.log.debug(`Adding missing content type: ${ct} to the Audit report.`, this.config.auditContext);
95
- this.missingCts.add(ct);
96
- });
97
- this.missingCtInWorkflows.push(tempwf);
92
+ if (ctNotPresent.length || (branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.length)) {
93
+ cli_utilities_1.log.debug(`Workflow ${name} has issues - missing content types: ${ctNotPresent.length}, branches to remove: ${branchesToBeRemoved.length}`, this.config.auditContext);
94
+ const tempwf = (0, lodash_1.cloneDeep)(workflow);
95
+ tempwf.content_types = ctNotPresent || [];
96
+ if ((workflow === null || workflow === void 0 ? void 0 : workflow.branches) && ((_e = this.config) === null || _e === void 0 ? void 0 : _e.branch)) {
97
+ tempwf.branches = branchesToBeRemoved;
98
+ }
99
+ if (branchesToBeRemoved === null || branchesToBeRemoved === void 0 ? void 0 : branchesToBeRemoved.length) {
100
+ cli_utilities_1.log.debug(`Branch fix will be needed`, this.config.auditContext);
101
+ this.isBranchFixDone = true;
102
+ }
103
+ ctNotPresent.forEach((ct) => {
104
+ cli_utilities_1.log.debug(`Adding missing content type: ${ct} to the Audit report.`, this.config.auditContext);
105
+ this.missingCts.add(ct);
106
+ });
107
+ this.missingCtInWorkflows.push(tempwf);
108
+ }
109
+ else {
110
+ cli_utilities_1.log.debug(`Workflow ${name} has no issues`, this.config.auditContext);
111
+ }
112
+ cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_WF_SUCCESS_MSG, {
113
+ name: workflow.name,
114
+ uid: workflow.uid,
115
+ }), this.config.auditContext);
98
116
  }
99
- else {
100
- cli_utilities_1.log.debug(`Workflow ${name} has no issues`, this.config.auditContext);
117
+ cli_utilities_1.log.debug(`Workflows audit completed. Found ${this.missingCtInWorkflows.length} workflows with issues`, this.config.auditContext);
118
+ cli_utilities_1.log.debug(`Total missing content types: ${this.missingCts.size}`, this.config.auditContext);
119
+ cli_utilities_1.log.debug(`Branch fix needed: ${this.isBranchFixDone}`, this.config.auditContext);
120
+ if (this.fix && (this.missingCtInWorkflows.length || this.isBranchFixDone)) {
121
+ cli_utilities_1.log.debug(`Fix mode enabled, fixing ${this.missingCtInWorkflows.length} workflows`, this.config.auditContext);
122
+ await this.fixWorkflowSchema();
123
+ this.missingCtInWorkflows.forEach((wf) => {
124
+ cli_utilities_1.log.debug(`Marking workflow ${wf.name} as fixed`, this.config.auditContext);
125
+ wf.fixStatus = 'Fixed';
126
+ });
127
+ cli_utilities_1.log.debug(`Workflows fix completed`, this.config.auditContext);
128
+ this.completeProgress(true);
129
+ return this.missingCtInWorkflows;
101
130
  }
102
- cli_utilities_1.log.info((0, messages_1.$t)(messages_1.auditMsg.SCAN_WF_SUCCESS_MSG, {
103
- name: workflow.name,
104
- uid: workflow.uid,
105
- }), this.config.auditContext);
106
- }
107
- cli_utilities_1.log.debug(`Workflows audit completed. Found ${this.missingCtInWorkflows.length} workflows with issues`, this.config.auditContext);
108
- cli_utilities_1.log.debug(`Total missing content types: ${this.missingCts.size}`, this.config.auditContext);
109
- cli_utilities_1.log.debug(`Branch fix needed: ${this.isBranchFixDone}`, this.config.auditContext);
110
- if (this.fix && (this.missingCtInWorkflows.length || this.isBranchFixDone)) {
111
- cli_utilities_1.log.debug(`Fix mode enabled, fixing ${this.missingCtInWorkflows.length} workflows`, this.config.auditContext);
112
- await this.fixWorkflowSchema();
113
- this.missingCtInWorkflows.forEach((wf) => {
114
- cli_utilities_1.log.debug(`Marking workflow ${wf.name} as fixed`, this.config.auditContext);
115
- wf.fixStatus = 'Fixed';
116
- });
117
- cli_utilities_1.log.debug(`Workflows fix completed`, this.config.auditContext);
131
+ cli_utilities_1.log.debug(`Workflows audit completed without fixes`, this.config.auditContext);
132
+ this.completeProgress(true);
118
133
  return this.missingCtInWorkflows;
119
134
  }
120
- cli_utilities_1.log.debug(`Workflows audit completed without fixes`, this.config.auditContext);
121
- return this.missingCtInWorkflows;
135
+ catch (error) {
136
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Workflows audit failed');
137
+ throw error;
138
+ }
122
139
  }
123
140
  async fixWorkflowSchema() {
124
141
  var _a;
@@ -127,8 +127,7 @@ declare enum OutputColumn {
127
127
  "Fixable" = "Fixable",
128
128
  "Non-Fixable" = "Non-Fixable",
129
129
  "Fixed" = "Fixed",
130
- "Not-Fixed" = "Not-Fixed",
131
- "Issues" = "issues"
130
+ "Not-Fixed" = "Not-Fixed"
132
131
  }
133
132
  export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, ExtensionOrAppFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, ContentTypeSchemaType, GlobalFieldSchemaTypes, WorkflowExtensionsRefErrorReturnType, SelectFeildStruct, FieldRuleStruct, };
134
133
  type FieldRuleStruct = {
@@ -42,5 +42,4 @@ var OutputColumn;
42
42
  OutputColumn["Non-Fixable"] = "Non-Fixable";
43
43
  OutputColumn["Fixed"] = "Fixed";
44
44
  OutputColumn["Not-Fixed"] = "Not-Fixed";
45
- OutputColumn["Issues"] = "issues";
46
45
  })(OutputColumn || (exports.OutputColumn = OutputColumn = {}));
@@ -1,3 +1,8 @@
1
1
  export interface AuditContext {
2
+ command: string;
2
3
  module: string;
4
+ email: string | undefined;
5
+ sessionId: string | undefined;
6
+ clientId?: string;
7
+ authenticationMethod?: string;
3
8
  }
@@ -68,8 +68,7 @@
68
68
  "workflows",
69
69
  "custom-roles",
70
70
  "assets",
71
- "field-rules",
72
- "composable-studio"
71
+ "field-rules"
73
72
  ],
74
73
  "type": "option"
75
74
  },
@@ -264,8 +263,7 @@
264
263
  "workflows",
265
264
  "custom-roles",
266
265
  "assets",
267
- "field-rules",
268
- "composable-studio"
266
+ "field-rules"
269
267
  ],
270
268
  "type": "option"
271
269
  },
@@ -346,5 +344,5 @@
346
344
  ]
347
345
  }
348
346
  },
349
- "version": "1.17.0"
347
+ "version": "2.0.0-beta"
350
348
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentstack/cli-audit",
3
- "version": "1.17.0",
3
+ "version": "2.0.0-beta",
4
4
  "description": "Contentstack audit plugin",
5
5
  "author": "Contentstack CLI",
6
6
  "homepage": "https://github.com/contentstack/cli",
@@ -18,11 +18,11 @@
18
18
  "/oclif.manifest.json"
19
19
  ],
20
20
  "dependencies": {
21
- "@contentstack/cli-command": "~1.7.1",
22
- "@contentstack/cli-utilities": "~1.16.0",
21
+ "@contentstack/cli-command": "~1.6.1",
22
+ "@contentstack/cli-utilities": "~1.15.0",
23
23
  "@oclif/core": "^4.3.0",
24
24
  "@oclif/plugin-help": "^6.2.28",
25
- "@oclif/plugin-plugins": "^5.4.54",
25
+ "@oclif/plugin-plugins": "^5.4.38",
26
26
  "chalk": "^4.1.2",
27
27
  "fast-csv": "^4.3.6",
28
28
  "fs-extra": "^11.3.0",