@contentstack/cli-cm-import 1.0.1 → 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.
@@ -10,16 +10,18 @@ const _ = require('lodash');
10
10
  const mkdirp = require('mkdirp');
11
11
  const chalk = require('chalk');
12
12
 
13
+ const util = require('../util');
13
14
  const helper = require('../util/fs');
14
15
  const { addlogs } = require('../util/log');
15
- const lookupReplaceAssets = require('../util/lookupReplaceAssets');
16
- const lookupReplaceEntries = require('../util/lookupReplaceEntries');
17
16
  const suppress = require('../util/supress-mandatory-fields');
18
- const extension_suppress = require('../util/extensionsUidReplace');
19
- const util = require('../util');
20
- let config = util.getConfig();
21
17
  const stack = require('../util/contentstack-management-sdk');
18
+ const extension_suppress = require('../util/extensionsUidReplace');
19
+ const lookupReplaceAssets = require('../util/lookupReplaceAssets');
20
+ const lookupReplaceEntries = require('../util/lookupReplaceEntries');
21
+ const { getInstalledExtensions } = require('../util/marketplace-app-helper');
22
+
22
23
  let client;
24
+ let config = util.getConfig();
23
25
 
24
26
  let reqConcurrency = config.concurrency;
25
27
  let eConfig = config.modules.entries;
@@ -40,8 +42,10 @@ let masterLanguage;
40
42
 
41
43
  let skipFiles = ['__master.json', '__priority.json', 'schema.json'];
42
44
  let entryBatchLimit = config.rateLimit || 10;
45
+ const importConcurrency = eConfig.importConcurrency || config.importConcurrency;
46
+ const writeConcurrency = eConfig.writeConcurrency || config.writeConcurrency;
43
47
 
44
- function importEntries() {
48
+ function EntriesImport() {
45
49
  let self = this;
46
50
  mappedAssetUidPath = path.resolve(config.data, 'mapper', 'assets', 'uid-mapping.json');
47
51
  mappedAssetUrlPath = path.resolve(config.data, 'mapper', 'assets', 'url-mapping.json');
@@ -56,6 +60,7 @@ function importEntries() {
56
60
 
57
61
  createdEntriesWOUidPath = path.join(entryMapperPath, 'created-entries-wo-uid.json');
58
62
  failedWOPath = path.join(entryMapperPath, 'failedWO.json');
63
+
59
64
  // Object of Schemas, referred to by their content type uid
60
65
  this.ctSchemas = {};
61
66
  // Array of content type uids, that have reference fields
@@ -76,9 +81,11 @@ function importEntries() {
76
81
  this.success = [];
77
82
  // Entries that failed to get created OR updated
78
83
  this.fails = [];
84
+ // List of installed extensions to replace uid
85
+ this.installedExtensions = [];
79
86
 
80
87
  let files = fs.readdirSync(ctPath);
81
- this.environment = helper.readFile(environmentPath);
88
+ this.environment = helper.readFileSync(environmentPath);
82
89
  for (let index in files) {
83
90
  if (index) {
84
91
  try {
@@ -89,14 +96,14 @@ function importEntries() {
89
96
  }
90
97
  }
91
98
  } catch (error) {
92
- console.error(error);
99
+ addlogs(config, `Failed to read the content types to import entries ${util.formatError(error)}`);
93
100
  process.exit(0);
94
101
  }
95
102
  }
96
103
  }
97
104
  }
98
105
 
99
- importEntries.prototype = {
106
+ EntriesImport.prototype = {
100
107
  /**
101
108
  * Start point for entry import
102
109
  * @return promise
@@ -107,7 +114,17 @@ importEntries.prototype = {
107
114
  client = stack.Client(config);
108
115
  masterLanguage = config.master_locale;
109
116
  addlogs(config, 'Migrating entries', 'success');
110
- let languages = helper.readFile(lPath);
117
+ let languages = helper.readFileSync(lPath);
118
+ const appMapperFolderPath = path.join(config.data, 'mapper', 'marketplace_apps');
119
+
120
+ if (fs.existsSync(path.join(appMapperFolderPath, 'marketplace-apps.json'))) {
121
+ self.installedExtensions = helper.readFileSync(path.join(appMapperFolderPath, 'marketplace-apps.json')) || {};
122
+ }
123
+
124
+ if (_.isEmpty(self.installedExtensions)) {
125
+ self.installedExtensions = await getInstalledExtensions(config);
126
+ }
127
+
111
128
  return new Promise(function (resolve, reject) {
112
129
  let langs = [masterLanguage.code];
113
130
  for (let i in languages) {
@@ -123,8 +140,10 @@ importEntries.prototype = {
123
140
  return self
124
141
  .supressFields()
125
142
  .then(async function () {
126
- let mappedAssetUids = helper.readFile(mappedAssetUidPath) || {};
127
- let mappedAssetUrls = helper.readFile(mappedAssetUrlPath) || {};
143
+ addlogs(config, 'Completed suppressing content type reference fields', 'success');
144
+
145
+ let mappedAssetUids = helper.readFileSync(mappedAssetUidPath) || {};
146
+ let mappedAssetUrls = helper.readFileSync(mappedAssetUrlPath) || {};
128
147
 
129
148
  // Step 2: Iterate over available languages to create entries in each.
130
149
  let counter = 0;
@@ -136,8 +155,18 @@ importEntries.prototype = {
136
155
  (config.hasOwnProperty('onlylocales') && config.onlylocales.indexOf(lang) !== -1) ||
137
156
  !config.hasOwnProperty('onlylocales')
138
157
  ) {
158
+ addlogs(config, `Starting to create entries ${lang} locale`, 'info');
139
159
  await self.createEntries(lang, mappedAssetUids, mappedAssetUrls);
140
- await self.getCreatedEntriesWOUid();
160
+ addlogs(config, 'Entries created successfully', 'info');
161
+ try {
162
+ await self.getCreatedEntriesWOUid();
163
+ } catch (error) {
164
+ addlogs(
165
+ config,
166
+ `Failed get the existing entries to update the mapper ${util.formatError(error)}, 'error`,
167
+ );
168
+ }
169
+ addlogs(config, 'Starting to update entries with references', 'info');
141
170
  await self.repostEntries(lang);
142
171
  addlogs(config, "Successfully imported '" + lang + "' entries!", 'success');
143
172
  counter++;
@@ -151,51 +180,62 @@ importEntries.prototype = {
151
180
  },
152
181
  ).then(async function () {
153
182
  // Step 3: Revert all the changes done in content type in step 1
183
+ addlogs(config, 'Restoring content type changes', 'info');
154
184
  await self.unSuppressFields();
185
+ addlogs(config, 'Removing entries from master language which got created by default', 'info');
155
186
  await self.removeBuggedEntries();
156
- let ct_field_visibility_uid = helper.readFile(path.join(ctPath + '/field_rules_uid.json'));
187
+ addlogs(config, 'Updating the field rules of content type', 'info');
188
+ let ct_field_visibility_uid = helper.readFileSync(path.join(ctPath + '/field_rules_uid.json'));
157
189
  let ct_files = fs.readdirSync(ctPath);
158
190
  if (ct_field_visibility_uid && ct_field_visibility_uid != 'undefined') {
159
191
  for (const element of ct_field_visibility_uid) {
160
192
  if (ct_files.indexOf(element + '.json') > -1) {
161
193
  let schema = require(path.resolve(ctPath, element));
162
- await self.field_rules_update(schema);
194
+ try {
195
+ await self.field_rules_update(schema);
196
+ } catch (error) {
197
+ addlogs(
198
+ config,
199
+ `Failed to update the field rules for content type ${schema.uid} ${util.formatError(error)}`,
200
+ );
201
+ }
163
202
  }
164
203
  }
165
204
  }
166
205
  addlogs(config, chalk.green('Entries have been imported successfully!'), 'success');
167
206
  if (config.entriesPublish) {
207
+ addlogs(config, chalk.green('Publishing entries'), 'success');
168
208
  return self
169
209
  .publish(langs)
170
210
  .then(function () {
171
211
  addlogs(config, chalk.green('All the entries have been published successfully'), 'success');
172
212
  return resolve();
173
213
  })
174
- .catch((errors) => {
175
- addlogs(config, chalk.error('Some entries might have failed to publish.'), 'error');
176
- return reject(errors);
214
+ .catch((error) => {
215
+ addlogs(config, `Error in publishing entries ${util.formatError(error)}`, 'error');
177
216
  });
178
217
  }
179
218
  return resolve();
180
219
  });
181
220
  })
182
221
  .catch(function (error) {
183
- return reject(error);
222
+ addlogs.log(config, util.formatError(error), 'error');
223
+ reject('Failed import entries');
184
224
  });
185
225
  });
186
226
  },
187
227
 
188
228
  createEntries: function (lang, mappedAssetUids, mappedAssetUrls) {
189
229
  let self = this;
190
- return new Promise(function (resolve, reject) {
230
+ return new Promise(async function (resolve, reject) {
191
231
  let contentTypeUids = Object.keys(self.ctSchemas);
192
232
  if (fs.existsSync(entryUidMapperPath)) {
193
- self.mappedUids = helper.readFile(entryUidMapperPath);
233
+ self.mappedUids = await helper.readLargeFile(entryUidMapperPath);
194
234
  }
195
235
  self.mappedUids = self.mappedUids || {};
196
236
  return Promise.map(
197
237
  contentTypeUids,
198
- function (ctUid) {
238
+ async function (ctUid) {
199
239
  let eLangFolderPath = path.join(entryMapperPath, lang);
200
240
  let eLogFolderPath = path.join(entryMapperPath, lang, ctUid);
201
241
  mkdirp.sync(eLogFolderPath);
@@ -213,11 +253,11 @@ importEntries.prototype = {
213
253
  });
214
254
 
215
255
  if (fs.existsSync(createdEntriesPath)) {
216
- createdEntries = helper.readFile(createdEntriesPath);
256
+ createdEntries = await helper.readLargeFile(createdEntriesPath);
217
257
  createdEntries = createdEntries || {};
218
258
  }
219
259
  if (fs.existsSync(eFilePath)) {
220
- let entries = helper.readFile(eFilePath);
260
+ let entries = await helper.readLargeFile(eFilePath);
221
261
  if (!_.isPlainObject(entries) || _.isEmpty(entries)) {
222
262
  addlogs(
223
263
  config,
@@ -228,42 +268,51 @@ importEntries.prototype = {
228
268
  addlogs(config, `Creating entries for content type ${ctUid} in language ${lang} ...`, 'success');
229
269
  for (let eUid in entries) {
230
270
  if (eUid) {
231
- // check ctUid in self.ctJsonRte array, if ct exists there... only then remove entry references for json rte
232
- // also with json rte, api creates the json-rte field with the same uid as passed in the payload.
271
+ try {
272
+ // check ctUid in self.ctJsonRte array, if ct exists there... only then remove entry references for json rte
273
+ // also with json rte, api creates the json-rte field with the same uid as passed in the payload.
233
274
 
234
- if (self.ctJsonRte.indexOf(ctUid) > -1) {
235
- entries[eUid] = self.removeUidsFromJsonRteFields(entries[eUid], self.ctSchemas[ctUid].schema);
236
- }
275
+ if (self.ctJsonRte.indexOf(ctUid) > -1) {
276
+ entries[eUid] = self.removeUidsFromJsonRteFields(entries[eUid], self.ctSchemas[ctUid].schema);
277
+ }
237
278
 
238
- // remove entry references from json-rte fields
239
- if (self.ctJsonRteWithEntryRefs.indexOf(ctUid) > -1) {
240
- entries[eUid] = self.removeEntryRefsFromJSONRTE(entries[eUid], self.ctSchemas[ctUid].schema);
279
+ // remove entry references from json-rte fields
280
+ if (self.ctJsonRteWithEntryRefs.indexOf(ctUid) > -1) {
281
+ entries[eUid] = self.removeEntryRefsFromJSONRTE(entries[eUid], self.ctSchemas[ctUid].schema);
282
+ }
283
+ // will replace all old asset uid/urls with new ones
284
+ entries[eUid] = lookupReplaceAssets(
285
+ {
286
+ content_type: self.ctSchemas[ctUid],
287
+ entry: entries[eUid],
288
+ },
289
+ mappedAssetUids,
290
+ mappedAssetUrls,
291
+ eLangFolderPath,
292
+ self.installedExtensions,
293
+ );
294
+ } catch (error) {
295
+ addlogs(config, 'Failed to update entry while creating entry id ' + eUid);
296
+ addlogs(config, util.formatError(error), 'error');
241
297
  }
242
- // will replace all old asset uid/urls with new ones
243
- entries[eUid] = lookupReplaceAssets(
244
- {
245
- content_type: self.ctSchemas[ctUid],
246
- entry: entries[eUid],
247
- },
248
- mappedAssetUids,
249
- mappedAssetUrls,
250
- eLangFolderPath,
251
- );
252
298
  }
253
299
  }
254
300
  let eUids = Object.keys(entries);
255
301
  let batches = [];
256
302
 
303
+ let entryBatchLimit = eConfig.batchLimit || 10;
304
+ let batchSize = Math.round(entryBatchLimit / 3);
305
+
257
306
  // Run entry creation in batches of ~16~ entries
258
- for (let i = 0; i < eUids.length; i += Math.round(entryBatchLimit / 3)) {
259
- batches.push(eUids.slice(i, i + Math.round(entryBatchLimit / 3)));
307
+ for (let i = 0; i < eUids.length; i += batchSize) {
308
+ batches.push(eUids.slice(i, i + batchSize));
260
309
  }
261
310
  return Promise.map(
262
311
  batches,
263
312
  async function (batch) {
264
313
  return Promise.map(
265
314
  batch,
266
- async function (eUid) {
315
+ async function (eUid, batchIndex) {
267
316
  // if entry is already created
268
317
  if (createdEntries.hasOwnProperty(eUid)) {
269
318
  addlogs(
@@ -322,16 +371,15 @@ importEntries.prototype = {
322
371
  }
323
372
  }
324
373
  })
325
- .catch(function (err) {
326
- let error = JSON.parse(err.message);
327
- addlogs(config, chalk.red('Error updating entry', JSON.stringify(error)), 'error');
374
+ .catch(function (error) {
375
+ addlogs(config, `Failed to update an entry ${eUid} ${util.formatError(error)}`, 'error');
328
376
  self.fails.push({
329
377
  content_type: ctUid,
330
378
  locale: lang,
331
379
  entry: entries[eUid],
332
- error: error,
380
+ error: util.formatError(error),
333
381
  });
334
- return err;
382
+ return error;
335
383
  });
336
384
  }
337
385
  delete requestObject.json.entry.publish_details;
@@ -367,11 +415,7 @@ importEntries.prototype = {
367
415
  'error',
368
416
  );
369
417
  } else {
370
- addlogs(
371
- config,
372
- chalk.red('Error creating entry due to: ' + JSON.stringify(error)),
373
- 'error',
374
- );
418
+ addlogs(config, `Failed to create an entry ${eUid} ${util.formatError(error)}`, 'error');
375
419
  }
376
420
  self.createdEntriesWOUid.push({
377
421
  content_type: ctUid,
@@ -379,12 +423,12 @@ importEntries.prototype = {
379
423
  entry: entries[eUid],
380
424
  error: error,
381
425
  });
382
- helper.writeFile(createdEntriesWOUidPath, self.createdEntriesWOUid);
426
+ helper.writeFileSync(createdEntriesWOUidPath, self.createdEntriesWOUid);
383
427
  return;
384
428
  }
385
429
  // TODO: if status code: 422, check the reason
386
430
  // 429 for rate limit
387
- addlogs(config, chalk.red('Error creating entry', JSON.stringify(error)), 'error');
431
+ addlogs(config, `Failed to create an entry ${eUid} ${util.formatError(error)}`, 'error');
388
432
  self.fails.push({
389
433
  content_type: ctUid,
390
434
  locale: lang,
@@ -395,14 +439,14 @@ importEntries.prototype = {
395
439
  // create/update 5 entries at a time
396
440
  },
397
441
  {
398
- concurrency: 1,
442
+ concurrency: importConcurrency,
399
443
  },
400
444
  ).then(function () {
401
- helper.writeFile(successEntryLogPath, self.success[ctUid]);
402
- helper.writeFile(failedEntryLogPath, self.fails[ctUid]);
403
- helper.writeFile(entryUidMapperPath, self.mappedUids);
404
- helper.writeFile(uniqueUidMapperPath, self.uniqueUids);
405
- helper.writeFile(createdEntriesPath, createdEntries);
445
+ helper.writeFileSync(successEntryLogPath, self.success[ctUid]);
446
+ helper.writeFileSync(failedEntryLogPath, self.fails[ctUid]);
447
+ helper.writeFileSync(entryUidMapperPath, self.mappedUids);
448
+ helper.writeFileSync(uniqueUidMapperPath, self.uniqueUids);
449
+ helper.writeFileSync(createdEntriesPath, createdEntries);
406
450
  });
407
451
  // process one batch at a time
408
452
  },
@@ -451,7 +495,7 @@ importEntries.prototype = {
451
495
  }
452
496
  },
453
497
  {
454
- concurrency: reqConcurrency,
498
+ concurrency: 1,
455
499
  },
456
500
  )
457
501
  .then(function () {
@@ -467,7 +511,7 @@ importEntries.prototype = {
467
511
  getCreatedEntriesWOUid: function () {
468
512
  let self = this;
469
513
  return new Promise(function (resolve) {
470
- self.createdEntriesWOUid = helper.readFile(createdEntriesWOUidPath);
514
+ self.createdEntriesWOUid = helper.readFileSync(createdEntriesWOUidPath);
471
515
  self.failedWO = [];
472
516
  if (_.isArray(self.createdEntriesWOUid) && self.createdEntriesWOUid.length > 0) {
473
517
  return Promise.map(
@@ -476,10 +520,10 @@ importEntries.prototype = {
476
520
  return self.fetchEntry(entry);
477
521
  },
478
522
  {
479
- concurrency: reqConcurrency,
523
+ concurrency: importConcurrency,
480
524
  },
481
525
  ).then(function () {
482
- helper.writeFile(failedWOPath, self.failedWO);
526
+ helper.writeFileSync(failedWOPath, self.failedWO);
483
527
  addlogs(config, 'Mapped entries without mapped uid successfully!', 'success');
484
528
  return resolve();
485
529
  });
@@ -490,25 +534,25 @@ importEntries.prototype = {
490
534
  },
491
535
  repostEntries: function (lang) {
492
536
  let self = this;
493
- return new Promise(function (resolve, reject) {
494
- let _mapped_ = helper.readFile(path.join(entryMapperPath, 'uid-mapping.json'));
537
+ return new Promise(async function (resolve, reject) {
538
+ let _mapped_ = await helper.readLargeFile(path.join(entryMapperPath, 'uid-mapping.json'));
495
539
  if (_.isPlainObject(_mapped_)) {
496
540
  self.mappedUids = _.merge(_mapped_, self.mappedUids);
497
541
  }
498
542
  return Promise.map(
499
543
  self.refSchemas,
500
- function (ctUid) {
544
+ async function (ctUid) {
501
545
  let eFolderPath = path.join(entryMapperPath, lang, ctUid);
502
546
  let eSuccessFilePath = path.join(eFolderPath, 'success.json');
503
547
  let eFilePath = path.resolve(ePath, ctUid, lang + '.json');
504
- let sourceStackEntries = helper.readFile(eFilePath);
548
+ let sourceStackEntries = await helper.readLargeFile(eFilePath);
505
549
 
506
550
  if (!fs.existsSync(eSuccessFilePath)) {
507
551
  addlogs(config, 'Success file was not found at: ' + eSuccessFilePath, 'success');
508
552
  return;
509
553
  }
510
554
 
511
- let entries = helper.readFile(eSuccessFilePath);
555
+ let entries = await helper.readLargeFile(eSuccessFilePath, { type: 'array' }); // TBD LARGE
512
556
  entries = entries || [];
513
557
  if (entries.length === 0) {
514
558
  addlogs(config, "No entries were created to be updated in '" + lang + "' language!", 'success');
@@ -516,8 +560,8 @@ importEntries.prototype = {
516
560
  }
517
561
 
518
562
  // Keep track of entries that have their references updated
519
- let refsUpdatedUids = helper.readFile(path.join(eFolderPath, 'refsUpdatedUids.json'));
520
- let refsUpdateFailed = helper.readFile(path.join(eFolderPath, 'refsUpdateFailed.json'));
563
+ let refsUpdatedUids = helper.readFileSync(path.join(eFolderPath, 'refsUpdatedUids.json'));
564
+ let refsUpdateFailed = helper.readFileSync(path.join(eFolderPath, 'refsUpdateFailed.json'));
521
565
  let schema = self.ctSchemas[ctUid];
522
566
 
523
567
  let batches = [];
@@ -528,6 +572,8 @@ importEntries.prototype = {
528
572
  // map failed reference uids @mapper/language/unmapped-uids.json
529
573
  let refUidMapperPath = path.join(entryMapperPath, lang);
530
574
 
575
+ addlogs(config, 'staring to update the entry for reposting');
576
+
531
577
  entries = _.map(entries, function (entry) {
532
578
  try {
533
579
  let uid = entry.uid;
@@ -553,14 +599,20 @@ importEntries.prototype = {
553
599
  _entry.uid = uid;
554
600
  return _entry;
555
601
  } catch (error) {
556
- console.error(error);
557
- return error;
602
+ addlogs(
603
+ config,
604
+ `Failed to update the entry ${uid} references while reposting ${util.formatError(error)}`,
605
+ );
558
606
  }
559
607
  });
560
608
 
561
- // Run entry creation in batches of ~16~ entries
562
- for (let i = 0; i < entries.length; i += Math.round(entryBatchLimit / 3)) {
563
- batches.push(entries.slice(i, i + Math.round(entryBatchLimit / 3)));
609
+ addlogs(config, 'Starting the reposting process for entries');
610
+
611
+ const entryBatchLimit = eConfig.batchLimit || 10;
612
+ const batchSize = Math.round(entryBatchLimit / 3);
613
+ // Run entry creation in batches
614
+ for (let i = 0; i < entries.length; i += batchSize) {
615
+ batches.push(entries.slice(i, i + batchSize));
564
616
  }
565
617
  return Promise.map(
566
618
  batches,
@@ -594,12 +646,12 @@ importEntries.prototype = {
594
646
  return entryResponse
595
647
  .update({ locale: lang })
596
648
  .then((response) => {
597
- for (let j = 0; j < entries.length; j++) {
598
- if (entries[j].uid === response.uid) {
599
- entries[j] = response;
600
- break;
601
- }
602
- }
649
+ // for (let j = 0; j < entries.length; j++) {
650
+ // if (entries[j].uid === response.uid) {
651
+ // entries[j] = response;
652
+ // break;
653
+ // }
654
+ // }
603
655
  refsUpdatedUids.push(response.uid);
604
656
  return resolveUpdatedUids();
605
657
  })
@@ -617,7 +669,7 @@ importEntries.prototype = {
617
669
  'error',
618
670
  );
619
671
 
620
- addlogs(config, error, 'error');
672
+ addlogs(config, util.formatError(error), 'error');
621
673
  refsUpdateFailed.push({
622
674
  content_type: ctUid,
623
675
  entry: entry,
@@ -630,24 +682,25 @@ importEntries.prototype = {
630
682
  await promiseResult;
631
683
  },
632
684
  {
633
- concurrency: reqConcurrency,
685
+ concurrency: importConcurrency,
634
686
  },
635
687
  )
636
688
  .then(function () {
637
689
  // batch completed successfully
638
- helper.writeFile(path.join(eFolderPath, 'success.json'), entries);
639
- helper.writeFile(path.join(eFolderPath, 'refsUpdatedUids.json'), refsUpdatedUids);
640
- helper.writeFile(path.join(eFolderPath, 'refsUpdateFailed.json'), refsUpdateFailed);
690
+ helper.writeFileSync(path.join(eFolderPath, 'success.json'), entries);
691
+ helper.writeFileSync(path.join(eFolderPath, 'refsUpdatedUids.json'), refsUpdatedUids);
692
+ helper.writeFileSync(path.join(eFolderPath, 'refsUpdateFailed.json'), refsUpdateFailed);
641
693
  addlogs(config, 'Completed re-post entries batch no: ' + (index + 1) + ' successfully!', 'success');
642
694
  })
643
695
  .catch(function (error) {
644
696
  // error while executing entry in batch
645
697
  addlogs(config, chalk.red('Failed re-post entries at batch no: ' + (index + 1)), 'error');
646
- throw error;
698
+ addlogs(config, util.formatError(error), 'error');
699
+ // throw error;
647
700
  });
648
701
  },
649
702
  {
650
- concurrency: reqConcurrency,
703
+ concurrency: 1,
651
704
  },
652
705
  )
653
706
  .then(function () {
@@ -660,22 +713,13 @@ importEntries.prototype = {
660
713
  })
661
714
  .catch(function (error) {
662
715
  // error while updating entries with references
663
- addlogs(
664
- config,
665
- chalk.red(
666
- "Failed while importing entries of Content Type: '" +
667
- ctUid +
668
- "' in language: '" +
669
- lang +
670
- "' successfully!",
671
- ),
672
- 'error',
673
- );
674
- throw error;
716
+ addlogs(config, chalk.red(`Failed re-post entries of content type ${ctUid} locale ${lang}`, 'error'));
717
+ addlogs(config, util.formatError(error), 'error');
718
+ // throw error;
675
719
  });
676
720
  },
677
721
  {
678
- concurrency: reqConcurrency,
722
+ concurrency: 1,
679
723
  },
680
724
  )
681
725
  .then(function () {
@@ -692,9 +736,9 @@ importEntries.prototype = {
692
736
  },
693
737
  supressFields: async function () {
694
738
  // it should be spelled as suppressFields
695
- addlogs(config, chalk.white('Suppressing content type fields...'), 'success');
739
+ addlogs(config, 'Suppressing content type reference fields', 'success');
696
740
  let self = this;
697
- return new Promise(function (resolve, reject) {
741
+ return new Promise(async function (resolve, reject) {
698
742
  let modifiedSchemas = [];
699
743
  let suppressedSchemas = [];
700
744
 
@@ -750,12 +794,12 @@ importEntries.prototype = {
750
794
  }
751
795
 
752
796
  // Replace extensions with new UID
753
- extension_suppress(contentTypeSchema.schema, config.preserveStackVersion);
797
+ extension_suppress(contentTypeSchema.schema, config.preserveStackVersion, self.installedExtensions);
754
798
  }
755
799
  }
756
800
 
757
801
  // write modified schema in backup file
758
- helper.writeFile(modifiedSchemaPath, modifiedSchemas);
802
+ helper.writeFileSync(modifiedSchemaPath, modifiedSchemas);
759
803
 
760
804
  return Promise.map(
761
805
  suppressedSchemas,
@@ -770,25 +814,22 @@ importEntries.prototype = {
770
814
  // empty function
771
815
  })
772
816
  .catch(function (_error) {
773
- addlogs(
774
- config,
775
- chalk.red("Failed to modify mandatory field of '" + schema.uid + "' content type"),
776
- 'error',
777
- );
817
+ addlogs(config, util.formatError(error), 'error');
818
+ reject(`Failed suppress content type ${schema.uid} reference fields`);
778
819
  });
779
820
  // update 5 content types at a time
780
821
  },
781
822
  {
782
823
  // update reqConcurrency content types at a time
783
- concurrency: reqConcurrency,
824
+ concurrency: importConcurrency,
784
825
  },
785
826
  )
786
827
  .then(function () {
787
828
  return resolve();
788
829
  })
789
830
  .catch(function (error) {
790
- addlogs(config, chalk.red('Error while suppressing mandatory field schemas'), 'error');
791
- return reject(error);
831
+ addlogs(config, util.formatError(error), 'error');
832
+ return reject('Failed to suppress reference fields in content type');
792
833
  });
793
834
  });
794
835
  },
@@ -818,9 +859,9 @@ importEntries.prototype = {
818
859
  }
819
860
  self.mappedUids[query.entry.uid] = response.body.entries[0].uid;
820
861
  let _ePath = path.join(entryMapperPath, query.locale, query.content_type, 'success.json');
821
- let entries = helper.readFile(_ePath);
862
+ let entries = helper.readFileSync(_ePath);
822
863
  entries.push(query.entry);
823
- helper.writeFile(_ePath, entries);
864
+ helper.writeFileSync(_ePath, entries);
824
865
  addlogs(
825
866
  config,
826
867
  'Completed mapping entry wo uid: ' + query.entry.uid + ': ' + response.body.entries[0].uid,
@@ -834,8 +875,9 @@ importEntries.prototype = {
834
875
  });
835
876
  },
836
877
  unSuppressFields: function () {
837
- return new Promise(function (resolve, reject) {
838
- let modifiedSchemas = helper.readFile(modifiedSchemaPath);
878
+ let self = this;
879
+ return new Promise(async function (resolve, reject) {
880
+ let modifiedSchemas = helper.readFileSync(modifiedSchemaPath);
839
881
  let modifiedSchemasUids = [];
840
882
  let updatedExtensionUidsSchemas = [];
841
883
  for (let uid in modifiedSchemas) {
@@ -844,7 +886,8 @@ importEntries.prototype = {
844
886
  if (_contentTypeSchema.field_rules) {
845
887
  delete _contentTypeSchema.field_rules;
846
888
  }
847
- extension_suppress(_contentTypeSchema.schema, config.preserveStackVersion);
889
+
890
+ extension_suppress(_contentTypeSchema.schema, config.preserveStackVersion, self.installedExtensions);
848
891
  updatedExtensionUidsSchemas.push(_contentTypeSchema);
849
892
  }
850
893
  }
@@ -894,7 +937,7 @@ importEntries.prototype = {
894
937
  }
895
938
  }
896
939
  // re-write, in case some schemas failed to update
897
- helper.writeFile(modifiedSchemaPath, _.compact(modifiedSchemas));
940
+ helper.writeFileSync(modifiedSchemaPath, _.compact(modifiedSchemas));
898
941
  addlogs(config, 'Re-modified content type schemas to their original form!', 'success');
899
942
  return resolve();
900
943
  })
@@ -907,7 +950,7 @@ importEntries.prototype = {
907
950
  removeBuggedEntries: function () {
908
951
  let self = this;
909
952
  return new Promise(function (resolve, reject) {
910
- let entries = helper.readFile(uniqueUidMapperPath);
953
+ let entries = helper.readFileSync(uniqueUidMapperPath);
911
954
  let bugged = [];
912
955
  let removed = [];
913
956
  for (let uid in entries) {
@@ -933,12 +976,11 @@ importEntries.prototype = {
933
976
  })
934
977
  .catch(function (error) {
935
978
  addlogs(config, chalk.red('Failed to remove bugged entry from master language'), 'error');
936
- addlogs(config, error, 'error');
937
- addlogs(config, JSON.stringify(entry), 'error');
979
+ addlogs(config, util.formatError(error), 'error');
938
980
  });
939
981
  },
940
982
  {
941
- concurrency: reqConcurrency,
983
+ concurrency: importConcurrency,
942
984
  },
943
985
  )
944
986
  .then(function () {
@@ -949,15 +991,15 @@ importEntries.prototype = {
949
991
  }
950
992
  }
951
993
 
952
- helper.writeFile(path.join(entryMapperPath, 'removed-uids.json'), removed);
953
- helper.writeFile(path.join(entryMapperPath, 'pending-uids.json'), bugged);
994
+ helper.writeFileSync(path.join(entryMapperPath, 'removed-uids.json'), removed);
995
+ helper.writeFileSync(path.join(entryMapperPath, 'pending-uids.json'), bugged);
954
996
 
955
997
  addlogs(config, chalk.green('The stack has been eradicated from bugged entries!'), 'success');
956
998
  return resolve();
957
999
  })
958
1000
  .catch(function (error) {
959
1001
  // error while removing bugged entries from stack
960
- return reject(error);
1002
+ addlogs(config, util.formatError(error), 'error');
961
1003
  });
962
1004
  });
963
1005
  },
@@ -974,7 +1016,7 @@ importEntries.prototype = {
974
1016
  let updatedValue = [];
975
1017
  for (const element of fieldRulesArray) {
976
1018
  let splitedFieldRulesValue = element;
977
- let oldUid = helper.readFile(path.join(entryUidMapperPath));
1019
+ let oldUid = helper.readFileSync(path.join(entryUidMapperPath));
978
1020
  if (oldUid.hasOwnProperty(splitedFieldRulesValue)) {
979
1021
  updatedValue.push(oldUid[splitedFieldRulesValue]);
980
1022
  } else {
@@ -986,7 +1028,7 @@ importEntries.prototype = {
986
1028
  }
987
1029
  }
988
1030
  } else {
989
- addlogs(config, 'field_rules is not available...', 'error');
1031
+ addlogs(config, 'field_rules is not available', 'error');
990
1032
  }
991
1033
 
992
1034
  client
@@ -996,13 +1038,13 @@ importEntries.prototype = {
996
1038
  .then((contentTypeResponse) => {
997
1039
  // Object.assign(ctObj, _.cloneDeep(schema))
998
1040
  contentTypeResponse.field_rules = schema.field_rules;
999
- contentTypeResponse.update();
1041
+ return contentTypeResponse.update();
1000
1042
  })
1001
1043
  .then(() => {
1002
1044
  return resolve();
1003
1045
  })
1004
1046
  .catch(function (error) {
1005
- return reject(error);
1047
+ addlogs(config, `failed to update the field rules ${util.formatError(error)}`);
1006
1048
  });
1007
1049
  });
1008
1050
  },
@@ -1013,7 +1055,7 @@ importEntries.prototype = {
1013
1055
  };
1014
1056
 
1015
1057
  let contentTypeUids = Object.keys(self.ctSchemas);
1016
- let entryMapper = helper.readFile(entryUidMapperPath);
1058
+ let entryMapper = helper.readFileSync(entryUidMapperPath);
1017
1059
 
1018
1060
  return new Promise(function (resolve, reject) {
1019
1061
  return Promise.map(
@@ -1022,16 +1064,20 @@ importEntries.prototype = {
1022
1064
  let lang = langs[counter];
1023
1065
  return Promise.map(
1024
1066
  contentTypeUids,
1025
- function (ctUid) {
1067
+ async function (ctUid) {
1026
1068
  let eFilePath = path.resolve(ePath, ctUid, lang + '.json');
1027
- let entries = helper.readFile(eFilePath);
1069
+ let entries = await helper.readLargeFile(eFilePath);
1028
1070
 
1029
1071
  let eUids = Object.keys(entries);
1030
1072
  let batches = [];
1073
+ let batchSize;
1031
1074
 
1032
1075
  if (eUids.length > 0) {
1033
- for (let i = 0; i < eUids.length; i += entryBatchLimit) {
1034
- batches.push(eUids.slice(i, i + entryBatchLimit));
1076
+ let entryBatchLimit = eConfig.batchLimit || 10;
1077
+ batchSize = Math.round(entryBatchLimit / 3);
1078
+ // Run entry creation in batches
1079
+ for (let i = 0; i < eUids.length; i += batchSize) {
1080
+ batches.push(eUids.slice(i, i + batchSize));
1035
1081
  }
1036
1082
  } else {
1037
1083
  return;
@@ -1039,7 +1085,7 @@ importEntries.prototype = {
1039
1085
 
1040
1086
  return Promise.map(
1041
1087
  batches,
1042
- async function (batch) {
1088
+ async function (batch, index) {
1043
1089
  return Promise.map(
1044
1090
  batch,
1045
1091
  async function (eUid) {
@@ -1075,16 +1121,20 @@ importEntries.prototype = {
1075
1121
  // eslint-disable-next-line max-nested-callbacks
1076
1122
  .then((result) => {
1077
1123
  // addlogs(config, 'Entry ' + eUid + ' published successfully in ' + ctUid + ' content type', 'success')
1078
- console.log('Entry ' + eUid + ' published successfully in ' + ctUid + ' content type');
1124
+ addlogs(
1125
+ config,
1126
+ 'Entry ' + eUid + ' published successfully in ' + ctUid + ' content type',
1127
+ 'success',
1128
+ );
1079
1129
  return resolveEntryPublished(result);
1080
1130
  // eslint-disable-next-line max-nested-callbacks
1081
1131
  })
1082
1132
  .catch(function (err) {
1083
- // addlogs(config, 'Entry ' + eUid + ' not published successfully in ' + ctUid + ' content type', 'error')
1084
- console.log(
1085
- 'Entry ' + eUid + ' not published successfully in ' + ctUid + ' content type',
1133
+ addlogs(
1134
+ config,
1135
+ `failed to publish entry ${eUid} content type ${ctUid} ${util.formatError(err)}`,
1086
1136
  );
1087
- return rejectEntryPublished(err.errorMessage);
1137
+ return resolveEntryPublished('');
1088
1138
  });
1089
1139
  });
1090
1140
  }
@@ -1093,7 +1143,7 @@ importEntries.prototype = {
1093
1143
  }
1094
1144
  },
1095
1145
  {
1096
- concurrency: reqConcurrency,
1146
+ concurrency: 1,
1097
1147
  },
1098
1148
  )
1099
1149
  .then(function () {
@@ -1101,8 +1151,7 @@ importEntries.prototype = {
1101
1151
  })
1102
1152
  .catch(function (error) {
1103
1153
  // error while executing entry in batch
1104
- addlogs(config, error, 'error');
1105
- return error;
1154
+ addlogs(config, util.formatError(error), 'error');
1106
1155
  });
1107
1156
  },
1108
1157
  {
@@ -1111,15 +1160,10 @@ importEntries.prototype = {
1111
1160
  )
1112
1161
  .then(function () {
1113
1162
  // addlogs(config, 'Entries published successfully in ' + ctUid + ' content type', 'success')
1114
- console.log('Entries published successfully in ' + ctUid + ' content type');
1163
+ addlogs('Entries published successfully in ' + ctUid + ' content type');
1115
1164
  })
1116
1165
  .catch(function (error) {
1117
- addlogs(
1118
- config,
1119
- 'Failed some of the Entry publishing in ' + ctUid + ' content type, go through logs for details.',
1120
- 'error',
1121
- );
1122
- return error;
1166
+ addlogs(config, `failed to publish entry in content type ${ctUid} ${util.formatError(error)}`);
1123
1167
  });
1124
1168
  },
1125
1169
  {
@@ -1128,9 +1172,10 @@ importEntries.prototype = {
1128
1172
  )
1129
1173
  .then(function () {
1130
1174
  // empty function
1175
+ // addlogs('Published entries successfully in ' +);
1131
1176
  })
1132
1177
  .catch(function (error) {
1133
- return error;
1178
+ addlogs(`Failed to publish few entries in ${lang} ${util.formatError(error)}`);
1134
1179
  });
1135
1180
  },
1136
1181
  {
@@ -1141,7 +1186,8 @@ importEntries.prototype = {
1141
1186
  return resolve();
1142
1187
  })
1143
1188
  .catch((error) => {
1144
- return reject(error);
1189
+ addlogs(`Failed to publish entries ${util.formatError(error)}`);
1190
+ // return reject(error);
1145
1191
  });
1146
1192
  });
1147
1193
  },
@@ -1209,11 +1255,7 @@ importEntries.prototype = {
1209
1255
 
1210
1256
  if (element.length) {
1211
1257
  for (const item of element) {
1212
- if (
1213
- (item.type === 'p' || item.type === 'a') &&
1214
- item.children &&
1215
- item.children.length > 0
1216
- ) {
1258
+ if ((item.type === 'p' || item.type === 'a') && item.children && item.children.length > 0) {
1217
1259
  return this.doEntryReferencesExist(item.children);
1218
1260
  } else if (this.isEntryRef(item)) {
1219
1261
  return true;
@@ -1231,8 +1273,8 @@ importEntries.prototype = {
1231
1273
  return false;
1232
1274
  },
1233
1275
  restoreJsonRteEntryRefs: function (entry, sourceStackEntry, ctSchema) {
1234
- let mappedAssetUids = helper.readFile(mappedAssetUidPath) || {};
1235
- let mappedAssetUrls = helper.readFile(mappedAssetUrlPath) || {};
1276
+ let mappedAssetUids = helper.readFileSync(mappedAssetUidPath) || {};
1277
+ let mappedAssetUrls = helper.readFileSync(mappedAssetUrlPath) || {};
1236
1278
  for (const element of ctSchema) {
1237
1279
  switch (element.data_type) {
1238
1280
  case 'blocks': {
@@ -1314,7 +1356,9 @@ importEntries.prototype = {
1314
1356
 
1315
1357
  if (entryRefs.length > 0) {
1316
1358
  entryRefs.forEach((entryRef) => {
1317
- entry[entryRef.uid].children.splice(entryRef.index, 0, entryRef.value);
1359
+ if (!_.isEmpty(entry[entryRef.uid]) && entry[entryRef.uid].children) {
1360
+ entry[entryRef.uid].children.splice(entryRef.index, 0, entryRef.value);
1361
+ }
1318
1362
  });
1319
1363
  }
1320
1364
  }
@@ -1363,16 +1407,27 @@ importEntries.prototype = {
1363
1407
  if (element.multiple) {
1364
1408
  entry[element.uid] = entry[element.uid].map((jsonRteData) => {
1365
1409
  delete jsonRteData.uid; // remove uid
1366
- jsonRteData.attrs.dirty = true;
1367
- jsonRteData.children = jsonRteData.children.map((child) => this.removeUidsFromChildren(child));
1410
+
1411
+ if (_.isObject(jsonRteData.attrs)) {
1412
+ jsonRteData.attrs.dirty = true;
1413
+ }
1414
+
1415
+ if (!_.isEmpty(jsonRteData.children)) {
1416
+ jsonRteData.children = _.map(jsonRteData.children, (child) => this.removeUidsFromChildren(child));
1417
+ }
1418
+
1368
1419
  return jsonRteData;
1369
1420
  });
1370
1421
  } else {
1371
1422
  delete entry[element.uid].uid; // remove uid
1372
- entry[element.uid].attrs.dirty = true;
1373
- entry[element.uid].children = entry[element.uid].children.map((child) =>
1374
- this.removeUidsFromChildren(child),
1375
- );
1423
+ if (entry[element.uid] && _.isObject(entry[element.uid].attrs)) {
1424
+ entry[element.uid].attrs.dirty = true;
1425
+ }
1426
+ if (entry[element.uid] && !_.isEmpty(entry[element.uid].children)) {
1427
+ entry[element.uid].children = _.map(entry[element.uid].children, (child) =>
1428
+ this.removeUidsFromChildren(child),
1429
+ );
1430
+ }
1376
1431
  }
1377
1432
  }
1378
1433
  break;
@@ -1386,7 +1441,10 @@ importEntries.prototype = {
1386
1441
  return children.map((child) => {
1387
1442
  if (child.type && child.type.length > 0) {
1388
1443
  delete child.uid; // remove uid
1389
- child.attrs.dirty = true;
1444
+
1445
+ if (_.isObject(child.attrs)) {
1446
+ child.attrs.dirty = true;
1447
+ }
1390
1448
  }
1391
1449
  if (child.children && child.children.length > 0) {
1392
1450
  child.children = this.removeUidsFromChildren(child.children);
@@ -1396,7 +1454,9 @@ importEntries.prototype = {
1396
1454
  } else {
1397
1455
  if (children.type && children.type.length > 0) {
1398
1456
  delete children.uid; // remove uid
1399
- children.attrs.dirty = true;
1457
+ if (_.isObject(children.attrs)) {
1458
+ children.attrs.dirty = true;
1459
+ }
1400
1460
  }
1401
1461
  if (children.children && children.children.length > 0) {
1402
1462
  children.children = this.removeUidsFromChildren(children.children);
@@ -1407,7 +1467,9 @@ importEntries.prototype = {
1407
1467
  setDirtyTrue: function (jsonRteChild) {
1408
1468
  // also removing uids in this function
1409
1469
  if (jsonRteChild.type) {
1410
- jsonRteChild.attrs['dirty'] = true;
1470
+ if (_.isObject(jsonRteChild.attrs)) {
1471
+ jsonRteChild.attrs['dirty'] = true;
1472
+ }
1411
1473
  delete jsonRteChild.uid;
1412
1474
 
1413
1475
  if (jsonRteChild.children && jsonRteChild.children.length > 0) {
@@ -1450,4 +1512,4 @@ importEntries.prototype = {
1450
1512
  },
1451
1513
  };
1452
1514
 
1453
- module.exports = new importEntries();
1515
+ module.exports = EntriesImport;