@contentstack/cli-cm-import 1.8.4 → 1.9.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 (34) hide show
  1. package/README.md +1 -1
  2. package/bin/dev +4 -15
  3. package/lib/commands/cm/stacks/import.js +5 -2
  4. package/lib/config/index.js +2 -16
  5. package/lib/import/module-importer.js +2 -5
  6. package/lib/import/modules/assets.js +5 -2
  7. package/lib/import/modules/base-class.js +29 -14
  8. package/lib/import/modules/custom-roles.d.ts +1 -1
  9. package/lib/import/modules/custom-roles.js +12 -7
  10. package/lib/import/modules/entries.js +119 -68
  11. package/lib/import/modules/environments.d.ts +1 -1
  12. package/lib/import/modules/environments.js +3 -4
  13. package/lib/import/modules/extensions.js +3 -4
  14. package/lib/import/modules/global-fields.js +3 -2
  15. package/lib/import/modules/labels.d.ts +2 -2
  16. package/lib/import/modules/labels.js +6 -7
  17. package/lib/import/modules/marketplace-apps.d.ts +1 -0
  18. package/lib/import/modules/marketplace-apps.js +11 -5
  19. package/lib/import/modules/webhooks.d.ts +1 -1
  20. package/lib/import/modules/webhooks.js +3 -4
  21. package/lib/import/modules/workflows.js +6 -6
  22. package/lib/import/modules-js/marketplace-apps.d.ts +1 -0
  23. package/lib/import/modules-js/marketplace-apps.js +9 -2
  24. package/lib/types/default-config.d.ts +0 -2
  25. package/lib/types/import-config.d.ts +1 -0
  26. package/lib/utils/asset-helper.d.ts +1 -1
  27. package/lib/utils/backup-handler.js +37 -17
  28. package/lib/utils/entries-helper.d.ts +6 -3
  29. package/lib/utils/entries-helper.js +11 -10
  30. package/lib/utils/import-config-handler.js +7 -0
  31. package/lib/utils/logger.js +1 -1
  32. package/lib/utils/marketplace-app-helper.js +9 -2
  33. package/oclif.manifest.json +1 -1
  34. package/package.json +5 -4
@@ -4,13 +4,12 @@ const tslib_1 = require("tslib");
4
4
  const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
5
5
  const values_1 = tslib_1.__importDefault(require("lodash/values"));
6
6
  const node_path_1 = require("node:path");
7
- const config_1 = tslib_1.__importDefault(require("../../config"));
8
7
  const utils_1 = require("../../utils");
9
8
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
10
9
  class ImportEnvironments extends base_class_1.default {
11
10
  constructor({ importConfig, stackAPIClient }) {
12
11
  super({ importConfig, stackAPIClient });
13
- this.environmentsConfig = config_1.default.modules.environments;
12
+ this.environmentsConfig = importConfig.modules.environments;
14
13
  this.mapperDirPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'environments');
15
14
  this.environmentsFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.environmentsConfig.dirName);
16
15
  this.envUidMapperPath = (0, node_path_1.join)(this.mapperDirPath, 'uid-mapping.json');
@@ -51,7 +50,7 @@ class ImportEnvironments extends base_class_1.default {
51
50
  async importEnvironments() {
52
51
  if (this.environments === undefined || (0, isEmpty_1.default)(this.environments)) {
53
52
  (0, utils_1.log)(this.importConfig, 'No Environment Found', 'info');
54
- return (0, node_path_1.resolve)();
53
+ return;
55
54
  }
56
55
  const apiContent = (0, values_1.default)(this.environments);
57
56
  const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
@@ -83,7 +82,7 @@ class ImportEnvironments extends base_class_1.default {
83
82
  entity: 'create-environments',
84
83
  includeParamOnCompletion: true,
85
84
  },
86
- concurrencyLimit: config_1.default.fetchConcurrency || 2,
85
+ concurrencyLimit: this.importConfig.fetchConcurrency || 2,
87
86
  }, undefined, false);
88
87
  }
89
88
  /**
@@ -4,13 +4,12 @@ const tslib_1 = require("tslib");
4
4
  const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
5
5
  const values_1 = tslib_1.__importDefault(require("lodash/values"));
6
6
  const node_path_1 = require("node:path");
7
- const config_1 = tslib_1.__importDefault(require("../../config"));
8
7
  const utils_1 = require("../../utils");
9
8
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
10
9
  class ImportExtensions extends base_class_1.default {
11
10
  constructor({ importConfig, stackAPIClient }) {
12
11
  super({ importConfig, stackAPIClient });
13
- this.extensionsConfig = config_1.default.modules.extensions;
12
+ this.extensionsConfig = importConfig.modules.extensions;
14
13
  this.mapperDirPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'extensions');
15
14
  this.extensionsFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.extensionsConfig.dirName);
16
15
  this.extUidMapperPath = (0, node_path_1.join)(this.mapperDirPath, 'uid-mapping.json');
@@ -51,7 +50,7 @@ class ImportExtensions extends base_class_1.default {
51
50
  async importExtensions() {
52
51
  if (this.extensions === undefined || (0, isEmpty_1.default)(this.extensions)) {
53
52
  (0, utils_1.log)(this.importConfig, 'No Extensions Found', 'info');
54
- return (0, node_path_1.resolve)();
53
+ return;
55
54
  }
56
55
  const apiContent = (0, values_1.default)(this.extensions);
57
56
  const onSuccess = ({ response, apiData: { uid, title } = { uid: null, title: '' } }) => {
@@ -83,7 +82,7 @@ class ImportExtensions extends base_class_1.default {
83
82
  entity: 'create-extensions',
84
83
  includeParamOnCompletion: true,
85
84
  },
86
- concurrencyLimit: config_1.default.concurrency || config_1.default.fetchConcurrency || 1,
85
+ concurrencyLimit: this.importConfig.concurrency || this.importConfig.fetchConcurrency || 1,
87
86
  }, undefined, false);
88
87
  }
89
88
  /**
@@ -72,8 +72,9 @@ class ImportGlobalFields extends base_class_1.default {
72
72
  async createGFs({ apiParams, element: globalField, isLastRequest, }) {
73
73
  return new Promise(async (resolve, reject) => {
74
74
  (0, utils_1.lookupExtension)(this.config, globalField.schema, this.config.preserveStackVersion, this.installedExtensions);
75
- const isReferenceFieldRemoved = await (0, utils_1.removeReferenceFields)(globalField.schema, undefined, this.stackAPIClient);
76
- if (isReferenceFieldRemoved) {
75
+ let flag = { supressed: false };
76
+ await (0, utils_1.removeReferenceFields)(globalField.schema, flag, this.stackAPIClient);
77
+ if (flag.supressed) {
77
78
  this.pendingGFs.push(globalField.uid);
78
79
  }
79
80
  return this.stack
@@ -17,7 +17,7 @@ export default class Importlabels extends BaseClass {
17
17
  * @returns {Promise<void>} Promise<void>
18
18
  */
19
19
  start(): Promise<void>;
20
- importlabels(): Promise<string>;
20
+ importlabels(): Promise<void>;
21
21
  /**
22
22
  * @method serializelabels
23
23
  * @param {ApiOptions} apiOptions ApiOptions
@@ -30,5 +30,5 @@ export default class Importlabels extends BaseClass {
30
30
  * @param {ApiOptions} apiOptions ApiOptions
31
31
  * @returns {ApiOptions} ApiOptions
32
32
  */
33
- serializeUpdatelabels(apiOptions: ApiOptions): ApiOptions;
33
+ serializeUpdateLabels(apiOptions: ApiOptions): ApiOptions;
34
34
  }
@@ -5,13 +5,12 @@ const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
5
5
  const values_1 = tslib_1.__importDefault(require("lodash/values"));
6
6
  const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
7
7
  const node_path_1 = require("node:path");
8
- const config_1 = tslib_1.__importDefault(require("../../config"));
9
8
  const utils_1 = require("../../utils");
10
9
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
11
10
  class Importlabels extends base_class_1.default {
12
11
  constructor({ importConfig, stackAPIClient }) {
13
12
  super({ importConfig, stackAPIClient });
14
- this.labelsConfig = config_1.default.modules.labels;
13
+ this.labelsConfig = importConfig.modules.labels;
15
14
  this.mapperDirPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'labels');
16
15
  this.labelsFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.labelsConfig.dirName);
17
16
  this.labelUidMapperPath = (0, node_path_1.join)(this.mapperDirPath, 'uid-mapping.json');
@@ -56,7 +55,7 @@ class Importlabels extends base_class_1.default {
56
55
  async importlabels() {
57
56
  if (this.labels === undefined || (0, isEmpty_1.default)(this.labels)) {
58
57
  (0, utils_1.log)(this.importConfig, 'No Label Found', 'info');
59
- return (0, node_path_1.resolve)();
58
+ return;
60
59
  }
61
60
  const apiContent = (0, values_1.default)(this.labels);
62
61
  const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
@@ -86,7 +85,7 @@ class Importlabels extends base_class_1.default {
86
85
  entity: 'create-labels',
87
86
  includeParamOnCompletion: true,
88
87
  },
89
- concurrencyLimit: config_1.default.fetchConcurrency || 1,
88
+ concurrencyLimit: this.importConfig.fetchConcurrency || 1,
90
89
  }, undefined, false);
91
90
  }
92
91
  /**
@@ -124,13 +123,13 @@ class Importlabels extends base_class_1.default {
124
123
  apiContent,
125
124
  processName: 'update labels',
126
125
  apiParams: {
127
- serializeData: this.serializeUpdatelabels.bind(this),
126
+ serializeData: this.serializeUpdateLabels.bind(this),
128
127
  reject: onReject.bind(this),
129
128
  resolve: onSuccess.bind(this),
130
129
  entity: 'update-labels',
131
130
  includeParamOnCompletion: true,
132
131
  },
133
- concurrencyLimit: config_1.default.fetchConcurrency || 1,
132
+ concurrencyLimit: this.importConfig.fetchConcurrency || 1,
134
133
  }, undefined, false);
135
134
  }
136
135
  }
@@ -139,7 +138,7 @@ class Importlabels extends base_class_1.default {
139
138
  * @param {ApiOptions} apiOptions ApiOptions
140
139
  * @returns {ApiOptions} ApiOptions
141
140
  */
142
- serializeUpdatelabels(apiOptions) {
141
+ serializeUpdateLabels(apiOptions) {
143
142
  var _a, _b;
144
143
  const { apiData: label } = apiOptions;
145
144
  const labelUid = label.uid;
@@ -16,6 +16,7 @@ export default class ImportMarketplaceApps extends BaseClass {
16
16
  developerHubBaseUrl: string;
17
17
  sdkClient: ContentstackClient;
18
18
  nodeCrypto: NodeCrypto;
19
+ appSdkAxiosInstance: any;
19
20
  constructor({ importConfig, stackAPIClient }: ModuleClassParams);
20
21
  /**
21
22
  * @method start
@@ -13,14 +13,13 @@ const filter_1 = tslib_1.__importDefault(require("lodash/filter"));
13
13
  const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
14
14
  const toLower_1 = tslib_1.__importDefault(require("lodash/toLower"));
15
15
  const cli_utilities_1 = require("@contentstack/cli-utilities");
16
- const config_1 = tslib_1.__importDefault(require("../../config"));
17
16
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
18
17
  const interactive_1 = require("../../utils/interactive");
19
18
  const utils_1 = require("../../utils");
20
19
  class ImportMarketplaceApps extends base_class_1.default {
21
20
  constructor({ importConfig, stackAPIClient }) {
22
21
  super({ importConfig, stackAPIClient });
23
- this.marketPlaceAppConfig = config_1.default.modules.marketplace_apps;
22
+ this.marketPlaceAppConfig = importConfig.modules.marketplace_apps;
24
23
  this.mapperDirPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'marketplace_apps');
25
24
  this.marketPlaceFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.marketPlaceAppConfig.dirName);
26
25
  this.marketPlaceUidMapperPath = (0, node_path_1.join)(this.mapperDirPath, 'uid-mapping.json');
@@ -54,6 +53,9 @@ class ImportMarketplaceApps extends base_class_1.default {
54
53
  await utils_1.fsUtil.makeDirectory(this.mapperDirPath);
55
54
  this.developerHubBaseUrl = this.importConfig.developerHubBaseUrl || (await (0, utils_1.getDeveloperHubUrl)(this.importConfig));
56
55
  this.sdkClient = await (0, cli_utilities_1.managementSDKClient)({ endpoint: this.developerHubBaseUrl });
56
+ this.appSdkAxiosInstance = await (0, cli_utilities_1.managementSDKClient)({
57
+ host: this.developerHubBaseUrl.split('://').pop()
58
+ });
57
59
  this.importConfig.org_uid = await (0, utils_1.getOrgUid)(this.importConfig);
58
60
  await this.setHttpClient();
59
61
  await this.startInstallation();
@@ -298,10 +300,14 @@ class ImportMarketplaceApps extends base_class_1.default {
298
300
  }
299
301
  // TODO migrate this HTTP API call into SDK
300
302
  // NOTE Use updateAppConfig(this.sdkClient, this.importConfig, app, payload) utility when migrating to SDK call;
301
- return this.httpClient
302
- .put(`${this.developerHubBaseUrl}/installations/${uid}`, payload)
303
+ return this.appSdkAxiosInstance.axiosInstance
304
+ .put(`${this.developerHubBaseUrl}/installations/${uid}`, payload, {
305
+ headers: {
306
+ organization_uid: this.importConfig.org_uid,
307
+ },
308
+ })
303
309
  .then(({ data }) => {
304
- if (data.message) {
310
+ if (data === null || data === void 0 ? void 0 : data.message) {
305
311
  (0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(data.message), 'success');
306
312
  }
307
313
  else {
@@ -17,7 +17,7 @@ export default class ImportWebhooks extends BaseClass {
17
17
  * @returns {Promise<void>} Promise<void>
18
18
  */
19
19
  start(): Promise<void>;
20
- importWebhooks(): Promise<string>;
20
+ importWebhooks(): Promise<void>;
21
21
  /**
22
22
  * @method serializeWebhooks
23
23
  * @param {ApiOptions} apiOptions ApiOptions
@@ -4,13 +4,12 @@ const tslib_1 = require("tslib");
4
4
  const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
5
5
  const values_1 = tslib_1.__importDefault(require("lodash/values"));
6
6
  const node_path_1 = require("node:path");
7
- const config_1 = tslib_1.__importDefault(require("../../config"));
8
7
  const utils_1 = require("../../utils");
9
8
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
10
9
  class ImportWebhooks extends base_class_1.default {
11
10
  constructor({ importConfig, stackAPIClient }) {
12
11
  super({ importConfig, stackAPIClient });
13
- this.webhooksConfig = config_1.default.modules.webhooks;
12
+ this.webhooksConfig = importConfig.modules.webhooks;
14
13
  this.mapperDirPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'webhooks');
15
14
  this.webhooksFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.webhooksConfig.dirName);
16
15
  this.webhookUidMapperPath = (0, node_path_1.join)(this.mapperDirPath, 'uid-mapping.json');
@@ -53,7 +52,7 @@ class ImportWebhooks extends base_class_1.default {
53
52
  async importWebhooks() {
54
53
  if (this.webhooks === undefined || (0, isEmpty_1.default)(this.webhooks)) {
55
54
  (0, utils_1.log)(this.importConfig, 'No Webhook Found', 'info');
56
- return (0, node_path_1.resolve)();
55
+ return;
57
56
  }
58
57
  const apiContent = (0, values_1.default)(this.webhooks);
59
58
  const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
@@ -84,7 +83,7 @@ class ImportWebhooks extends base_class_1.default {
84
83
  entity: 'create-webhooks',
85
84
  includeParamOnCompletion: true,
86
85
  },
87
- concurrencyLimit: config_1.default.fetchConcurrency || 1,
86
+ concurrencyLimit: this.importConfig.fetchConcurrency || 1,
88
87
  }, undefined, false);
89
88
  }
90
89
  /**
@@ -10,13 +10,12 @@ const filter_1 = tslib_1.__importDefault(require("lodash/filter"));
10
10
  const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
11
11
  const cloneDeep_1 = tslib_1.__importDefault(require("lodash/cloneDeep"));
12
12
  const findIndex_1 = tslib_1.__importDefault(require("lodash/findIndex"));
13
- const config_1 = tslib_1.__importDefault(require("../../config"));
14
13
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
15
14
  const utils_1 = require("../../utils");
16
15
  class ImportWorkflows extends base_class_1.default {
17
16
  constructor({ importConfig, stackAPIClient }) {
18
17
  super({ importConfig, stackAPIClient });
19
- this.workflowsConfig = config_1.default.modules.workflows;
18
+ this.workflowsConfig = importConfig.modules.workflows;
20
19
  this.mapperDirPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'workflows');
21
20
  this.workflowsFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.workflowsConfig.dirName);
22
21
  this.workflowUidMapperPath = (0, node_path_1.join)(this.mapperDirPath, 'uid-mapping.json');
@@ -99,10 +98,11 @@ class ImportWorkflows extends base_class_1.default {
99
98
  utils_1.fsUtil.writeFile(this.workflowUidMapperPath, this.workflowUidMapper);
100
99
  };
101
100
  const onReject = ({ error, apiData }) => {
102
- var _a;
101
+ var _a, _b;
103
102
  const err = (error === null || error === void 0 ? void 0 : error.message) ? JSON.parse(error.message) : error;
104
103
  const { name } = apiData;
105
- if ((_a = err === null || err === void 0 ? void 0 : err.errors) === null || _a === void 0 ? void 0 : _a.name) {
104
+ const workflowExists = ((_a = err === null || err === void 0 ? void 0 : err.errors) === null || _a === void 0 ? void 0 : _a.name) || ((_b = err === null || err === void 0 ? void 0 : err.errors) === null || _b === void 0 ? void 0 : _b['workflow.name']);
105
+ if (workflowExists) {
106
106
  (0, utils_1.log)(this.importConfig, `Workflow '${name}' already exists`, 'info');
107
107
  }
108
108
  else {
@@ -125,7 +125,7 @@ class ImportWorkflows extends base_class_1.default {
125
125
  entity: 'create-workflows',
126
126
  includeParamOnCompletion: true,
127
127
  },
128
- concurrencyLimit: config_1.default.fetchConcurrency || 1,
128
+ concurrencyLimit: this.importConfig.fetchConcurrency || 1,
129
129
  }, undefined, false);
130
130
  }
131
131
  updateNextAvailableStagesUid(workflow, newWorkflowStages, oldWorkflowStages) {
@@ -209,7 +209,7 @@ class ImportWorkflows extends base_class_1.default {
209
209
  includeParamOnCompletion: true,
210
210
  additionalInfo: { workflowUid: workflow.uid, stageIndex },
211
211
  },
212
- concurrencyLimit: config_1.default.fetchConcurrency || 1,
212
+ concurrencyLimit: this.importConfig.fetchConcurrency || 1,
213
213
  }, undefined, false);
214
214
  }
215
215
  stageIndex++;
@@ -19,6 +19,7 @@ declare class ImportMarketplaceApps {
19
19
  start(): Promise<void>;
20
20
  mapperDirPath: string;
21
21
  uidMapperPath: string;
22
+ appSdkAxiosInstance: any;
22
23
  getOrgUid(): Promise<void>;
23
24
  getAndValidateEncryptionKey(defaultValue: any, retry?: number): any;
24
25
  nodeCrypto: NodeCrypto;
@@ -38,6 +38,9 @@ module.exports = class ImportMarketplaceApps {
38
38
  }
39
39
  this.developerHubBaseUrl = this.config.developerHubBaseUrl || (await getDeveloperHubUrl(this.config));
40
40
  this.client = await managementSDKClient({ endpoint: this.developerHubBaseUrl });
41
+ this.appSdkAxiosInstance = await managementSDKClient({
42
+ host: this.developerHubBaseUrl.split('://').pop()
43
+ });
41
44
  await this.getOrgUid();
42
45
  const httpClient = new HttpClient();
43
46
  if (!this.config.auth_token) {
@@ -392,8 +395,12 @@ module.exports = class ImportMarketplaceApps {
392
395
  if (_.isEmpty(app) || _.isEmpty(payload) || !uid) {
393
396
  return Promise.resolve();
394
397
  }
395
- return this.httpClient
396
- .put(`${this.developerHubBaseUrl}/installations/${uid}`, payload)
398
+ return this.appSdkAxiosInstance.axiosInstance
399
+ .put(`${this.developerHubBaseUrl}/installations/${uid}`, payload, {
400
+ headers: {
401
+ organization_uid: this.config.org_uid
402
+ },
403
+ })
397
404
  .then(({ data }) => {
398
405
  if (data.message) {
399
406
  log(this.config, formatError(data.message), 'success');
@@ -128,7 +128,6 @@ export default interface DefaultConfig {
128
128
  stacks: string;
129
129
  labels: string;
130
130
  };
131
- updatedModules: string[];
132
131
  rateLimit: number;
133
132
  preserveStackVersion: boolean;
134
133
  entriesPublish: boolean;
@@ -139,6 +138,5 @@ export default interface DefaultConfig {
139
138
  developerHubBaseUrl: string;
140
139
  marketplaceAppEncryptionKey: string;
141
140
  getEncryptionKeyMaxRetry: number;
142
- useNewModuleStructure: boolean;
143
141
  createBackupDir?: string;
144
142
  }
@@ -41,6 +41,7 @@ export default interface ImportConfig extends DefaultConfig, ExternalConfig {
41
41
  authtoken?: string;
42
42
  destinationStackName?: string;
43
43
  org_uid?: string;
44
+ contentVersion: number;
44
45
  }
45
46
  type branch = {
46
47
  uid: string;
@@ -1,4 +1,4 @@
1
1
  import Bluebird from 'bluebird';
2
- import { ImportConfig } from 'src/types';
2
+ import { ImportConfig } from '../types';
3
3
  export declare const uploadAssetHelper: (config: ImportConfig, req: any, fsPath: string, RETRY?: number) => Bluebird<unknown>;
4
4
  export declare const lookupAssets: (data: Record<string, any>, mappedAssetUids: Record<string, any>, mappedAssetUrls: Record<string, any>, assetUidMapperPath: string, installedExtensions: Record<string, any>[]) => any;
@@ -2,33 +2,38 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const path = tslib_1.__importStar(require("path"));
5
- const ncp_1 = tslib_1.__importDefault(require("ncp"));
5
+ const fs_extra_1 = require("fs-extra");
6
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
6
7
  const index_1 = require("./index");
7
8
  function setupBackupDir(importConfig) {
8
9
  return new Promise(async (resolve, reject) => {
9
10
  if (importConfig.hasOwnProperty('useBackedupDir')) {
10
11
  return resolve(importConfig.useBackedupDir);
11
12
  }
12
- //NOTE: If the backup folder's directory is provided, create it at that location; otherwise, the default path (working directory).
13
- let backupDirPath = path.join(process.cwd(), '_backup_' + Math.floor(Math.random() * 1000));
14
- if (importConfig.createBackupDir) {
15
- if (index_1.fileHelper.fileExistsSync(importConfig.createBackupDir)) {
16
- index_1.fileHelper.removeDirSync(importConfig.createBackupDir);
13
+ const subDir = isSubDirectory(importConfig);
14
+ let backupDirPath;
15
+ if (subDir) {
16
+ backupDirPath = path.resolve(importConfig.contentDir, '..', '_backup_' + Math.floor(Math.random() * 1000));
17
+ if (importConfig.createBackupDir) {
18
+ cli_utilities_1.cliux.print(`Warning!!! Provided backup directory path is a sub directory of the content directory, Cannot copy to a sub directory. Hence new backup directory created - ${backupDirPath}`, {
19
+ color: 'yellow',
20
+ });
17
21
  }
18
- index_1.fileHelper.makeDirectory(importConfig.createBackupDir);
19
- backupDirPath = importConfig.createBackupDir;
20
22
  }
21
- const limit = importConfig.backupConcurrency || 16;
22
- if (path.isAbsolute(importConfig.contentDir)) {
23
- return (0, ncp_1.default)(importConfig.contentDir, backupDirPath, { limit }, (error) => {
24
- if (error) {
25
- return reject(error);
23
+ else {
24
+ //NOTE: If the backup folder's directory is provided, create it at that location; otherwise, the default path (working directory).
25
+ backupDirPath = path.join(process.cwd(), '_backup_' + Math.floor(Math.random() * 1000));
26
+ if (importConfig.createBackupDir) {
27
+ if (index_1.fileHelper.fileExistsSync(importConfig.createBackupDir)) {
28
+ index_1.fileHelper.removeDirSync(importConfig.createBackupDir);
26
29
  }
27
- return resolve(backupDirPath);
28
- });
30
+ index_1.fileHelper.makeDirectory(importConfig.createBackupDir);
31
+ backupDirPath = importConfig.createBackupDir;
32
+ }
29
33
  }
30
- else {
31
- (0, ncp_1.default)(importConfig.contentDir, backupDirPath, (error) => {
34
+ if (backupDirPath) {
35
+ cli_utilities_1.cliux.print('Copying content to the backup directory...');
36
+ return (0, fs_extra_1.copy)(importConfig.contentDir, backupDirPath, (error) => {
32
37
  if (error) {
33
38
  return reject(error);
34
39
  }
@@ -38,3 +43,18 @@ function setupBackupDir(importConfig) {
38
43
  });
39
44
  }
40
45
  exports.default = setupBackupDir;
46
+ /**
47
+ * Check whether provided backup directory path is sub directory or not
48
+ * @param importConfig
49
+ * @returns
50
+ */
51
+ function isSubDirectory(importConfig) {
52
+ const parent = importConfig.contentDir;
53
+ const child = importConfig.createBackupDir ? importConfig.createBackupDir : process.cwd();
54
+ const relative = path.relative(parent, child);
55
+ if (relative) {
56
+ return relative && !relative.startsWith('..') && !path.isAbsolute(relative);
57
+ }
58
+ //true if both parent and child have same path
59
+ return true;
60
+ }
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * Entries lookup
3
3
  */
4
- export declare const lookupEntries: (data: any, mappedUids: Record<string, any>, uidMapperPath: string) => any;
5
- export declare const removeUidsFromJsonRteFields: (entry: Record<string, any>, ctSchema: Record<string, any>[]) => Record<string, any>;
6
- export declare const removeEntryRefsFromJSONRTE: (entry: Record<string, any>, ctSchema: Record<string, any>[]) => Record<string, any>;
4
+ export declare const lookupEntries: (data: {
5
+ content_type: any;
6
+ entry: any;
7
+ }, mappedUids: Record<string, any>, uidMapperPath: string) => any;
8
+ export declare const removeUidsFromJsonRteFields: (entry: Record<string, any>, ctSchema?: Record<string, any>[]) => Record<string, any>;
9
+ export declare const removeEntryRefsFromJSONRTE: (entry: Record<string, any>, ctSchema?: Record<string, any>[]) => Record<string, any>;
7
10
  export declare const restoreJsonRteEntryRefs: (entry: Record<string, any>, sourceStackEntry: any, ctSchema: any, { mappedAssetUids, mappedAssetUrls }: any) => Record<string, any>;
@@ -94,7 +94,7 @@ const lookupEntries = function (data, mappedUids, uidMapperPath) {
94
94
  }
95
95
  };
96
96
  const find = function (schema = [], _entry) {
97
- for (let i = 0, _i = schema.length; i < _i; i++) {
97
+ for (let i = 0, _i = schema === null || schema === void 0 ? void 0 : schema.length; i < _i; i++) {
98
98
  switch (schema[i].data_type) {
99
99
  case 'reference':
100
100
  if (Array.isArray(schema[i].reference_to)) {
@@ -134,7 +134,7 @@ const lookupEntries = function (data, mappedUids, uidMapperPath) {
134
134
  }
135
135
  }
136
136
  };
137
- function findEntryIdsFromJsonRte(entry, ctSchema) {
137
+ function findEntryIdsFromJsonRte(entry, ctSchema = []) {
138
138
  for (const element of ctSchema) {
139
139
  switch (element.data_type) {
140
140
  case 'blocks': {
@@ -249,7 +249,7 @@ function findUidsInNewRefFields(entry, uids) {
249
249
  }
250
250
  }
251
251
  }
252
- const removeUidsFromJsonRteFields = (entry, ctSchema) => {
252
+ const removeUidsFromJsonRteFields = (entry, ctSchema = []) => {
253
253
  for (const element of ctSchema) {
254
254
  switch (element.data_type) {
255
255
  case 'blocks': {
@@ -339,7 +339,7 @@ function removeUidsFromChildren(children) {
339
339
  return children;
340
340
  }
341
341
  }
342
- const removeEntryRefsFromJSONRTE = (entry, ctSchema) => {
342
+ const removeEntryRefsFromJSONRTE = (entry, ctSchema = []) => {
343
343
  for (const element of ctSchema) {
344
344
  switch (element.data_type) {
345
345
  case 'blocks': {
@@ -379,7 +379,8 @@ const removeEntryRefsFromJSONRTE = (entry, ctSchema) => {
379
379
  let entryReferences = jsonRteData.children.filter((e) => doEntryReferencesExist(e));
380
380
  if (entryReferences.length > 0) {
381
381
  jsonRteData.children = jsonRteData.children.filter((e) => !doEntryReferencesExist(e));
382
- if (jsonRteData.children.length === 0) { // empty children array are no longer acceptable by the API, a default structure must be there
382
+ if (jsonRteData.children.length === 0) {
383
+ // empty children array are no longer acceptable by the API, a default structure must be there
383
384
  jsonRteData.children.push(JSON.parse(structuredPTag));
384
385
  }
385
386
  return jsonRteData; // return jsonRteData without entry references
@@ -432,14 +433,14 @@ function doEntryReferencesExist(element) {
432
433
  function isEntryRef(element) {
433
434
  return element.type === 'reference' && element.attrs.type === 'entry';
434
435
  }
435
- const restoreJsonRteEntryRefs = (entry, sourceStackEntry, ctSchema, { mappedAssetUids, mappedAssetUrls }) => {
436
+ const restoreJsonRteEntryRefs = (entry, sourceStackEntry, ctSchema = [], { mappedAssetUids, mappedAssetUrls }) => {
436
437
  // let mappedAssetUids = fileHelper.readFileSync(this.mappedAssetUidPath) || {};
437
438
  // let mappedAssetUrls = fileHelper.readFileSync(this.mappedAssetUrlPath) || {};
438
439
  for (const element of ctSchema) {
439
440
  switch (element.data_type) {
440
441
  case 'blocks': {
441
442
  if (entry[element.uid]) {
442
- if (element.multiple) {
443
+ if (element.multiple && Array.isArray(entry[element.uid])) {
443
444
  entry[element.uid] = entry[element.uid].map((e, eIndex) => {
444
445
  let key = Object.keys(e).pop();
445
446
  let subBlock = element.blocks.filter((block) => block.uid === key).pop();
@@ -457,7 +458,7 @@ const restoreJsonRteEntryRefs = (entry, sourceStackEntry, ctSchema, { mappedAsse
457
458
  case 'global_field':
458
459
  case 'group': {
459
460
  if (entry[element.uid]) {
460
- if (element.multiple) {
461
+ if (element.multiple && Array.isArray(entry[element.uid])) {
461
462
  entry[element.uid] = entry[element.uid].map((e, eIndex) => {
462
463
  let sourceStackElement = sourceStackEntry[element.uid][eIndex];
463
464
  e = (0, exports.restoreJsonRteEntryRefs)(e, sourceStackElement, element.schema, { mappedAssetUids, mappedAssetUrls });
@@ -476,7 +477,7 @@ const restoreJsonRteEntryRefs = (entry, sourceStackEntry, ctSchema, { mappedAsse
476
477
  }
477
478
  case 'json': {
478
479
  if (entry[element.uid] && element.field_metadata.rich_text_type) {
479
- if (element.multiple) {
480
+ if (element.multiple && Array.isArray(entry[element.uid])) {
480
481
  entry[element.uid] = entry[element.uid].map((field, index) => {
481
482
  // i am facing a Maximum call stack exceeded issue,
482
483
  // probably because of this loop operation
@@ -543,7 +544,7 @@ function setDirtyTrue(jsonRteChild) {
543
544
  }
544
545
  delete jsonRteChild.uid;
545
546
  if (jsonRteChild.children && jsonRteChild.children.length > 0) {
546
- jsonRteChild.children = jsonRteChild.children.map((subElement) => this.setDirtyTrue(subElement));
547
+ jsonRteChild.children = jsonRteChild.children.map((subElement) => setDirtyTrue(subElement));
547
548
  }
548
549
  }
549
550
  return jsonRteChild;
@@ -24,6 +24,13 @@ const setupConfig = async (importCmdFlags) => {
24
24
  config.contentDir = path.resolve(config.contentDir);
25
25
  //Note to support the old key
26
26
  config.data = config.contentDir;
27
+ if ((0, file_helper_1.fileExistsSync)(path.join(config.contentDir, 'export-info.json'))) {
28
+ config.contentVersion =
29
+ ((await (0, file_helper_1.readFile)(path.join(config.contentDir, 'export-info.json'))) || {}).contentVersion || 2;
30
+ }
31
+ else {
32
+ config.contentVersion = 1;
33
+ }
27
34
  const managementTokenAlias = importCmdFlags['management-token-alias'] || importCmdFlags['alias'];
28
35
  if (managementTokenAlias) {
29
36
  const { token, apiKey } = cli_utilities_1.configHandler.get(`tokens.${managementTokenAlias}`);
@@ -55,7 +55,7 @@ let successTransport;
55
55
  let errorTransport;
56
56
  function init(_logPath) {
57
57
  if (!logger || !errorLogger) {
58
- var logsDir = path.resolve(_logPath, 'logs', 'export');
58
+ var logsDir = path.resolve(_logPath, 'logs', 'import');
59
59
  // Create dir if doesn't already exist
60
60
  mkdirp_1.default.sync(logsDir);
61
61
  successTransport = {
@@ -13,8 +13,15 @@ const interactive_1 = require("./interactive");
13
13
  const utils_1 = require("../utils");
14
14
  const interactive_2 = require("../utils/interactive");
15
15
  const getAllStackSpecificApps = async (developerHubBaseUrl, httpClient, config) => {
16
- return await httpClient
17
- .get(`${developerHubBaseUrl}/installations?target_uids=${config.target_stack}`)
16
+ const appSdkAxiosInstance = await (0, cli_utilities_1.managementSDKClient)({
17
+ host: developerHubBaseUrl.split('://').pop()
18
+ });
19
+ return await appSdkAxiosInstance.axiosInstance
20
+ .get(`${developerHubBaseUrl}/installations?target_uids=${config.target_stack}`, {
21
+ headers: {
22
+ organization_uid: config.org_uid,
23
+ },
24
+ })
18
25
  .then(({ data }) => data.data)
19
26
  .catch((error) => (0, logger_1.log)(config, `Failed to export marketplace-apps ${(0, utils_1.formatError)(error)}`, 'error'));
20
27
  };
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.4",
2
+ "version": "1.9.0",
3
3
  "commands": {
4
4
  "cm:stacks:import": {
5
5
  "id": "cm:stacks:import",
package/package.json CHANGED
@@ -1,34 +1,35 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-import",
3
3
  "description": "Contentstack CLI plugin to import content into stack",
4
- "version": "1.8.4",
4
+ "version": "1.9.0",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
8
+ "@contentstack/management": "~1.10.2",
8
9
  "@contentstack/cli-command": "~1.2.12",
9
10
  "@contentstack/cli-utilities": "~1.5.2",
10
- "@contentstack/management": "~1.10.0",
11
11
  "@oclif/core": "^2.9.3",
12
12
  "big-json": "^3.2.0",
13
13
  "bluebird": "^3.7.2",
14
14
  "chalk": "^4.1.2",
15
15
  "debug": "^4.1.0",
16
+ "fs-extra": "^11.1.1",
16
17
  "lodash": "^4.17.20",
17
18
  "marked": "^4.0.17",
18
19
  "merge": "^2.1.1",
19
20
  "mkdirp": "^1.0.4",
20
- "ncp": "^2.0.0",
21
21
  "promise-limit": "^2.7.0",
22
22
  "tslib": "^2.4.1",
23
23
  "winston": "^3.7.2"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@oclif/test": "^1.2.6",
27
+ "@types/big-json": "^3.2.0",
27
28
  "@types/bluebird": "^3.5.38",
28
29
  "@types/chai": "^4.2.18",
30
+ "@types/fs-extra": "^11.0.1",
29
31
  "@types/mkdirp": "^1.0.2",
30
32
  "@types/mocha": "^8.2.2",
31
- "@types/ncp": "^2.0.5",
32
33
  "@types/node": "^14.14.32",
33
34
  "@types/sinon": "^10.0.2",
34
35
  "@types/tar": "^4.0.3",