@contentstack/cli-cm-import 1.14.3 → 1.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import
47
47
  $ csdx COMMAND
48
48
  running command...
49
49
  $ csdx (--version)
50
- @contentstack/cli-cm-import/1.14.3 linux-x64 node-v18.19.1
50
+ @contentstack/cli-cm-import/1.15.1 linux-x64 node-v18.20.1
51
51
  $ csdx --help [COMMAND]
52
52
  USAGE
53
53
  $ csdx COMMAND
@@ -99,6 +99,7 @@ class ModuleImporter {
99
99
  const basePath = (0, path_1.resolve)(this.importConfig.backupDir, 'logs', 'audit');
100
100
  const auditConfig = this.importConfig.auditConfig;
101
101
  auditConfig.config.basePath = basePath;
102
+ auditConfig.config.branch = this.importConfig.branchName;
102
103
  try {
103
104
  const args = [
104
105
  '--data-dir',
@@ -36,6 +36,8 @@ export default class EntriesImport extends BaseClass {
36
36
  private autoCreatedEntries;
37
37
  private taxonomiesPath;
38
38
  taxonomies: Record<string, unknown>;
39
+ rteCTs: any;
40
+ rteCTsWithRef: any;
39
41
  constructor({ importConfig, stackAPIClient }: ModuleClassParams);
40
42
  start(): Promise<any>;
41
43
  disableMandatoryCTReferences(): Promise<void>;
@@ -63,7 +65,7 @@ export default class EntriesImport extends BaseClass {
63
65
  cTUid: string;
64
66
  locale: string;
65
67
  }): Promise<void>;
66
- replaceEntriesHandler({ apiParams, element: entry }: {
68
+ replaceEntriesHandler({ apiParams, element: entry, }: {
67
69
  apiParams: ApiOptions;
68
70
  element: Record<string, string>;
69
71
  isLastRequest: boolean;
@@ -37,6 +37,8 @@ class EntriesImport extends base_class_1.default {
37
37
  this.envs = {};
38
38
  this.autoCreatedEntries = [];
39
39
  this.failedEntries = [];
40
+ this.rteCTs = [];
41
+ this.rteCTsWithRef = [];
40
42
  }
41
43
  async start() {
42
44
  var _a;
@@ -150,6 +152,8 @@ class EntriesImport extends base_class_1.default {
150
152
  references: false,
151
153
  jsonRte: false,
152
154
  jsonRteEmbeddedEntries: false,
155
+ rte: false,
156
+ rteEmbeddedEntries: false,
153
157
  };
154
158
  (0, utils_1.suppressSchemaReference)(contentType.schema, flag);
155
159
  if (flag.references) {
@@ -164,6 +168,15 @@ class EntriesImport extends base_class_1.default {
164
168
  }
165
169
  }
166
170
  }
171
+ if (flag.rte) {
172
+ this.rteCTs.push(contentType.uid);
173
+ if (flag.rteEmbeddedEntries) {
174
+ this.rteCTsWithRef.push(contentType.uid);
175
+ if (this.refCTs.indexOf(contentType.uid) === -1) {
176
+ this.refCTs.push(contentType.uid);
177
+ }
178
+ }
179
+ }
167
180
  // Check if suppress modified flag
168
181
  if (flag.suppressed) {
169
182
  this.modifiedCTs.push((0, lodash_1.find)(this.cTs, { uid: contentType.uid }));
@@ -318,6 +331,12 @@ class EntriesImport extends base_class_1.default {
318
331
  if (this.jsonRteCTsWithRef.indexOf(cTUid) > -1) {
319
332
  entry = (0, utils_1.removeEntryRefsFromJSONRTE)(entry, contentType.schema);
320
333
  }
334
+ if (this.rteCTs.indexOf(cTUid) > -1) {
335
+ entry = (0, utils_1.removeEntryRefsFromJSONRTE)(entry, contentType.schema);
336
+ }
337
+ if (this.rteCTsWithRef.indexOf(cTUid) > -1) {
338
+ entry = (0, utils_1.removeEntryRefsFromJSONRTE)(entry, contentType.schema);
339
+ }
321
340
  //will remove term if term doesn't exists in taxonomy
322
341
  (0, utils_1.lookUpTerms)(contentType === null || contentType === void 0 ? void 0 : contentType.schema, entry, this.taxonomies, this.importConfig);
323
342
  // will replace all old asset uid/urls with new ones
@@ -410,7 +429,7 @@ class EntriesImport extends base_class_1.default {
410
429
  }
411
430
  }
412
431
  }
413
- async replaceEntriesHandler({ apiParams, element: entry }) {
432
+ async replaceEntriesHandler({ apiParams, element: entry, }) {
414
433
  const { additionalInfo: { cTUid, locale } = {} } = apiParams;
415
434
  return new Promise(async (resolve, reject) => {
416
435
  const { items: [entryInStack] = [] } = (await this.stack
@@ -536,7 +555,7 @@ class EntriesImport extends base_class_1.default {
536
555
  // Removing temp values
537
556
  delete entry.sourceEntryFilePath;
538
557
  delete entry.entryOldUid;
539
- if (this.jsonRteCTs.indexOf(cTUid) > -1) {
558
+ if (this.jsonRteCTs.indexOf(cTUid) > -1 || this.rteCTs.indexOf(cTUid) > -1) {
540
559
  // the entries stored in eSuccessFilePath, have the same uids as the entries from source data
541
560
  entry = (0, utils_1.restoreJsonRteEntryRefs)(entry, sourceEntry, contentType.schema, {
542
561
  uidMapper: this.entriesUidMapper,
@@ -544,6 +563,10 @@ class EntriesImport extends base_class_1.default {
544
563
  mappedAssetUrls: this.assetUrlMapper,
545
564
  });
546
565
  }
566
+ entry = (0, utils_1.lookupAssets)({
567
+ content_type: contentType,
568
+ entry: entry,
569
+ }, this.assetUidMapper, this.assetUrlMapper, path.join(this.entriesPath, cTUid), this.installedExtensions);
547
570
  entry = (0, utils_1.lookupEntries)({
548
571
  content_type: contentType,
549
572
  entry,
@@ -687,11 +710,11 @@ class EntriesImport extends base_class_1.default {
687
710
  return Promise.resolve();
688
711
  }
689
712
  // log(this.importConfig, `Starting publish entries for ${cTUid} in locale ${locale}`, 'info');
690
- const onSuccess = ({ response, apiData: { environments, entryUid }, additionalInfo }) => {
691
- (0, utils_1.log)(this.importConfig, `Published entry: '${entryUid}' of content type ${cTUid} and locale ${locale} in ${environments === null || environments === void 0 ? void 0 : environments.join(',')} environments`, 'info');
713
+ const onSuccess = ({ response, apiData: { environments, entryUid, locales }, additionalInfo }) => {
714
+ (0, utils_1.log)(this.importConfig, `Published the entry: '${entryUid}' of Content Type '${cTUid}' and Locale '${locale}' in Environments '${environments === null || environments === void 0 ? void 0 : environments.join(',')}' and Locales '${locales === null || locales === void 0 ? void 0 : locales.join(',')}'`, 'info');
692
715
  };
693
- const onReject = ({ error, apiData, additionalInfo }) => {
694
- (0, utils_1.log)(this.importConfig, `${apiData.entryUid} entry of content type ${cTUid} in locale ${locale} failed to publish`, 'error');
716
+ const onReject = ({ error, apiData: { environments, entryUid, locales }, additionalInfo }) => {
717
+ (0, utils_1.log)(this.importConfig, `Failed to publish: '${entryUid}' entry of Content Type '${cTUid}' and Locale '${locale}' in Environments '${environments === null || environments === void 0 ? void 0 : environments.join(',')}' and Locales '${locales === null || locales === void 0 ? void 0 : locales.join(',')}'`, 'error');
695
718
  (0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
696
719
  };
697
720
  for (const index in indexer) {
@@ -163,31 +163,37 @@ class ImportMarketplaceApps {
163
163
  if ((0, isEmpty_1.default)(privateApps)) {
164
164
  return Promise.resolve();
165
165
  }
166
- await (0, utils_1.getConfirmationToCreateApps)(privateApps, this.importConfig);
167
- (0, utils_1.log)(this.importConfig, 'Starting developer hub private apps re-creation', 'success');
168
- for (let app of privateApps) {
169
- if (this.importConfig.skipPrivateAppRecreationIfExist && (await this.isPrivateAppExistInDeveloperHub(app))) {
170
- // NOTE Found app already exist in the same org
171
- this.appUidMapping[app.uid] = app.uid;
172
- cli_utilities_1.cliux.print(`App '${app.manifest.name}' already exist. skipping app recreation.!`, { color: 'yellow' });
173
- continue;
166
+ let canCreatePrivateApp = await (0, utils_1.getConfirmationToCreateApps)(privateApps, this.importConfig);
167
+ this.importConfig.canCreatePrivateApp = canCreatePrivateApp;
168
+ if (canCreatePrivateApp) {
169
+ (0, utils_1.log)(this.importConfig, 'Starting developer hub private apps re-creation', 'success');
170
+ for (let app of privateApps) {
171
+ if (this.importConfig.skipPrivateAppRecreationIfExist && (await this.isPrivateAppExistInDeveloperHub(app))) {
172
+ // NOTE Found app already exist in the same org
173
+ this.appUidMapping[app.uid] = app.uid;
174
+ cli_utilities_1.cliux.print(`App '${app.manifest.name}' already exist. skipping app recreation.!`, { color: 'yellow' });
175
+ continue;
176
+ }
177
+ // NOTE keys can be passed to install new app in the developer hub
178
+ const validKeys = [
179
+ 'uid',
180
+ 'name',
181
+ 'icon',
182
+ 'oauth',
183
+ 'webhook',
184
+ 'visibility',
185
+ 'target_type',
186
+ 'description',
187
+ 'ui_location',
188
+ 'framework_version',
189
+ ];
190
+ const manifest = (0, pick_1.default)(app.manifest, validKeys);
191
+ this.appOriginalName = manifest.name;
192
+ await this.createPrivateApp(manifest);
174
193
  }
175
- // NOTE keys can be passed to install new app in the developer hub
176
- const validKeys = [
177
- 'uid',
178
- 'name',
179
- 'icon',
180
- 'oauth',
181
- 'webhook',
182
- 'visibility',
183
- 'target_type',
184
- 'description',
185
- 'ui_location',
186
- 'framework_version',
187
- ];
188
- const manifest = (0, pick_1.default)(app.manifest, validKeys);
189
- this.appOriginalName = manifest.name;
190
- await this.createPrivateApp(manifest);
194
+ }
195
+ else {
196
+ (0, utils_1.log)(this.importConfig, 'Skipping private apps creation on Developer Hub...', 'success');
191
197
  }
192
198
  this.appOriginalName = undefined;
193
199
  }
@@ -332,6 +338,10 @@ class ImportMarketplaceApps {
332
338
  const currentStackApp = (0, find_1.default)(this.installedApps, { manifest: { uid: (_a = app === null || app === void 0 ? void 0 : app.manifest) === null || _a === void 0 ? void 0 : _a.uid } });
333
339
  if (!currentStackApp) {
334
340
  // NOTE install new app
341
+ if (app.manifest.visibility === 'private' && !this.importConfig.canCreatePrivateApp) {
342
+ (0, utils_1.log)(this.importConfig, `Skipping the installation of the private app ${app.manifest.name}...`, 'info');
343
+ return Promise.resolve();
344
+ }
335
345
  const installation = await this.installApp(this.importConfig,
336
346
  // NOTE if it's private app it should get uid from mapper else will use manifest uid
337
347
  this.appUidMapping[app.manifest.uid] || app.manifest.uid);
@@ -85,7 +85,7 @@ module.exports = class ImportMarketplaceApps {
85
85
  return "Encryption key can't be empty.";
86
86
  return true;
87
87
  },
88
- message: 'Enter marketplace app configurations encryption key',
88
+ message: 'Enter Marketplace app configurations encryption key',
89
89
  });
90
90
  try {
91
91
  appConfig = !_.isEmpty(appConfig.configuration) ? appConfig.configuration : appConfig.server_configuration;
@@ -153,6 +153,7 @@ export default interface DefaultConfig {
153
153
  noTerminalOutput?: boolean;
154
154
  config?: {
155
155
  basePath?: string;
156
+ branch?: string;
156
157
  } & Record<string, any>;
157
158
  };
158
159
  }
@@ -9,6 +9,7 @@ export interface ExternalConfig {
9
9
  password?: string;
10
10
  }
11
11
  export default interface ImportConfig extends DefaultConfig, ExternalConfig {
12
+ canCreatePrivateApp: boolean;
12
13
  contentDir: string;
13
14
  data: string;
14
15
  management_token?: string;
@@ -235,9 +235,11 @@ const lookupAssets = function (data, mappedAssetUids, mappedAssetUrls, assetUidM
235
235
  assetUrls.forEach(function (assetUrl) {
236
236
  let mappedAssetUrl = mappedAssetUrls[assetUrl];
237
237
  if (typeof mappedAssetUrl !== 'undefined') {
238
- const sanitizedUrl = escapeRegExp(assetUrl).replace(/\.\./g, '\\$&');
239
- const escapedMappedUrl = escapeRegExp(mappedAssetUrl).replace(/\.\./g, '\\$&');
240
- entry = entry.replace(new RegExp(sanitizedUrl, 'img'), escapedMappedUrl);
238
+ //NOTE - This code was added to resolve the SRE issue but once the code was merged Assets URLs in JSON RTE started breaking
239
+ // const sanitizedUrl = escapeRegExp(assetUrl).replace(/\.\./g, '\\$&');
240
+ // const escapedMappedUrl = escapeRegExp(mappedAssetUrl).replace(/\.\./g, '\\$&');
241
+ // entry = entry.replace(new RegExp(sanitizedUrl, 'img'), escapedMappedUrl);
242
+ entry = entry.replace(new RegExp(assetUrl, 'img'), mappedAssetUrl);
241
243
  matchedUrls.push(mappedAssetUrl);
242
244
  }
243
245
  else {
@@ -68,6 +68,11 @@ const suppressSchemaReference = function (schema, flag) {
68
68
  if (schema[i].field_metadata.embed_entry === true)
69
69
  flag.jsonRteEmbeddedEntries = true;
70
70
  }
71
+ else if (schema[i].data_type === 'text' && schema[i].field_metadata.rich_text_type) {
72
+ flag.rte = true;
73
+ if (schema[i].field_metadata.embed_entry === true)
74
+ flag.rteEmbeddedEntries = true;
75
+ }
71
76
  if ((schema[i].hasOwnProperty('mandatory') && schema[i].mandatory) ||
72
77
  (schema[i].hasOwnProperty('unique') && schema[i].unique)) {
73
78
  if (schema[i].uid !== 'title') {
@@ -418,6 +418,21 @@ const removeEntryRefsFromJSONRTE = (entry, ctSchema = []) => {
418
418
  }
419
419
  break;
420
420
  }
421
+ case 'text': {
422
+ if (entry[element.uid] && element.field_metadata.rich_text_type) {
423
+ if (element.multiple) {
424
+ let rteContent = [];
425
+ for (let i = 0; i < entry[element.uid].length; i++) {
426
+ rteContent.push('<p></p>');
427
+ }
428
+ entry[element.uid] = rteContent;
429
+ }
430
+ else {
431
+ entry[element.uid] = '<p></p>';
432
+ }
433
+ }
434
+ break;
435
+ }
421
436
  }
422
437
  }
423
438
  return entry;
@@ -525,11 +540,34 @@ const restoreJsonRteEntryRefs = (entry, sourceStackEntry, ctSchema = [], { uidMa
525
540
  }
526
541
  break;
527
542
  }
543
+ case 'text': {
544
+ if (entry[element.uid] && element.field_metadata.rich_text_type) {
545
+ entry[element.uid] = sourceStackEntry[element.uid];
546
+ const matches = Object.keys(uidMapper).filter((uid) => {
547
+ if (sourceStackEntry[element.uid].indexOf(uid) !== -1)
548
+ return uid;
549
+ });
550
+ if (element.multiple && Array.isArray(entry[element.uid])) {
551
+ for (let i = 0; i < matches.length; i++) {
552
+ entry[element.uid] = entry[element.uid].map((el) => updateUids(el, matches[i], uidMapper));
553
+ }
554
+ }
555
+ else {
556
+ for (let i = 0; i < matches.length; i++) {
557
+ entry[element.uid] = updateUids(entry[element.uid], matches[i], uidMapper);
558
+ }
559
+ }
560
+ }
561
+ break;
562
+ }
528
563
  }
529
564
  }
530
565
  return entry;
531
566
  };
532
567
  exports.restoreJsonRteEntryRefs = restoreJsonRteEntryRefs;
568
+ function updateUids(str, match, uidMapper) {
569
+ return str.replace(new RegExp(match, 'g'), (match) => uidMapper[match]);
570
+ }
533
571
  function setDirtyTrue(jsonRteChild) {
534
572
  // also removing uids in this function
535
573
  if (jsonRteChild.type) {
@@ -35,7 +35,7 @@ const askEncryptionKey = async (defaultValue) => {
35
35
  return "Encryption key can't be empty.";
36
36
  return true;
37
37
  },
38
- message: 'Enter marketplace app configurations encryption key',
38
+ message: 'Enter Marketplace app configurations encryption key',
39
39
  });
40
40
  };
41
41
  exports.askEncryptionKey = askEncryptionKey;
@@ -60,10 +60,15 @@ const getConfirmationToCreateApps = async (privateApps, config) => {
60
60
  if (!config.forceStopMarketplaceAppsPrompt) {
61
61
  if (!(await cli_utilities_1.cliux.confirm(chalk_1.default.yellow(`WARNING!!! The listed apps are private apps that are not available in the destination stack: \n\n${(0, map_1.default)(privateApps, ({ manifest: { name } }, index) => `${String(index + 1)}) ${name}`).join('\n')}\n\nWould you like to re-create the private app and then proceed with the installation? (y/n)`)))) {
62
62
  if (await cli_utilities_1.cliux.confirm(chalk_1.default.yellow(`\nWARNING!!! Canceling the app re-creation may break the content type and entry import. Would you like to proceed without re-create the private app? (y/n)`))) {
63
- return Promise.resolve(true);
63
+ return Promise.resolve(false);
64
64
  }
65
- if (!(await cli_utilities_1.cliux.confirm(chalk_1.default.yellow('\nWould you like to re-create the private app and then proceed with the installation? (y/n)')))) {
66
- process.exit();
65
+ else {
66
+ if (await cli_utilities_1.cliux.confirm(chalk_1.default.yellow('\nWould you like to re-create the private app and then proceed with the installation? (y/n)'))) {
67
+ return Promise.resolve(true);
68
+ }
69
+ else {
70
+ return Promise.resolve(false);
71
+ }
67
72
  }
68
73
  }
69
74
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.14.3",
2
+ "version": "1.15.1",
3
3
  "commands": {
4
4
  "cm:stacks:import": {
5
5
  "id": "cm:stacks:import",
@@ -12,6 +12,7 @@
12
12
  "aliases": [
13
13
  "cm:import"
14
14
  ],
15
+ "hiddenAliases": [],
15
16
  "examples": [
16
17
  "csdx cm:stacks:import --stack-api-key <stack_api_key> --data-dir <path/of/export/destination/dir>",
17
18
  "csdx cm:stacks:import --config <path/of/config/dir>",
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-import",
3
3
  "description": "Contentstack CLI plugin to import content into stack",
4
- "version": "1.14.3",
4
+ "version": "1.15.1",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
8
- "@contentstack/cli-audit": "~1.5.0",
8
+ "@contentstack/cli-audit": "~1.5.3",
9
9
  "@contentstack/cli-command": "~1.2.16",
10
10
  "@contentstack/cli-utilities": "~1.6.0",
11
11
  "@contentstack/management": "~1.15.3",
@@ -34,7 +34,7 @@
34
34
  "@types/mocha": "^8.2.2",
35
35
  "@types/node": "^14.14.32",
36
36
  "@types/sinon": "^10.0.2",
37
- "@types/tar": "^4.0.3",
37
+ "@types/tar": "^6.1.3",
38
38
  "@types/uuid": "^9.0.7",
39
39
  "@typescript-eslint/eslint-plugin": "^5.48.2",
40
40
  "chai": "^4.2.0",
@@ -99,4 +99,4 @@
99
99
  }
100
100
  },
101
101
  "repository": "https://github.com/contentstack/cli"
102
- }
102
+ }