@contentstack/cli-cm-export 1.0.0 → 1.2.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.
@@ -4,19 +4,16 @@
4
4
  * MIT Licensed
5
5
  */
6
6
 
7
- var chalk = require('chalk');
8
- var mkdirp = require('mkdirp');
9
- var path = require('path');
10
-
11
- var app = require('../../app');
12
- var helper = require('../util/helper');
13
- var { addlogs } = require('../util/log');
14
- const stack = require('../util/contentstack-management-sdk');
7
+ let path = require('path');
8
+ let mkdirp = require('mkdirp');
15
9
 
10
+ let helper = require('../util/helper');
11
+ let { addlogs } = require('../util/log');
16
12
  let config = require('../../config/default');
13
+ const stack = require('../util/contentstack-management-sdk');
17
14
 
18
- var stackConfig = config.modules.stack;
19
15
  let client;
16
+ let stackConfig = config.modules.stack;
20
17
 
21
18
  function ExportStack() {
22
19
  this.requestOption = {
@@ -26,17 +23,33 @@ function ExportStack() {
26
23
  };
27
24
  }
28
25
 
29
- ExportStack.prototype.start = function (credentialConfig) {
26
+ ExportStack.prototype.start = async function (credentialConfig) {
30
27
  config = credentialConfig;
31
28
  client = stack.Client(config);
32
- const self = this
29
+ const self = this;
30
+
31
+ // NOTE get org uid
32
+ if (config.auth_token) {
33
+ const stack = await client
34
+ .stack({ api_key: config.source_stack, authtoken: config.auth_token })
35
+ .fetch()
36
+ .catch((error) => {
37
+ console.log(error);
38
+ });
39
+
40
+ if (stack && stack.org_uid) {
41
+ config.org_uid = stack.org_uid;
42
+ config.sourceStackName = stack.name;
43
+ }
44
+ }
45
+
33
46
  if (!config.preserveStackVersion && !config.hasOwnProperty('master_locale')) {
34
47
  const apiDetails = {
35
48
  limit: 100,
36
49
  skip: 0,
37
50
  include_count: true,
38
- }
39
- return self.getLocales(apiDetails)
51
+ };
52
+ return self.getLocales(apiDetails);
40
53
  } else if (config.preserveStackVersion) {
41
54
  addlogs(config, 'Exporting stack details', 'success');
42
55
  let stackFolderPath = path.resolve(config.data, stackConfig.dirName);
@@ -59,12 +72,12 @@ ExportStack.prototype.start = function (credentialConfig) {
59
72
  };
60
73
 
61
74
  ExportStack.prototype.getLocales = function (apiDetails) {
62
- let self = this
75
+ let self = this;
63
76
  return new Promise((resolve, reject) => {
64
77
  const result = client
65
78
  .stack({ api_key: config.source_stack, management_token: config.management_token })
66
79
  .locale()
67
- .query(apiDetails)
80
+ .query(apiDetails);
68
81
 
69
82
  result
70
83
  .find()
@@ -75,11 +88,11 @@ ExportStack.prototype.getLocales = function (apiDetails) {
75
88
  }
76
89
  });
77
90
  apiDetails.skip += apiDetails.limit;
78
- if (masterLocalObj) { return resolve(masterLocalObj); }
79
- else if (apiDetails.skip <= response.count) {
80
- return resolve(self.getLocales(apiDetails))
81
- }
82
- else {
91
+ if (masterLocalObj) {
92
+ return resolve(masterLocalObj);
93
+ } else if (apiDetails.skip <= response.count) {
94
+ return resolve(self.getLocales(apiDetails));
95
+ } else {
83
96
  return reject('Master locale not found');
84
97
  }
85
98
  })
@@ -87,6 +100,6 @@ ExportStack.prototype.getLocales = function (apiDetails) {
87
100
  return reject(error);
88
101
  });
89
102
  });
90
- }
103
+ };
91
104
 
92
- module.exports = new ExportStack();
105
+ module.exports = ExportStack;
@@ -4,72 +4,77 @@
4
4
  * MIT Licensed
5
5
  */
6
6
 
7
- const mkdirp = require('mkdirp');
8
7
  const path = require('path');
9
8
  const chalk = require('chalk');
9
+ const mkdirp = require('mkdirp');
10
+ const { merge } = require('lodash');
10
11
 
11
12
  const helper = require('../util/helper');
13
+ const { formatError } = require('../util');
12
14
  const { addlogs } = require('../util/log');
13
-
14
- let config = require('../../config/default');
15
+ const config = require('../../config/default');
15
16
  const stack = require('../util/contentstack-management-sdk');
16
- const webhooksConfig = config.modules.webhooks;
17
- let client;
18
17
 
19
18
  // Create folder for environments
20
19
 
21
- function ExportWebhooks() {
22
- this.requestOptions = {
20
+ module.exports = class ExportWebhooks {
21
+ config;
22
+ master = {};
23
+ webhooks = {};
24
+ requestOptions = {
23
25
  include_count: true,
24
26
  asc: 'updated_at',
25
27
  };
26
- this.master = {};
27
- this.webhooks = {};
28
- }
28
+ webhooksConfig = config.modules.webhooks;
29
+
30
+ constructor(credentialConfig) {
31
+ this.config = merge(config, credentialConfig);
32
+ }
29
33
 
30
- ExportWebhooks.prototype.start = function (credentialConfig) {
31
- addlogs(config, 'Starting webhooks export', 'success');
32
- this.master = {};
33
- this.webhooks = {};
34
- let self = this;
35
- config = credentialConfig;
36
- client = stack.Client(config);
37
- const webhooksFolderPath = path.resolve(config.data, config.branchName || '', webhooksConfig.dirName);
38
- mkdirp.sync(webhooksFolderPath);
39
- return new Promise(function (resolve, reject) {
40
- client
41
- .stack({ api_key: config.source_stack, management_token: config.management_token })
42
- .webhook()
43
- .fetchAll(self.requestOptions)
44
- .then((webhooks) => {
45
- if (webhooks.items.length !== 0) {
46
- for (var i = 0, total = webhooks.count; i < total; i++) {
47
- const webUid = webhooks.items[i].uid;
48
- self.master[webUid] = '';
49
- self.webhooks[webUid] = webhooks.items[i];
50
- delete self.webhooks[webUid].uid;
51
- delete self.webhooks[webUid].SYS_ACL;
34
+ start() {
35
+ addlogs(this.config, 'Starting webhooks export', 'success');
36
+
37
+ const self = this;
38
+ const client = stack.Client(this.config);
39
+ const webhooksFolderPath = path.resolve(
40
+ this.config.data,
41
+ this.config.branchName || '',
42
+ self.webhooksConfig.dirName,
43
+ );
44
+ mkdirp.sync(webhooksFolderPath);
45
+ return new Promise((resolve, reject) => {
46
+ client
47
+ .stack({ api_key: self.config.source_stack, management_token: self.config.management_token })
48
+ .webhook()
49
+ .fetchAll(self.requestOptions)
50
+ .then((webhooks) => {
51
+ if (webhooks.items.length !== 0) {
52
+ for (let i = 0, total = webhooks.count; i < total; i++) {
53
+ const webUid = webhooks.items[i].uid;
54
+ self.master[webUid] = '';
55
+ self.webhooks[webUid] = webhooks.items[i];
56
+ delete self.webhooks[webUid].uid;
57
+ delete self.webhooks[webUid].SYS_ACL;
58
+ }
59
+ helper.writeFileSync(path.join(webhooksFolderPath, self.webhooksConfig.fileName), self.webhooks);
60
+ addlogs(self.config, chalk.green('All the webhooks have been exported successfully'), 'success');
61
+ return resolve();
62
+ }
63
+ addlogs(self.config, 'No webhooks found', 'success');
64
+ resolve();
65
+ })
66
+ .catch(function (error) {
67
+ if (error.statusCode === 401) {
68
+ addlogs(
69
+ self.config,
70
+ chalk.red('You are not allowed to export webhooks, Unless you provide email and password in config'),
71
+ 'error',
72
+ );
73
+ return resolve();
52
74
  }
53
- helper.writeFile(path.join(webhooksFolderPath, webhooksConfig.fileName), self.webhooks);
54
- addlogs(config, chalk.green('All the webhooks have been exported successfully'), 'success');
55
- return resolve();
56
- }
57
- addlogs(config, 'No webhooks found', 'success');
58
- return resolve();
59
- })
60
- .catch(function (error) {
61
- if (error.statusCode === 401) {
62
- addlogs(
63
- config,
64
- chalk.red('You are not allowed to export webhooks, Unless you provide email and password in config'),
65
- 'error',
66
- );
67
- return resolve();
68
- }
69
- addlogs(config, error, 'error');
70
- return reject();
71
- });
72
- });
75
+ addlogs(self.config, formatError(error), 'error');
76
+ reject('Failed export webhooks');
77
+ });
78
+ });
79
+ }
73
80
  };
74
-
75
- module.exports = new ExportWebhooks();
@@ -4,67 +4,106 @@
4
4
  * MIT Licensed
5
5
  */
6
6
 
7
- const mkdirp = require('mkdirp');
8
7
  const path = require('path');
9
8
  const chalk = require('chalk');
9
+ const mkdirp = require('mkdirp');
10
+ const { merge } = require('lodash');
10
11
 
11
- let helper = require('../util/helper');
12
- let { addlogs } = require('../util/log');
13
-
12
+ const helper = require('../util/helper');
13
+ const { addlogs } = require('../util/log');
14
+ const { formatError } = require('../util');
15
+ const config = require('../../config/default');
14
16
  const stack = require('../util/contentstack-management-sdk');
15
- let config = require('../../config/default');
16
- let workFlowConfig = config.modules.workflows;
17
- let client;
18
17
 
19
- function ExportWorkFlows() {
20
- this.workflows = {};
21
- }
18
+ module.exports = class ExportWorkFlows {
19
+ client;
20
+ config;
21
+ workflows = {};
22
+ workFlowConfig = config.modules.workflows;
22
23
 
23
- ExportWorkFlows.prototype.start = function (credentialConfig) {
24
- addlogs(config, 'Starting workflow export', 'success');
25
- this.workflows = {};
26
- let self = this;
27
- config = credentialConfig;
28
- client = stack.Client(config);
24
+ constructor(credentialConfig) {
25
+ this.config = merge(config, credentialConfig);
26
+ }
29
27
 
30
- let workflowsFolderPath = path.resolve(config.data, config.branchName || '', workFlowConfig.dirName);
31
- mkdirp.sync(workflowsFolderPath);
32
- return new Promise(function (resolve) {
33
- return client
34
- .stack({ api_key: config.source_stack, management_token: config.management_token })
35
- .workflow()
36
- .fetchAll()
37
- .then((response) => {
38
- if (response.items.length !== 0) {
39
- response.items.forEach(function (workflow) {
40
- addlogs(config, workflow.name + ' workflow was exported successfully', 'success');
41
- self.workflows[workflow.uid] = workflow;
42
- let deleteItems = config.modules.workflows.invalidKeys;
43
- deleteItems.forEach((e) => delete workflow[e]);
44
- });
45
- addlogs(config, chalk.green('All the workflow have been exported successfully'), 'success');
46
- }
47
- if (response.items.length === 0) {
48
- addlogs(config, 'No workflow were found in the Stack', 'success');
49
- }
50
- helper.writeFile(path.join(workflowsFolderPath, workFlowConfig.fileName), self.workflows);
51
- return resolve();
52
- })
53
- .catch(function (error) {
54
- if (error.statusCode === 401) {
55
- addlogs(
56
- config,
57
- chalk.red(
58
- 'You are not allowed to export workflow, Unless you provide email and password in config',
59
- 'error',
60
- ),
61
- );
62
- return resolve();
28
+ start() {
29
+ addlogs(this.config, 'Starting workflow export', 'success');
30
+
31
+ const self = this;
32
+ this.client = stack.Client(this.config);
33
+ let workflowsFolderPath = path.resolve(this.config.data, this.config.branchName || '', this.workFlowConfig.dirName);
34
+
35
+ mkdirp.sync(workflowsFolderPath);
36
+
37
+ return new Promise(function (resolve, reject) {
38
+ return self.client
39
+ .stack({ api_key: self.config.source_stack, management_token: self.config.management_token })
40
+ .workflow()
41
+ .fetchAll()
42
+ .then(async (response) => {
43
+ try {
44
+ if (response.items.length) {
45
+ await self.getWorkflowsData(self, response.items);
46
+ addlogs(self.config, chalk.green('All the workflow have been exported successfully'), 'success');
47
+ }
48
+ if (!response.items.length) {
49
+ addlogs(self.config, 'No workflow were found in the Stack', 'success');
50
+ }
51
+ helper.writeFileSync(path.join(workflowsFolderPath, self.workFlowConfig.fileName), self.workflows);
52
+ resolve();
53
+ } catch (error) {
54
+ addlogs(self.config, formatError(error), 'error');
55
+ reject(error);
56
+ }
57
+ })
58
+ .catch(function (error) {
59
+ if (error.statusCode === 401) {
60
+ addlogs(
61
+ self.config,
62
+ chalk.red(
63
+ 'You are not allowed to export workflow, Unless you provide email and password in config',
64
+ 'error',
65
+ ),
66
+ );
67
+ return resolve();
68
+ }
69
+ addlogs(self.config, formatError(error), 'error');
70
+ resolve();
71
+ });
72
+ });
73
+ }
74
+
75
+ async getWorkflowRoles(self, workflow) {
76
+ try {
77
+ for (const stage of workflow.workflow_stages) {
78
+ if (stage.SYS_ACL.roles.uids.length) {
79
+ for (let i = 0; i < stage.SYS_ACL.roles.uids.length; i++) {
80
+ const roleUid = stage.SYS_ACL.roles.uids[i];
81
+ const roleData = await self.client
82
+ .stack({ api_key: config.source_stack, management_token: config.management_token })
83
+ .role(roleUid)
84
+ .fetch({ include_rules: true, include_permissions: true });
85
+ stage.SYS_ACL.roles.uids[i] = roleData;
86
+ }
63
87
  }
64
- addlogs(config, error, 'error');
65
- return resolve();
66
- });
67
- });
68
- };
88
+ }
89
+ } catch (error) {
90
+ console.log('Error getting roles', error && error.message);
91
+ addlogs(self.config, 'Error fetching roles in export workflows task.', 'error');
92
+ throw new Error({ message: 'Error fetching roles in export workflows task.' });
93
+ }
94
+ }
69
95
 
70
- module.exports = new ExportWorkFlows();
96
+ async getWorkflowsData(self, workflows) {
97
+ try {
98
+ for (const workflow of workflows) {
99
+ addlogs(self.config, workflow.name + ' workflow was exported successfully', 'success');
100
+ await self.getWorkflowRoles(self, workflow);
101
+ self.workflows[workflow.uid] = workflow;
102
+ let deleteItems = config.modules.workflows.invalidKeys;
103
+ deleteItems.forEach((e) => delete workflow[e]);
104
+ }
105
+ } catch (error) {
106
+ throw error;
107
+ }
108
+ }
109
+ };
@@ -11,7 +11,7 @@ const helper = require('../util/helper');
11
11
  let _ = require('lodash');
12
12
  const { cliux } = require('@contentstack/cli-utilities');
13
13
 
14
- exports.configWithMToken = function (config, managementTokens, host, contentTypes, branchName, securedAssets, moduleName) {
14
+ exports.configWithMToken = async function (config, managementTokens, host, contentTypes, branchName, securedAssets, moduleName) {
15
15
  let externalConfig = require(config);
16
16
  defaultConfig.securedAssets = securedAssets;
17
17
  defaultConfig.management_token = managementTokens.token;
@@ -27,7 +27,7 @@ exports.configWithMToken = function (config, managementTokens, host, contentType
27
27
  }
28
28
  }
29
29
  defaultConfig = _.merge(defaultConfig, externalConfig);
30
- initial(defaultConfig);
30
+ await initial(defaultConfig);
31
31
  };
32
32
 
33
33
  exports.parameterWithMToken = async function (
@@ -87,10 +87,10 @@ exports.withoutParameterMToken = async (
87
87
  }
88
88
  defaultConfig.source_stack = stackUid;
89
89
  defaultConfig.data = pathOfExport;
90
- initial(defaultConfig);
90
+ await initial(defaultConfig);
91
91
  };
92
92
 
93
- exports.configWithAuthToken = function (config, _authToken, moduleName, host, contentTypes, branchName, securedAssets) {
93
+ exports.configWithAuthToken = async function (config, _authToken, moduleName, host, contentTypes, branchName, securedAssets) {
94
94
  let externalConfig = helper.readFile(path.resolve(config));
95
95
  defaultConfig.auth_token = _authToken;
96
96
  defaultConfig.host = host.cma;
@@ -105,7 +105,7 @@ exports.configWithAuthToken = function (config, _authToken, moduleName, host, co
105
105
  }
106
106
  }
107
107
  defaultConfig = _.merge(defaultConfig, externalConfig);
108
- initial(defaultConfig);
108
+ await initial(defaultConfig);
109
109
  };
110
110
 
111
111
  exports.parametersWithAuthToken = function (
@@ -133,8 +133,7 @@ exports.parametersWithAuthToken = function (
133
133
  defaultConfig.cdn = host.cda;
134
134
  defaultConfig.data = data;
135
135
  defaultConfig.securedAssets = securedAssets;
136
- var exportStart = initial(defaultConfig);
137
- exportStart
136
+ await initial(defaultConfig)
138
137
  .then(() => {
139
138
  return resolve();
140
139
  })
@@ -168,5 +167,5 @@ exports.withoutParametersWithAuthToken = async (
168
167
  defaultConfig.data = pathOfExport;
169
168
  defaultConfig.host = host.cma;
170
169
  defaultConfig.cdn = host.cda;
171
- initial(defaultConfig);
170
+ await initial(defaultConfig);
172
171
  };
@@ -7,8 +7,9 @@
7
7
  var fs = require('fs');
8
8
  var path = require('path');
9
9
  var mkdirp = require('mkdirp');
10
+ var bigJSON = require('big-json');
10
11
 
11
- exports.readFile = function (filePath, parse) {
12
+ exports.readFileSync = function (filePath, parse) {
12
13
  var data;
13
14
  parse = typeof parse === 'undefined' ? true : parse;
14
15
  filePath = path.resolve(filePath);
@@ -18,11 +19,91 @@ exports.readFile = function (filePath, parse) {
18
19
  return data;
19
20
  };
20
21
 
21
- exports.writeFile = function (filePath, data) {
22
+ // by default file type is json
23
+ exports.readFile = async (filePath, options = { type: 'json' }) => {
24
+ return new Promise((resolve, reject) => {
25
+ filePath = path.resolve(filePath);
26
+ fs.readFile(filePath, 'utf-8', (error, data) => {
27
+ if (error) {
28
+ reject(error);
29
+ } else {
30
+ if (options.type !== 'json') {
31
+ return resolve(data);
32
+ }
33
+ resolve(JSON.parse(data));
34
+ }
35
+ });
36
+ });
37
+ };
38
+
39
+ exports.makeDirectory = async function (path) {
40
+ if (!path) {
41
+ throw new Error('Invalid path to create directory');
42
+ }
43
+ return mkdirp(path);
44
+ };
45
+
46
+ exports.readLargeFile = function (filePath, opts = {}) {
47
+ if (typeof filePath !== 'string') {
48
+ return;
49
+ }
50
+ filePath = path.resolve(filePath);
51
+ if (fs.existsSync(filePath)) {
52
+ return new Promise((resolve, reject) => {
53
+ const readStream = fs.createReadStream(filePath, { encoding: 'utf-8' });
54
+ const parseStream = bigJSON.createParseStream();
55
+ parseStream.on('data', function (data) {
56
+ if (opts.type === 'array') {
57
+ return resolve(Object.values(data));
58
+ }
59
+ resolve(data);
60
+ });
61
+ parseStream.on('error', function (error) {
62
+ console.log('error', error);
63
+ reject(error);
64
+ });
65
+ readStream.pipe(parseStream);
66
+ });
67
+ }
68
+ };
69
+
70
+ exports.writeLargeFile = function (filePath, data) {
71
+ if (typeof filePath !== 'string' || typeof data !== 'object') {
72
+ return;
73
+ }
74
+ filePath = path.resolve(filePath);
75
+ return new Promise((resolve, reject) => {
76
+ const stringifyStream = bigJSON.createStringifyStream({
77
+ body: data,
78
+ });
79
+ var writeStream = fs.createWriteStream(filePath, 'utf-8');
80
+ stringifyStream.pipe(writeStream);
81
+ writeStream.on('finish', () => {
82
+ resolve();
83
+ });
84
+ writeStream.on('error', (error) => {
85
+ reject(error);
86
+ });
87
+ });
88
+ };
89
+
90
+ exports.writeFileSync = function (filePath, data) {
22
91
  data = typeof data === 'object' ? JSON.stringify(data) : data || '{}';
23
92
  fs.writeFileSync(filePath, data);
24
93
  };
25
94
 
95
+ exports.writeFile = function (filePath, data) {
96
+ return new Promise((resolve, reject) => {
97
+ data = typeof data === 'object' ? JSON.stringify(data) : data || '{}';
98
+ fs.writeFile(filePath, data, (error) => {
99
+ if (error) {
100
+ return reject(error);
101
+ }
102
+ resolve('done');
103
+ });
104
+ });
105
+ };
106
+
26
107
  exports.makeDirectory = function () {
27
108
  for (var key in arguments) {
28
109
  var dirname = path.resolve(arguments[key]);
@@ -6,8 +6,8 @@
6
6
 
7
7
  var _ = require('lodash');
8
8
  var defaultConfig = require('../../config/default');
9
- var { addlogs } = require('../util/log');
10
9
  const chalk = require('chalk');
10
+ const promiseLimit = require('promise-limit');
11
11
 
12
12
  exports.validateConfig = function (config) {
13
13
  if (!config.host || !config.cdn) {
@@ -43,3 +43,38 @@ exports.buildAppConfig = function (config) {
43
43
  config = _.merge(defaultConfig, config);
44
44
  return config;
45
45
  };
46
+
47
+ exports.formatError = function (error) {
48
+ try {
49
+ if (typeof error === 'string') {
50
+ error = JSON.parse(error);
51
+ } else {
52
+ error = JSON.parse(error.message);
53
+ }
54
+ } catch (e) {}
55
+ let message = error.errorMessage || error.error_message || error.message || error;
56
+ if (error.errors && Object.keys(error.errors).length > 0) {
57
+ Object.keys(error.errors).forEach((e) => {
58
+ let entity = e;
59
+ if (e === 'authorization') entity = 'Management Token';
60
+ if (e === 'api_key') entity = 'Stack API key';
61
+ if (e === 'uid') entity = 'Content Type';
62
+ if (e === 'access_token') entity = 'Delivery Token';
63
+ message += ' ' + [entity, error.errors[e]].join(' ');
64
+ });
65
+ }
66
+ return message;
67
+ };
68
+
69
+ exports.executeTask = function (tasks = [], handler, options) {
70
+ if (typeof handler !== 'function') {
71
+ throw new Error('Invalid handler');
72
+ }
73
+ const { concurrency = 1 } = options;
74
+ const limit = promiseLimit(concurrency);
75
+ return Promise.all(
76
+ tasks.map((task) => {
77
+ return limit(() => handler(task));
78
+ }),
79
+ );
80
+ };
@@ -11,7 +11,7 @@ var slice = Array.prototype.slice;
11
11
 
12
12
  const ansiRegexPattern = [
13
13
  '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
14
- '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
14
+ '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))',
15
15
  ].join('|');
16
16
 
17
17
  function returnString(args) {
@@ -20,14 +20,17 @@ function returnString(args) {
20
20
  returnStr = args
21
21
  .map(function (item) {
22
22
  if (item && typeof item === 'object') {
23
- return JSON.stringify(item).replace(/authtoken\":\"blt................/g, 'authtoken":"blt....');
23
+ try {
24
+ return JSON.stringify(item).replace(/authtoken\":\"blt................/g, 'authtoken":"blt....');
25
+ } catch (error) {}
26
+ return item;
24
27
  }
25
28
  return item;
26
29
  })
27
30
  .join(' ')
28
31
  .trim();
29
32
  }
30
- returnStr = returnStr.replace(new RegExp(ansiRegexPattern, 'g'), "").trim();
33
+ returnStr = returnStr.replace(new RegExp(ansiRegexPattern, 'g'), '').trim();
31
34
  return returnStr;
32
35
  }
33
36
  var myCustomLevels = {