@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 +1 -1
- package/lib/branch/merge-handler.js +79 -10
- package/lib/utils/branch-diff-utility.js +13 -8
- package/lib/utils/index.js +11 -3
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
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.
|
|
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
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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'
|
|
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
|
-
|
|
74
|
-
case '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/lib/utils/index.js
CHANGED
|
@@ -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
|
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED