@contentstack/cli-cm-import 0.1.1-beta.13 → 0.1.1-beta.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,6 +9,24 @@ It is Contentstack’s CLI plugin to import content in the stack. To learn how t
9
9
  * [Usage](#usage)
10
10
  * [Commands](#commands)
11
11
  <!-- tocstop -->
12
+
13
+ For switching to EU region update the hosts at config/default.js
14
+ ```js
15
+ {
16
+ host:'https://eu-api.contentstack.com/v3',
17
+ cdn: 'https://eu-cdn.contentstack.com/v3',
18
+ ...
19
+ }
20
+ ```
21
+
22
+ For switching to AZURE-NA region update the hosts at config/default.js
23
+ ```js
24
+ {
25
+ host:'https://azure-na-api.contentstack.com/v3',
26
+ cdn: 'https://azure-na-cdn.contentstack.com/v3'
27
+ ...
28
+ }
29
+ ```
12
30
  # Usage
13
31
  <!-- usage -->
14
32
  ```sh-session
@@ -16,7 +34,7 @@ $ npm install -g @contentstack/cli-cm-import
16
34
  $ csdx COMMAND
17
35
  running command...
18
36
  $ csdx (-v|--version|version)
19
- @contentstack/cli-cm-import/0.1.1-beta.13 linux-x64 node-v12.22.7
37
+ @contentstack/cli-cm-import/0.1.1-beta.16 linux-x64 node-v16.14.2
20
38
  $ csdx --help [COMMAND]
21
39
  USAGE
22
40
  $ csdx COMMAND
@@ -62,5 +80,5 @@ EXAMPLES
62
80
  csdx cm:import -A -B <branch name>
63
81
  ```
64
82
 
65
- _See code: [src/commands/cm/import.js](https://github.com/contentstack/cli/blob/v0.1.1-beta.13/packages/contentstack-import/src/commands/cm/import.js)_
83
+ _See code: [src/commands/cm/import.js](https://github.com/contentstack/cli/blob/v0.1.1-beta.16/packages/contentstack-import/src/commands/cm/import.js)_
66
84
  <!-- commandsstop -->
@@ -1 +1 @@
1
- {"version":"0.1.1-beta.13","commands":{"cm:import":{"id":"cm:import","description":"Import script for importing the content into new stack\n...\nOnce you export content from the source stack, import it to your destination stack by using the cm:import command.\n","pluginName":"@contentstack/cli-cm-import","pluginType":"core","aliases":[],"examples":["csdx cm:import -A","csdx cm:import -A -s <stack_ApiKey> -d <path/of/export/destination/dir>","csdx cm:import -A -c <path/of/config/dir>","csdx cm:import -A -m <single module name>","csdx cm:import -A -m <single module name> -b <backup dir>","csdx cm:import -a <management_token_alias>","csdx cm:import -a <management_token_alias> -d <path/of/export/destination/dir>","csdx cm:import -a <management_token_alias> -c <path/of/config/file>","csdx cm:import -A -m <single module name>","csdx cm:import -A -B <branch name>"],"flags":{"config":{"name":"config","type":"option","char":"c","description":"[optional] path of config file"},"stack-uid":{"name":"stack-uid","type":"option","char":"s","description":"API key of the target stack"},"data":{"name":"data","type":"option","char":"d","description":"path and location where data is stored"},"management-token-alias":{"name":"management-token-alias","type":"option","char":"a","description":"alias of the management token"},"auth-token":{"name":"auth-token","type":"boolean","char":"A","description":"to use auth token","allowNo":false},"module":{"name":"module","type":"option","char":"m","description":"[optional] specific module name"},"backup-dir":{"name":"backup-dir","type":"option","char":"b","description":"[optional] backup directory name when using specific module"},"branch":{"name":"branch","type":"option","char":"B","description":"[optional] branch name"}},"args":[]}}}
1
+ {"version":"0.1.1-beta.16","commands":{"cm:import":{"id":"cm:import","description":"Import script for importing the content into new stack\n...\nOnce you export content from the source stack, import it to your destination stack by using the cm:import command.\n","pluginName":"@contentstack/cli-cm-import","pluginType":"core","aliases":[],"examples":["csdx cm:import -A","csdx cm:import -A -s <stack_ApiKey> -d <path/of/export/destination/dir>","csdx cm:import -A -c <path/of/config/dir>","csdx cm:import -A -m <single module name>","csdx cm:import -A -m <single module name> -b <backup dir>","csdx cm:import -a <management_token_alias>","csdx cm:import -a <management_token_alias> -d <path/of/export/destination/dir>","csdx cm:import -a <management_token_alias> -c <path/of/config/file>","csdx cm:import -A -m <single module name>","csdx cm:import -A -B <branch name>"],"flags":{"config":{"name":"config","type":"option","char":"c","description":"[optional] path of config file"},"stack-uid":{"name":"stack-uid","type":"option","char":"s","description":"API key of the target stack"},"data":{"name":"data","type":"option","char":"d","description":"path and location where data is stored"},"management-token-alias":{"name":"management-token-alias","type":"option","char":"a","description":"alias of the management token"},"auth-token":{"name":"auth-token","type":"boolean","char":"A","description":"to use auth token","allowNo":false},"module":{"name":"module","type":"option","char":"m","description":"[optional] specific module name"},"backup-dir":{"name":"backup-dir","type":"option","char":"b","description":"[optional] backup directory name when using specific module"},"branch":{"name":"branch","type":"option","char":"B","description":"[optional] branch name"}},"args":[]}}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-import",
3
3
  "description": "Contentstack CLI plugin to import content into stack",
4
- "version": "0.1.1-beta.13",
4
+ "version": "0.1.1-beta.16",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
@@ -1,5 +1,9 @@
1
1
  module.exports = {
2
2
  versioning: false,
3
+ // use below hosts for eu region
4
+ // host:'https://eu-api.contentstack.com/v3',
5
+ // use below hosts for azure-na region
6
+ // host:'https://azure-na-api.contentstack.com/v3',
3
7
  // pass locale, only to migrate entries from that locale
4
8
  // not passing `locale` will migrate all the locales present
5
9
  // locales: ['fr-fr'],
@@ -9,6 +9,7 @@ const path = require('path')
9
9
  const _ = require('lodash')
10
10
  const mkdirp = require('mkdirp')
11
11
  const chalk = require('chalk')
12
+ const crypto = require('crypto')
12
13
 
13
14
  const helper = require('../util/fs')
14
15
  const {addlogs} = require('../util/log')
@@ -60,6 +61,12 @@ function importEntries() {
60
61
  this.ctSchemas = {}
61
62
  // Array of content type uids, that have reference fields
62
63
  this.refSchemas = []
64
+ // map of content types uids and their json-rte fields
65
+ this.ctJsonRte = []
66
+ // map of content types uids and their json-rte fields
67
+ this.ctJsonRteWithEntryRefs = []
68
+ // Entry refs that are held back to resolve after all entries have been created
69
+ this.jsonRteEntryRefs = {}
63
70
  // Collection of entries, that were not created, as they already exist on Stack
64
71
  this.createdEntriesWOUid = []
65
72
  // Collection of entry uids, mapped to the language they exist in
@@ -201,6 +208,23 @@ importEntries.prototype = {
201
208
  addlogs(config, `Creating entries for content type ${ctUid} in language ${lang} ...`, 'success')
202
209
  for (let eUid in entries) {
203
210
  if (eUid) {
211
+
212
+ // check ctUid in self.ctJsonRte array, if ct exists there... only then remove entry references for json rte
213
+ // also with json rte, api creates the json-rte field with the same uid as passed in the payload. So use the node's inbuilt
214
+ // crypto module to generate a random uid and populate the json rte data
215
+ // https://www.kindacode.com/article/how-to-easily-generate-a-random-string-in-node-js/
216
+
217
+ // while creating entries with json-rte field, the api does not create fresh uids for the json-rte field
218
+ // and its subsequent children. If the data is passed without a uid, then the fields aren't created. So, I'll
219
+ // generate the uids for now, and will come up with a better solution later
220
+ if (self.ctJsonRte.indexOf(ctUid) > -1) {
221
+ entries[eUid] = self.generateUidsForJsonRteFields(entries[eUid], self.ctSchemas[ctUid].schema)
222
+ }
223
+
224
+ // remove entry references from json-rte fields
225
+ if (self.ctJsonRteWithEntryRefs.indexOf(ctUid) > -1) {
226
+ entries[eUid] = self.removeEntryRefsFromJSONRTE(entries[eUid], self.ctSchemas[ctUid].schema)
227
+ }
204
228
  // will replace all old asset uid/urls with new ones
205
229
  entries[eUid] = lookupReplaceAssets({
206
230
  content_type: self.ctSchemas[ctUid],
@@ -393,6 +417,8 @@ importEntries.prototype = {
393
417
  return Promise.map(self.refSchemas, function (ctUid) {
394
418
  let eFolderPath = path.join(entryMapperPath, lang, ctUid)
395
419
  let eSuccessFilePath = path.join(eFolderPath, 'success.json')
420
+ let eFilePath = path.resolve(ePath, ctUid, lang + '.json')
421
+ let sourceStackEntries = helper.readFile(eFilePath)
396
422
 
397
423
  if (!fs.existsSync(eSuccessFilePath)) {
398
424
  addlogs(config, 'Success file was not found at: ' + eSuccessFilePath, 'success')
@@ -419,12 +445,22 @@ importEntries.prototype = {
419
445
  // map failed reference uids @mapper/language/unmapped-uids.json
420
446
  let refUidMapperPath = path.join(entryMapperPath, lang)
421
447
 
448
+ // add entry references to JSON RTE fields
422
449
  entries = _.map(entries, function (entry) {
423
450
  try {
424
451
  let uid = entry.uid
452
+ let updatedEntry
453
+
454
+ // restores json rte entry refs if they exist
455
+ if (self.ctJsonRte.indexOf(ctUid) > -1) {
456
+ updatedEntry = self.restoreJsonRteEntryRefs(entry, sourceStackEntries[self.mappedUids[entry.uid]], schema)
457
+ } else {
458
+ updatedEntry = entry
459
+ }
460
+
425
461
  let _entry = lookupReplaceEntries({
426
462
  content_type: schema,
427
- entry: entry,
463
+ entry: updatedEntry,
428
464
  }, _.clone(self.mappedUids), refUidMapperPath)
429
465
  // if there's self references, the uid gets replaced
430
466
  _entry.uid = uid
@@ -516,7 +552,7 @@ importEntries.prototype = {
516
552
  })
517
553
  })
518
554
  },
519
- supressFields: async function () {
555
+ supressFields: async function () { // it should be spelled as suppressFields
520
556
  addlogs(config, chalk.white('Suppressing content type fields...'), 'success')
521
557
  let self = this
522
558
  return new Promise(function (resolve, reject) {
@@ -529,6 +565,8 @@ importEntries.prototype = {
529
565
  let flag = {
530
566
  suppressed: false,
531
567
  references: false,
568
+ jsonRte: false,
569
+ jsonRteEmbeddedEntries: false
532
570
  }
533
571
  if (contentTypeSchema.field_rules) {
534
572
  delete contentTypeSchema.field_rules
@@ -546,6 +584,19 @@ importEntries.prototype = {
546
584
  self.refSchemas.push(uid)
547
585
  }
548
586
 
587
+ if (flag.jsonRte) {
588
+ self.ctJsonRte.push(uid)
589
+ if (flag.jsonRteEmbeddedEntries) {
590
+ self.ctJsonRteWithEntryRefs.push(uid)
591
+ // pushing ct uid to refSchemas, because
592
+ // repostEntries uses refSchemas content types for
593
+ // reposting entries
594
+ if (self.refSchemas.indexOf(uid) === -1) {
595
+ self.refSchemas.push(uid)
596
+ }
597
+ }
598
+ }
599
+
549
600
  // Replace extensions with new UID
550
601
  extension_suppress(contentTypeSchema.schema, config.preserveStackVersion)
551
602
  }
@@ -851,6 +902,233 @@ importEntries.prototype = {
851
902
  })
852
903
  })
853
904
  },
905
+ removeEntryRefsFromJSONRTE(entry, ctSchema) {
906
+ for (let i = 0; i < ctSchema.length; i++) {
907
+ switch(ctSchema[i].data_type) {
908
+ case 'blocks': {
909
+ if (entry[ctSchema[i].uid] !== undefined) {
910
+ if (ctSchema[i].multiple) {
911
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map(e => {
912
+ let key = Object.keys(e).pop()
913
+ let subBlock = ctSchema[i].blocks.filter(e => e.uid === key).pop()
914
+ e[key] = this.removeEntryRefsFromJSONRTE(e[key], subBlock.schema)
915
+ return e
916
+ })
917
+ }
918
+ }
919
+ break;
920
+ }
921
+ case 'global_field':
922
+ case 'group': {
923
+ if (entry[ctSchema[i].uid] !== undefined) {
924
+ if (ctSchema[i].multiple) {
925
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map(e => {
926
+ e = this.removeEntryRefsFromJSONRTE(e, ctSchema[i].schema)
927
+ return e
928
+ })
929
+ } else {
930
+ entry[ctSchema[i].uid] = this.removeEntryRefsFromJSONRTE(entry[ctSchema[i].uid], ctSchema[i].schema)
931
+ }
932
+ }
933
+ break;
934
+ }
935
+ case 'json': {
936
+ if (entry[ctSchema[i].uid] !== undefined) {
937
+ if (ctSchema[i].multiple) {
938
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map(jsonRteData => {
939
+ // repeated code from else block, will abstract later
940
+ let entryReferences = jsonRteData.children.filter(e => this.doEntryReferencesExist(e))
941
+ if (entryReferences.length > 0) {
942
+ jsonRteData.children = jsonRteData.children.filter(e => !this.doEntryReferencesExist(e))
943
+ return jsonRteData // return jsonRteData without entry references
944
+ } else {
945
+ return jsonRteData // return jsonRteData as it is, because there are no entry references
946
+ }
947
+ })
948
+ } else {
949
+ let entryReferences = entry[ctSchema[i].uid].children.filter(e => this.doEntryReferencesExist(e))
950
+ if (entryReferences.length > 0) {
951
+ entry[ctSchema[i].uid].children = entry[ctSchema[i].uid].children.filter(e => !this.doEntryReferencesExist(e))
952
+ }
953
+ }
954
+ }
955
+ break;
956
+ }
957
+ }
958
+ }
959
+ return entry
960
+ },
961
+ doEntryReferencesExist(element) {
962
+ // checks if the children of p element contain any references
963
+ // only checking one level deep, not recursive
964
+
965
+ if (element.length) {
966
+ for(let i=0; i < element.length; i++) {
967
+ // although most data has only one level of nesting, and this case might never come up
968
+ // I've handled multiple level of nesting for 'p' elements
969
+ if(element[i].type === 'p' && element[i].children && element[i].children.length > 0) {
970
+ return this.doEntryReferencesExist(element[i].children)
971
+ } else if(this.isEntryRef(element[i])) {
972
+ return true
973
+ }
974
+ }
975
+ } else {
976
+ if(this.isEntryRef(element)) {
977
+ return true
978
+ }
979
+
980
+ if (element.type === "p" && element.children && element.children.length > 0) {
981
+ return this.doEntryReferencesExist(element.children)
982
+ }
983
+ }
984
+ return false
985
+ },
986
+ restoreJsonRteEntryRefs(entry, sourceStackEntry, ctSchema) {
987
+ for (let i = 0; i < ctSchema.length; i++) {
988
+ switch (ctSchema[i].data_type) {
989
+ case 'blocks': {
990
+ if (entry[ctSchema[i].uid] !== undefined) {
991
+ if (ctSchema[i].multiple) {
992
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map((e, eIndex) => {
993
+ let key = Object.keys(e).pop()
994
+ let subBlock = ctSchema[i].blocks.filter(e => e.uid === key).pop()
995
+ let sourceStackElement = sourceStackEntry[ctSchema[i].uid][eIndex][key]
996
+ e[key] = this.restoreJsonRteEntryRefs(e[key], sourceStackElement, subBlock.schema)
997
+ return e
998
+ })
999
+ }
1000
+ }
1001
+ break;
1002
+ }
1003
+ case 'global_field':
1004
+ case 'group': {
1005
+ if (entry[ctSchema[i].uid] !== undefined) {
1006
+ if (ctSchema[i].multiple) {
1007
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map((e, eIndex) => {
1008
+ let sourceStackElement = sourceStackEntry[ctSchema[i].uid][eIndex]
1009
+ e = this.restoreJsonRteEntryRefs(e, sourceStackElement, ctSchema[i].schema)
1010
+ return e
1011
+ })
1012
+ } else {
1013
+ let sourceStackElement = sourceStackEntry[ctSchema[i].uid]
1014
+ entry[ctSchema[i].uid] = this.restoreJsonRteEntryRefs(entry[ctSchema[i].uid], sourceStackElement, ctSchema[i].schema)
1015
+ }
1016
+ }
1017
+ break;
1018
+ }
1019
+ case 'json': {
1020
+ if (entry[ctSchema[i].uid] !== undefined) {
1021
+ if (ctSchema[i].multiple) {
1022
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map((field, index) => {
1023
+ field.children = [
1024
+ ...field.children,
1025
+ ...sourceStackEntry[ctSchema[i].uid][index].children.filter(e => this.doEntryReferencesExist(e))
1026
+ ]
1027
+ return field
1028
+ })
1029
+ } else {
1030
+ entry[ctSchema[i].uid].children = [
1031
+ ...entry[ctSchema[i].uid].children,
1032
+ ...sourceStackEntry[ctSchema[i].uid].children.filter(e => this.doEntryReferencesExist(e)),
1033
+ ]
1034
+ }
1035
+ }
1036
+ break;
1037
+ }
1038
+ }
1039
+ }
1040
+ return entry
1041
+ //------------------------------------------------------------------------------------------------------------
1042
+ // if (Object.keys(self.jsonRteEntryRefs).indexOf(entry.uid) > -1) {
1043
+ // Object.keys(self.jsonRteEntryRefs[entry.uid]).forEach(jsonRteFieldUid => {
1044
+ // if (self.jsonRteEntryRefs[entry.uid][jsonRteFieldUid].length) { // handles when json_rte is multiple
1045
+ // entry[jsonRteFieldUid] = entry[jsonRteFieldUid].map((field, index) => {
1046
+ // field.children = [...field.children, ...self.jsonRteEntryRefs[entry.uid][jsonRteFieldUid][index]]
1047
+ // return field
1048
+ // })
1049
+ // } else {
1050
+ // entry[jsonRteFieldUid].children = [...entry[jsonRteFieldUid].children, ...self.jsonRteEntryRefs[entry.uid][jsonRteFieldUid].children]
1051
+ // }
1052
+ // })
1053
+ // }
1054
+ // return entry
1055
+ },
1056
+ isEntryRef(element) {
1057
+ return element.type === "reference" && element.attrs.type === "entry"
1058
+ },
1059
+ generateUidsForJsonRteFields(entry, ctSchema) {
1060
+ for (let i = 0; i < ctSchema.length; i++) {
1061
+ switch (ctSchema[i].data_type) {
1062
+ case 'blocks': {
1063
+ if (entry[ctSchema[i].uid] !== undefined) {
1064
+ if (ctSchema[i].multiple) {
1065
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map(e => {
1066
+ let key = Object.keys(e).pop()
1067
+ let subBlock = ctSchema[i].blocks.filter(e => e.uid === key).pop()
1068
+ e[key] = this.generateUidsForJsonRteFields(e[key], subBlock.schema)
1069
+ return e
1070
+ })
1071
+ }
1072
+ }
1073
+ break;
1074
+ }
1075
+ case 'global_field':
1076
+ case 'group': {
1077
+ if (entry[ctSchema[i].uid] !== undefined) {
1078
+ if (ctSchema[i].multiple) {
1079
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map(e => {
1080
+ e = this.generateUidsForJsonRteFields(e, ctSchema[i].schema)
1081
+ return e
1082
+ })
1083
+ } else {
1084
+ entry[ctSchema[i].uid] = this.generateUidsForJsonRteFields(entry[ctSchema[i].uid], ctSchema[i].schema)
1085
+ }
1086
+ }
1087
+ break;
1088
+ }
1089
+ case 'json': {
1090
+ if (entry[ctSchema[i].uid] !== undefined) {
1091
+ if (ctSchema[i].multiple) {
1092
+ entry[ctSchema[i].uid] = entry[ctSchema[i].uid].map(jsonRteData => {
1093
+ jsonRteData.uid = this.generateUid()
1094
+ jsonRteData.children = jsonRteData.children.map(child => this.populateChildrenWithUids(child))
1095
+ return jsonRteData
1096
+ })
1097
+ } else {
1098
+ entry[ctSchema[i].uid].uid = this.generateUid()
1099
+ entry[ctSchema[i].uid].children = entry[ctSchema[i].uid].children.map(child => this.populateChildrenWithUids(child))
1100
+ }
1101
+ }
1102
+ break;
1103
+ }
1104
+ }
1105
+ }
1106
+ return entry
1107
+ },
1108
+ populateChildrenWithUids(children) {
1109
+ if (children.length && children.length > 0) {
1110
+ return children.map(child => {
1111
+ if(child.type && child.type.length > 0) {
1112
+ child.uid = this.generateUid()
1113
+ }
1114
+ if(child.children && child.children.length > 0) {
1115
+ child.children = this.populateChildrenWithUids(child.children)
1116
+ }
1117
+ return child
1118
+ })
1119
+ } else {
1120
+ if (children.type && children.type.length > 0) {
1121
+ children.uid = this.generateUid()
1122
+ }
1123
+ if (children.children && children.children.length > 0) {
1124
+ children.children = this.populateChildrenWithUids(children.children)
1125
+ }
1126
+ return children
1127
+ }
1128
+ },
1129
+ generateUid() {
1130
+ return crypto.randomBytes(16).toString('hex')
1131
+ }
854
1132
  }
855
1133
 
856
1134
  module.exports = new importEntries()
@@ -45,6 +45,15 @@ var extension_uid_Replace = module.exports = function (schema, preserveStackVers
45
45
  // eslint-disable-next-line camelcase
46
46
  schema[i].extension_uid = data[extension_key_value]
47
47
  }
48
+ } else if (schema[i].data_type === 'json' && schema[i].hasOwnProperty('plugins') && schema[i].plugins.length > 0) {
49
+ const newPluginUidsArray = [];
50
+ const data = helper.readFile(path.join(extensionPath));
51
+ schema[i].plugins.forEach((extension_key_value) => {
52
+ if (data && data.hasOwnProperty(extension_key_value)) {
53
+ newPluginUidsArray.push(data[extension_key_value]);
54
+ }
55
+ });
56
+ schema[i].plugins = newPluginUidsArray;
48
57
  }
49
58
  }
50
59
  }
@@ -24,7 +24,6 @@ function returnString (args) {
24
24
 
25
25
  var myCustomLevels = {
26
26
  levels: {
27
- error: 0,
28
27
  warn: 1,
29
28
  info: 2,
30
29
  debug: 3
@@ -37,26 +36,53 @@ var myCustomLevels = {
37
36
  }
38
37
  };
39
38
 
40
- function init (_logPath, logfileName) {
41
- var logsDir = path.resolve(_logPath, 'logs', 'import')
42
- // Create dir if doesn't already exist
43
- mkdirp.sync(logsDir)
44
- var logPath = path.join(logsDir, logfileName + '.log');
39
+ let logger
40
+ let errorLogger
45
41
 
46
- var transports = [new(winston.transports.File)({
47
- filename: logPath,
48
- maxFiles: 20,
49
- maxsize: 1000000,
50
- tailable: true,
51
- json: true
52
- })];
42
+ let successTransport
43
+ let errorTransport
53
44
 
54
- transports.push(new(winston.transports.Console)());
45
+ // removed logfileName from arguments
46
+ function init(_logPath) {
47
+ if (!logger || !errorLogger) {
48
+ var logsDir = path.resolve(_logPath, 'logs', 'import')
49
+ // Create dir if doesn't already exist
50
+ mkdirp.sync(logsDir)
55
51
 
56
- var logger = new(winston.Logger)({
57
- transports: transports,
58
- levels: myCustomLevels.levels
59
- });
52
+ successTransport = {
53
+ filename: path.join(logsDir, 'success.log'),
54
+ maxFiles: 20,
55
+ maxsize: 1000000,
56
+ tailable: true,
57
+ json: true,
58
+ level: 'info',
59
+ }
60
+
61
+ errorTransport = {
62
+ filename: path.join(logsDir, 'error.log'),
63
+ maxFiles: 20,
64
+ maxsize: 1000000,
65
+ tailable: true,
66
+ json: true,
67
+ level: 'error',
68
+ }
69
+
70
+ logger = new (winston.Logger)({
71
+ transports: [
72
+ new (winston.transports.File)(successTransport),
73
+ new (winston.transports.Console)()
74
+ ],
75
+ levels: myCustomLevels.levels,
76
+ });
77
+
78
+ errorLogger = new (winston.Logger)({
79
+ transports: [
80
+ new (winston.transports.File)(errorTransport),
81
+ new (winston.transports.Console)({level: 'error'})
82
+ ],
83
+ levels: { error: 0 }
84
+ })
85
+ }
60
86
 
61
87
  return {
62
88
  log: function () {
@@ -77,7 +103,7 @@ function init (_logPath, logfileName) {
77
103
  var args = slice.call(arguments);
78
104
  var logString = returnString(args);
79
105
  if (logString) {
80
- logger.log('error', logString);
106
+ errorLogger.log('error', logString);
81
107
  }
82
108
  },
83
109
  debug: function () {
@@ -93,9 +119,11 @@ function init (_logPath, logfileName) {
93
119
  exports.addlogs = async (config, message, type) => {
94
120
  var configLogPath
95
121
  config.source_stack && config.target_stack ? configLogPath = config.data : configLogPath = config.oldPath
122
+ // ignoring the type argument, as we are not using it to create a logfile anymore
96
123
  if (type !== 'error') {
97
- init(configLogPath, type).log(message)
124
+ // removed type argument from init method
125
+ init(configLogPath).log(message)
98
126
  } else {
99
- init(configLogPath, type).error(message)
127
+ init(configLogPath).error(message)
100
128
  }
101
129
  }
@@ -30,7 +30,7 @@ module.exports = function (data, mappedAssetUids, mappedAssetUrls, assetUidMappe
30
30
  if ((schema[i].data_type === 'text' && schema[i].field_metadata && (schema[i].field_metadata.markdown ||
31
31
  schema[i].field_metadata.rich_text_type))) {
32
32
  parent.push(schema[i].uid);
33
- findFileUrls(parent, schema[i], entry, assetUrls);
33
+ findFileUrls(schema[i], entry, assetUrls);
34
34
  parent.pop();
35
35
  }
36
36
  if (schema[i].data_type === 'group' || schema[i].data_type === 'global_field') {
@@ -49,35 +49,112 @@ module.exports = function (data, mappedAssetUids, mappedAssetUrls, assetUidMappe
49
49
  }
50
50
  }
51
51
  }
52
+ // added rich_text_type field check because some marketplace extensions also
53
+ // have data_type has json
54
+ if (schema[i].data_type === "json" && schema[i].field_metadata.rich_text_type) {
55
+ parent.push(schema[i].uid)
56
+ // findFileUrls(schema[i], entry, assetUrls)
57
+ if (assetUids.length === 0) {
58
+ findAssetIdsFromJsonRte(data.entry, data.content_type.schema)
59
+ }
60
+ // maybe only one of these checks would be enough
61
+ parent.pop()
62
+ }
52
63
  }
53
64
  };
54
-
55
-
65
+
66
+ function findAssetIdsFromJsonRte(entry, ctSchema) {
67
+ for (let i = 0; i < ctSchema.length; i++) {
68
+ switch (ctSchema[i].data_type) {
69
+ case 'blocks': {
70
+ if (entry[ctSchema[i].uid] !== undefined) {
71
+ if (ctSchema[i].multiple) {
72
+ entry[ctSchema[i].uid].forEach(e => {
73
+ let key = Object.keys(e).pop()
74
+ let subBlock = ctSchema[i].blocks.filter(e => e.uid === key).pop()
75
+ findAssetIdsFromJsonRte(e[key], subBlock.schema)
76
+ })
77
+ }
78
+ }
79
+ break;
80
+ }
81
+ case 'global_field':
82
+ case 'group': {
83
+ if (entry[ctSchema[i].uid] !== undefined) {
84
+ if (ctSchema[i].multiple) {
85
+ entry[ctSchema[i].uid].forEach(e => {
86
+ findAssetIdsFromJsonRte(e, ctSchema[i].schema)
87
+ })
88
+ } else {
89
+ findAssetIdsFromJsonRte(entry[ctSchema[i].uid], ctSchema[i].schema)
90
+ }
91
+ }
92
+ break;
93
+ }
94
+ case 'json': {
95
+ if (entry[ctSchema[i].uid] !== undefined) {
96
+ if (ctSchema[i].multiple) {
97
+ entry[ctSchema[i].uid].forEach(jsonRteData => {
98
+ gatherJsonRteAssetIds(jsonRteData)
99
+ })
100
+ } else {
101
+ gatherJsonRteAssetIds(entry[ctSchema[i].uid])
102
+ }
103
+ }
104
+ break;
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ function gatherJsonRteAssetIds(jsonRteData) {
111
+ jsonRteData.children.forEach(element => {
112
+ if (element.type) {
113
+ switch (element.type) {
114
+ case 'p': {
115
+ if (element.children && element.children.length > 0) {
116
+ gatherJsonRteAssetIds(element)
117
+ }
118
+ break;
119
+ }
120
+ case 'reference': {
121
+ if (Object.keys(element.attrs).length > 0 && element.attrs.type === "asset") {
122
+ assetUids.push(element.attrs['asset-uid'])
123
+ assetUrls.push(element.attrs['asset-link'])
124
+ }
125
+ break;
126
+ }
127
+ }
128
+ }
129
+ })
130
+ }
131
+
56
132
  find(data.content_type.schema, data.entry);
57
133
  updateFileFields(data.entry, data, null, mappedAssetUids, matchedUids, unmatchedUids);
58
134
  assetUids = _.uniq(assetUids);
59
135
  assetUrls = _.uniq(assetUrls);
60
136
  var entry = JSON.stringify(data.entry);
61
- assetUids.forEach(function (assetUid) {
62
- var uid = mappedAssetUids[assetUid];
63
- if (typeof uid !== 'undefined') {
64
- entry = entry.replace(new RegExp(assetUid, 'img'), uid);
65
- matchedUids.push(assetUid);
66
- } else {
67
- unmatchedUids.push(assetUid);
68
- }
69
- });
70
137
 
71
138
  assetUrls.forEach(function (assetUrl) {
72
139
  var url = mappedAssetUrls[assetUrl];
73
140
  if (typeof url !== 'undefined') {
74
141
  entry = entry.replace(new RegExp(assetUrl, 'img'), url);
75
- unmatchedUrls.push(url);
142
+ matchedUrls.push(url);
76
143
  } else {
77
144
  unmatchedUrls.push(assetUrl);
78
145
  }
79
146
  });
80
147
 
148
+ assetUids.forEach(function (assetUid) {
149
+ var uid = mappedAssetUids[assetUid];
150
+ if (typeof uid !== 'undefined') {
151
+ entry = entry.replace(new RegExp(assetUid, 'img'), uid);
152
+ matchedUids.push(assetUid);
153
+ } else {
154
+ unmatchedUids.push(assetUid);
155
+ }
156
+ });
157
+
81
158
  if (matchedUids.length) {
82
159
  var matchedAssetUids = helper.readFile(path.join(assetUidMapperPath, 'matched-asset-uids.json'));
83
160
  matchedAssetUids = matchedAssetUids || {};
@@ -160,9 +237,9 @@ function findFileUrls (schema, _entry, assetUrls) {
160
237
  if (schema && schema.field_metadata && schema.field_metadata.markdown) {
161
238
  text = marked(_entry);
162
239
  } else {
163
- text = _entry;
240
+ text = JSON.stringify(_entry);
164
241
  }
165
- markdownRegEx = new RegExp('(https://(assets|images).contentstack.io/v3/assets/(.*?)/(.*?)/(.*?)/(.*)(?="))', 'g');
242
+ markdownRegEx = new RegExp('(https://(assets|(eu-|azure-na-|stag-)?images).contentstack.(io|com)/v3/assets/(.*?)/(.*?)/(.*?)/(.*?)(?="))', 'g');
166
243
  while ((markdownMatch = markdownRegEx.exec(text)) !== null) {
167
244
  if (markdownMatch && typeof markdownMatch[0] === 'string') {
168
245
  assetUrls.push(markdownMatch[0]);
@@ -21,6 +21,27 @@ module.exports = function (data, mappedUids, uidMapperPath) {
21
21
  var isNewRefFields = false
22
22
  var preserveStackVersion = config.preserveStackVersion
23
23
 
24
+ function gatherJsonRteEntryIds(jsonRteData) {
25
+ jsonRteData.children.forEach(element => {
26
+ if (element.type) {
27
+ switch (element.type) {
28
+ case 'p': {
29
+ if (element.children && element.children.length > 0) {
30
+ gatherJsonRteEntryIds(element)
31
+ }
32
+ break;
33
+ }
34
+ case 'reference': {
35
+ if (Object.keys(element.attrs).length > 0 && element.attrs.type === "entry") {
36
+ uids.push(element.attrs['entry-uid'])
37
+ }
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ })
43
+ }
44
+
24
45
  var update = function (parent, form_id, entry) {
25
46
  var _entry = entry
26
47
  var len = parent.length
@@ -97,9 +118,61 @@ module.exports = function (data, mappedUids, uidMapperPath) {
97
118
  parent.pop()
98
119
  }
99
120
  break
121
+ case 'json':
122
+ if (schema[i].field_metadata.rich_text_type) {
123
+ if (uids.length === 0) {
124
+ findEntryIdsFromJsonRte(data.entry, data.content_type.schema)
125
+ }
126
+ }
127
+ break
128
+ }
129
+ }
130
+ }
131
+
132
+ function findEntryIdsFromJsonRte(entry, ctSchema) {
133
+ for (let i = 0; i < ctSchema.length; i++) {
134
+ switch (ctSchema[i].data_type) {
135
+ case 'blocks': {
136
+ if (entry[ctSchema[i].uid] !== undefined) {
137
+ if (ctSchema[i].multiple) {
138
+ entry[ctSchema[i].uid].forEach(e => {
139
+ let key = Object.keys(e).pop()
140
+ let subBlock = ctSchema[i].blocks.filter(e => e.uid === key).pop()
141
+ findEntryIdsFromJsonRte(e[key], subBlock.schema)
142
+ })
143
+ }
144
+ }
145
+ break;
146
+ }
147
+ case 'global_field':
148
+ case 'group': {
149
+ if (entry[ctSchema[i].uid] !== undefined) {
150
+ if (ctSchema[i].multiple) {
151
+ entry[ctSchema[i].uid].forEach(e => {
152
+ findEntryIdsFromJsonRte(e, ctSchema[i].schema)
153
+ })
154
+ } else {
155
+ findEntryIdsFromJsonRte(entry[ctSchema[i].uid], ctSchema[i].schema)
156
+ }
157
+ }
158
+ break;
159
+ }
160
+ case 'json': {
161
+ if (entry[ctSchema[i].uid] !== undefined) {
162
+ if (ctSchema[i].multiple) {
163
+ entry[ctSchema[i].uid].forEach(jsonRteData => {
164
+ gatherJsonRteEntryIds(jsonRteData)
165
+ })
166
+ } else {
167
+ gatherJsonRteEntryIds(entry[ctSchema[i].uid])
168
+ }
169
+ }
170
+ break;
171
+ }
100
172
  }
101
173
  }
102
174
  }
175
+
103
176
  find(data.content_type.schema, data.entry)
104
177
  if (isNewRefFields) {
105
178
  findUidsInNewRefFields(data.entry, uids)
@@ -35,6 +35,13 @@ var removeReferenceFields = module.exports = function (schema, flag) {
35
35
  'non_localizable': false
36
36
  });
37
37
  }
38
- }
38
+ } else if( // handling entry references in json rte
39
+ schema[i].data_type === 'json'
40
+ && schema[i].field_metadata.rich_text_type
41
+ && schema[i].field_metadata.embed_entry
42
+ && schema[i].reference_to.length > 1) {
43
+ flag.supressed = true;
44
+ schema[i].reference_to = ["sys_assets"]
45
+ }
39
46
  }
40
47
  };
@@ -14,6 +14,10 @@ var supress = module.exports = function (schema, flag) {
14
14
  }
15
15
  } else if (schema[i].data_type === 'reference') {
16
16
  flag.references = true;
17
+ } else if (schema[i].data_type === 'json' && schema[i].field_metadata.rich_text_type) {
18
+ flag.jsonRte = true
19
+ if (schema[i].field_metadata.embed_entry === true)
20
+ flag.jsonRteEmbeddedEntries = true;
17
21
  }
18
22
 
19
23
  if ((schema[i].hasOwnProperty('mandatory') && schema[i].mandatory) || (schema[i].hasOwnProperty('unique') &&