@contentstack/cli-cm-branches 1.0.19 → 1.0.21

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Contentstack
3
+ Copyright (c) 2024 Contentstack
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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.0.19 linux-x64 node-v18.19.0
40
+ @contentstack/cli-cm-branches/1.0.21 linux-x64 node-v18.19.0
41
41
  $ csdx --help [COMMAND]
42
42
  USAGE
43
43
  $ csdx COMMAND
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ const os_1 = tslib_1.__importDefault(require("os"));
4
5
  const path_1 = tslib_1.__importDefault(require("path"));
5
6
  const forEach_1 = tslib_1.__importDefault(require("lodash/forEach"));
6
7
  const cli_utilities_1 = require("@contentstack/cli-utilities");
@@ -217,49 +218,52 @@ class MergeHandler {
217
218
  async executeEntryExpFlow(mergeJobUID, mergePayload) {
218
219
  const { mergeContent } = this.mergeSettings;
219
220
  let mergePreference = await (0, utils_1.selectContentMergePreference)();
220
- let selectedMergePreference;
221
221
  const updateEntryMergeStrategy = (items, mergeStrategy) => {
222
222
  items &&
223
223
  items.forEach((item) => {
224
224
  item.entry_merge_strategy = mergeStrategy;
225
225
  });
226
226
  };
227
- switch (mergePreference) {
228
- case 'existing_new':
229
- selectedMergePreference = 'merge_existing_new';
230
- updateEntryMergeStrategy(mergeContent.content_types.added, selectedMergePreference);
231
- updateEntryMergeStrategy(mergeContent.content_types.modified, selectedMergePreference);
232
- break;
233
- case 'new':
234
- selectedMergePreference = 'merge_new';
235
- updateEntryMergeStrategy(mergeContent.content_types.added, selectedMergePreference);
236
- break;
237
- case 'existing':
238
- selectedMergePreference = 'merge_existing';
239
- updateEntryMergeStrategy(mergeContent.content_types.modified, selectedMergePreference);
240
- break;
241
- case 'ask_preference':
242
- selectedMergePreference = 'custom';
227
+ const mergePreferencesMap = {
228
+ 'existing_new': 'merge_existing_new',
229
+ 'new': 'merge_new',
230
+ 'existing': 'merge_existing',
231
+ 'ask_preference': 'custom',
232
+ };
233
+ const selectedMergePreference = mergePreferencesMap[mergePreference];
234
+ if (selectedMergePreference) {
235
+ if (selectedMergePreference === 'custom') {
243
236
  const selectedMergeItems = await (0, utils_1.selectContentMergeCustomPreferences)(mergeContent.content_types);
244
237
  mergeContent.content_types = {
245
238
  added: [],
246
239
  modified: [],
247
240
  deleted: [],
248
241
  };
249
- selectedMergeItems.forEach((item) => {
242
+ selectedMergeItems === null || selectedMergeItems === void 0 ? void 0 : selectedMergeItems.forEach((item) => {
250
243
  mergeContent.content_types[item.status].push(item.value);
251
244
  });
252
- break;
253
- default:
254
- cli_utilities_1.cliux.error(`error: Invalid preference ${mergePreference}`);
255
- process.exit(1);
245
+ }
246
+ else {
247
+ updateEntryMergeStrategy(mergeContent.content_types.added, selectedMergePreference);
248
+ updateEntryMergeStrategy(mergeContent.content_types.modified, selectedMergePreference);
249
+ }
250
+ }
251
+ else {
252
+ cli_utilities_1.cliux.error(`error: Invalid preference ${mergePreference}`);
253
+ process.exit(1);
256
254
  }
257
255
  let scriptFolderPath = (0, utils_1.generateMergeScripts)(mergeContent.content_types, mergeJobUID);
258
256
  if (scriptFolderPath !== undefined) {
259
257
  cli_utilities_1.cliux.success(`\nSuccess! We have generated entry migration files in the folder ${scriptFolderPath}`);
260
258
  cli_utilities_1.cliux.print('\nWARNING!!! Migration is not intended to be run more than once. Migrated(entries/assets) will be duplicated if run more than once', { color: 'yellow' });
261
- const migrationCommand = `csdx cm:stacks:migration --multiple --file-path ./${scriptFolderPath} --config {compare-branch:${mergePayload.compare_branch},file-path:./${scriptFolderPath}} --branch ${mergePayload.base_branch} --stack-api-key ${this.stackAPIKey}`;
262
- cli_utilities_1.cliux.print(`\nKindly follow the steps in the guide "https://www.contentstack.com/docs/developers/cli/migrate-branch-entries" to update the migration scripts, and then run the command:\n\n${migrationCommand}`, { color: 'blue' });
259
+ let migrationCommand;
260
+ if (os_1.default.platform() === 'win32') {
261
+ migrationCommand = `csdx cm:stacks:migration --multiple --file-path ./${scriptFolderPath} --config compare-branch:${mergePayload.compare_branch} file-path:./${scriptFolderPath} --branch ${mergePayload.base_branch} --stack-api-key ${this.stackAPIKey}`;
262
+ }
263
+ else {
264
+ migrationCommand = `csdx cm:stacks:migration --multiple --file-path ./${scriptFolderPath} --config {compare-branch:${mergePayload.compare_branch},file-path:./${scriptFolderPath}} --branch ${mergePayload.base_branch} --stack-api-key ${this.stackAPIKey}`;
265
+ }
266
+ cli_utilities_1.cliux.print(`\nKindly follow the steps in the guide "https://www.contentstack.com/docs/developers/cli/entry-migration" to update the migration scripts, and then run the command:\n\n${migrationCommand}`, { color: 'blue' });
263
267
  }
264
268
  }
265
269
  async restartMergeProcess() {
@@ -26,22 +26,19 @@ function generateMergeScripts(mergeSummary, mergeJobUID) {
26
26
  merge_existing_new: entry_create_update_script_1.entryCreateUpdateScript,
27
27
  merge_existing: entry_update_script_1.entryUpdateScript,
28
28
  merge_new: entry_create_script_1.entryCreateScript,
29
- ignore: entry_create_update_script_1.entryCreateUpdateScript,
30
29
  };
31
30
  const processContentTypes = (contentTypes, messageType) => {
32
31
  if (contentTypes && contentTypes.length > 0) {
33
- processContentType({ type: 'assets', uid: '', entry_merge_strategy: '' }, mergeStrategies['asset_create_folder']);
34
32
  contentTypes.forEach((contentType) => {
35
33
  const mergeStrategy = contentType.entry_merge_strategy;
36
34
  if (mergeStrategies.hasOwnProperty(mergeStrategy)) {
37
35
  processContentType(contentType, mergeStrategies[mergeStrategy]);
38
36
  }
39
37
  });
40
- }
41
- else {
42
- cli_utilities_1.cliux.print(`No ${messageType} entries selected for merge`, { color: 'yellow' });
38
+ cli_utilities_1.cliux.print(`Info: Entries of ${messageType} content types selected for the migration`, { color: 'blue' });
43
39
  }
44
40
  };
41
+ processContentType({ type: 'assets', uid: '', entry_merge_strategy: '' }, mergeStrategies['asset_create_folder']);
45
42
  processContentTypes(mergeSummary.modified, 'Modified');
46
43
  processContentTypes(mergeSummary.added, 'New');
47
44
  return scriptFolderPath;
@@ -61,6 +58,9 @@ function getContentTypeMergeStatus(status) {
61
58
  else if (status === 'merge_existing_new') {
62
59
  return 'created_updated';
63
60
  }
61
+ else if (status === 'ignore') {
62
+ return;
63
+ }
64
64
  else {
65
65
  return '';
66
66
  }
@@ -83,11 +83,12 @@ function createMergeScripts(contentType, mergeJobUID, content) {
83
83
  fs_1.default.mkdirSync(fullPath);
84
84
  }
85
85
  let filePath;
86
+ let milliSeconds = date.getMilliseconds().toString().padStart(3, '0');
86
87
  if (contentType.type === 'assets') {
87
- filePath = `${fullPath}/${fileCreatedAt}_create_assets_folder.js`;
88
+ filePath = `${fullPath}/${fileCreatedAt}${milliSeconds}_create_assets_folder.js`;
88
89
  }
89
90
  else {
90
- filePath = `${fullPath}/${fileCreatedAt}_${getContentTypeMergeStatus(contentType.entry_merge_strategy)}_${contentType.uid}.js`;
91
+ filePath = `${fullPath}/${fileCreatedAt}${milliSeconds}_${getContentTypeMergeStatus(contentType.entry_merge_strategy)}_${contentType.uid}.js`;
91
92
  }
92
93
  fs_1.default.writeFileSync(filePath, content, 'utf-8');
93
94
  }
@@ -5,6 +5,14 @@ function entryCreateScript(contentType) {
5
5
  return `
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
+ const { marked } = require('marked');
9
+ const has = require('lodash/has');
10
+ const isArray = require('lodash/isArray');
11
+ const isObject = require('lodash/isObject');
12
+ const omit = require('lodash/omit');
13
+ const compact = require('lodash/compact')
14
+ const isPlainObject = require('lodash/isPlainObject');
15
+ const {cliux, LoggerService} = require('@contentstack/cli-utilities')
8
16
  module.exports = async ({ migration, stackSDKInstance, managementAPIClient, config, branch, apiKey }) => {
9
17
  const keysToRemove = [
10
18
  'content_type_uid',
@@ -34,20 +42,18 @@ function entryCreateScript(contentType) {
34
42
  let assetUIDMapper = {};
35
43
  let assetUrlMapper = {};
36
44
  let assetRefPath = {};
37
- let isAssetDownload = false;
45
+ let downloadedAssets = [];
46
+ let parent=[];
47
+ let logger;
38
48
 
39
49
  function getValueByPath(obj, path) {
40
50
  return path.split('[').reduce((o, key) => o && o[key.replace(/\]$/, '')], obj);
41
51
  }
42
52
 
43
- function updateValueByPath(obj, path, newValue, type, fileIndex) {
53
+ function updateValueByPath(obj, path, newValue) {
44
54
  path.split('[').reduce((o, key, index, arr) => {
45
55
  if (index === arr.length - 1) {
46
- if (type === 'file') {
47
- o[key.replace(/]$/, '')][fileIndex] = newValue;
48
- } else {
49
56
  o[key.replace(/]$/, '')][0].uid = newValue;
50
- }
51
57
  } else {
52
58
  return o[key.replace(/\]$/, '')];
53
59
  }
@@ -80,35 +86,52 @@ function entryCreateScript(contentType) {
80
86
  return references;
81
87
  };
82
88
 
83
- const findAssets = function (schema, entry, refPath, path) {
89
+ const findAssets = function (schema, entry) {
84
90
  for (const i in schema) {
85
- const currentPath = path ? path + '[' + schema[i].uid : schema[i].uid;
86
91
  if (schema[i].data_type === 'group' || schema[i].data_type === 'global_field') {
87
- findAssets(schema[i].schema, entry, refPath, currentPath + '[0]');
88
- } else if (schema[i].data_type === 'blocks') {
89
- for (const block in schema[i].blocks) {
92
+ parent.push(schema[i].uid);
93
+ findAssets(schema[i].schema, entry);
94
+ parent.pop();
95
+ }
96
+ if (schema[i].data_type === 'blocks') {
97
+ for (const j = 0; j < schema[i].blocks; j++) {
90
98
  {
91
- if (schema[i].blocks[block].schema) {
92
- findAssets(
93
- schema[i].blocks[block].schema,
94
- entry,
95
- refPath,
96
- currentPath + '[' + block + '][' + schema[i].blocks[block].uid + ']',
97
- );
99
+ if (schema[i].blocks[j].schema) {
100
+ parent.push(schema[i].uid);
101
+ parent.push(j);
102
+ parent.push(schema[i].blocks[j].uid);
103
+ findAssets(schema[i].blocks[j].schema, entry);
104
+ parent.pop();
105
+ parent.pop();
106
+ parent.pop();
98
107
  }
99
108
  }
100
109
  }
101
- } else if (schema[i].data_type === 'json' && schema[i].field_metadata.rich_text_type) {
102
- findAssetIdsFromJsonRte(entry, schema, refPath, path);
103
- } else if (
110
+ }
111
+ if (schema[i].data_type === 'json' && schema[i].field_metadata.rich_text_type) {
112
+ parent.push(schema[i].uid);
113
+ findAssetIdsFromJsonRte(entry, schema);
114
+ parent.pop();
115
+ }
116
+ if (
104
117
  schema[i].data_type === 'text' &&
105
118
  schema[i].field_metadata &&
106
119
  (schema[i].field_metadata.markdown || schema[i].field_metadata.rich_text_type)
107
120
  ) {
121
+ parent.push(schema[i].uid);
108
122
  findFileUrls(schema[i], entry);
109
- } else if (schema[i].data_type === 'file') {
110
- refPath.push(currentPath)
111
- const imgDetails = getValueByPath(entry, currentPath);
123
+ if (schema[i].field_metadata.rich_text_type) {
124
+ findAssetIdsFromHtmlRte(entry, schema[i]);
125
+ }
126
+ parent.pop();
127
+ }
128
+ if (schema[i].data_type === 'file') {
129
+ parent.push(schema[i].uid);
130
+ let updatedEntry = entry;
131
+ for (let i = 0; i < parent.length; i++) {
132
+ updatedEntry = updatedEntry[parent[i]];
133
+ }
134
+ const imgDetails = updatedEntry;
112
135
  if (schema[i].multiple) {
113
136
  if (imgDetails && imgDetails.length) {
114
137
  imgDetails.forEach((img) => {
@@ -136,10 +159,21 @@ function entryCreateScript(contentType) {
136
159
  cAssetDetails.push(obj);
137
160
  }
138
161
  }
162
+ parent.pop();
139
163
  }
140
164
  }
141
165
  };
142
166
 
167
+ function findAssetIdsFromHtmlRte(entryObj, ctSchema) {
168
+ const regex = /<img asset_uid=\\"([^"]+)\\"/g;
169
+ let match;
170
+ const entry = JSON.stringify(entryObj);
171
+ while ((match = regex.exec(entry)) !== null) {
172
+ //insert into asset details
173
+ cAssetDetails.push({uid: match[1]});
174
+ }
175
+ }
176
+
143
177
  function findFileUrls(schema, _entry) {
144
178
  let markdownRegEx;
145
179
  let markdownMatch;
@@ -259,31 +293,8 @@ function entryCreateScript(contentType) {
259
293
  }
260
294
 
261
295
  const updateAssetDetailsInEntries = function (entry) {
262
- assetRefPath[entry.uid].forEach((refPath) => {
263
- let imgDetails = entry[refPath];
264
- if (imgDetails !== undefined) {
265
- if (imgDetails && !Array.isArray(imgDetails)) {
266
- entry[refPath] = assetUIDMapper[imgDetails.uid];
267
- } else if (imgDetails && Array.isArray(imgDetails)) {
268
- for (let i = 0; i < imgDetails.length; i++) {
269
- const img = imgDetails[i];
270
- entry[refPath][i] = assetUIDMapper[img.uid];
271
- }
272
- }
273
- } else {
274
- imgDetails = getValueByPath(entry, refPath);
275
- if (imgDetails && !Array.isArray(imgDetails)) {
276
- const imgUID = imgDetails?.uid;
277
- updateValueByPath(entry, refPath, assetUIDMapper[imgUID], 'file', 0);
278
- } else if (imgDetails && Array.isArray(imgDetails)) {
279
- for (let i = 0; i < imgDetails.length; i++) {
280
- const img = imgDetails[i];
281
- const imgUID = img?.uid;
282
- updateValueByPath(entry, refPath, assetUIDMapper[imgUID], 'file', i);
283
- }
284
- }
285
- }
286
- });
296
+ let updatedEntry = Object.assign({},entry);
297
+ entry = updateFileFields(updatedEntry, entry, null)
287
298
  entry = JSON.stringify(entry);
288
299
  const assetUrls = cAssetDetails.map((asset) => asset.url);
289
300
  const assetUIDs = cAssetDetails.map((asset) => asset.uid);
@@ -302,6 +313,65 @@ function entryCreateScript(contentType) {
302
313
  });
303
314
  return JSON.parse(entry);
304
315
  };
316
+
317
+ function updateFileFields(
318
+ object,
319
+ parent,
320
+ pos
321
+ ) {
322
+ if (isPlainObject(object) && has(object, 'filename') && has(object, 'uid')) {
323
+ if (typeof pos !== 'undefined') {
324
+ if (typeof pos === 'number' || typeof pos === 'string') {
325
+ const replacer = () => {
326
+ if (assetUIDMapper.hasOwnProperty(object.uid)) {
327
+ parent[pos] = assetUIDMapper[object.uid];
328
+ } else {
329
+ parent[pos] = '';
330
+ }
331
+ };
332
+
333
+ if (parent.uid && assetUIDMapper[parent.uid]) {
334
+ parent.uid = assetUIDMapper[parent.uid];
335
+ }
336
+
337
+ if (
338
+ object &&
339
+ isObject(parent[pos]) &&
340
+ parent[pos].uid &&
341
+ parent[pos].url &&
342
+ has(parent, 'asset') &&
343
+ has(parent, '_content_type_uid') &&
344
+ parent._content_type_uid === 'sys_assets'
345
+ ) {
346
+ if (
347
+ has(parent, 'asset') &&
348
+ has(parent, '_content_type_uid') &&
349
+ parent._content_type_uid === 'sys_assets'
350
+ ) {
351
+ parent = omit(parent, ['asset']);
352
+ }
353
+
354
+ if (object.uid && assetUIDMapper[object.uid]) {
355
+ object.uid = assetUIDMapper[object.uid];
356
+ }
357
+ if (object.url && assetUrlMapper[object.url]) {
358
+ object.url = assetUrlMapper[object.url];
359
+ }
360
+ } else {
361
+ replacer();
362
+ }
363
+ }
364
+ }
365
+ } else if (isPlainObject(object)) {
366
+ for (let key in object) updateFileFields(object[key], object, key);
367
+ } else if (isArray(object) && object.length) {
368
+ for (let i = 0; i <= object.length; i++){
369
+ updateFileFields(object[i], object, i);
370
+ }
371
+ parent[pos] = compact(object);
372
+ }
373
+ return object;
374
+ }
305
375
 
306
376
  const checkAndDownloadAsset = async function (cAsset) {
307
377
  const assetUID = cAsset?.uid;
@@ -318,7 +388,6 @@ function entryCreateScript(contentType) {
318
388
  return false;
319
389
  }
320
390
  else {
321
- isAssetDownload = true;
322
391
  const cAssetDetail = await managementAPIClient
323
392
  .stack({ api_key: stackSDKInstance.api_key, branch_uid: compareBranch })
324
393
  .asset(assetUID)
@@ -360,8 +429,8 @@ function entryCreateScript(contentType) {
360
429
  const uploadAssets = async function () {
361
430
  const assetFolderMap = JSON.parse(fs.readFileSync(path.resolve(filePath, 'folder-mapper.json'), 'utf8'));
362
431
  const stackAPIClient = managementAPIClient.stack({ api_key: stackSDKInstance.api_key, branch_uid: branch });
363
- for (let i = 0; i < cAssetDetails?.length; i++) {
364
- const asset = cAssetDetails[i];
432
+ for (let i = 0; i < downloadedAssets?.length; i++) {
433
+ const asset = downloadedAssets[i];
365
434
  let requestOption = {};
366
435
 
367
436
  requestOption.parent_uid = assetFolderMap[asset.parent_uid] || asset.parent_uid;
@@ -404,6 +473,11 @@ function entryCreateScript(contentType) {
404
473
  successTitle: 'Entries Created Successfully',
405
474
  failedTitle: 'Failed to create entries',
406
475
  task: async () => {
476
+ //logger file
477
+ if(!fs.existsSync(path.join(filePath, 'entry-migration'))){
478
+ logger = new LoggerService(filePath, 'entry-migration');
479
+ }
480
+
407
481
  const compareBranchEntries = await managementAPIClient
408
482
  .stack({ api_key: stackSDKInstance.api_key, branch_uid: compareBranch })
409
483
  .contentType('${contentType}')
@@ -435,9 +509,10 @@ function entryCreateScript(contentType) {
435
509
  const updatedCAsset = await checkAndDownloadAsset(asset);
436
510
  if (updatedCAsset) {
437
511
  cAssetDetails[i] = updatedCAsset;
512
+ downloadedAssets.push(updatedCAsset)
438
513
  }
439
514
  }
440
- if (isAssetDownload) await uploadAssets();
515
+ if (downloadedAssets?.length) await uploadAssets();
441
516
  }
442
517
 
443
518
  let flag = {
@@ -448,7 +523,17 @@ function entryCreateScript(contentType) {
448
523
 
449
524
  async function updateEntry(entry, entryDetails) {
450
525
  Object.assign(entry, { ...entryDetails });
451
- await entry.update();
526
+ await entry.update().catch(err => {
527
+ let errorMsg = 'Entry update failed for uid: ' + entry?.uid + ', title: ' + entry?.title + '. ';
528
+ if(err?.errors?.title){
529
+ errorMsg += 'title'+ err?.errors?.title;
530
+ }else if(err?.errors?.entry){
531
+ errorMsg += err?.errors?.entry;
532
+ }else{
533
+ errorMsg += (err?.entry?.errorMessage || err?.errorMessage || err?.message) ?? 'Something went wrong!';
534
+ }
535
+ logger.error(errorMsg)
536
+ });
452
537
  }
453
538
 
454
539
  async function updateReferences(entryDetails, baseEntry, references) {
@@ -480,8 +565,16 @@ function entryCreateScript(contentType) {
480
565
  compareFilteredProperties.forEach(async (entryDetails) => {
481
566
  if(entryDetails !== undefined){
482
567
  entryDetails = updateAssetDetailsInEntries(entryDetails);
483
- let createdEntry = await stackSDKInstance.contentType('${contentType}').entry().create({ entry: entryDetails }).catch(error => {
484
- throw error;
568
+ let createdEntry = await stackSDKInstance.contentType('${contentType}').entry().create({ entry: entryDetails }).catch(err => {
569
+ let errorMsg = 'Entry creation failed for contentType: ' + contentType + ', title: ' + entryDetails?.title + '. ';
570
+ if(err?.errors?.title){
571
+ errorMsg += err?.errors?.title;
572
+ }else if(err?.errors?.entry){
573
+ errorMsg += err?.errors?.entry;
574
+ }else{
575
+ errorMsg += (err?.entry?.errorMessage || err?.errorMessage || err?.message) ?? 'Something went wrong!';
576
+ }
577
+ logger.error(errorMsg)
485
578
  });
486
579
  if(createdEntry){
487
580
  if (flag.references) {
@@ -5,6 +5,14 @@ function entryCreateUpdateScript(contentType) {
5
5
  return `
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
+ const { marked } = require('marked');
9
+ const has = require('lodash/has');
10
+ const isArray = require('lodash/isArray');
11
+ const isObject = require('lodash/isObject');
12
+ const omit = require('lodash/omit');
13
+ const compact = require('lodash/compact')
14
+ const isPlainObject = require('lodash/isPlainObject');
15
+ const {cliux, LoggerService} = require('@contentstack/cli-utilities')
8
16
  module.exports = async ({ migration, stackSDKInstance, managementAPIClient, config, branch, apiKey }) => {
9
17
  const keysToRemove = [
10
18
  'content_type_uid',
@@ -32,10 +40,12 @@ function entryCreateUpdateScript(contentType) {
32
40
  let assetDirPath = path.resolve(filePath, 'assets');
33
41
  let assetDetails = [];
34
42
  let newAssetDetails = [];
43
+ let downloadedAssets = [];
35
44
  let assetUIDMapper = {};
36
45
  let assetUrlMapper = {};
37
46
  let assetRefPath = {};
38
- let isAssetDownload = false;
47
+ let parent=[];
48
+ let logger;
39
49
 
40
50
  function converter(data) {
41
51
  let arr = [];
@@ -62,14 +72,10 @@ function entryCreateUpdateScript(contentType) {
62
72
  return path.split('[').reduce((o, key) => o && o[key.replace(/\]$/, '')], obj);
63
73
  }
64
74
 
65
- function updateValueByPath(obj, path, newValue, type, fileIndex) {
75
+ function updateValueByPath(obj, path, newValue) {
66
76
  path.split('[').reduce((o, key, index, arr) => {
67
77
  if (index === arr.length - 1) {
68
- if (type === 'file') {
69
- o[key.replace(/]$/, '')][fileIndex] = newValue;
70
- } else {
71
78
  o[key.replace(/]$/, '')][0].uid = newValue;
72
- }
73
79
  } else {
74
80
  return o[key.replace(/\]$/, '')];
75
81
  }
@@ -102,65 +108,93 @@ function entryCreateUpdateScript(contentType) {
102
108
  return references;
103
109
  };
104
110
 
105
- const findAssets = function (schema, entry, refPath, path) {
106
- for (const i in schema) {
107
- const currentPath = path ? path + '[' + schema[i].uid : schema[i].uid;
108
- if (schema[i].data_type === 'group' || schema[i].data_type === 'global_field') {
109
- findAssets(schema[i].schema, entry, refPath, currentPath + '[0]');
110
- } else if (schema[i].data_type === 'blocks') {
111
- for (const block in schema[i].blocks) {
112
- {
113
- if (schema[i].blocks[block].schema) {
114
- findAssets(
115
- schema[i].blocks[block].schema,
116
- entry,
117
- refPath,
118
- currentPath + '[' + block + '][' + schema[i].blocks[block].uid + ']',
119
- );
111
+ const findAssets = function (schema, entry) {
112
+ for (const i in schema) {
113
+ if (schema[i].data_type === 'group' || schema[i].data_type === 'global_field') {
114
+ parent.push(schema[i].uid);
115
+ findAssets(schema[i].schema, entry);
116
+ parent.pop();
117
+ }
118
+ if (schema[i].data_type === 'blocks') {
119
+ for (const j = 0; j < schema[i].blocks; j++) {
120
+ {
121
+ if (schema[i].blocks[j].schema) {
122
+ parent.push(schema[i].uid);
123
+ parent.push(j);
124
+ parent.push(schema[i].blocks[j].uid);
125
+ findAssets(schema[i].blocks[j].schema, entry);
126
+ parent.pop();
127
+ parent.pop();
128
+ parent.pop();
129
+ }
120
130
  }
121
131
  }
122
132
  }
123
- } else if (schema[i].data_type === 'json' && schema[i].field_metadata.rich_text_type) {
124
- findAssetIdsFromJsonRte(entry, schema, refPath, path);
125
- } else if (
126
- schema[i].data_type === 'text' &&
127
- schema[i].field_metadata &&
128
- (schema[i].field_metadata.markdown || schema[i].field_metadata.rich_text_type)
129
- ) {
130
- findFileUrls(schema[i], entry);
131
- } else if (schema[i].data_type === 'file') {
132
- refPath.push(currentPath)
133
- const imgDetails = getValueByPath(entry, currentPath);
134
- if (schema[i].multiple) {
135
- if (imgDetails && imgDetails.length) {
136
- imgDetails.forEach((img) => {
133
+ if (schema[i].data_type === 'json' && schema[i].field_metadata.rich_text_type) {
134
+ parent.push(schema[i].uid);
135
+ findAssetIdsFromJsonRte(entry, schema);
136
+ parent.pop();
137
+ }
138
+ if (
139
+ schema[i].data_type === 'text' &&
140
+ schema[i].field_metadata &&
141
+ (schema[i].field_metadata.markdown || schema[i].field_metadata.rich_text_type)
142
+ ) {
143
+ parent.push(schema[i].uid);
144
+ findFileUrls(schema[i], entry);
145
+ if (schema[i].field_metadata.rich_text_type) {
146
+ findAssetIdsFromHtmlRte(entry, schema[i]);
147
+ }
148
+ parent.pop();
149
+ }
150
+ if (schema[i].data_type === 'file') {
151
+ parent.push(schema[i].uid);
152
+ let updatedEntry = entry;
153
+ for (let i = 0; i < parent.length; i++) {
154
+ updatedEntry = updatedEntry[parent[i]];
155
+ }
156
+ const imgDetails = updatedEntry;
157
+ if (schema[i].multiple) {
158
+ if (imgDetails && imgDetails.length) {
159
+ imgDetails.forEach((img) => {
160
+ const obj = {
161
+ uid: img.uid,
162
+ parent_uid: img.parent_uid,
163
+ description: img.description,
164
+ title: img.title,
165
+ filename: img.filename,
166
+ url: img.url,
167
+ };
168
+ assetDetails.push(obj);
169
+ });
170
+ }
171
+ } else {
172
+ if (imgDetails) {
137
173
  const obj = {
138
- uid: img.uid,
139
- parent_uid: img.parent_uid,
140
- description: img.description,
141
- title: img.title,
142
- filename: img.filename,
143
- url: img.url,
174
+ uid: imgDetails.uid,
175
+ parent_uid: imgDetails.parent_uid,
176
+ description: imgDetails.description,
177
+ title: imgDetails.title,
178
+ filename: imgDetails.filename,
179
+ url: imgDetails.url,
144
180
  };
145
181
  assetDetails.push(obj);
146
- });
147
- }
148
- } else {
149
- if (imgDetails) {
150
- const obj = {
151
- uid: imgDetails.uid,
152
- parent_uid: imgDetails.parent_uid,
153
- description: imgDetails.description,
154
- title: imgDetails.title,
155
- filename: imgDetails.filename,
156
- url: imgDetails.url,
157
- };
158
- assetDetails.push(obj);
182
+ }
159
183
  }
184
+ parent.pop();
160
185
  }
161
186
  }
187
+ };
188
+
189
+ function findAssetIdsFromHtmlRte(entryObj, ctSchema) {
190
+ const regex = /<img asset_uid=\\"([^"]+)\\"/g;
191
+ let match;
192
+ const entry = JSON.stringify(entryObj);
193
+ while ((match = regex.exec(entry)) !== null) {
194
+ //insert into asset details
195
+ assetDetails.push({uid: match[1]});
196
+ }
162
197
  }
163
- };
164
198
 
165
199
  function findFileUrls(schema, _entry) {
166
200
  let markdownRegEx;
@@ -281,31 +315,8 @@ function entryCreateUpdateScript(contentType) {
281
315
  }
282
316
 
283
317
  const updateAssetDetailsInEntries = function (entry) {
284
- assetRefPath[entry.uid].forEach((refPath) => {
285
- let imgDetails = entry[refPath];
286
- if (imgDetails !== undefined) {
287
- if (imgDetails && !Array.isArray(imgDetails)) {
288
- entry[refPath] = assetUIDMapper[imgDetails.uid];
289
- } else if (imgDetails && Array.isArray(imgDetails)) {
290
- for (let i = 0; i < imgDetails.length; i++) {
291
- const img = imgDetails[i];
292
- entry[refPath][i] = assetUIDMapper[img.uid];
293
- }
294
- }
295
- } else {
296
- imgDetails = getValueByPath(entry, refPath);
297
- if (imgDetails && !Array.isArray(imgDetails)) {
298
- const imgUID = imgDetails?.uid;
299
- updateValueByPath(entry, refPath, assetUIDMapper[imgUID], 'file', 0);
300
- } else if (imgDetails && Array.isArray(imgDetails)) {
301
- for (let i = 0; i < imgDetails.length; i++) {
302
- const img = imgDetails[i];
303
- const imgUID = img?.uid;
304
- updateValueByPath(entry, refPath, assetUIDMapper[imgUID], 'file', i);
305
- }
306
- }
307
- }
308
- });
318
+ let updatedEntry = Object.assign({},entry);
319
+ entry = updateFileFields(updatedEntry, entry, null)
309
320
  entry = JSON.stringify(entry);
310
321
  const assetUrls = assetDetails.map((asset) => asset.url);
311
322
  const assetUIDs = assetDetails.map((asset) => asset.uid);
@@ -324,6 +335,65 @@ function entryCreateUpdateScript(contentType) {
324
335
  });
325
336
  return JSON.parse(entry);
326
337
  };
338
+
339
+ function updateFileFields(
340
+ object,
341
+ parent,
342
+ pos
343
+ ) {
344
+ if (isPlainObject(object) && has(object, 'filename') && has(object, 'uid')) {
345
+ if (typeof pos !== 'undefined') {
346
+ if (typeof pos === 'number' || typeof pos === 'string') {
347
+ const replacer = () => {
348
+ if (assetUIDMapper.hasOwnProperty(object.uid)) {
349
+ parent[pos] = assetUIDMapper[object.uid];
350
+ } else {
351
+ parent[pos] = '';
352
+ }
353
+ };
354
+
355
+ if (parent.uid && assetUIDMapper[parent.uid]) {
356
+ parent.uid = assetUIDMapper[parent.uid];
357
+ }
358
+
359
+ if (
360
+ object &&
361
+ isObject(parent[pos]) &&
362
+ parent[pos].uid &&
363
+ parent[pos].url &&
364
+ has(parent, 'asset') &&
365
+ has(parent, '_content_type_uid') &&
366
+ parent._content_type_uid === 'sys_assets'
367
+ ) {
368
+ if (
369
+ has(parent, 'asset') &&
370
+ has(parent, '_content_type_uid') &&
371
+ parent._content_type_uid === 'sys_assets'
372
+ ) {
373
+ parent = omit(parent, ['asset']);
374
+ }
375
+
376
+ if (object.uid && assetUIDMapper[object.uid]) {
377
+ object.uid = assetUIDMapper[object.uid];
378
+ }
379
+ if (object.url && assetUrlMapper[object.url]) {
380
+ object.url = assetUrlMapper[object.url];
381
+ }
382
+ } else {
383
+ replacer();
384
+ }
385
+ }
386
+ }
387
+ } else if (isPlainObject(object)) {
388
+ for (let key in object) updateFileFields(object[key], object, key);
389
+ } else if (isArray(object) && object.length) {
390
+ for (let i = 0; i <= object.length; i++){
391
+ updateFileFields(object[i], object, i);
392
+ }
393
+ parent[pos] = compact(object);
394
+ }
395
+ return object;
396
+ }
327
397
 
328
398
  const checkAndDownloadAsset = async function (cAsset) {
329
399
  if (cAsset) {
@@ -340,7 +410,6 @@ function entryCreateUpdateScript(contentType) {
340
410
  return false;
341
411
  }
342
412
  else {
343
- isAssetDownload = true;
344
413
  const cAssetDetail = await managementAPIClient
345
414
  .stack({ api_key: stackSDKInstance.api_key, branch_uid: compareBranch })
346
415
  .asset(assetUID)
@@ -382,8 +451,8 @@ function entryCreateUpdateScript(contentType) {
382
451
  const uploadAssets = async function () {
383
452
  const assetFolderMap = JSON.parse(fs.readFileSync(path.resolve(filePath, 'folder-mapper.json'), 'utf8'));
384
453
  const stackAPIClient = managementAPIClient.stack({ api_key: stackSDKInstance.api_key, branch_uid: branch });
385
- for (let i = 0; i < assetDetails?.length; i++) {
386
- const asset = assetDetails[i];
454
+ for (let i = 0; i < downloadedAssets?.length; i++) {
455
+ const asset = downloadedAssets[i];
387
456
  let requestOption = {};
388
457
 
389
458
  requestOption.parent_uid = assetFolderMap[asset.parent_uid] || asset.parent_uid;
@@ -419,6 +488,10 @@ function entryCreateUpdateScript(contentType) {
419
488
  successMessage: 'Entries Updated Successfully',
420
489
  failedMessage: 'Failed to update entries',
421
490
  task: async () => {
491
+ //logger file
492
+ if(!fs.existsSync(path.join(filePath, 'entry-migration'))){
493
+ logger = new LoggerService(filePath, 'entry-migration');
494
+ }
422
495
  let compareBranchEntries = await managementAPIClient
423
496
  .stack({ api_key: stackSDKInstance.api_key, branch_uid: compareBranch })
424
497
  .contentType('${contentType}')
@@ -454,9 +527,10 @@ function entryCreateUpdateScript(contentType) {
454
527
  const updatedCAsset = await checkAndDownloadAsset(asset);
455
528
  if(updatedCAsset){
456
529
  newAssetDetails[i] = updatedCAsset;
530
+ downloadedAssets.push(updatedCAsset)
457
531
  }
458
532
  }
459
- if (isAssetDownload) await uploadAssets();
533
+ if (downloadedAssets?.length) await uploadAssets();
460
534
  }
461
535
 
462
536
  let flag = {
@@ -468,7 +542,17 @@ function entryCreateUpdateScript(contentType) {
468
542
  async function updateEntry(entry, entryDetails) {
469
543
  if (entry) {
470
544
  Object.assign(entry, { ...entryDetails });
471
- await entry.update();
545
+ await entry.update().catch(err => {
546
+ let errorMsg = 'Entry update failed for uid: ' + entry?.uid + ', title: ' + entry?.title + '.';
547
+ if(err?.errors?.title){
548
+ errorMsg += err?.errors?.title;
549
+ }else if(err?.errors?.entry){
550
+ errorMsg += err?.errors?.entry;
551
+ }else{
552
+ errorMsg += (err?.entry?.errorMessage || err?.errorMessage || err?.message) ?? 'Something went wrong!';
553
+ }
554
+ logger.error(errorMsg)
555
+ });
472
556
  }
473
557
  }
474
558
 
@@ -5,6 +5,14 @@ function entryUpdateScript(contentType) {
5
5
  return `
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
+ const { marked } = require('marked');
9
+ const has = require('lodash/has');
10
+ const isArray = require('lodash/isArray');
11
+ const isObject = require('lodash/isObject');
12
+ const omit = require('lodash/omit');
13
+ const compact = require('lodash/compact')
14
+ const isPlainObject = require('lodash/isPlainObject');
15
+ const {cliux, LoggerService} = require('@contentstack/cli-utilities')
8
16
  module.exports = async ({ migration, stackSDKInstance, managementAPIClient, config, branch, apiKey }) => {
9
17
  const keysToRemove = [
10
18
  'content_type_uid',
@@ -32,10 +40,12 @@ function entryUpdateScript(contentType) {
32
40
  let assetDirPath = path.resolve(filePath, 'assets');
33
41
  let assetDetails = [];
34
42
  let newAssetDetails = [];
43
+ let downloadedAssets = [];
35
44
  let assetUIDMapper = {};
36
45
  let assetUrlMapper = {};
37
46
  let assetRefPath = {};
38
- let isAssetDownload = false;
47
+ let parent=[];
48
+ let logger;
39
49
 
40
50
  function converter(data) {
41
51
  let arr = [];
@@ -62,14 +72,10 @@ function entryUpdateScript(contentType) {
62
72
  return path.split('[').reduce((o, key) => o && o[key.replace(/\]$/, '')], obj);
63
73
  }
64
74
 
65
- function updateValueByPath(obj, path, newValue, type, fileIndex) {
75
+ function updateValueByPath(obj, path, newValue) {
66
76
  path.split('[').reduce((o, key, index, arr) => {
67
77
  if (index === arr.length - 1) {
68
- if (type === 'file') {
69
- o[key.replace(/]$/, '')][fileIndex] = newValue;
70
- } else {
71
78
  o[key.replace(/]$/, '')][0].uid = newValue;
72
- }
73
79
  } else {
74
80
  return o[key.replace(/\]$/, '')];
75
81
  }
@@ -102,35 +108,52 @@ function entryUpdateScript(contentType) {
102
108
  return references;
103
109
  };
104
110
 
105
- const findAssets = function (schema, entry, refPath, path) {
111
+ const findAssets = function (schema, entry) {
106
112
  for (const i in schema) {
107
- const currentPath = path ? path + '[' + schema[i].uid : schema[i].uid;
108
113
  if (schema[i].data_type === 'group' || schema[i].data_type === 'global_field') {
109
- findAssets(schema[i].schema, entry, refPath, currentPath + '[0]');
110
- } else if (schema[i].data_type === 'blocks') {
111
- for (const block in schema[i].blocks) {
114
+ parent.push(schema[i].uid);
115
+ findAssets(schema[i].schema, entry);
116
+ parent.pop();
117
+ }
118
+ if (schema[i].data_type === 'blocks') {
119
+ for (const j = 0; j < schema[i].blocks; j++) {
112
120
  {
113
- if (schema[i].blocks[block].schema) {
114
- findAssets(
115
- schema[i].blocks[block].schema,
116
- entry,
117
- refPath,
118
- currentPath + '[' + block + '][' + schema[i].blocks[block].uid + ']',
119
- );
121
+ if (schema[i].blocks[j].schema) {
122
+ parent.push(schema[i].uid);
123
+ parent.push(j);
124
+ parent.push(schema[i].blocks[j].uid);
125
+ findAssets(schema[i].blocks[j].schema, entry);
126
+ parent.pop();
127
+ parent.pop();
128
+ parent.pop();
120
129
  }
121
130
  }
122
131
  }
123
- } else if (schema[i].data_type === 'json' && schema[i].field_metadata.rich_text_type) {
124
- findAssetIdsFromJsonRte(entry, schema, refPath, path);
125
- } else if (
132
+ }
133
+ if (schema[i].data_type === 'json' && schema[i].field_metadata.rich_text_type) {
134
+ parent.push(schema[i].uid);
135
+ findAssetIdsFromJsonRte(entry, schema);
136
+ parent.pop();
137
+ }
138
+ if (
126
139
  schema[i].data_type === 'text' &&
127
140
  schema[i].field_metadata &&
128
141
  (schema[i].field_metadata.markdown || schema[i].field_metadata.rich_text_type)
129
142
  ) {
143
+ parent.push(schema[i].uid);
130
144
  findFileUrls(schema[i], entry);
131
- } else if (schema[i].data_type === 'file') {
132
- refPath.push(currentPath)
133
- const imgDetails = getValueByPath(entry, currentPath);
145
+ if (schema[i].field_metadata.rich_text_type) {
146
+ findAssetIdsFromHtmlRte(entry, schema[i]);
147
+ }
148
+ parent.pop();
149
+ }
150
+ if (schema[i].data_type === 'file') {
151
+ parent.push(schema[i].uid);
152
+ let updatedEntry = entry;
153
+ for (let i = 0; i < parent.length; i++) {
154
+ updatedEntry = updatedEntry[parent[i]];
155
+ }
156
+ const imgDetails = updatedEntry;
134
157
  if (schema[i].multiple) {
135
158
  if (imgDetails && imgDetails.length) {
136
159
  imgDetails.forEach((img) => {
@@ -158,10 +181,21 @@ function entryUpdateScript(contentType) {
158
181
  assetDetails.push(obj);
159
182
  }
160
183
  }
184
+ parent.pop();
161
185
  }
162
186
  }
163
187
  };
164
188
 
189
+ function findAssetIdsFromHtmlRte(entryObj, ctSchema) {
190
+ const regex = /<img asset_uid=\\"([^"]+)\\"/g;
191
+ let match;
192
+ const entry = JSON.stringify(entryObj);
193
+ while ((match = regex.exec(entry)) !== null) {
194
+ //insert into asset details
195
+ assetDetails.push({uid: match[1]});
196
+ }
197
+ }
198
+
165
199
  function findFileUrls(schema, _entry) {
166
200
  let markdownRegEx;
167
201
  let markdownMatch;
@@ -281,31 +315,8 @@ function entryUpdateScript(contentType) {
281
315
  }
282
316
 
283
317
  const updateAssetDetailsInEntries = function (entry) {
284
- assetRefPath[entry.uid].forEach((refPath) => {
285
- let imgDetails = entry[refPath];
286
- if (imgDetails !== undefined) {
287
- if (imgDetails && !Array.isArray(imgDetails)) {
288
- entry[refPath] = assetUIDMapper[imgDetails.uid];
289
- } else if (imgDetails && Array.isArray(imgDetails)) {
290
- for (let i = 0; i < imgDetails.length; i++) {
291
- const img = imgDetails[i];
292
- entry[refPath][i] = assetUIDMapper[img.uid];
293
- }
294
- }
295
- } else {
296
- imgDetails = getValueByPath(entry, refPath);
297
- if (imgDetails && !Array.isArray(imgDetails)) {
298
- const imgUID = imgDetails?.uid;
299
- updateValueByPath(entry, refPath, assetUIDMapper[imgUID], 'file', 0);
300
- } else if (imgDetails && Array.isArray(imgDetails)) {
301
- for (let i = 0; i < imgDetails.length; i++) {
302
- const img = imgDetails[i];
303
- const imgUID = img?.uid;
304
- updateValueByPath(entry, refPath, assetUIDMapper[imgUID], 'file', i);
305
- }
306
- }
307
- }
308
- });
318
+ let updatedEntry = Object.assign({},entry);
319
+ entry = updateFileFields(updatedEntry, entry, null)
309
320
  entry = JSON.stringify(entry);
310
321
  const assetUrls = assetDetails.map((asset) => asset.url);
311
322
  const assetUIDs = assetDetails.map((asset) => asset.uid);
@@ -324,6 +335,65 @@ function entryUpdateScript(contentType) {
324
335
  });
325
336
  return JSON.parse(entry);
326
337
  };
338
+
339
+ function updateFileFields(
340
+ object,
341
+ parent,
342
+ pos
343
+ ) {
344
+ if (isPlainObject(object) && has(object, 'filename') && has(object, 'uid')) {
345
+ if (typeof pos !== 'undefined') {
346
+ if (typeof pos === 'number' || typeof pos === 'string') {
347
+ const replacer = () => {
348
+ if (assetUIDMapper.hasOwnProperty(object.uid)) {
349
+ parent[pos] = assetUIDMapper[object.uid];
350
+ } else {
351
+ parent[pos] = '';
352
+ }
353
+ };
354
+
355
+ if (parent.uid && assetUIDMapper[parent.uid]) {
356
+ parent.uid = assetUIDMapper[parent.uid];
357
+ }
358
+
359
+ if (
360
+ object &&
361
+ isObject(parent[pos]) &&
362
+ parent[pos].uid &&
363
+ parent[pos].url &&
364
+ has(parent, 'asset') &&
365
+ has(parent, '_content_type_uid') &&
366
+ parent._content_type_uid === 'sys_assets'
367
+ ) {
368
+ if (
369
+ has(parent, 'asset') &&
370
+ has(parent, '_content_type_uid') &&
371
+ parent._content_type_uid === 'sys_assets'
372
+ ) {
373
+ parent = omit(parent, ['asset']);
374
+ }
375
+
376
+ if (object.uid && assetUIDMapper[object.uid]) {
377
+ object.uid = assetUIDMapper[object.uid];
378
+ }
379
+ if (object.url && assetUrlMapper[object.url]) {
380
+ object.url = assetUrlMapper[object.url];
381
+ }
382
+ } else {
383
+ replacer();
384
+ }
385
+ }
386
+ }
387
+ } else if (isPlainObject(object)) {
388
+ for (let key in object) updateFileFields(object[key], object, key);
389
+ } else if (isArray(object) && object.length) {
390
+ for (let i = 0; i <= object.length; i++){
391
+ updateFileFields(object[i], object, i);
392
+ }
393
+ parent[pos] = compact(object);
394
+ }
395
+ return object;
396
+ }
327
397
 
328
398
  const checkAndDownloadAsset = async function (cAsset) {
329
399
  if (cAsset) {
@@ -340,7 +410,6 @@ function entryUpdateScript(contentType) {
340
410
  return false;
341
411
  }
342
412
  else {
343
- isAssetDownload = true;
344
413
  const cAssetDetail = await managementAPIClient
345
414
  .stack({ api_key: stackSDKInstance.api_key, branch_uid: compareBranch })
346
415
  .asset(assetUID)
@@ -382,8 +451,8 @@ function entryUpdateScript(contentType) {
382
451
  const uploadAssets = async function () {
383
452
  const assetFolderMap = JSON.parse(fs.readFileSync(path.resolve(filePath, 'folder-mapper.json'), 'utf8'));
384
453
  const stackAPIClient = managementAPIClient.stack({ api_key: stackSDKInstance.api_key, branch_uid: branch });
385
- for (let i = 0; i < assetDetails?.length; i++) {
386
- const asset = assetDetails[i];
454
+ for (let i = 0; i < downloadedAssets?.length; i++) {
455
+ const asset = downloadedAssets[i];
387
456
  let requestOption = {};
388
457
 
389
458
  requestOption.parent_uid = assetFolderMap[asset.parent_uid] || asset.parent_uid;
@@ -418,6 +487,11 @@ function entryUpdateScript(contentType) {
418
487
  successMessage: 'Entries Updated Successfully',
419
488
  failedMessage: 'Failed to update entries',
420
489
  task: async () => {
490
+ //logger file
491
+ if(!fs.existsSync(path.join(filePath, 'entry-migration'))){
492
+ logger = new LoggerService(filePath, 'entry-migration');
493
+ }
494
+
421
495
  let compareBranchEntries = await managementAPIClient
422
496
  .stack({ api_key: stackSDKInstance.api_key, branch_uid: compareBranch })
423
497
  .contentType('${contentType}')
@@ -453,9 +527,10 @@ function entryUpdateScript(contentType) {
453
527
  const updatedCAsset = await checkAndDownloadAsset(asset);
454
528
  if(updatedCAsset){
455
529
  newAssetDetails[i] = updatedCAsset;
530
+ downloadedAssets.push(updatedCAsset);
456
531
  }
457
532
  }
458
- if (isAssetDownload) await uploadAssets();
533
+ if (downloadedAssets?.length) await uploadAssets();
459
534
  }
460
535
 
461
536
  let flag = {
@@ -466,7 +541,17 @@ function entryUpdateScript(contentType) {
466
541
 
467
542
  async function updateEntry(entry, entryDetails) {
468
543
  Object.assign(entry, { ...entryDetails });
469
- await entry.update();
544
+ await entry.update().catch(err => {
545
+ let errorMsg = 'Entry update failed for uid: ' + entry?.uid + ', title: ' + entry?.title + '.';
546
+ if(err?.errors?.title){
547
+ errorMsg += err?.errors?.title;
548
+ }else if(err?.errors?.entry){
549
+ errorMsg += err?.errors?.entry;
550
+ }else{
551
+ errorMsg += (err?.entry?.errorMessage || err?.errorMessage || err?.message) ?? 'Something went wrong!';
552
+ }
553
+ logger.error(errorMsg)
554
+ });
470
555
  }
471
556
 
472
557
  async function updateReferences(entryDetails, baseEntry, references) {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.19",
2
+ "version": "1.0.21",
3
3
  "commands": {
4
4
  "cm:branches:create": {
5
5
  "id": "cm:branches:create",
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-branches",
3
3
  "description": "Contentstack CLI plugin to do branches operations",
4
- "version": "1.0.19",
4
+ "version": "1.0.21",
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.8",
9
+ "@contentstack/cli-utilities": "~1.5.10",
10
10
  "@oclif/core": "^2.9.3",
11
11
  "async": "^3.2.4",
12
12
  "big-json": "^3.2.0",
@@ -95,4 +95,4 @@
95
95
  }
96
96
  },
97
97
  "repository": "https://github.com/contentstack/cli"
98
- }
98
+ }