@contentstack/cli-cm-clone 1.1.0 → 1.1.3

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
@@ -15,7 +15,7 @@ $ npm install -g @contentstack/cli-cm-clone
15
15
  $ csdx COMMAND
16
16
  running command...
17
17
  $ csdx (-v|--version|version)
18
- @contentstack/cli-cm-clone/0.1.0-beta-1 darwin-x64 node-v13.14.0
18
+ @contentstack/cli-cm-clone/1.1.3 darwin-arm64 node-v18.11.0
19
19
  $ csdx --help [COMMAND]
20
20
  USAGE
21
21
  $ csdx COMMAND
@@ -33,23 +33,63 @@ USAGE
33
33
  ```
34
34
  # Commands
35
35
  <!-- commands -->
36
- * [`csdx cm:stacks:clone`](#csdx-cmstack-clone)
36
+ * [`csdx cm:stacks:clone [--source-branch <value>] [--target-branch <value>] [--source-management-token-alias <value>] [--destination-management-token-alias <value>] [-n <value>] [--type a|b] [--source-stack-api-key <value>] [--destination-stack-api-key <value>] [--import-webhook-status disable|current]`](#csdx-cmstacksclone---source-branch-value---target-branch-value---source-management-token-alias-value---destination-management-token-alias-value--n-value---type-ab---source-stack-api-key-value---destination-stack-api-key-value---import-webhook-status-disablecurrent)
37
37
 
38
- ## `csdx cm:stacks:clone`
38
+ ## `csdx cm:stacks:clone [--source-branch <value>] [--target-branch <value>] [--source-management-token-alias <value>] [--destination-management-token-alias <value>] [-n <value>] [--type a|b] [--source-stack-api-key <value>] [--destination-stack-api-key <value>] [--import-webhook-status disable|current]`
39
39
 
40
- This command allows you to migrate data (structure or content or both) from one stack to another stack (either new or existing)
40
+ Clone data (structure/content or both) of a stack into another stack
41
41
 
42
42
  ```
43
43
  USAGE
44
- $ csdx cm:stacks:clone
44
+ $ csdx cm:stacks:clone [--source-branch <value>] [--target-branch <value>] [--source-management-token-alias <value>]
45
+ [--destination-management-token-alias <value>] [-n <value>] [--type a|b] [--source-stack-api-key <value>]
46
+ [--destination-stack-api-key <value>] [--import-webhook-status disable|current]
47
+
48
+ OPTIONS
49
+ -n, --stack-name=stack-name Name for the new stack to store the cloned
50
+ content.
51
+
52
+ -y, --yes [optional] Override marketplace prompts
53
+
54
+ --destination-management-token-alias=destination-management-token-alias Source API key of the target stack token
55
+ alias.
56
+
57
+ --destination-stack-api-key=destination-stack-api-key Destination stack API Key
58
+
59
+ --import-webhook-status=disable|current [default: disable] Webhook state
60
+
61
+ --source-branch=source-branch Branch of the source stack.
62
+
63
+ --source-management-token-alias=source-management-token-alias Source API key of the target stack token
64
+ alias.
65
+
66
+ --source-stack-api-key=source-stack-api-key Source stack API Key
67
+
68
+ --target-branch=target-branch Branch of the target stack.
69
+
70
+ --type=a|b Type of data to clone
71
+ a) Structure (all modules except entries &
72
+ assets)
73
+ b) Structure with content (all modules
74
+ including entries & assets)
45
75
 
46
76
  DESCRIPTION
47
- ...
48
- Use this plugin to automate the process of cloning a stack in a few steps.
77
+ Use this plugin to automate the process of cloning a stack in few steps.
78
+
79
+ ALIASES
80
+ $ csdx cm:stack-clone
49
81
 
50
- EXAMPLE
82
+ EXAMPLES
51
83
  csdx cm:stacks:clone
84
+ csdx cm:stacks:clone --source-branch <source-branch-name> --target-branch <target-branch-name> --yes
85
+ csdx cm:stacks:clone --source-stack-api-key <apiKey> --destination-stack-api-key <apiKey>
86
+ csdx cm:stacks:clone --source-management-token-alias <management token alias> --destination-management-token-alias
87
+ <management token alias>
88
+ csdx cm:stacks:clone --source-branch --target-branch --source-management-token-alias <management token alias>
89
+ --destination-management-token-alias <management token alias>
90
+ csdx cm:stacks:clone --source-branch --target-branch --source-management-token-alias <management token alias>
91
+ --destination-management-token-alias <management token alias> --type <value a or b>
52
92
  ```
53
93
 
54
- _See code: [src/commands/cm/stacks/clone.js](https://github.com/contentstack/cli/blob/v0.1.0-beta-1/src/commands/cm/stack-clone.js)_
94
+ _See code: [src/commands/cm/stacks/clone.js](https://github.com/contentstack/cli/blob/main/packages/contentstack-clone/src/commands/cm/stacks/clone.js)_
55
95
  <!-- commandsstop -->
@@ -0,0 +1 @@
1
+ {"version":"1.1.3","commands":{"cm:stacks:clone":{"id":"cm:stacks:clone","description":"Clone data (structure/content or both) of a stack into another stack\nUse this plugin to automate the process of cloning a stack in few steps.\n","usage":"cm:stacks:clone [--source-branch <value>] [--target-branch <value>] [--source-management-token-alias <value>] [--destination-management-token-alias <value>] [-n <value>] [--type a|b] [--source-stack-api-key <value>] [--destination-stack-api-key <value>] [--import-webhook-status disable|current]","pluginName":"@contentstack/cli-cm-clone","pluginType":"core","aliases":["cm:stack-clone"],"examples":["csdx cm:stacks:clone","csdx cm:stacks:clone --source-branch <source-branch-name> --target-branch <target-branch-name> --yes","csdx cm:stacks:clone --source-stack-api-key <apiKey> --destination-stack-api-key <apiKey>","csdx cm:stacks:clone --source-management-token-alias <management token alias> --destination-management-token-alias <management token alias>","csdx cm:stacks:clone --source-branch --target-branch --source-management-token-alias <management token alias> --destination-management-token-alias <management token alias>","csdx cm:stacks:clone --source-branch --target-branch --source-management-token-alias <management token alias> --destination-management-token-alias <management token alias> --type <value a or b>"],"flags":{"source-branch":{"name":"source-branch","type":"option","description":"Branch of the source stack.","required":false},"target-branch":{"name":"target-branch","type":"option","description":"Branch of the target stack.","required":false},"source-management-token-alias":{"name":"source-management-token-alias","type":"option","description":"Source API key of the target stack token alias.","required":false},"destination-management-token-alias":{"name":"destination-management-token-alias","type":"option","description":"Source API key of the target stack token alias.","required":false},"stack-name":{"name":"stack-name","type":"option","char":"n","description":"Name for the new stack to store the cloned content.","required":false},"type":{"name":"type","type":"option","description":"Type of data to clone\na) Structure (all modules except entries & assets)\nb) Structure with content (all modules including entries & assets)\n ","required":false,"options":["a","b"]},"source-stack-api-key":{"name":"source-stack-api-key","type":"option","description":"Source stack API Key"},"destination-stack-api-key":{"name":"destination-stack-api-key","type":"option","description":"Destination stack API Key"},"import-webhook-status":{"name":"import-webhook-status","type":"option","description":"Webhook state","required":false,"options":["disable","current"],"default":"disable"},"yes":{"name":"yes","type":"boolean","char":"y","description":"[optional] Override marketplace prompts","required":false,"allowNo":false}},"args":[]}}}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-clone",
3
3
  "description": "Contentstack stack clone plugin",
4
- "version": "1.1.0",
4
+ "version": "1.1.3",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/rohitmishra209/cli-cm-clone/issues",
7
7
  "dependencies": {
8
- "@contentstack/cli-cm-export": "^1.1.0",
9
- "@contentstack/cli-cm-import": "^1.1.0",
10
- "@contentstack/cli-command": "^1.0.1",
11
- "@contentstack/cli-utilities": "^1.0.2",
8
+ "@contentstack/cli-cm-export": "^1.2.1",
9
+ "@contentstack/cli-cm-import": "^1.2.1",
10
+ "@contentstack/cli-command": "^1.0.2",
11
+ "@contentstack/cli-utilities": "^1.0.3",
12
12
  "@contentstack/management": "^1.3.0",
13
13
  "@oclif/command": "^1.8.16",
14
14
  "@oclif/config": "^1.18.3",
@@ -16,7 +16,7 @@
16
16
  "async": "^3.2.4",
17
17
  "child_process": "^1.0.2",
18
18
  "fancy-test": "^1.4.10",
19
- "inquirer": "^7.3.3",
19
+ "inquirer": "^8.2.4",
20
20
  "ora": "^5.1.0",
21
21
  "rimraf": "^3.0.2",
22
22
  "winston": "^3.7.2"
@@ -54,11 +54,15 @@
54
54
  "bin": "csdx",
55
55
  "devPlugins": [
56
56
  "@oclif/plugin-help"
57
- ]
57
+ ],
58
+ "repositoryPrefix": "<%- repo %>/blob/main/packages/contentstack-clone/<%- commandPath %>"
58
59
  },
59
60
  "repository": "https://github.com/contentstack/cli",
60
61
  "scripts": {
61
- "test": "nyc --reporter=html mocha \"test/**/*.test.js\"",
62
+ "postpack": "rm -f oclif.manifest.json",
63
+ "prepack": "oclif-dev manifest && oclif-dev readme",
64
+ "test": "nyc --reporter=html mocha --forbid-only \"test/**/*.test.js\"",
65
+ "posttest": "eslint .",
62
66
  "version": "oclif-dev readme && git add README.md"
63
67
  },
64
68
  "csdxConfig": {
@@ -66,4 +70,4 @@
66
70
  "cm:stack-clone": "csdx cm:stacks:clone"
67
71
  }
68
72
  }
69
- }
73
+ }
@@ -14,6 +14,7 @@ class StackCloneCommand extends Command {
14
14
  let _authToken = configHandler.get('authtoken');
15
15
  const cloneCommandFlags = self.parse(StackCloneCommand).flags;
16
16
  const {
17
+ yes,
17
18
  type: cloneType,
18
19
  'stack-name': stackName,
19
20
  'source-branch': sourceStackBranch,
@@ -23,12 +24,13 @@ class StackCloneCommand extends Command {
23
24
  'source-management-token-alias': sourceManagementTokenAlias,
24
25
  'destination-management-token-alias': destinationManagementTokenAlias,
25
26
  'import-webhook-status': importWebhookStatus,
26
- 'master-locale': masterLocale
27
27
  } = cloneCommandFlags;
28
28
 
29
29
  const handleClone = async () => {
30
30
  const listOfTokens = configHandler.get('tokens');
31
31
 
32
+ config.forceMarketplaceAppsImport = yes;
33
+
32
34
  if (cloneType) {
33
35
  config.cloneType = cloneType;
34
36
  }
@@ -68,16 +70,13 @@ class StackCloneCommand extends Command {
68
70
  await this.removeContentDirIfNotEmptyBeforeClone(pathdir); // NOTE remove if folder not empty before clone
69
71
  this.registerCleanupOnInterrupt(pathdir);
70
72
 
71
- if (masterLocale) {
72
- config.master_locale = { code: masterLocale }
73
- }
74
73
  config.auth_token = _authToken;
75
74
  config.host = this.cmaHost;
76
75
  config.cdn = this.cdaHost;
77
76
  config.pathDir = pathdir;
78
77
  const cloneHandler = new CloneHandler(config);
79
78
  cloneHandler.execute().catch();
80
- }
79
+ };
81
80
 
82
81
  if (sourceManagementTokenAlias && destinationManagementTokenAlias) {
83
82
  if (sourceStackBranch || targetStackBranch) {
@@ -151,7 +150,7 @@ class StackCloneCommand extends Command {
151
150
  if (exitOrError) {
152
151
  // eslint-disable-next-line no-console
153
152
  console.log('\nCleaning up');
154
- await this.cleanUp(pathDir)
153
+ await this.cleanUp(pathDir);
155
154
  // eslint-disable-next-line no-console
156
155
  console.log('done');
157
156
  // eslint-disable-next-line no-process-exit
@@ -160,9 +159,9 @@ class StackCloneCommand extends Command {
160
159
  exitOrError.catch((error) => {
161
160
  console.log((error && error.message) || '');
162
161
  });
163
- } else if (exitOrError && exitOrError.message) {
162
+ } else if (exitOrError.message) {
164
163
  console.log(exitOrError.message);
165
- } else if (exitOrError && exitOrError.errorMessage) {
164
+ } else if (exitOrError.errorMessage) {
166
165
  console.log(exitOrError.message);
167
166
  }
168
167
 
@@ -181,7 +180,7 @@ Use this plugin to automate the process of cloning a stack in few steps.
181
180
 
182
181
  StackCloneCommand.examples = [
183
182
  'csdx cm:stacks:clone',
184
- 'csdx cm:stacks:clone --source-branch <source-branch-name> --target-branch <target-branch-name>',
183
+ 'csdx cm:stacks:clone --source-branch <source-branch-name> --target-branch <target-branch-name> --yes',
185
184
  'csdx cm:stacks:clone --source-stack-api-key <apiKey> --destination-stack-api-key <apiKey>',
186
185
  'csdx cm:stacks:clone --source-management-token-alias <management token alias> --destination-management-token-alias <management token alias>',
187
186
  'csdx cm:stacks:clone --source-branch --target-branch --source-management-token-alias <management token alias> --destination-management-token-alias <management token alias>',
@@ -238,8 +237,10 @@ b) Structure with content (all modules including entries & assets)
238
237
  required: false,
239
238
  default: 'disable',
240
239
  }),
241
- 'master-locale': flags.string({
242
- description: 'Master language for stack clone',
240
+ yes: flags.boolean({
241
+ char: 'y',
242
+ required: false,
243
+ description: '[optional] Override marketplace prompts',
243
244
  }),
244
245
  };
245
246
 
@@ -29,7 +29,7 @@ const SetBranchCommand = function (params, parentContext) {
29
29
  };
30
30
 
31
31
  const CreateNewStackCommand = function (params, parentContext) {
32
- return new CloneCommand(parentContext.createNewStack, null, params, parentContext);
32
+ return new CloneCommand(parentContext.createNewStack, parentContext.executeDestination, params, parentContext);
33
33
  };
34
34
 
35
35
  const CloneTypeSelectionCommand = function (params, parentContext) {
@@ -6,7 +6,7 @@ const chalk = require('chalk');
6
6
 
7
7
  let exportCmd = require('@contentstack/cli-cm-export');
8
8
  let importCmd = require('@contentstack/cli-cm-import');
9
- const { HttpClient, chooseLocalePrompt } = require('@contentstack/cli-utilities');
9
+ const { HttpClient } = require('@contentstack/cli-utilities');
10
10
  let sdkInstance = require('../../lib/util/contentstack-management-sdk');
11
11
  const defaultConfig = require('@contentstack/cli-cm-export/src/config/default');
12
12
  const { CustomAbortController } = require('./abort-controller');
@@ -88,7 +88,7 @@ class CloneHandler {
88
88
  const { org = {}, msg = '', isSource = true, stackAbortController } = options || {}
89
89
 
90
90
  keyPressHandler = async function (_ch, key) {
91
- if (key.name === 'backspace') {
91
+ if (key.name === 'left' && key.shift) {
92
92
  stackAbortController.abort();
93
93
  console.clear();
94
94
  process.stdin.removeListener('keypress', keyPressHandler);
@@ -101,8 +101,7 @@ class CloneHandler {
101
101
 
102
102
  if (stackList) {
103
103
  const ui = new inquirer.ui.BottomBar();
104
- // Use chalk to prettify the text.
105
- ui.updateBottomBar(chalk.cyan('\nFor undo operation press backspace\n'));
104
+ ui.updateBottomBar(chalk.cyan('\nPress shift & left arrow together to undo the operation\n'));
106
105
 
107
106
  const selectedStack = await inquirer.prompt(stackList);
108
107
 
@@ -240,15 +239,6 @@ class CloneHandler {
240
239
  const sourceStack = await cloneCommand.execute(new HandleStackCommand({ org, isSource: true, msg: stackMsg, stackAbortController }, this));
241
240
 
242
241
  if (config.source_stack) {
243
- if (!(config.master_locale && config.master_locale.code)) {
244
-
245
- const res = await chooseLocalePrompt(client.stack({ api_key: config.source_stack }), 'Choose Master Locale', master_locale)
246
- master_locale = res.code
247
- config.master_locale = res
248
- }
249
- else {
250
- master_locale = config.master_locale.code
251
- }
252
242
  await cloneCommand.execute(
253
243
  new HandleBranchCommand({ api_key: config.source_stack }, this)
254
244
  );
@@ -307,9 +297,10 @@ class CloneHandler {
307
297
  await cloneCommand.execute(new HandleBranchCommand({ isSource: false, api_key: config.target_stack }, this));
308
298
  }
309
299
  } else {
310
- const destinationOrg = await this.handleOrgSelection({ isSource: false, msg: 'Choose an organization where you want to create a stack: ' });
300
+ const orgMsg = 'Choose an organization where you want to create a stack: ';
301
+ const destinationOrg = await cloneCommand.execute(new HandleOrgCommand({ msg: orgMsg }, this));
311
302
  const orgUid = orgUidList[destinationOrg.Organization];
312
- await cloneCommand.execute(new CreateNewStackCommand(orgUid, this));
303
+ await cloneCommand.execute(new CreateNewStackCommand({ orgUid, stackAbortController }, this));
313
304
  }
314
305
  await cloneCommand.execute(new CloneTypeSelectionCommand(null, this));
315
306
  return resolve();
@@ -397,30 +388,63 @@ class CloneHandler {
397
388
  });
398
389
  };
399
390
 
400
- async createNewStack(orgUid) {
391
+ async createNewStack(options) {
392
+ let keyPressHandler;
401
393
  return new Promise(async (resolve, reject) => {
402
- let inputvalue;
394
+ try {
395
+ const { orgUid, stackAbortController } = options;
396
+ let inputvalue;
397
+ let uiPromise;
403
398
 
404
- if (!config.stackName) {
405
- inputvalue = await inquirer.prompt(stackName);
406
- } else {
407
- inputvalue = { stack: config.stackName };
408
- }
399
+ keyPressHandler = async function (_ch, key) {
400
+ if (key.name === 'left' && key.shift) {
401
+ stackAbortController.abort();
402
+ // We need to close the inquirer promise correctly, otherwise the unclosed question/answer text is displayed in next line.
403
+ if (uiPromise) {
404
+ uiPromise.ui.close();
405
+ }
406
+ console.clear();
407
+ process.stdin.removeListener('keypress', keyPressHandler);
408
+ await cloneCommand.undo();
409
+ }
410
+ };
411
+ process.stdin.addListener('keypress', keyPressHandler);
412
+
413
+ const ui = new inquirer.ui.BottomBar();
414
+ ui.updateBottomBar(chalk.cyan('\nPress shift & left arrow together to undo the operation\n'));
409
415
 
410
- let stack = { name: inputvalue.stack, master_locale: master_locale };
411
- const spinner = ora('Creating New stack').start();
412
- let newStack = client.stack().create({ stack }, { organization_uid: orgUid });
413
- newStack
414
- .then((result) => {
415
- spinner.succeed('New Stack created Successfully name as ' + result.name);
416
- config.target_stack = result.api_key;
417
- config.destinationStackName = result.name;
418
- return resolve(result);
419
- })
420
- .catch((error) => {
421
- spinner.fail();
422
- return reject(error.errorMessage + ' Contact the Organization owner for Stack Creation access.');
423
- });
416
+ if (!config.stackName) {
417
+ uiPromise = inquirer.prompt(stackName);
418
+ inputvalue = await uiPromise;
419
+ } else {
420
+ inputvalue = { stack: config.stackName };
421
+ }
422
+
423
+ if (stackAbortController.signal.aborted) {
424
+ return reject();
425
+ }
426
+
427
+ let stack = { name: inputvalue.stack, master_locale: master_locale };
428
+ const spinner = ora('Creating New stack').start();
429
+ let newStack = client.stack().create({ stack }, { organization_uid: orgUid });
430
+ newStack
431
+ .then((result) => {
432
+ spinner.succeed('New Stack created Successfully name as ' + result.name);
433
+ config.target_stack = result.api_key;
434
+ config.destinationStackName = result.name;
435
+ return resolve(result);
436
+ })
437
+ .catch((error) => {
438
+ spinner.fail();
439
+ return reject(error.errorMessage + ' Contact the Organization owner for Stack Creation access.');
440
+ });
441
+ } catch (error) {
442
+ return reject(error);
443
+ } finally {
444
+ if (keyPressHandler) {
445
+ process.stdin.removeListener('keypress', keyPressHandler);
446
+ }
447
+ }
424
448
  });
425
449
  }
426
450
 
@@ -492,6 +516,8 @@ class CloneHandler {
492
516
  cmd.push('--import-webhook-status', config.importWebhookStatus);
493
517
  }
494
518
 
519
+ if (config.forceMarketplaceAppsImport) cmd.push('-y')
520
+
495
521
  await importCmd.run(cmd);
496
522
  return resolve();
497
523
  });