@contentstack/cli-cm-import 1.5.11 → 1.7.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.
Files changed (126) hide show
  1. package/README.md +6 -14
  2. package/bin/dev +17 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/run +6 -0
  5. package/bin/run.cmd +3 -0
  6. package/lib/commands/cm/stacks/import.d.ts +10 -0
  7. package/lib/commands/cm/stacks/import.js +111 -0
  8. package/lib/config/index.d.ts +3 -0
  9. package/lib/config/index.js +395 -0
  10. package/lib/import/index.d.ts +1 -0
  11. package/lib/import/index.js +8 -0
  12. package/lib/import/module-importer.d.ts +13 -0
  13. package/lib/import/module-importer.js +70 -0
  14. package/lib/import/modules/assets.d.ts +63 -0
  15. package/lib/import/modules/assets.js +265 -0
  16. package/lib/import/modules/base-class.d.ts +70 -0
  17. package/lib/import/modules/base-class.js +218 -0
  18. package/lib/import/modules/content-types.d.ts +56 -0
  19. package/lib/import/modules/content-types.js +186 -0
  20. package/lib/import/modules/custom-roles.d.ts +37 -0
  21. package/lib/import/modules/custom-roles.js +171 -0
  22. package/lib/import/modules/environments.d.ts +27 -0
  23. package/lib/import/modules/environments.js +106 -0
  24. package/lib/import/modules/extensions.d.ts +27 -0
  25. package/lib/import/modules/extensions.js +106 -0
  26. package/lib/import/modules/global-fields.d.ts +34 -0
  27. package/lib/import/modules/global-fields.js +99 -0
  28. package/lib/import/modules/index.d.ts +2 -0
  29. package/lib/import/modules/index.js +19 -0
  30. package/lib/import/modules/labels.d.ts +34 -0
  31. package/lib/import/modules/labels.js +171 -0
  32. package/lib/import/modules/locales.d.ts +31 -0
  33. package/lib/import/modules/locales.js +144 -0
  34. package/lib/import/modules/marketplace-apps.d.ts +51 -0
  35. package/lib/import/modules/marketplace-apps.js +297 -0
  36. package/lib/import/modules/webhooks.d.ts +27 -0
  37. package/lib/import/modules/webhooks.js +110 -0
  38. package/lib/import/modules-js/assets.d.ts +33 -0
  39. package/lib/import/modules-js/assets.js +415 -0
  40. package/lib/import/modules-js/content-types.d.ts +33 -0
  41. package/lib/import/modules-js/content-types.js +176 -0
  42. package/lib/import/modules-js/custom-roles.d.ts +15 -0
  43. package/lib/import/modules-js/custom-roles.js +143 -0
  44. package/lib/import/modules-js/entries.d.ts +54 -0
  45. package/lib/import/modules-js/entries.js +1260 -0
  46. package/lib/import/modules-js/environments.d.ts +13 -0
  47. package/lib/import/modules-js/environments.js +85 -0
  48. package/lib/import/modules-js/extensions.d.ts +18 -0
  49. package/lib/import/modules-js/extensions.js +86 -0
  50. package/lib/import/modules-js/global-fields.d.ts +13 -0
  51. package/lib/import/modules-js/global-fields.js +109 -0
  52. package/lib/import/modules-js/index.d.ts +1 -0
  53. package/lib/import/modules-js/index.js +33 -0
  54. package/lib/import/modules-js/labels.d.ts +20 -0
  55. package/lib/import/modules-js/labels.js +148 -0
  56. package/lib/import/modules-js/locales.d.ts +24 -0
  57. package/lib/import/modules-js/locales.js +196 -0
  58. package/lib/import/modules-js/marketplace-apps.d.ts +60 -0
  59. package/lib/import/modules-js/marketplace-apps.js +409 -0
  60. package/lib/import/modules-js/webhooks.d.ts +17 -0
  61. package/lib/import/modules-js/webhooks.js +85 -0
  62. package/lib/import/modules-js/workflows.d.ts +18 -0
  63. package/lib/import/modules-js/workflows.js +132 -0
  64. package/lib/types/default-config.d.ts +143 -0
  65. package/lib/types/default-config.js +2 -0
  66. package/lib/types/import-config.d.ts +52 -0
  67. package/lib/types/import-config.js +2 -0
  68. package/lib/types/index.d.ts +63 -0
  69. package/lib/types/index.js +4 -0
  70. package/lib/utils/asset-helper.d.ts +4 -0
  71. package/lib/utils/asset-helper.js +387 -0
  72. package/lib/utils/backup-handler.d.ts +2 -0
  73. package/lib/utils/backup-handler.js +31 -0
  74. package/lib/utils/common-helper.d.ts +20 -0
  75. package/lib/utils/common-helper.js +244 -0
  76. package/lib/utils/content-type-helper.d.ts +51 -0
  77. package/lib/utils/content-type-helper.js +145 -0
  78. package/lib/utils/entries-helper.d.ts +4 -0
  79. package/lib/utils/entries-helper.js +252 -0
  80. package/lib/utils/extension-helper.d.ts +5 -0
  81. package/lib/utils/extension-helper.js +84 -0
  82. package/lib/utils/file-helper.d.ts +14 -0
  83. package/lib/utils/file-helper.js +140 -0
  84. package/lib/utils/import-config-handler.d.ts +3 -0
  85. package/lib/utils/import-config-handler.js +73 -0
  86. package/lib/utils/index.d.ts +12 -0
  87. package/lib/utils/index.js +39 -0
  88. package/lib/utils/interactive.d.ts +7 -0
  89. package/lib/utils/interactive.js +88 -0
  90. package/lib/utils/logger.d.ts +8 -0
  91. package/lib/utils/logger.js +154 -0
  92. package/lib/utils/login-handler.d.ts +8 -0
  93. package/lib/utils/login-handler.js +53 -0
  94. package/lib/utils/marketplace-app-helper.d.ts +16 -0
  95. package/lib/utils/marketplace-app-helper.js +143 -0
  96. package/messages/index.json +1 -7
  97. package/oclif.manifest.json +2 -2
  98. package/package.json +46 -20
  99. package/src/app.js +0 -217
  100. package/src/commands/cm/stacks/import.js +0 -161
  101. package/src/config/default.js +0 -352
  102. package/src/lib/import/assets.js +0 -495
  103. package/src/lib/import/content-types.js +0 -201
  104. package/src/lib/import/custom-roles.js +0 -169
  105. package/src/lib/import/entries.js +0 -1495
  106. package/src/lib/import/environments.js +0 -106
  107. package/src/lib/import/extensions.js +0 -108
  108. package/src/lib/import/global-fields.js +0 -135
  109. package/src/lib/import/labels.js +0 -175
  110. package/src/lib/import/locales.js +0 -216
  111. package/src/lib/import/marketplace-apps.js +0 -542
  112. package/src/lib/import/webhooks.js +0 -113
  113. package/src/lib/import/workflows.js +0 -166
  114. package/src/lib/util/extensionsUidReplace.js +0 -67
  115. package/src/lib/util/fs.js +0 -124
  116. package/src/lib/util/import-flags.js +0 -187
  117. package/src/lib/util/index.js +0 -222
  118. package/src/lib/util/log.js +0 -144
  119. package/src/lib/util/login.js +0 -58
  120. package/src/lib/util/lookupReplaceAssets.js +0 -366
  121. package/src/lib/util/lookupReplaceEntries.js +0 -250
  122. package/src/lib/util/marketplace-app-helper.js +0 -31
  123. package/src/lib/util/removeReferenceFields.js +0 -59
  124. package/src/lib/util/schemaTemplate.js +0 -38
  125. package/src/lib/util/supress-mandatory-fields.js +0 -34
  126. package/src/lib/util/upload.js +0 -56
@@ -1,495 +0,0 @@
1
- /*!
2
- * Contentstack Import
3
- * Copyright (c) 2019 Contentstack LLC
4
- * MIT Licensed
5
- */
6
- const fs = require('fs');
7
- const _ = require('lodash');
8
- const path = require('path');
9
- const chalk = require('chalk');
10
- const mkdirp = require('mkdirp');
11
- const Promise = require('bluebird');
12
-
13
- const helper = require('../util/fs');
14
- let upload = require('../util/upload');
15
- const { addlogs } = require('../util/log');
16
- let config = require('../../config/default');
17
-
18
- module.exports = class ImportAssets {
19
- assets;
20
- fails = [];
21
- assetConfig;
22
- mapperDirPath;
23
- assetBatchLimit;
24
- uidMapping = {};
25
- urlMapping = {};
26
- environmentPath;
27
- assetBucket = [];
28
- assetsFolderPath;
29
- folderBucket = [];
30
- folderDetails = [];
31
- mappedFolderUids = {};
32
-
33
- constructor(importConfig, stackAPIClient) {
34
- this.config = _.merge(config, importConfig);
35
- this.stackAPIClient = stackAPIClient;
36
- this.assetConfig = config.modules.assets;
37
- this.assetBatchLimit =
38
- this.assetConfig.hasOwnProperty('assetBatchLimit') && typeof this.assetConfig.assetBatchLimit === 'number'
39
- ? this.assetConfig.assetBatchLimit
40
- : 2;
41
- }
42
-
43
- start() {
44
- let self = this;
45
- addlogs(self.config, 'Migrating assets', 'success');
46
- this.assetsFolderPath = path.join(this.config.data, this.config.modules.assets.dirName);
47
- this.mapperDirPath = path.resolve(this.config.data, 'mapper', 'assets');
48
- this.environmentPath = path.resolve(this.config.data, 'environments', 'environments.json');
49
- this.uidMapperPath = path.join(this.mapperDirPath, 'uid-mapping.json');
50
- this.urlMapperPath = path.join(this.mapperDirPath, 'url-mapping.json');
51
- this.failsPath = path.join(this.mapperDirPath, 'fail.json');
52
- this.assets = helper.readFileSync(path.join(this.assetsFolderPath, this.assetConfig.fileName));
53
- this.environment = helper.readFileSync(this.environmentPath);
54
- if (fs.existsSync(this.uidMapperPath)) {
55
- this.uidMapping = helper.readFileSync(this.uidMapperPath);
56
- }
57
- if (fs.existsSync(this.urlMapperPath)) {
58
- this.urlMapping = helper.readFileSync(this.urlMapperPath);
59
- }
60
-
61
- mkdirp.sync(this.mapperDirPath);
62
-
63
- return new Promise(function (resolve, reject) {
64
- if (self.assets === undefined || _.isEmpty(self.assets)) {
65
- addlogs(self.config, 'No Assets Found', 'success');
66
- return resolve({ empty: true });
67
- }
68
-
69
- let batches = [];
70
- let assetUids = Object.keys(self.assets);
71
-
72
- for (let i = 0; i < assetUids.length; i += self.assetBatchLimit) {
73
- batches.push(assetUids.slice(i, i + self.assetBatchLimit));
74
- }
75
-
76
- return self
77
- .importFolders()
78
- .then(function () {
79
- return Promise.map(
80
- batches,
81
- async function (batch, index) {
82
- return Promise.map(
83
- batch,
84
- function (assetUid) {
85
- if (self.uidMapping.hasOwnProperty(assetUid)) {
86
- addlogs(
87
- self.config,
88
- 'Skipping upload of asset: ' + assetUid + '. Its mapped to: ' + self.uidMapping[assetUid],
89
- 'success',
90
- );
91
- // the asset has been already imported
92
- return void 0;
93
- }
94
- let currentAssetFolderPath = path.join(self.assetsFolderPath, assetUid);
95
- if (fs.existsSync(currentAssetFolderPath)) {
96
- // if this is true, means, the exported asset data is versioned
97
- // hence, upload each asset with its version
98
- if (self.config.versioning) {
99
- return self.uploadVersionedAssets(assetUid, currentAssetFolderPath).catch(function (error) {
100
- addlogs(self.config, `Asset upload failed.\n ${error}`, 'error');
101
- });
102
- }
103
-
104
- let uidContainer = {};
105
- let urlContainer = {};
106
- let assetPath = path.resolve(currentAssetFolderPath, self.assets[assetUid].filename);
107
-
108
- if (self.assets[assetUid].parent_uid && typeof self.assets[assetUid].parent_uid === 'string') {
109
- if (self.mappedFolderUids.hasOwnProperty(self.assets[assetUid].parent_uid)) {
110
- self.assets[assetUid].parent_uid = self.mappedFolderUids[self.assets[assetUid].parent_uid];
111
- } else {
112
- addlogs(
113
- self.config,
114
- `'${self.assets[assetUid].parent_uid}' parent_uid was not found! Thus, setting it as 'null'`,
115
- 'error',
116
- );
117
- }
118
- }
119
-
120
- return self
121
- .uploadAsset(assetPath, self.assets[assetUid], uidContainer, urlContainer)
122
- .then(async function () {
123
- self.uidMapping[assetUid] = uidContainer[assetUid];
124
- self.urlMapping[self.assets[assetUid].url] = urlContainer[self.assets[assetUid].url];
125
-
126
- if (self.config.entriesPublish && self.assets[assetUid].publish_details.length > 0) {
127
- let assetsUid = uidContainer[assetUid];
128
- try {
129
- return await self.publish(assetsUid, self.assets[assetUid]);
130
- } catch (error) {
131
- return error;
132
- }
133
- }
134
- // assetUid has been successfully uploaded
135
- // log them onto /mapper/assets/success.json
136
- })
137
- .catch(function (error) {
138
- addlogs(self.config, `Asset upload failed.\n ${error}`, 'error');
139
- return error;
140
- // asset failed to upload
141
- // log them onto /mapper/assets/fail.json
142
- });
143
- }
144
- addlogs(self.config, `'${currentAssetFolderPath}' does not exist!`, 'error');
145
- },
146
- { concurrency: self.assetConfig.assetBatchLimit },
147
- ).then(function () {
148
- helper.writeFileSync(self.uidMapperPath, self.uidMapping);
149
- helper.writeFileSync(self.urlMapperPath, self.urlMapping);
150
- // completed uploading assets
151
- addlogs(self.config, 'Completed asset import of batch no: ' + (index + 1), 'success');
152
- return index + 1;
153
- // TODO: if there are failures, retry
154
- });
155
- },
156
- { concurrency: 1 },
157
- )
158
- .then(function () {
159
- let numberOfSuccessfulAssetUploads = Object.keys(self.uidMapping).length;
160
- if (numberOfSuccessfulAssetUploads > 0) {
161
- addlogs(
162
- self.config,
163
- chalk.green(numberOfSuccessfulAssetUploads + ' assets uploaded successfully!'),
164
- 'success',
165
- );
166
- }
167
- // TODO: if there are failures, retry
168
- return resolve();
169
- })
170
- .catch(function (error) {
171
- addlogs(self.config, error, 'error');
172
- return reject(error);
173
- });
174
- })
175
- .catch(function (error) {
176
- addlogs(self.config, error, 'error');
177
- return reject(error);
178
- });
179
- });
180
- }
181
-
182
- uploadVersionedAssets(uid, assetFolderPath) {
183
- let self = this;
184
- return new Promise(function (resolve, reject) {
185
- let versionedAssetMetadata = helper.readFileSync(path.join(assetFolderPath, '_contentstack_' + uid + '.json'));
186
- // using last version, find asset's parent
187
- let lastVersion = versionedAssetMetadata[versionedAssetMetadata.length - 1];
188
-
189
- if (typeof lastVersion.parent_uid === 'string') {
190
- if (self.mappedFolderUids.hasOwnProperty(lastVersion.parent_uid)) {
191
- // update each version of that asset with the last version's parent_uid
192
- versionedAssetMetadata.forEach(function (assetMetadata) {
193
- assetMetadata.parent_uid = self.mappedFolderUids[lastVersion.parent_uid];
194
- });
195
- } else {
196
- addlogs(
197
- self.config,
198
- `'${lastVersion.parent_uid}' parent_uid was not found! Thus, setting it as 'null'`,
199
- 'error'
200
- );
201
- versionedAssetMetadata.forEach(function (assetMetadata) {
202
- assetMetadata.parent_uid = null;
203
- });
204
- }
205
- }
206
- let counter = 0;
207
- let uidContainer = {};
208
- let urlContainer = {};
209
- let filesStreamed = [];
210
-
211
- return Promise.map(
212
- versionedAssetMetadata,
213
- function () {
214
- let assetMetadata = versionedAssetMetadata[counter];
215
- let assetPath = path.join(assetFolderPath, assetMetadata.filename);
216
-
217
- if (++counter === 1) {
218
- return self
219
- .uploadAsset(assetPath, assetMetadata, uidContainer, urlContainer)
220
- .then(function () {
221
- filesStreamed.push(assetMetadata.filename);
222
- })
223
- .catch((error) => {
224
- addlogs(self.config, error, 'error');
225
- reject(error);
226
- });
227
- }
228
-
229
- return self
230
- .updateAsset(assetPath, assetMetadata, filesStreamed, uidContainer, urlContainer)
231
- .then(function () {
232
- filesStreamed.push(assetMetadata.filename);
233
- })
234
- .catch((error) => {
235
- addlogs(self.config, error, 'error');
236
- });
237
- },
238
- { concurrency: self.assetConfig.uploadAssetsConcurrency },
239
- )
240
- .then(function () {
241
- self.uidMapping[uid] = uidContainer[uid];
242
- for (let url in urlContainer) {
243
- self.urlMapping[url] = urlContainer[url];
244
- }
245
- // completed uploading all the versions of the asset
246
- return resolve();
247
- })
248
- .catch(function (error) {
249
- // failed to upload asset
250
- // write it on fail logs, but do not stop the process
251
- addlogs(self.config, `Failed to upload asset\n ${error}`, 'error');
252
- return resolve();
253
- });
254
- });
255
- }
256
-
257
- updateAsset(assetPath, metadata, filesStreamed, _uidContainer, urlContainer) {
258
- const self = this;
259
- return new Promise(function (resolve, reject) {
260
- let requestOption = {};
261
- if (filesStreamed && filesStreamed.indexOf(metadata.filename) !== -1) {
262
- addlogs(self.config, 'Skipping re-upload/streaming of ' + metadata.uid + '/' + metadata.filename, 'success');
263
- requestOption.formData = {};
264
- return resolve();
265
- }
266
-
267
- addlogs(self.config, 'Streaming: ' + metadata.uid + '/' + metadata.filename, 'success');
268
- requestOption.formData = {};
269
-
270
- if (metadata.hasOwnProperty('parent_uid') && typeof metadata.parent_uid === 'string') {
271
- requestOption.formData['asset[parent_uid]'] = metadata.parent_uid;
272
- }
273
-
274
- if (metadata.hasOwnProperty('description') && typeof metadata.description === 'string') {
275
- requestOption.formData['asset[description]'] = metadata.description;
276
- }
277
-
278
- if (metadata.hasOwnProperty('tags') && Array.isArray(metadata.tags)) {
279
- requestOption.formData['asset[tags]'] = metadata.tags;
280
- }
281
-
282
- if (metadata.hasOwnProperty('title') && typeof metadata.title === 'string') {
283
- requestOption.formData['asset[title]'] = metadata.title;
284
- }
285
-
286
- return upload(requestOption, assetPath)
287
- .then(function (response) {
288
- urlContainer[metadata.url] = response.url;
289
- return resolve();
290
- })
291
- .catch(function (error) {
292
- addlogs(self.config, error, 'error');
293
- return reject(error);
294
- });
295
- });
296
- }
297
-
298
- uploadAsset(assetPath, metadata, uidContainer, urlContainer) {
299
- const self = this;
300
- return new Promise(function (resolve, reject) {
301
- let requestOption = {};
302
-
303
- if (metadata.hasOwnProperty('parent_uid') && typeof metadata.parent_uid === 'string') {
304
- requestOption.parent_uid = metadata.parent_uid;
305
- }
306
-
307
- if (metadata.hasOwnProperty('description') && typeof metadata.description === 'string') {
308
- requestOption.description = metadata.description;
309
- }
310
-
311
- // eslint-disable-next-line no-prototype-builtins
312
- if (metadata.hasOwnProperty('tags') && Array.isArray(metadata.tags)) {
313
- requestOption.tags = metadata.tags;
314
- }
315
-
316
- if (metadata.hasOwnProperty('title') && typeof metadata.title === 'string') {
317
- requestOption.title = metadata.title;
318
- }
319
- return upload(requestOption, assetPath)
320
- .then(function (response) {
321
- uidContainer[metadata.uid] = response.uid;
322
- urlContainer[metadata.url] = response.url;
323
- return resolve();
324
- })
325
- .catch(function (error) {
326
- addlogs(self.config, error, 'error');
327
- return reject(error);
328
- });
329
- });
330
- }
331
-
332
- importFolders() {
333
- let self = this;
334
- return new Promise(function (resolve, reject) {
335
- let mappedFolderPath = path.resolve(self.config.data, 'mapper', 'assets', 'folder-mapping.json');
336
- self.folderDetails = helper.readFileSync(path.resolve(self.assetsFolderPath, 'folders.json'));
337
-
338
- if (_.isEmpty(self.folderDetails)) {
339
- addlogs(
340
- self.config,
341
- 'No folders were found at: ' + path.join(self.assetsFolderPath, 'folders.json'),
342
- 'success',
343
- );
344
- return resolve();
345
- }
346
- let tree = self.buildTree(_.cloneDeep(self.folderDetails));
347
- let createdFolders = {};
348
- let createdFolderUids = [];
349
- // if a few folders have already been created, skip re-creating them
350
- if (fs.existsSync(mappedFolderPath)) {
351
- createdFolders = helper.readFileSync(mappedFolderPath);
352
- // check if the read file has mapped objects
353
- if (_.isPlainObject(createdFolders)) {
354
- createdFolderUids = Object.keys(createdFolders);
355
- }
356
- }
357
- self.buildFolderReqObjs(createdFolderUids, tree, null);
358
- let idx = 0;
359
- return Promise.map(
360
- self.folderBucket,
361
- function () {
362
- let folder = self.folderBucket[idx];
363
- if (createdFolders.hasOwnProperty(folder.json.asset.parent_uid)) {
364
- // replace old uid with new
365
- folder.json.asset.parent_uid = createdFolders[folder.json.asset.parent_uid];
366
- }
367
- return self.stackAPIClient
368
- .asset()
369
- .folder()
370
- .create(folder.json)
371
- .then((response) => {
372
- addlogs(self.config, "Created folder: '" + folder.json.asset.name + "'", 'success');
373
- // assigning newUid to oldUid
374
- createdFolders[folder.oldUid] = response.uid;
375
- helper.writeFileSync(mappedFolderPath, createdFolders);
376
- idx++;
377
- })
378
- .catch(function (err) {
379
- let error = JSON.parse(err.message);
380
- if (error.errors.authorization || error.errors.api_key) {
381
- addlogs(self.config, 'Api_key or management_token is not valid', 'error');
382
- return reject(error);
383
- }
384
-
385
- addlogs(self.config, err, 'error');
386
- return error;
387
- });
388
- },
389
- { concurrency: self.assetConfig.importFoldersConcurrency },
390
- )
391
- .then(function () {
392
- self.mappedFolderUids = helper.readFileSync(mappedFolderPath);
393
- // completed creating folders
394
- return resolve();
395
- })
396
- .catch(function (error) {
397
- addlogs(self.config, error, 'error');
398
- return reject(error);
399
- });
400
- });
401
- }
402
-
403
- buildFolderReqObjs(createdFolderUids, tree, parent_uid) {
404
- let self = this;
405
- for (let leaf in tree) {
406
- // if the folder is already created, skip
407
- if (createdFolderUids.indexOf(leaf) !== -1) {
408
- continue;
409
- }
410
- let folderObj = _.find(self.folderDetails, { uid: leaf });
411
- let requestOption = {
412
- json: {
413
- asset: {
414
- name: folderObj.name,
415
- parent_uid: parent_uid || null,
416
- },
417
- },
418
- oldUid: leaf,
419
- };
420
- self.folderBucket.push(requestOption);
421
- if (Object.keys(tree[leaf]).length > 0) {
422
- self.buildFolderReqObjs(createdFolderUids, tree[leaf], leaf);
423
- }
424
- }
425
- }
426
-
427
- buildTree(coll) {
428
- let tree = {};
429
- for (let i = 0; i < coll.length; i++) {
430
- if (coll[i].parent_uid === null || !coll[i].hasOwnProperty('parent_uid')) {
431
- tree[coll[i].uid] = {};
432
- coll.splice(i, 1);
433
- i--;
434
- }
435
- }
436
- this.findBranches(tree, _.keys(tree), coll);
437
- return tree;
438
- }
439
-
440
- findBranches(tree, branches, coll) {
441
- let self = this;
442
- _.forEach(branches, (branch) => {
443
- for (const element of coll) {
444
- if (branch === element.parent_uid) {
445
- let childUid = element.uid;
446
- tree[branch][childUid] = {};
447
- self.findBranches(tree[branch], [childUid], coll);
448
- }
449
- }
450
- });
451
- }
452
-
453
- publish(assetUid, assetObject) {
454
- let envId = [];
455
- let self = this;
456
- let locales = [];
457
- let requestObject = { json: { asset: {} } };
458
-
459
- return new Promise(function (resolve, reject) {
460
- _.forEach(assetObject.publish_details, function (pubObject) {
461
- if (self.environment.hasOwnProperty(pubObject.environment)) {
462
- envId.push(self.environment[pubObject.environment].name);
463
- let idx = _.indexOf(locales, pubObject.locale);
464
- if (idx === -1) {
465
- locales.push(pubObject.locale);
466
- }
467
- }
468
- });
469
- requestObject.json.asset.environments = envId;
470
- requestObject.json.asset.locales = locales;
471
- return self.stackAPIClient
472
- .asset(assetUid)
473
- .publish({ publishDetails: requestObject.json.asset })
474
- .then(function () {
475
- addlogs(self.config, 'Asset ' + assetUid + ' published successfully', 'success');
476
- return resolve();
477
- })
478
- .catch(function (err) {
479
- if (err && err.message) {
480
- let error;
481
- try {
482
- error = JSON.parse(err.message);
483
- } catch (cError) {
484
- error = { errorMessage: err.message };
485
- }
486
-
487
- addlogs(self.config, `Asset '${assetUid}' not published, ${error.errorMessage}`, 'error');
488
- return reject(err);
489
- }
490
-
491
- return reject(err);
492
- });
493
- });
494
- }
495
- };
@@ -1,201 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const chalk = require('chalk');
4
- const { cloneDeep, find, findIndex } = require('lodash');
5
-
6
- const fileHelper = require('../util/fs');
7
- const { addlogs } = require('../util/log');
8
- const supress = require('../util/extensionsUidReplace');
9
- const { executeTask, formatError } = require('../util');
10
- const schemaTemplate = require('../util/schemaTemplate');
11
-
12
- class ContentTypesImport {
13
- constructor(importConfig, stackAPIClient) {
14
- this.stackAPIClient = stackAPIClient;
15
- this.importConfig = importConfig;
16
- this.contentTypeConfig = importConfig.modules.content_types;
17
- this.globalFieldConfig = importConfig.modules.globalfields;
18
- this.importConcurrency = this.contentTypeConfig.importConcurrency || this.importConfig.importConcurrency;
19
- this.writeConcurrency = this.contentTypeConfig.writeConcurrency || this.importConfig.writeConcurrency;
20
- this.contentTypesFolderPath = path.join(this.importConfig.data, this.contentTypeConfig.dirName);
21
- this.mapperFolderPath = path.join(this.importConfig.data, 'mapper', 'content_types');
22
- this.existingContentTypesPath = path.join(this.mapperFolderPath, 'success.json');
23
- this.globalFieldsFolderPath = path.resolve(this.importConfig.data, this.globalFieldConfig.dirName);
24
- this.globalFieldMapperFolderPath = path.join(importConfig.data, 'mapper', 'global_fields', 'success.json');
25
- this.globalFieldPendingPath = path.join(importConfig.data, 'mapper', 'global_fields', 'pending_global_fields.js');
26
- this.ignoredFilesInContentTypesFolder = new Map([
27
- ['__master.json', 'true'],
28
- ['__priority.json', 'true'],
29
- ['schema.json', 'true'],
30
- ['.DS_Store', 'true'],
31
- ]);
32
- this.contentTypes = [];
33
- this.existingContentTypesUIds = [];
34
- this.titleToUIdMap = new Map();
35
- this.requestOptions = {
36
- json: {},
37
- };
38
- this.fieldRules = [];
39
- this.installedExtensions = [];
40
- this.globalFields = [];
41
- this.existingGlobalFields = [];
42
- this.pendingGlobalFields = [];
43
- }
44
-
45
- async start() {
46
- try {
47
- const appMapperPath = path.join(this.importConfig.data, 'mapper', 'marketplace_apps', 'uid-mapping.json');
48
- this.installedExtensions = (
49
- (await fileHelper.readFileSync(appMapperPath)) || { extension_uid: {} }
50
- ).extension_uid;
51
- // read content types
52
- // remove content types already existing
53
- if (fs.existsSync(this.existingContentTypesPath)) {
54
- this.existingContentTypesUIds = fileHelper.readFileSync(this.existingContentTypesPath) || [];
55
- this.existingContentTypesUIds = new Map(this.existingContentTypesUIds.map((id) => [id, 'true']));
56
- }
57
-
58
- const contentTypeFiles = fileHelper.readdirSync(this.contentTypesFolderPath);
59
- for (let contentTypeName of contentTypeFiles) {
60
- if (!this.ignoredFilesInContentTypesFolder.has(contentTypeName)) {
61
- const contentTypePath = path.join(this.contentTypesFolderPath, contentTypeName);
62
- const contentType = await fileHelper.readFile(contentTypePath);
63
- if (!this.existingContentTypesUIds.length || !this.existingContentTypesUIds.has(contentType.uid)) {
64
- this.contentTypes.push(await fileHelper.readFile(contentTypePath));
65
- }
66
- }
67
- }
68
-
69
- // seed content type
70
- addlogs(this.importConfig, 'Started to seed content types', 'info');
71
- await executeTask(this.seedContentType.bind(this), { concurrency: this.importConcurrency }, this.contentTypes);
72
- addlogs(this.importConfig, 'Created content types', 'success');
73
-
74
- addlogs(this.importConfig, 'Started to update content types with references', 'info');
75
- await executeTask(this.updateContentType.bind(this), { concurrency: this.importConcurrency }, this.contentTypes);
76
- addlogs(this.importConfig, 'Updated content types with references', 'success');
77
-
78
- // global field update
79
- this.pendingGlobalFields = fileHelper.readFileSync(this.globalFieldPendingPath);
80
- if (Array.isArray(this.pendingGlobalFields) && this.pendingGlobalFields.length > 0) {
81
- this.globalFields = fileHelper.readFileSync(
82
- path.resolve(this.globalFieldsFolderPath, this.globalFieldConfig.fileName),
83
- );
84
- this.existingGlobalFields = fileHelper.readFileSync(this.globalFieldMapperFolderPath);
85
- try {
86
- addlogs(this.importConfig, 'Started to update pending global field with content type references', 'info');
87
- await executeTask(
88
- this.updateGlobalFields.bind(this),
89
- {
90
- concurrency: this.importConcurrency,
91
- },
92
- this.pendingGlobalFields,
93
- );
94
- addlogs(this.importConfig, 'Updated pending global fields with content type with references', 'success');
95
- } catch (error) {
96
- addlogs(
97
- this.importConfig,
98
- `Failed to updates global fields with content type reference ${formatError(error)}`,
99
- 'error',
100
- );
101
- }
102
- }
103
-
104
- // write field rules
105
- if (this.fieldRules.length > 0) {
106
- try {
107
- await fileHelper.writeFile(path.join(this.contentTypesFolderPath, 'field_rules_uid.json'), this.fieldRules);
108
- } catch (error) {
109
- addlogs(this.importConfig, `Failed to write field rules ${formatError(error)}`, 'error');
110
- }
111
- }
112
-
113
- addlogs(this.importConfig, chalk.green('Content types imported successfully'), 'success');
114
- } catch (error) {
115
- let message_content_type = "";
116
- if (error.request !== undefined && JSON.parse(error.request.data).content_type !== undefined) {
117
- if (JSON.parse(error.request.data).content_type.uid) {
118
- message_content_type =
119
- ' Update the content type with content_type_uid - ' + JSON.parse(error.request.data).content_type.uid;
120
- } else if (JSON.parse(error.request.data).content_type.title) {
121
- message_content_type =
122
- ' Update the content type with content_type_title - ' + JSON.parse(error.request.data).content_type.title;
123
- }
124
- error.errorMessage = error.errorMessage + message_content_type;
125
- }
126
- addlogs(this.importConfig, formatError(error.errorMessage), 'error');
127
- addlogs(this.importConfig, formatError(error), 'error');
128
- throw new Error('Failed to import content types');
129
- }
130
- }
131
-
132
- async seedContentType(contentType) {
133
- const body = cloneDeep(schemaTemplate);
134
- body.content_type.uid = contentType.uid;
135
- body.content_type.title = contentType.title;
136
- const requestObject = cloneDeep(this.requestOptions);
137
- requestObject.json = body;
138
-
139
- try {
140
- await this.stackAPIClient.contentType().create(requestObject.json);
141
- } catch (error) {
142
- if (error.errorCode === 115 && (error.errors.uid || error.errors.title)) {
143
- // content type uid already exists
144
- // _.remove(self.contentTypes, { uid: uid });
145
- return true;
146
- }
147
- throw error;
148
- }
149
- }
150
-
151
- async updateContentType(contentType) {
152
- if (typeof contentType !== 'object') return;
153
- const requestObject = cloneDeep(this.requestOptions);
154
- if (contentType.field_rules) {
155
- this.fieldRules.push(contentType.uid);
156
- delete contentType.field_rules;
157
- }
158
-
159
- supress(contentType.schema, this.importConfig.preserveStackVersion, this.installedExtensions);
160
- requestObject.json.content_type = contentType;
161
- const contentTypeResponse = this.stackAPIClient.contentType(contentType.uid);
162
- Object.assign(contentTypeResponse, cloneDeep(contentType));
163
- await contentTypeResponse.update();
164
- addlogs(this.importConfig, `'${contentType.uid}' updated with references`, 'success');
165
- }
166
-
167
- async updateGlobalFields(uid) {
168
- const globalField = find(this.globalFields, { uid });
169
- if (globalField) {
170
- supress(globalField.schema, this.importConfig.preserveStackVersion, this.installedExtensions);
171
- let globalFieldObj = this.stackAPIClient.globalField(globalField.uid);
172
- Object.assign(globalFieldObj, cloneDeep(globalField));
173
- try {
174
- const globalFieldResponse = await globalFieldObj.update();
175
- const existingGlobalField = findIndex(this.existingGlobalFields, (existingGlobalFieldUId) => {
176
- return globalFieldResponse.uid === existingGlobalFieldUId;
177
- });
178
-
179
- // Improve write the updated global fields once all updates are completed
180
- this.existingGlobalFields.splice(existingGlobalField, 1, globalField);
181
- await fileHelper.writeFile(this.globalFieldMapperFolderPath, this.existingGlobalFields).catch((error) => {
182
- addlogs(this.importConfig, `failed to write updated the global field '${uid}'. ${formatError(error)}`);
183
- });
184
- addlogs(this.importConfig, `Updated the global field '${uid}' with content type references `);
185
- return true;
186
- } catch (error) {
187
- addlogs(this.importConfig, `failed to update the global field '${uid}'. ${formatError(error)}`);
188
- }
189
- } else {
190
- addlogs(this.importConfig, `Global field '${uid}' does not exist, and hence failed to update.`);
191
- }
192
- }
193
-
194
- async mapUidToTitle() {
195
- this.contentTypes.forEach((ct) => {
196
- this.titleToUIdMap.set(ct.uid, ct.title);
197
- });
198
- }
199
- }
200
-
201
- module.exports = ContentTypesImport;