@contentstack/cli-cm-import 0.1.1-beta.1 → 0.1.1-beta.12

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.
@@ -21,7 +21,7 @@ let util = require('../util')
21
21
  let config = require('../../config/default')
22
22
  const assetsConfig = config.modules.assets
23
23
  let assetBatchLimit = (assetsConfig.hasOwnProperty('batchLimit') && typeof assetBatchLimit === 'number') ?
24
- assetsConfig.assetBatchLimit : 2
24
+ assetsConfig.assetBatchLimit : 2
25
25
  let assetsFolderPath
26
26
  let mapperDirPath
27
27
  let environmentPath
@@ -52,12 +52,12 @@ importAssets.prototype = {
52
52
  self.assets = helper.readFile(path.join(assetsFolderPath, assetsConfig.fileName))
53
53
  self.environment = helper.readFile(environmentPath)
54
54
  if (fs.existsSync(self.uidMapperPath)) {
55
- self.uidMapping = helper.readFile(self.uidMapperPath)
55
+ self.uidMapping = helper.readFile(self.uidMapperPath)
56
56
  }
57
57
  if (fs.existsSync(self.urlMapperPath)) {
58
58
  self.urlMapping = helper.readFile(self.urlMapperPath)
59
59
  }
60
-
60
+
61
61
  mkdirp.sync(mapperDirPath)
62
62
 
63
63
  return new Promise(function (resolve, reject) {
@@ -72,7 +72,7 @@ importAssets.prototype = {
72
72
  }
73
73
 
74
74
  return self.importFolders().then(function () {
75
- return Promise.map(batches, function (batch, index) {
75
+ return Promise.map(batches, async function (batch, index) {
76
76
  return Promise.map(batch, function (assetUid) {
77
77
  if (self.uidMapping.hasOwnProperty(assetUid)) {
78
78
  addlogs(config, 'Skipping upload of asset: ' + assetUid + '. Its mapped to: ' + self.uidMapping[
@@ -87,7 +87,7 @@ importAssets.prototype = {
87
87
  if (config.versioning) {
88
88
  return self.uploadVersionedAssets(assetUid, currentAssetFolderPath).then(function () {
89
89
  }).catch(function (error) {
90
- addlogs(config, (chalk.red('Asset upload failed to import\n' + error), 'error'))
90
+ addlogs(config, (chalk.red('Asset upload failed \n' + error), 'error'))
91
91
  })
92
92
  }
93
93
  let assetPath = path.resolve(currentAssetFolderPath, self.assets[assetUid].filename)
@@ -101,54 +101,53 @@ importAssets.prototype = {
101
101
  }
102
102
  }
103
103
 
104
- return self.uploadAsset(assetPath, self.assets[assetUid], uidContainer, urlContainer).then(function () {
104
+ return self.uploadAsset(assetPath, self.assets[assetUid], uidContainer, urlContainer).then(async function () {
105
105
  self.uidMapping[assetUid] = uidContainer[assetUid]
106
- self.urlMapping[self.assets[assetUid].url] = urlContainer[self.assets[
107
- assetUid].url]
106
+ self.urlMapping[self.assets[assetUid].url] = urlContainer[self.assets[assetUid].url]
108
107
 
109
- if (config.entriesPublish) {
110
- if (self.assets[assetUid].publish_details.length > 0) {
111
- let assetsUid = uidContainer[assetUid]
112
- if(self.assets[assetUid].publish_details.length !== 0 ) {
113
- return self.publish(assetsUid, self.assets[assetUid]).then(function () {
114
- return
115
- }).catch(error => {
116
- return
117
- })
118
- }
108
+ if (config.entriesPublish && self.assets[assetUid].publish_details.length > 0) {
109
+ let assetsUid = uidContainer[assetUid]
110
+ try {
111
+ return await self.publish(assetsUid, self.assets[assetUid])
112
+ } catch (error) {
113
+ return error
119
114
  }
120
115
  }
121
- return
122
116
  // assetUid has been successfully uploaded
123
117
  // log them onto /mapper/assets/success.json
124
118
  }).catch(function (error) {
125
- addlogs(config, chalk.red('Asset upload failed to import\n' + error, 'error'))
119
+ addlogs(config, chalk.red('Asset upload failed \n' + error, 'error'))
120
+ return error
126
121
  // asset failed to upload
127
122
  // log them onto /mapper/assets/fail.json
128
123
  })
129
124
  }
130
125
  addlogs(config, (currentAssetFolderPath + ' does not exist!'), 'error')
131
126
  }, {
132
- concurrency: assetBatchLimit,
127
+ concurrency: 1,
133
128
  }).then(function () {
134
129
  helper.writeFile(self.uidMapperPath, self.uidMapping)
135
130
  helper.writeFile(self.urlMapperPath, self.urlMapping)
136
131
  // completed uploading assets
137
132
  addlogs(config, 'Completed asset import of batch no: ' + (index + 1), 'success')
133
+ return index + 1
138
134
  // TODO: if there are failures, retry
139
135
  })
140
136
  }, {
141
137
  concurrency: 1,
142
138
  }).then(function () {
143
- addlogs(config, chalk.green('Asset import completed successfully!'), 'success')
139
+ let numberOfSuccessfulAssetUploads = Object.keys(self.uidMapping).length
140
+ if (numberOfSuccessfulAssetUploads > 0) {
141
+ addlogs(config, chalk.green(numberOfSuccessfulAssetUploads + ' assets uploaded successfully!'), 'success')
142
+ }
144
143
  // TODO: if there are failures, retry
145
144
  return resolve()
146
- }).catch(function () {
147
- return reject()
145
+ }).catch(function (error) {
146
+ return reject(error)
148
147
  })
149
- }).catch(function (error) {
150
- return reject()
151
- })
148
+ }).catch(function (error) {
149
+ return reject(error)
150
+ })
152
151
  })
153
152
  },
154
153
  uploadVersionedAssets: function (uid, assetFolderPath) {
@@ -187,7 +186,7 @@ importAssets.prototype = {
187
186
  return self.updateAsset(assetPath, assetMetadata, filesStreamed, uidContainer, urlContainer)
188
187
  .then(function () {
189
188
  filesStreamed.push(assetMetadata.filename)
190
- }).catch(error => {
189
+ }).catch(error => {
191
190
  })
192
191
  }, {
193
192
  concurrency: 1,
@@ -239,6 +238,7 @@ importAssets.prototype = {
239
238
  urlContainer[metadata.url] = response.url
240
239
  return resolve()
241
240
  }).catch(function (error) {
241
+ return reject(error)
242
242
  })
243
243
  })
244
244
  },
@@ -246,7 +246,7 @@ importAssets.prototype = {
246
246
  // let self = this
247
247
  return new Promise(function (resolve, reject) {
248
248
  let requestOption = {}
249
-
249
+
250
250
  if (metadata.hasOwnProperty('parent_uid') && typeof metadata.parent_uid === 'string') {
251
251
  requestOption.parent_uid = metadata.parent_uid
252
252
  }
@@ -275,7 +275,7 @@ importAssets.prototype = {
275
275
  },
276
276
 
277
277
  importFolders: function () {
278
- let self = this
278
+ let self = this
279
279
  return new Promise(function (resolve, reject) {
280
280
  let mappedFolderPath = path.resolve(config.data, 'mapper', 'assets', 'folder-mapping.json')
281
281
  self.folderDetails = helper.readFile(path.resolve(assetsFolderPath, 'folders.json'))
@@ -299,24 +299,24 @@ importAssets.prototype = {
299
299
  let idx = 0
300
300
  return Promise.map(self.folderBucket, function () {
301
301
  let folder = self.folderBucket[idx]
302
- if (createdFolders.hasOwnProperty(folder.json.asset.parent_uid)) {
302
+ if (createdFolders.hasOwnProperty(folder.json.asset.parent_uid)) {
303
303
  // replace old uid with new
304
304
  folder.json.asset.parent_uid = createdFolders[folder.json.asset.parent_uid]
305
- }
305
+ }
306
306
  return client.stack({api_key: config.target_stack, management_token: config.management_token}).asset().folder().create(folder.json)
307
- .then(response => {
307
+ .then(response => {
308
308
  addlogs(config, 'Created folder: \'' + folder.json.asset.name + '\'', 'success')
309
309
  // { oldUid: newUid }
310
310
  createdFolders[folder.oldUid] = response.uid
311
311
  helper.writeFile(mappedFolderPath, createdFolders)
312
312
  idx++
313
- return;
314
313
  }).catch(function (err) {
315
314
  let error = JSON.parse(err.message)
316
315
  if (error.errors.authorization || error.errors.api_key) {
317
316
  addlogs(config, chalk.red('Api_key or management_token is not valid'), 'error')
317
+ return reject(error)
318
318
  }
319
- return reject(error)
319
+ return error
320
320
  })
321
321
  }, {
322
322
  concurrency: 1,
@@ -374,6 +374,7 @@ importAssets.prototype = {
374
374
  let parent_uid = coll[j].parent_uid
375
375
  if (branch.hasOwnProperty(parent_uid)) {
376
376
  branch[parent_uid][coll[j].uid] = {}
377
+ coll.splice(j, 1);
377
378
  self.findBranches(branch[parent_uid], coll)
378
379
  }
379
380
  }
@@ -402,14 +403,17 @@ importAssets.prototype = {
402
403
  })
403
404
  requestObject.json.asset.environments = envId
404
405
  requestObject.json.asset.locales = locales
405
- return client.stack({api_key: config.target_stack, management_token: config.management_token}).asset(assetUid).publish({ publishDetails: requestObject.json.asset})
406
+ return client.stack({api_key: config.target_stack, management_token: config.management_token}).asset(assetUid).publish({publishDetails: requestObject.json.asset})
406
407
  .then(function () {
407
- addlogs(config, chalk.green('Asset ' + assetUid + ' published successfully'), 'success')
408
+ addlogs(config, 'Asset ' + assetUid + ' published successfully', 'success')
408
409
  return resolve()
409
410
  }).catch(function (err) {
410
- let error = JSON.parse(err.message)
411
- addlogs(config, chalk.red('Asset ' + assetUid + ' not published, '+ error.errorMessage), 'error')
412
- return reject(error)
411
+ if (err && err.message) {
412
+ let error = JSON.parse(err.message)
413
+ addlogs(config, chalk.red('Asset ' + assetUid + ' not published, ' + error.errorMessage), 'error')
414
+ return reject(err)
415
+ }
416
+ return reject(err)
413
417
  })
414
418
  })
415
419
  },
@@ -6,6 +6,7 @@
6
6
  */
7
7
  let mkdirp = require('mkdirp')
8
8
  let fs = require('fs')
9
+ let fsPromises = require('fs').promises
9
10
  let path = require('path')
10
11
  let _ = require('lodash')
11
12
  let Promise = require('bluebird')
@@ -15,24 +16,26 @@ let helper = require('../util/fs')
15
16
  let util = require('../util')
16
17
  let {addlogs} = require('../util/log')
17
18
  let supress = require('../util/extensionsUidReplace')
18
- let stack = require('../util/contentstack-management-sdk')
19
+ let sdkInstance = require('../util/contentstack-management-sdk')
19
20
 
20
21
  let config = require('../../config/default')
21
22
  let reqConcurrency = config.concurrency
23
+ let requestLimit = config.rateLimit
22
24
  let contentTypeConfig = config.modules.content_types
23
25
  let globalFieldConfig = config.modules.globalfields
24
- let globalfieldsFolderPath
26
+ let globalFieldsFolderPath
25
27
  let contentTypesFolderPath
26
28
  let mapperFolderPath
27
- let globalFieldMapperFolderpath
29
+ let globalFieldMapperFolderPath
28
30
  let globalFieldUpdateFile
29
- let skipFiles = ['__master.json', '__priority.json', 'schema.json']
31
+ let globalFieldPendingPath
32
+ let skipFiles = ['__master.json', '__priority.json', 'schema.json', '.DS_Store']
30
33
  let fileNames
31
34
  let field_rules_ct = []
32
35
  let client
36
+ let stack = {}
33
37
 
34
38
  function importContentTypes() {
35
- let self = this
36
39
  this.contentTypes = []
37
40
  this.schemaTemplate = require('../util/schemaTemplate')
38
41
  this.requestOptions = {
@@ -45,20 +48,22 @@ importContentTypes.prototype = {
45
48
  addlogs(config, 'Migrating contenttypes', 'success')
46
49
  let self = this
47
50
  config = credentialConfig
48
- client = stack.Client(config)
49
- globalfieldsFolderPath = path.resolve(config.data, globalFieldConfig.dirName)
51
+ client = sdkInstance.Client(config)
52
+ stack = client.stack({api_key: config.target_stack, management_token: config.management_token})
53
+ globalFieldsFolderPath = path.resolve(config.data, globalFieldConfig.dirName)
50
54
  contentTypesFolderPath = path.resolve(config.data, contentTypeConfig.dirName)
51
55
  mapperFolderPath = path.join(config.data, 'mapper', 'content_types')
52
- globalFieldMapperFolderpath = helper.readFile(path.join(config.data, 'mapper', 'global_fields', 'success.json'))
56
+ globalFieldMapperFolderPath = helper.readFile(path.join(config.data, 'mapper', 'global_fields', 'success.json'))
57
+ globalFieldPendingPath = helper.readFile(path.join(config.data, 'mapper', 'global_fields', 'pending_global_fields.js'))
53
58
  globalFieldUpdateFile = path.join(config.data, 'mapper', 'global_fields', 'success.json')
54
59
  fileNames = fs.readdirSync(path.join(contentTypesFolderPath))
55
- self.globalfields = helper.readFile(path.resolve(globalfieldsFolderPath, globalFieldConfig.fileName))
60
+ self.globalfields = helper.readFile(path.resolve(globalFieldsFolderPath, globalFieldConfig.fileName))
56
61
  for (let index in fileNames) {
57
62
  if (skipFiles.indexOf(fileNames[index]) === -1) {
58
63
  self.contentTypes.push(helper.readFile(path.join(contentTypesFolderPath, fileNames[index])))
59
64
  }
60
65
  }
61
-
66
+
62
67
  self.contentTypeUids = _.map(self.contentTypes, 'uid')
63
68
  self.createdContentTypeUids = []
64
69
  if (!fs.existsSync(mapperFolderPath)) {
@@ -69,13 +74,14 @@ importContentTypes.prototype = {
69
74
  self.createdContentTypeUids = helper.readFile(path.join(mapperFolderPath, 'success.json')) || []
70
75
  }
71
76
  self.contentTypeUids = _.difference(self.contentTypeUids, self.createdContentTypeUids)
77
+ self.uidToTitleMap = self.mapUidToTitle(self.contentTypes)
72
78
  // remove contet types, already created
73
79
  _.remove(this.contentTypes, function (contentType) {
74
80
  return self.contentTypeUids.indexOf(contentType.uid) === -1
75
81
  })
76
82
  return new Promise(function (resolve, reject) {
77
83
  return Promise.map(self.contentTypeUids, function (contentTypeUid) {
78
- return self.seedContentTypes(contentTypeUid).then(function () {
84
+ return self.seedContentTypes(contentTypeUid, self.uidToTitleMap[contentTypeUid]).then(function () {
79
85
 
80
86
  }).catch(function (error) {
81
87
  return reject(error)
@@ -84,84 +90,65 @@ importContentTypes.prototype = {
84
90
  // seed 3 content types at a time
85
91
  concurrency: reqConcurrency,
86
92
  }).then(function () {
87
- let batches = []
88
- let lenObj = self.contentTypes
89
- for (let i = 0; i < lenObj.length; i += 7) {
90
- batches.push(lenObj.slice(i, i + 7))
93
+ let batches = []
94
+ let lenObj = self.contentTypes
95
+ // var a = Math.round(2.60);
96
+ for (let i = 0; i < lenObj.length; i += Math.round(requestLimit / 3)) {
97
+ batches.push(lenObj.slice(i, i + Math.round(requestLimit / 3)))
91
98
  }
92
-
93
- return Promise.map(batches, function (batch) {
94
- return Promise.map(batch, function (contentType) {
95
- return self.updateContentTypes(contentType).then(function () {
99
+
100
+ return Promise.map(batches, async function (batch) {
101
+ return Promise.map(batch, async function (contentType) {
102
+ await self.updateContentTypes(contentType)
96
103
  addlogs(config, contentType.uid + ' was updated successfully!', 'success')
97
- return
98
- }).catch(function (err) {
99
- return reject()
104
+ },
105
+ {
106
+ concurrency: reqConcurrency,
107
+ }).then(function () {
108
+ }).catch(e => {
109
+ console.log('Something went wrong while migrating content type batch', e)
100
110
  })
101
- })
102
- }).then(function () {
111
+ }, {
112
+ concurrency: reqConcurrency,
113
+ }).then(async function () {
103
114
  // eslint-disable-next-line quotes
104
115
  if (field_rules_ct.length > 0) {
105
- fs.writeFile(contentTypesFolderPath + '/field_rules_uid.json', JSON.stringify(field_rules_ct), function (err) {
106
- if (err) throw err
116
+ // fs.writeFile(contentTypesFolderPath + '/field_rules_uid.json', JSON.stringify(field_rules_ct), function (err) {
117
+ // if (err) throw err
118
+ // })
119
+
120
+ await fsPromises.writeFile(contentTypesFolderPath + '/field_rules_uid.json', JSON.stringify(field_rules_ct))
121
+ }
122
+
123
+ if (globalFieldPendingPath && globalFieldPendingPath.length !== 0) {
124
+ return self.updateGlobalfields().then(function () {
125
+ addlogs(config, chalk.green('Content types have been imported successfully!'), 'success')
126
+ return resolve()
127
+ }).catch(error => {
128
+ addlogs(config, chalk.green('Error in GlobalFields'), 'success')
129
+ return reject()
107
130
  })
108
131
  }
109
-
110
- if( _globalField_pending.length !== 0 ) {
111
- return self.updateGlobalfields().then(function () {
112
- addlogs(config, chalk.green('Content types have been imported successfully!'), 'success')
113
- return resolve()
114
- }).catch(reject)
115
- } else {
116
- addlogs(config, chalk.green('Content types have been imported successfully!'), 'success')
117
- return resolve()
118
- }
132
+ addlogs(config, chalk.green('Content types have been imported successfully!'), 'success')
133
+ return resolve()
119
134
  }).catch(error => {
120
135
  return reject(error)
121
- })
122
- // content type seeidng completed
123
- // return Promise.map(self.contentTypes, function (contentType) {
124
- // return self.updateContentTypes(contentType).then(function () {
125
- // log.success(chalk.white(contentType.uid + ' was updated successfully!'))
126
- // return
127
- // }).catch(function (err) {
128
- // return reject()
129
- // })
130
- // }).then(function () {
131
- // // eslint-disable-next-line quotes
132
- // if (field_rules_ct.length > 0) {
133
- // fs.writeFile(contentTypesFolderPath + '/field_rules_uid.json', JSON.stringify(field_rules_ct), function (err) {
134
- // if (err) throw err
135
- // })
136
- // }
137
-
138
- // if( _globalField_pending.length !== 0 ) {
139
- // return self.updateGlobalfields().then(function () {
140
- // log.success(chalk.green('Content types have been imported successfully!'))
141
- // return resolve()
142
- // }).catch(reject)
143
- // } else {
144
- // log.success(chalk.green('Content types have been imported successfully!'))
145
- // return resolve()
146
- // }
147
- // }).catch(error => {
148
- // return reject(error)
149
- // })
136
+ })
150
137
  }).catch(error => {
151
138
  return reject(error)
152
139
  })
153
140
  })
154
141
  },
155
- seedContentTypes: function (uid) {
142
+ seedContentTypes: function (uid, title) {
156
143
  let self = this
157
144
  return new Promise(function (resolve, reject) {
158
145
  let body = _.cloneDeep(self.schemaTemplate)
159
146
  body.content_type.uid = uid
160
- body.content_type.title = uid
147
+ body.content_type.title = title
161
148
  let requestObject = _.cloneDeep(self.requestOptions)
162
149
  requestObject.json = body
163
- return client.stack({api_key: config.target_stack, management_token: config.management_token}).contentType().create(requestObject.json)
164
- .then(result => {
150
+ return stack.contentType().create(requestObject.json)
151
+ .then(() => {
165
152
  return resolve()
166
153
  })
167
154
  .catch(function (err) {
@@ -177,25 +164,24 @@ importContentTypes.prototype = {
177
164
  updateContentTypes: function (contentType) {
178
165
  let self = this
179
166
  return new Promise(function (resolve, reject) {
180
- let requestObject = _.cloneDeep(self.requestOptions)
181
- if (contentType.field_rules) {
182
- field_rules_ct.push(contentType.uid)
183
- delete contentType.field_rules
184
- }
185
- supress(contentType.schema)
186
- requestObject.json.content_type = contentType
187
- client.stack({api_key: config.target_stack, management_token: config.management_token}).contentType(contentType.uid).fetch()
188
- .then(contentTypeResponse => {
167
+ setTimeout(function () {
168
+ let requestObject = _.cloneDeep(self.requestOptions)
169
+ if (contentType.field_rules) {
170
+ field_rules_ct.push(contentType.uid)
171
+ delete contentType.field_rules
172
+ }
173
+ supress(contentType.schema)
174
+ requestObject.json.content_type = contentType
175
+ let contentTypeResponse = stack.contentType(contentType.uid)
189
176
  Object.assign(contentTypeResponse, _.cloneDeep(contentType))
190
177
  contentTypeResponse.update()
191
- })
192
- .then(UpdatedcontentType => {
193
- return resolve()
194
- }).catch(err => {
195
- let error = JSON.parse(err.message)
196
- addlogs(config, error, 'error')
197
- return reject()
198
- })
178
+ .then(UpdatedcontentType => {
179
+ return resolve()
180
+ }).catch(err => {
181
+ addlogs(config, err, 'error')
182
+ return reject(err)
183
+ })
184
+ }, 1000)
199
185
  })
200
186
  },
201
187
 
@@ -203,23 +189,22 @@ importContentTypes.prototype = {
203
189
  let self = this
204
190
  return new Promise(function (resolve, reject) {
205
191
  // eslint-disable-next-line no-undef
206
- return Promise.map(_globalField_pending, function (globalfield) {
207
- let lenGlobalField = (self.globalfields).length
208
- let Obj = _.find(self.globalfields, { 'uid': globalfield});
209
- return client.stack({api_key: config.target_stack, management_token: config.management_token}).globalField(globalfield).fetch()
192
+ return Promise.map(globalFieldPendingPath, function (globalfield) {
193
+ let Obj = _.find(self.globalfields, {uid: globalfield})
194
+ let globalFieldObj = stack.globalField(globalfield)
195
+ Object.assign(globalFieldObj, _.cloneDeep(Obj))
196
+ return globalFieldObj.update()
210
197
  .then(globalFieldResponse => {
211
- globalFieldResponse.schema = Obj.schema
212
- globalFieldResponse.update()
213
- let updateObjpos = _.findIndex(globalFieldMapperFolderpath, function (successobj) {
198
+ let updateObjpos = _.findIndex(globalFieldMapperFolderPath, function (successobj) {
214
199
  let global_field_uid = globalFieldResponse.uid
215
200
  return global_field_uid === successobj
216
201
  })
217
- globalFieldMapperFolderpath.splice(updateObjpos, 1, Obj)
218
- helper.writeFile(globalFieldUpdateFile, globalFieldMapperFolderpath)
202
+ globalFieldMapperFolderPath.splice(updateObjpos, 1, Obj)
203
+ helper.writeFile(globalFieldUpdateFile, globalFieldMapperFolderPath)
219
204
  }).catch(function (err) {
220
205
  let error = JSON.parse(err.message)
221
206
  // eslint-disable-next-line no-console
222
- addlogs(config, chalk.red('Globalfield failed to update ' + JSON.stringify(error.errors)), 'error')
207
+ addlogs(config, chalk.red('Global Field failed to update ' + JSON.stringify(error.errors)), 'error')
223
208
  })
224
209
  }, {
225
210
  concurrency: reqConcurrency,
@@ -231,6 +216,14 @@ importContentTypes.prototype = {
231
216
  })
232
217
  })
233
218
  },
219
+
220
+ mapUidToTitle: function (contentTypes) {
221
+ let result = {}
222
+ contentTypes.forEach(ct => {
223
+ result[ct.uid] = ct.title
224
+ })
225
+ return result
226
+ },
234
227
  }
235
228
 
236
- module.exports = new importContentTypes()
229
+ module.exports = new importContentTypes()