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

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
145
  }).catch(function () {
147
146
  return reject()
148
147
  })
149
- }).catch(function (error) {
150
- return reject()
151
- })
148
+ }).catch(function (error) {
149
+ return reject()
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,21 +16,24 @@ 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
39
  let self = this
@@ -45,20 +49,22 @@ importContentTypes.prototype = {
45
49
  addlogs(config, 'Migrating contenttypes', 'success')
46
50
  let self = this
47
51
  config = credentialConfig
48
- client = stack.Client(config)
49
- globalfieldsFolderPath = path.resolve(config.data, globalFieldConfig.dirName)
52
+ client = sdkInstance.Client(config)
53
+ stack = client.stack({api_key: config.target_stack, management_token: config.management_token})
54
+ globalFieldsFolderPath = path.resolve(config.data, globalFieldConfig.dirName)
50
55
  contentTypesFolderPath = path.resolve(config.data, contentTypeConfig.dirName)
51
56
  mapperFolderPath = path.join(config.data, 'mapper', 'content_types')
52
- globalFieldMapperFolderpath = helper.readFile(path.join(config.data, 'mapper', 'global_fields', 'success.json'))
57
+ globalFieldMapperFolderPath = helper.readFile(path.join(config.data, 'mapper', 'global_fields', 'success.json'))
58
+ globalFieldPendingPath = helper.readFile(path.join(config.data, 'mapper', 'global_fields', 'pending_global_fields.js'))
53
59
  globalFieldUpdateFile = path.join(config.data, 'mapper', 'global_fields', 'success.json')
54
60
  fileNames = fs.readdirSync(path.join(contentTypesFolderPath))
55
- self.globalfields = helper.readFile(path.resolve(globalfieldsFolderPath, globalFieldConfig.fileName))
61
+ self.globalfields = helper.readFile(path.resolve(globalFieldsFolderPath, globalFieldConfig.fileName))
56
62
  for (let index in fileNames) {
57
63
  if (skipFiles.indexOf(fileNames[index]) === -1) {
58
64
  self.contentTypes.push(helper.readFile(path.join(contentTypesFolderPath, fileNames[index])))
59
65
  }
60
66
  }
61
-
67
+
62
68
  self.contentTypeUids = _.map(self.contentTypes, 'uid')
63
69
  self.createdContentTypeUids = []
64
70
  if (!fs.existsSync(mapperFolderPath)) {
@@ -69,13 +75,14 @@ importContentTypes.prototype = {
69
75
  self.createdContentTypeUids = helper.readFile(path.join(mapperFolderPath, 'success.json')) || []
70
76
  }
71
77
  self.contentTypeUids = _.difference(self.contentTypeUids, self.createdContentTypeUids)
78
+ self.uidToTitleMap = self.mapUidToTitle(self.contentTypes)
72
79
  // remove contet types, already created
73
80
  _.remove(this.contentTypes, function (contentType) {
74
81
  return self.contentTypeUids.indexOf(contentType.uid) === -1
75
82
  })
76
83
  return new Promise(function (resolve, reject) {
77
84
  return Promise.map(self.contentTypeUids, function (contentTypeUid) {
78
- return self.seedContentTypes(contentTypeUid).then(function () {
85
+ return self.seedContentTypes(contentTypeUid, self.uidToTitleMap[contentTypeUid]).then(function () {
79
86
 
80
87
  }).catch(function (error) {
81
88
  return reject(error)
@@ -84,84 +91,65 @@ importContentTypes.prototype = {
84
91
  // seed 3 content types at a time
85
92
  concurrency: reqConcurrency,
86
93
  }).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))
94
+ let batches = []
95
+ let lenObj = self.contentTypes
96
+ // var a = Math.round(2.60);
97
+ for (let i = 0; i < lenObj.length; i += Math.round(requestLimit / 3)) {
98
+ batches.push(lenObj.slice(i, i + Math.round(requestLimit / 3)))
91
99
  }
92
-
93
- return Promise.map(batches, function (batch) {
94
- return Promise.map(batch, function (contentType) {
95
- return self.updateContentTypes(contentType).then(function () {
100
+
101
+ return Promise.map(batches, async function (batch) {
102
+ return Promise.map(batch, async function (contentType) {
103
+ await self.updateContentTypes(contentType)
96
104
  addlogs(config, contentType.uid + ' was updated successfully!', 'success')
97
- return
98
- }).catch(function (err) {
99
- return reject()
105
+ },
106
+ {
107
+ concurrency: reqConcurrency,
108
+ }).then(function () {
109
+ }).catch(e => {
110
+ console.log('Something went wrong while migrating content type batch', e)
100
111
  })
101
- })
102
- }).then(function () {
112
+ }, {
113
+ concurrency: reqConcurrency,
114
+ }).then(async function () {
103
115
  // eslint-disable-next-line quotes
104
116
  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
117
+ // fs.writeFile(contentTypesFolderPath + '/field_rules_uid.json', JSON.stringify(field_rules_ct), function (err) {
118
+ // if (err) throw err
119
+ // })
120
+
121
+ await fsPromises.writeFile(contentTypesFolderPath + '/field_rules_uid.json', JSON.stringify(field_rules_ct))
122
+ }
123
+
124
+ if (globalFieldPendingPath && globalFieldPendingPath.length !== 0) {
125
+ return self.updateGlobalfields().then(function () {
126
+ addlogs(config, chalk.green('Content types have been imported successfully!'), 'success')
127
+ return resolve()
128
+ }).catch(error => {
129
+ addlogs(config, chalk.green('Error in GlobalFields'), 'success')
130
+ return reject()
107
131
  })
108
132
  }
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
- }
133
+ addlogs(config, chalk.green('Content types have been imported successfully!'), 'success')
134
+ return resolve()
119
135
  }).catch(error => {
120
136
  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
- // })
137
+ })
150
138
  }).catch(error => {
151
139
  return reject(error)
152
140
  })
153
141
  })
154
142
  },
155
- seedContentTypes: function (uid) {
143
+ seedContentTypes: function (uid, title) {
156
144
  let self = this
157
145
  return new Promise(function (resolve, reject) {
158
146
  let body = _.cloneDeep(self.schemaTemplate)
159
147
  body.content_type.uid = uid
160
- body.content_type.title = uid
148
+ body.content_type.title = title
161
149
  let requestObject = _.cloneDeep(self.requestOptions)
162
150
  requestObject.json = body
163
- return client.stack({api_key: config.target_stack, management_token: config.management_token}).contentType().create(requestObject.json)
164
- .then(result => {
151
+ return stack.contentType().create(requestObject.json)
152
+ .then(() => {
165
153
  return resolve()
166
154
  })
167
155
  .catch(function (err) {
@@ -177,25 +165,24 @@ importContentTypes.prototype = {
177
165
  updateContentTypes: function (contentType) {
178
166
  let self = this
179
167
  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 => {
168
+ setTimeout(function () {
169
+ let requestObject = _.cloneDeep(self.requestOptions)
170
+ if (contentType.field_rules) {
171
+ field_rules_ct.push(contentType.uid)
172
+ delete contentType.field_rules
173
+ }
174
+ supress(contentType.schema)
175
+ requestObject.json.content_type = contentType
176
+ let contentTypeResponse = stack.contentType(contentType.uid)
189
177
  Object.assign(contentTypeResponse, _.cloneDeep(contentType))
190
178
  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
- })
179
+ .then(UpdatedcontentType => {
180
+ return resolve()
181
+ }).catch(err => {
182
+ addlogs(config, err, 'error')
183
+ return reject()
184
+ })
185
+ }, 1000)
199
186
  })
200
187
  },
201
188
 
@@ -203,23 +190,23 @@ importContentTypes.prototype = {
203
190
  let self = this
204
191
  return new Promise(function (resolve, reject) {
205
192
  // eslint-disable-next-line no-undef
206
- return Promise.map(_globalField_pending, function (globalfield) {
193
+ return Promise.map(globalFieldPendingPath, function (globalfield) {
207
194
  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()
195
+ let Obj = _.find(self.globalfields, {uid: globalfield})
196
+ let globalFieldObj = stack.globalField(globalfield)
197
+ Object.assign(globalFieldObj, _.cloneDeep(Obj))
198
+ return globalFieldObj.update()
210
199
  .then(globalFieldResponse => {
211
- globalFieldResponse.schema = Obj.schema
212
- globalFieldResponse.update()
213
- let updateObjpos = _.findIndex(globalFieldMapperFolderpath, function (successobj) {
200
+ let updateObjpos = _.findIndex(globalFieldMapperFolderPath, function (successobj) {
214
201
  let global_field_uid = globalFieldResponse.uid
215
202
  return global_field_uid === successobj
216
203
  })
217
- globalFieldMapperFolderpath.splice(updateObjpos, 1, Obj)
218
- helper.writeFile(globalFieldUpdateFile, globalFieldMapperFolderpath)
204
+ globalFieldMapperFolderPath.splice(updateObjpos, 1, Obj)
205
+ helper.writeFile(globalFieldUpdateFile, globalFieldMapperFolderPath)
219
206
  }).catch(function (err) {
220
207
  let error = JSON.parse(err.message)
221
208
  // eslint-disable-next-line no-console
222
- addlogs(config, chalk.red('Globalfield failed to update ' + JSON.stringify(error.errors)), 'error')
209
+ addlogs(config, chalk.red('Global Field failed to update ' + JSON.stringify(error.errors)), 'error')
223
210
  })
224
211
  }, {
225
212
  concurrency: reqConcurrency,
@@ -231,6 +218,14 @@ importContentTypes.prototype = {
231
218
  })
232
219
  })
233
220
  },
221
+
222
+ mapUidToTitle: function (contentTypes) {
223
+ let result = {}
224
+ contentTypes.forEach(ct => {
225
+ result[ct.uid] = ct.title
226
+ })
227
+ return result
228
+ },
234
229
  }
235
230
 
236
- module.exports = new importContentTypes()
231
+ module.exports = new importContentTypes()