@contentstack/cli-cm-export 1.10.5 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,7 @@ $ npm install -g @contentstack/cli-cm-export
48
48
  $ csdx COMMAND
49
49
  running command...
50
50
  $ csdx (--version)
51
- @contentstack/cli-cm-export/1.10.5 linux-x64 node-v18.19.0
51
+ @contentstack/cli-cm-export/1.11.1 linux-x64 node-v18.19.1
52
52
  $ csdx --help [COMMAND]
53
53
  USAGE
54
54
  $ csdx COMMAND
@@ -9,7 +9,7 @@ const utils_1 = require("../../../utils");
9
9
  class ExportCommand extends cli_command_1.Command {
10
10
  async run() {
11
11
  var _a;
12
- let exportDir;
12
+ let exportDir = (0, cli_utilities_1.pathValidator)('logs');
13
13
  try {
14
14
  const { flags } = await this.parse(ExportCommand);
15
15
  let exportConfig = await (0, utils_1.setupExportConfig)(flags);
@@ -23,11 +23,11 @@ class ExportCommand extends cli_command_1.Command {
23
23
  (0, utils_1.writeExportMetaFile)(exportConfig);
24
24
  }
25
25
  (0, utils_1.log)(exportConfig, `The content of the stack ${exportConfig.apiKey} has been exported successfully!`, 'success');
26
- (0, utils_1.log)(exportConfig, `The log has been stored at '${path_1.default.join(exportDir, 'logs', 'export')}'`, 'success');
26
+ (0, utils_1.log)(exportConfig, `The log has been stored at '${(0, cli_utilities_1.pathValidator)(path_1.default.join(exportDir, 'logs', 'export'))}'`, 'success');
27
27
  }
28
28
  catch (error) {
29
29
  (0, utils_1.log)({ data: exportDir }, `Failed to export stack content - ${(0, utils_1.formatError)(error)}`, 'error');
30
- (0, utils_1.log)({ data: exportDir }, `The log has been stored at ${exportDir ? path_1.default.join(exportDir, 'logs', 'export') : path_1.default.join(__dirname, 'logs')}`, 'info');
30
+ (0, utils_1.log)({ data: exportDir }, `The log has been stored at ${exportDir}`, 'info');
31
31
  }
32
32
  }
33
33
  }
@@ -165,13 +165,8 @@ const config = {
165
165
  taxonomies: {
166
166
  dirName: 'taxonomies',
167
167
  fileName: 'taxonomies.json',
168
- invalidKeys: ['updated_at', 'created_by', 'updated_by', 'stackHeaders', 'urlPath'],
169
- },
170
- terms: {
171
- dirName: 'terms',
172
- fileName: 'terms.json',
173
- invalidKeys: ['updated_at', 'created_by', 'updated_by', 'stackHeaders', 'urlPath'],
174
- },
168
+ invalidKeys: ['updated_at', 'created_by', 'updated_by', 'stackHeaders', 'urlPath', 'created_at'],
169
+ }
175
170
  },
176
171
  languagesCode: [
177
172
  'af-za',
@@ -23,7 +23,7 @@ export type CustomPromiseHandlerInput = {
23
23
  isLastRequest: boolean;
24
24
  };
25
25
  export type CustomPromiseHandler = (input: CustomPromiseHandlerInput) => Promise<any>;
26
- export type ApiModuleType = 'stack' | 'asset' | 'assets' | 'entry' | 'entries' | 'content-type' | 'content-types' | 'stacks' | 'versioned-entries' | 'download-asset';
26
+ export type ApiModuleType = 'stack' | 'asset' | 'assets' | 'entry' | 'entries' | 'content-type' | 'content-types' | 'stacks' | 'versioned-entries' | 'download-asset' | 'export-taxonomy';
27
27
  export default abstract class BaseClass {
28
28
  readonly client: any;
29
29
  exportConfig: ExportConfig;
@@ -110,6 +110,12 @@ class BaseClass {
110
110
  .download({ url, responseType: 'stream' })
111
111
  .then((response) => resolve({ response, isLastRequest, additionalInfo }))
112
112
  .catch((error) => reject({ error, isLastRequest, additionalInfo }));
113
+ case 'export-taxonomy':
114
+ return this.stack
115
+ .taxonomy(uid)
116
+ .export()
117
+ .then((response) => resolve({ response, uid }))
118
+ .catch((error) => reject({ error, uid }));
113
119
  default:
114
120
  return Promise.resolve();
115
121
  }
@@ -2,12 +2,9 @@ import BaseClass from './base-class';
2
2
  import { ModuleClassParams } from '../../types';
3
3
  export default class ExportTaxonomies extends BaseClass {
4
4
  private taxonomies;
5
- private terms;
6
5
  private taxonomiesConfig;
7
- private termsConfig;
8
6
  private qs;
9
7
  taxonomiesFolderPath: string;
10
- termsFolderPath: string;
11
8
  constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
12
9
  start(): Promise<void>;
13
10
  /**
@@ -23,23 +20,9 @@ export default class ExportTaxonomies extends BaseClass {
23
20
  */
24
21
  sanitizeTaxonomiesAttribs(taxonomies: Record<string, string>[]): void;
25
22
  /**
26
- * fetch all terms of respective taxonomy and write it into <taxonomy-uid>-terms file
23
+ * Export all taxonomies details using metadata(this.taxonomies) and write it into respective <taxonomy-uid>.json file
27
24
  * @returns {Promise<void>}
28
25
  */
29
- getAllTerms(): Promise<void>;
30
- /**
31
- * fetch all terms of the provided taxonomy uid
32
- * @async
33
- * @param {string} taxonomyUID
34
- * @param {number} skip
35
- * @returns {Promise<any>}
36
- */
37
- fetchTermsOfTaxonomy(taxonomyUID: string, skip?: number): Promise<any>;
38
- /**
39
- * remove invalid keys and write data into taxonomies
40
- * @function sanitizeTaxonomiesAttribs
41
- * @param terms
42
- */
43
- sanitizeTermsAttribs(terms: Record<string, string>[]): void;
26
+ exportTaxonomies(): Promise<void>;
44
27
  handleErrorMsg(err: any): void;
45
28
  }
@@ -11,18 +11,13 @@ class ExportTaxonomies extends base_class_1.default {
11
11
  constructor({ exportConfig, stackAPIClient }) {
12
12
  super({ exportConfig, stackAPIClient });
13
13
  this.taxonomies = {};
14
- this.terms = [];
15
14
  this.taxonomiesConfig = exportConfig.modules.taxonomies;
16
- this.termsConfig = exportConfig.modules.terms;
17
- this.qs = { include_count: true, skip: 0, asc: 'created_at' };
18
15
  }
19
16
  async start() {
20
17
  (0, utils_1.log)(this.exportConfig, 'Starting taxonomies export', 'info');
21
- //create taxonomies and terms folder in data directory path
18
+ //create taxonomies folder
22
19
  this.taxonomiesFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.taxonomiesConfig.dirName);
23
20
  await utils_1.fsUtil.makeDirectory(this.taxonomiesFolderPath);
24
- this.termsFolderPath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, this.termsConfig.dirName);
25
- await utils_1.fsUtil.makeDirectory(this.termsFolderPath);
26
21
  //fetch all taxonomies and write into taxonomies folder
27
22
  await this.getAllTaxonomies();
28
23
  if (this.taxonomies === undefined || (0, isEmpty_1.default)(this.taxonomies)) {
@@ -30,11 +25,10 @@ class ExportTaxonomies extends base_class_1.default {
30
25
  return;
31
26
  }
32
27
  else {
33
- utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.taxonomiesFolderPath, this.taxonomiesConfig.fileName), this.taxonomies);
34
- (0, utils_1.log)(this.exportConfig, 'All taxonomies exported successfully!', 'success');
28
+ utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.taxonomiesFolderPath, 'taxonomies.json'), this.taxonomies);
29
+ await this.exportTaxonomies();
35
30
  }
36
- //fetch all terms of respective and write into taxonomies/terms folder
37
- await this.getAllTerms();
31
+ (0, utils_1.log)(this.exportConfig, `All taxonomies exported successfully!`, 'success');
38
32
  }
39
33
  /**
40
34
  * fetch all taxonomies in the provided stack
@@ -74,72 +68,40 @@ class ExportTaxonomies extends base_class_1.default {
74
68
  for (let index = 0; index < (taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.length); index++) {
75
69
  const taxonomyUID = taxonomies[index].uid;
76
70
  this.taxonomies[taxonomyUID] = (0, omit_1.default)(taxonomies[index], this.taxonomiesConfig.invalidKeys);
77
- (0, utils_1.log)(this.exportConfig, `'${taxonomyUID}' taxonomy exported successfully!`, 'success');
78
71
  }
79
72
  }
80
73
  /**
81
- * fetch all terms of respective taxonomy and write it into <taxonomy-uid>-terms file
74
+ * Export all taxonomies details using metadata(this.taxonomies) and write it into respective <taxonomy-uid>.json file
82
75
  * @returns {Promise<void>}
83
76
  */
84
- async getAllTerms() {
85
- var _a;
77
+ async exportTaxonomies() {
86
78
  const taxonomiesUID = (0, keys_1.default)(this.taxonomies) || [];
87
- this.qs.depth = 0;
88
- for (let index = 0; index < (taxonomiesUID === null || taxonomiesUID === void 0 ? void 0 : taxonomiesUID.length); index++) {
89
- const taxonomyUID = taxonomiesUID[index];
90
- this.terms = [];
91
- await this.fetchTermsOfTaxonomy(taxonomyUID);
92
- if (!((_a = this.terms) === null || _a === void 0 ? void 0 : _a.length)) {
93
- (0, utils_1.log)(this.exportConfig, `No terms found for taxonomy - '${taxonomyUID}'!`, 'info');
79
+ const onSuccess = ({ response, uid }) => {
80
+ const filePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, `${uid}.json`);
81
+ utils_1.fsUtil.writeFile(filePath, response);
82
+ (0, utils_1.log)(this.exportConfig, `'${uid}' taxonomy exported successfully!`, 'success');
83
+ };
84
+ const onReject = ({ error, uid }) => {
85
+ var _a, _b;
86
+ if (error === null || error === void 0 ? void 0 : error.errorMessage) {
87
+ (0, utils_1.log)(this.exportConfig, `Failed to export taxonomy - '${uid}'! ${error.errorMessage}`, 'error');
94
88
  }
95
- else {
96
- utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.termsFolderPath, `${taxonomyUID}-${this.termsConfig.fileName}`), this.terms);
97
- (0, utils_1.log)(this.exportConfig, `Terms from taxonomy '${taxonomyUID}' exported successfully!`, 'success');
89
+ else if (error === null || error === void 0 ? void 0 : error.message) {
90
+ const errorMsg = ((_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.taxonomy) || ((_b = error === null || error === void 0 ? void 0 : error.errors) === null || _b === void 0 ? void 0 : _b.term) || (error === null || error === void 0 ? void 0 : error.message);
91
+ (0, utils_1.log)(this.exportConfig, `Failed to export taxonomy - '${uid}'! ${errorMsg}`, 'error');
98
92
  }
99
- }
100
- (0, utils_1.log)(this.exportConfig, `All the terms exported successfully!`, 'success');
101
- }
102
- /**
103
- * fetch all terms of the provided taxonomy uid
104
- * @async
105
- * @param {string} taxonomyUID
106
- * @param {number} skip
107
- * @returns {Promise<any>}
108
- */
109
- async fetchTermsOfTaxonomy(taxonomyUID, skip = 0) {
110
- if (skip) {
111
- this.qs.skip = skip;
112
- }
113
- await this.stack
114
- .taxonomy(taxonomyUID)
115
- .terms()
116
- .query(this.qs)
117
- .find()
118
- .then(async (data) => {
119
- const { items, count } = data;
120
- const termsCount = count !== undefined ? count : items === null || items === void 0 ? void 0 : items.length;
121
- if (items === null || items === void 0 ? void 0 : items.length) {
122
- this.sanitizeTermsAttribs(items);
123
- skip += this.taxonomiesConfig.limit || 100;
124
- if (skip >= termsCount) {
125
- return;
126
- }
127
- return await this.fetchTermsOfTaxonomy(taxonomyUID, skip);
93
+ else {
94
+ (0, utils_1.log)(this.exportConfig, `Failed to export taxonomy - '${uid}'! ${error}`, 'error');
128
95
  }
129
- })
130
- .catch((error) => {
131
- this.handleErrorMsg(error);
132
- });
133
- }
134
- /**
135
- * remove invalid keys and write data into taxonomies
136
- * @function sanitizeTaxonomiesAttribs
137
- * @param terms
138
- */
139
- sanitizeTermsAttribs(terms) {
140
- for (let index = 0; index < (terms === null || terms === void 0 ? void 0 : terms.length); index++) {
141
- const term = (0, omit_1.default)(terms[index], this.termsConfig.invalidKeys);
142
- this.terms.push(term);
96
+ };
97
+ for (let index = 0; index < (taxonomiesUID === null || taxonomiesUID === void 0 ? void 0 : taxonomiesUID.length); index++) {
98
+ const taxonomyUID = taxonomiesUID[index];
99
+ await this.makeAPICall({
100
+ reject: onReject,
101
+ resolve: onSuccess,
102
+ uid: taxonomyUID,
103
+ module: 'export-taxonomy',
104
+ });
143
105
  }
144
106
  }
145
107
  handleErrorMsg(err) {
@@ -140,12 +140,6 @@ export default interface DefaultConfig {
140
140
  invalidKeys: string[];
141
141
  dependencies?: Modules[];
142
142
  };
143
- terms: {
144
- dirName: string;
145
- fileName: string;
146
- invalidKeys: string[];
147
- dependencies?: Modules[];
148
- };
149
143
  };
150
144
  languagesCode: string[];
151
145
  apis: {
@@ -97,13 +97,6 @@ export interface TaxonomiesConfig {
97
97
  dependencies?: Modules[];
98
98
  limit?: number;
99
99
  }
100
- export interface TermsConfig {
101
- dirName: string;
102
- fileName: string;
103
- invalidKeys: string[];
104
- dependencies?: Modules[];
105
- limit?: number;
106
- }
107
100
  export { default as DefaultConfig } from './default-config';
108
101
  export { default as ExportConfig } from './export-config';
109
102
  export * from './marketplace-app';
@@ -17,6 +17,14 @@ const setupConfig = async (exportCmdFlags) => {
17
17
  config = merge_1.default.recursive(config, externalConfig);
18
18
  }
19
19
  config.exportDir = exportCmdFlags['data'] || exportCmdFlags['data-dir'] || config.data || (await (0, interactive_1.askExportDir)());
20
+ const pattern = /[*$%#<>{}!&?]/g;
21
+ if (pattern.test(config.exportDir)) {
22
+ cli_utilities_1.cliux.print(`\nPlease add a directory path without any of the special characters: (*,&,{,},[,],$,%,<,>,?,!)`, {
23
+ color: 'yellow',
24
+ });
25
+ config.exportDir = await (0, interactive_1.askExportDir)();
26
+ }
27
+ config.exportDir = config.exportDir.replace(/['"]/g, '');
20
28
  config.exportDir = path.resolve(config.exportDir);
21
29
  //Note to support the old key
22
30
  config.data = config.exportDir;
@@ -4,4 +4,3 @@ export declare const askOTP: () => Promise<string>;
4
4
  export declare const askUsername: () => Promise<string>;
5
5
  export declare const askExportDir: () => Promise<string>;
6
6
  export declare const askAPIKey: () => Promise<string>;
7
- export declare const askDeveloperHub: (regionName: string) => Promise<string>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.askDeveloperHub = exports.askAPIKey = exports.askExportDir = exports.askUsername = exports.askOTP = exports.askOTPChannel = exports.askPassword = void 0;
3
+ exports.askAPIKey = exports.askExportDir = exports.askUsername = exports.askOTP = exports.askOTPChannel = exports.askPassword = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const cli_utilities_1 = require("@contentstack/cli-utilities");
6
6
  const path = tslib_1.__importStar(require("path"));
@@ -48,15 +48,17 @@ const askUsername = async () => {
48
48
  };
49
49
  exports.askUsername = askUsername;
50
50
  const askExportDir = async () => {
51
- const result = await cli_utilities_1.cliux.inquire({
51
+ let result = await cli_utilities_1.cliux.inquire({
52
52
  type: 'input',
53
53
  message: 'Enter the path for storing the content: (current folder)',
54
54
  name: 'dir',
55
+ validate: cli_utilities_1.validatePath,
55
56
  });
56
57
  if (!result) {
57
58
  return process.cwd();
58
59
  }
59
60
  else {
61
+ result = result.replace(/['"]/g, '');
60
62
  return path.resolve(result);
61
63
  }
62
64
  };
@@ -69,16 +71,3 @@ const askAPIKey = async () => {
69
71
  });
70
72
  };
71
73
  exports.askAPIKey = askAPIKey;
72
- const askDeveloperHub = async (regionName) => {
73
- return await cli_utilities_1.cliux.inquire({
74
- type: 'input',
75
- name: 'name',
76
- validate: (url) => {
77
- if (!url)
78
- return "Developer-hub URL can't be empty.";
79
- return true;
80
- },
81
- message: `Enter the developer-hub base URL for the ${regionName} region - `,
82
- });
83
- };
84
- exports.askDeveloperHub = askDeveloperHub;
@@ -122,7 +122,7 @@ function init(_logPath) {
122
122
  };
123
123
  }
124
124
  const log = async (config, message, type) => {
125
- const logsPath = config.data || __dirname;
125
+ const logsPath = config.data;
126
126
  // ignoring the type argument, as we are not using it to create a logfile anymore
127
127
  if (type !== 'error') {
128
128
  // removed type argument from init method
@@ -1,5 +1,5 @@
1
1
  import { NodeCrypto } from '@contentstack/cli-utilities';
2
2
  import { ExportConfig } from '../types';
3
- export declare const getDeveloperHubUrl: (exportConfig: ExportConfig) => Promise<any>;
3
+ export declare const getDeveloperHubUrl: (exportConfig: ExportConfig) => Promise<string>;
4
4
  export declare function getOrgUid(config: ExportConfig): Promise<string>;
5
5
  export declare function createNodeCryptoInstance(config: ExportConfig): Promise<NodeCrypto>;
@@ -3,14 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createNodeCryptoInstance = exports.getOrgUid = exports.getDeveloperHubUrl = void 0;
4
4
  const cli_utilities_1 = require("@contentstack/cli-utilities");
5
5
  const utils_1 = require("../utils");
6
- const interactive_1 = require("./interactive");
7
6
  const getDeveloperHubUrl = async (exportConfig) => {
8
- const { cma, name } = cli_utilities_1.configHandler.get('region') || {};
9
- let developerHubBaseUrl = exportConfig === null || exportConfig === void 0 ? void 0 : exportConfig.developerHubUrls[cma];
10
- if (!developerHubBaseUrl) {
11
- developerHubBaseUrl = await (0, interactive_1.askDeveloperHub)(name);
12
- }
13
- return developerHubBaseUrl.startsWith('http') ? developerHubBaseUrl : `https://${developerHubBaseUrl}`;
7
+ return (0, cli_utilities_1.createDeveloperHubUrl)(exportConfig.host);
14
8
  };
15
9
  exports.getDeveloperHubUrl = getDeveloperHubUrl;
16
10
  async function getOrgUid(config) {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.10.5",
2
+ "version": "1.11.1",
3
3
  "commands": {
4
4
  "cm:stacks:export": {
5
5
  "id": "cm:stacks:export",
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-export",
3
3
  "description": "Contentstack CLI plugin to export content from stack",
4
- "version": "1.10.5",
4
+ "version": "1.11.1",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
8
8
  "@contentstack/cli-command": "~1.2.16",
9
- "@contentstack/cli-utilities": "~1.5.11",
9
+ "@contentstack/cli-utilities": "~1.6.0",
10
10
  "@oclif/core": "^2.9.3",
11
11
  "async": "^3.2.4",
12
12
  "big-json": "^3.2.0",