@contentstack/cli-cm-branches 1.4.0 → 1.4.2

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
@@ -37,7 +37,7 @@ $ npm install -g @contentstack/cli-cm-branches
37
37
  $ csdx COMMAND
38
38
  running command...
39
39
  $ csdx (--version)
40
- @contentstack/cli-cm-branches/1.4.0 linux-x64 node-v22.14.0
40
+ @contentstack/cli-cm-branches/1.4.2 linux-x64 node-v22.15.0
41
41
  $ csdx --help [COMMAND]
42
42
  USAGE
43
43
  $ csdx COMMAND
@@ -5,6 +5,7 @@ const os_1 = tslib_1.__importDefault(require("os"));
5
5
  const path_1 = tslib_1.__importDefault(require("path"));
6
6
  const forEach_1 = tslib_1.__importDefault(require("lodash/forEach"));
7
7
  const cli_utilities_1 = require("@contentstack/cli-utilities");
8
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
9
  const utils_1 = require("../utils");
9
10
  class MergeHandler {
10
11
  constructor(options) {
@@ -83,11 +84,13 @@ class MergeHandler {
83
84
  deleted: [],
84
85
  };
85
86
  const selectedItems = await (0, utils_1.selectCustomPreferences)(module, this.branchCompareData[module]);
86
- (0, forEach_1.default)(selectedItems, (item) => {
87
- this.mergeSettings.mergeContent[module][item.status].push(item.value);
88
- this.mergeSettings.itemMergeStrategies.push(item.value);
89
- });
90
- this.mergeSettings.strategy = 'ignore';
87
+ if (selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) {
88
+ (0, forEach_1.default)(selectedItems, (item) => {
89
+ this.mergeSettings.mergeContent[module][item.status].push(item.value);
90
+ this.mergeSettings.itemMergeStrategies.push(item.value);
91
+ });
92
+ this.mergeSettings.strategy = 'ignore';
93
+ }
91
94
  }
92
95
  }
93
96
  else if (this.strategy === 'merge_prefer_base') {
@@ -115,7 +118,20 @@ class MergeHandler {
115
118
  else if (this.strategy === 'overwrite_with_compare') {
116
119
  this.mergeSettings.strategy = 'overwrite_with_compare';
117
120
  }
118
- await this.displayMergeSummary();
121
+ const { allEmpty, moduleStatus } = this.checkEmptySelection();
122
+ const strategyName = this.mergeSettings.strategy;
123
+ if (allEmpty) {
124
+ cli_utilities_1.cliux.print(chalk_1.default.red(`No items selected according to the '${strategyName}' strategy.`));
125
+ process.exit(1);
126
+ }
127
+ for (const [type, { exists, empty }] of Object.entries(moduleStatus)) {
128
+ if (exists && empty) {
129
+ const readable = type === 'contentType' ? 'Content Types' : 'Global fields';
130
+ cli_utilities_1.cliux.print('\n');
131
+ cli_utilities_1.cliux.print(chalk_1.default.yellow(`Note: No ${readable} selected according to the '${strategyName}' strategy.`));
132
+ }
133
+ }
134
+ this.displayMergeSummary();
119
135
  if (!this.executeOption) {
120
136
  const executionResponse = await (0, utils_1.selectMergeExecution)();
121
137
  if (executionResponse === 'previous') {
@@ -135,6 +151,59 @@ class MergeHandler {
135
151
  }
136
152
  }
137
153
  }
154
+ /**
155
+ * Checks whether the selection of modules in the compare branch data is empty.
156
+ *
157
+ * This method evaluates the branch compare data and determines if there are any changes
158
+ * (added, modified, or deleted) in the modules based on the merge strategy defined in the
159
+ * merge settings. It categorizes the status of each module as either existing and empty or
160
+ * not empty.
161
+ *
162
+ * @returns An object containing:
163
+ * - `allEmpty`: A boolean indicating whether all modules are either non-existent or empty.
164
+ * - `moduleStatus`: A record mapping module types (`contentType` and `globalField`) to their
165
+ * respective statuses, which include:
166
+ * - `exists`: A boolean indicating whether the module exists in the branch comparison data.
167
+ * - `empty`: A boolean indicating whether the module has no changes (added, modified, or deleted).
168
+ */
169
+ checkEmptySelection() {
170
+ const strategy = this.mergeSettings.strategy;
171
+ const useMergeContent = new Set(['custom_preferences', 'ignore']);
172
+ const modifiedOnlyStrategies = new Set(['merge_modified_only_prefer_base', 'merge_modified_only_prefer_compare']);
173
+ const addedOnlyStrategies = new Set(['merge_new_only']);
174
+ const moduleStatus = {
175
+ contentType: { exists: false, empty: true },
176
+ globalField: { exists: false, empty: true },
177
+ };
178
+ for (const module in this.branchCompareData) {
179
+ const content = useMergeContent.has(strategy)
180
+ ? this.mergeSettings.mergeContent[module]
181
+ : this.branchCompareData[module];
182
+ if (!content)
183
+ continue;
184
+ const isGlobalField = module === 'global_fields';
185
+ const type = isGlobalField ? 'globalField' : 'contentType';
186
+ moduleStatus[type].exists = true;
187
+ let hasChanges = false;
188
+ if (modifiedOnlyStrategies.has(strategy)) {
189
+ hasChanges = Array.isArray(content.modified) && content.modified.length > 0;
190
+ }
191
+ else if (addedOnlyStrategies.has(strategy)) {
192
+ hasChanges = Array.isArray(content.added) && content.added.length > 0;
193
+ }
194
+ else {
195
+ hasChanges =
196
+ (Array.isArray(content.modified) && content.modified.length > 0) ||
197
+ (Array.isArray(content.added) && content.added.length > 0) ||
198
+ (Array.isArray(content.deleted) && content.deleted.length > 0);
199
+ }
200
+ if (hasChanges) {
201
+ moduleStatus[type].empty = false;
202
+ }
203
+ }
204
+ const allEmpty = Object.values(moduleStatus).every((status) => !status.exists || status.empty);
205
+ return { allEmpty, moduleStatus };
206
+ }
138
207
  displayMergeSummary() {
139
208
  if (this.mergeSettings.strategy !== 'ignore') {
140
209
  for (let module in this.branchCompareData) {
@@ -225,10 +294,10 @@ class MergeHandler {
225
294
  });
226
295
  };
227
296
  const mergePreferencesMap = {
228
- 'existing_new': 'merge_existing_new',
229
- 'new': 'merge_new',
230
- 'existing': 'merge_existing',
231
- 'ask_preference': 'custom',
297
+ existing_new: 'merge_existing_new',
298
+ new: 'merge_new',
299
+ existing: 'merge_existing',
300
+ ask_preference: 'custom',
232
301
  };
233
302
  const selectedMergePreference = mergePreferencesMap[mergePreference];
234
303
  if (selectedMergePreference) {
@@ -65,24 +65,23 @@ async function branchCompareSDK(payload, skip, limit) {
65
65
  queryParams['uid'] = payload.uid;
66
66
  const module = payload.module || 'all';
67
67
  switch (module) {
68
- case 'content_types' || 'content_type':
68
+ case 'content_types':
69
+ case 'content_type':
69
70
  return await branchQuery
70
71
  .contentTypes(queryParams)
71
72
  .then((data) => data)
72
73
  .catch((err) => handleErrorMsg(err, payload.spinner));
73
- break;
74
- case 'global_fields' || 'global_field':
74
+ case 'global_fields':
75
+ case 'global_field':
75
76
  return await branchQuery
76
77
  .globalFields(queryParams)
77
78
  .then((data) => data)
78
79
  .catch((err) => handleErrorMsg(err, payload.spinner));
79
- break;
80
80
  case 'all':
81
81
  return await branchQuery
82
82
  .all(queryParams)
83
83
  .then((data) => data)
84
84
  .catch((err) => handleErrorMsg(err, payload.spinner));
85
- break;
86
85
  default:
87
86
  handleErrorMsg({ errorMessage: 'Invalid module!' }, payload.spinner);
88
87
  }
@@ -181,13 +180,19 @@ function printCompactTextView(branchTextRes) {
181
180
  if (((_a = branchTextRes.modified) === null || _a === void 0 ? void 0 : _a.length) || ((_b = branchTextRes.added) === null || _b === void 0 ? void 0 : _b.length) || ((_c = branchTextRes.deleted) === null || _c === void 0 ? void 0 : _c.length)) {
182
181
  cli_utilities_1.cliux.print(' ');
183
182
  (0, forEach_1.default)(branchTextRes.added, (diff) => {
184
- cli_utilities_1.cliux.print(chalk_1.default.green(`+ '${diff.title}' ${(0, startCase_1.default)((0, camelCase_1.default)(diff.type))}`));
183
+ if (diff.merge_strategy !== 'ignore') {
184
+ cli_utilities_1.cliux.print(chalk_1.default.green(`+ '${diff.title}' ${(0, startCase_1.default)((0, camelCase_1.default)(diff.type))}`));
185
+ }
185
186
  });
186
187
  (0, forEach_1.default)(branchTextRes.modified, (diff) => {
187
- cli_utilities_1.cliux.print(chalk_1.default.blue(`± '${diff.title}' ${(0, startCase_1.default)((0, camelCase_1.default)(diff.type))}`));
188
+ if (diff.merge_strategy !== 'ignore') {
189
+ cli_utilities_1.cliux.print(chalk_1.default.blue(`± '${diff.title}' ${(0, startCase_1.default)((0, camelCase_1.default)(diff.type))}`));
190
+ }
188
191
  });
189
192
  (0, forEach_1.default)(branchTextRes.deleted, (diff) => {
190
- cli_utilities_1.cliux.print(chalk_1.default.red(`- '${diff.title}' ${(0, startCase_1.default)((0, camelCase_1.default)(diff.type))}`));
193
+ if (diff.merge_strategy !== 'ignore') {
194
+ cli_utilities_1.cliux.print(chalk_1.default.red(`- '${diff.title}' ${(0, startCase_1.default)((0, camelCase_1.default)(diff.type))}`));
195
+ }
191
196
  });
192
197
  }
193
198
  }
@@ -73,7 +73,7 @@ async function getMergeQueueStatus(stackAPIClient, payload) {
73
73
  .mergeQueue(mergeJobUID)
74
74
  .fetch()
75
75
  .then((data) => data)
76
- .catch((err) => handleErrorMsg(err));
76
+ .catch((err) => handleErrorMsg(err, () => getMergeQueueStatus(stackAPIClient, payload)));
77
77
  }
78
78
  exports.getMergeQueueStatus = getMergeQueueStatus;
79
79
  async function executeMergeRequest(stackAPIClient, payload) {
@@ -90,10 +90,18 @@ async function executeMergeRequest(stackAPIClient, payload) {
90
90
  .branch()
91
91
  .merge(itemMergeStrategies, queryParams)
92
92
  .then((data) => data)
93
- .catch((err) => handleErrorMsg(err));
93
+ .catch((err) => handleErrorMsg(err, () => executeMergeRequest(stackAPIClient, payload)));
94
94
  }
95
95
  exports.executeMergeRequest = executeMergeRequest;
96
- function handleErrorMsg(err) {
96
+ async function handleErrorMsg(err, retryCallback) {
97
+ var _a;
98
+ // Handle rate limit exceeded (status code 429)
99
+ if ((err === null || err === void 0 ? void 0 : err.status) === 429 || ((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.status) === 429) {
100
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // 1 sec delay
101
+ if (retryCallback) {
102
+ return retryCallback(); // Retry the request
103
+ }
104
+ }
97
105
  if (err === null || err === void 0 ? void 0 : err.errorMessage) {
98
106
  cli_utilities_1.cliux.print(`Error: ${err.errorMessage}`, { color: 'red' });
99
107
  }
@@ -355,5 +355,5 @@
355
355
  ]
356
356
  }
357
357
  },
358
- "version": "1.4.0"
358
+ "version": "1.4.2"
359
359
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-branches",
3
3
  "description": "Contentstack CLI plugin to do branches operations",
4
- "version": "1.4.0",
4
+ "version": "1.4.2",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {