@contentstack/cli-cm-clone 2.0.0-beta → 2.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,291 +0,0 @@
1
- const { Command } = require('@contentstack/cli-command');
2
- const { configHandler, flags, isAuthenticated, managementSDKClient } = require('@contentstack/cli-utilities');
3
- const { CloneHandler } = require('../../../lib/util/clone-handler');
4
- const path = require('path');
5
- const { rimraf } = require('rimraf');
6
- const merge = require('merge');
7
- let pathdir = path.join(__dirname.split('src')[0], 'contents');
8
- const { readdirSync, readFileSync } = require('fs');
9
- let config = {};
10
-
11
- class StackCloneCommand extends Command {
12
- async run() {
13
- try {
14
- let self = this;
15
- const { flags: cloneCommandFlags } = await self.parse(StackCloneCommand);
16
- const {
17
- yes,
18
- type: cloneType,
19
- 'stack-name': stackName,
20
- 'source-branch': sourceStackBranch,
21
- 'source-branch-alias': sourceStackBranchAlias,
22
- 'target-branch': targetStackBranch,
23
- 'target-branch-alias': targetStackBranchAlias,
24
- 'source-stack-api-key': sourceStackApiKey,
25
- 'destination-stack-api-key': destinationStackApiKey,
26
- 'source-management-token-alias': sourceManagementTokenAlias,
27
- 'destination-management-token-alias': destinationManagementTokenAlias,
28
- 'import-webhook-status': importWebhookStatus,
29
- config: externalConfigPath,
30
- } = cloneCommandFlags;
31
-
32
- const handleClone = async () => {
33
- const listOfTokens = configHandler.get('tokens');
34
-
35
- if (externalConfigPath) {
36
- let externalConfig = readFileSync(externalConfigPath, 'utf-8');
37
- externalConfig = JSON.parse(externalConfig);
38
- config = merge.recursive(config, externalConfig);
39
- }
40
- config.forceStopMarketplaceAppsPrompt = yes;
41
- config.skipAudit = cloneCommandFlags['skip-audit'];
42
-
43
- if (cloneType) {
44
- config.cloneType = cloneType;
45
- }
46
- if (stackName) {
47
- config.stackName = stackName;
48
- }
49
- if (sourceStackBranch) {
50
- config.sourceStackBranch = sourceStackBranch;
51
- }
52
- if (sourceStackBranchAlias) {
53
- config.sourceStackBranchAlias = sourceStackBranchAlias;
54
- }
55
- if (targetStackBranch) {
56
- config.targetStackBranch = targetStackBranch;
57
- }
58
- if (targetStackBranchAlias) {
59
- config.targetStackBranchAlias = targetStackBranchAlias;
60
- }
61
- if (sourceStackApiKey) {
62
- config.source_stack = sourceStackApiKey;
63
- }
64
- if (destinationStackApiKey) {
65
- config.target_stack = destinationStackApiKey;
66
- }
67
- if (sourceManagementTokenAlias && listOfTokens[sourceManagementTokenAlias]) {
68
- config.source_alias = sourceManagementTokenAlias;
69
- config.source_stack = listOfTokens[sourceManagementTokenAlias].apiKey;
70
- } else if (sourceManagementTokenAlias) {
71
- console.log(`Provided source token alias (${sourceManagementTokenAlias}) not found in your config.!`);
72
- }
73
- if (destinationManagementTokenAlias && listOfTokens[destinationManagementTokenAlias]) {
74
- config.destination_alias = destinationManagementTokenAlias;
75
- config.target_stack = listOfTokens[destinationManagementTokenAlias].apiKey;
76
- } else if (destinationManagementTokenAlias) {
77
- console.log(
78
- `Provided destination token alias (${destinationManagementTokenAlias}) not found in your config.!`,
79
- );
80
- }
81
- if (importWebhookStatus) {
82
- config.importWebhookStatus = importWebhookStatus;
83
- }
84
-
85
- const managementAPIClient = await managementSDKClient(config);
86
-
87
- await this.removeContentDirIfNotEmptyBeforeClone(pathdir); // NOTE remove if folder not empty before clone
88
- this.registerCleanupOnInterrupt(pathdir);
89
-
90
- config.auth_token = configHandler.get('authtoken');
91
- config.host = this.cmaHost;
92
- config.cdn = this.cdaHost;
93
- config.pathDir = pathdir;
94
- const cloneHandler = new CloneHandler(config);
95
- cloneHandler.setClient(managementAPIClient);
96
- cloneHandler.execute().catch((error) => {
97
- console.log(error);
98
- });
99
- };
100
-
101
- if (sourceManagementTokenAlias && destinationManagementTokenAlias) {
102
- if (sourceStackBranch || targetStackBranch) {
103
- if (isAuthenticated()) {
104
- handleClone();
105
- } else {
106
- console.log('Please login to execute this command, csdx auth:login');
107
- this.exit(1);
108
- }
109
- } else {
110
- handleClone();
111
- }
112
- } else if (isAuthenticated()) {
113
- handleClone();
114
- } else {
115
- console.log('Please login to execute this command, csdx auth:login');
116
- this.exit(1);
117
- }
118
- } catch (error) {
119
- if (error) {
120
- await this.cleanUp(pathdir);
121
- // eslint-disable-next-line no-console
122
- console.log(error.message || error);
123
- }
124
- }
125
- }
126
-
127
-
128
-
129
- async removeContentDirIfNotEmptyBeforeClone(dir) {
130
- try {
131
- const dirNotEmpty = readdirSync(dir).length;
132
-
133
- if (dirNotEmpty) {
134
- await this.cleanUp(dir);
135
- }
136
- } catch (error) {
137
- const omit = ['ENOENT']; // NOTE add emittable error codes in the array
138
-
139
- if (!omit.includes(error.code)) {
140
- console.log(error.message);
141
- }
142
- }
143
- }
144
-
145
- async cleanUp(pathDir, message) {
146
- try {
147
- await rimraf(pathDir);
148
- if (message) {
149
- // eslint-disable-next-line no-console
150
- console.log(message);
151
- }
152
- } catch (err) {
153
- if (err) {
154
- console.log('\nCleaning up');
155
- const skipCodeArr = ['ENOENT', 'EBUSY', 'EPERM', 'EMFILE', 'ENOTEMPTY'];
156
-
157
- if (skipCodeArr.includes(err.code)) {
158
- process.exit();
159
- }
160
- }
161
- }
162
- }
163
-
164
- registerCleanupOnInterrupt(pathDir) {
165
- const interrupt = ['SIGINT', 'SIGQUIT', 'SIGTERM'];
166
- const exceptions = ['unhandledRejection', 'uncaughtException'];
167
-
168
- const cleanUp = async (exitOrError) => {
169
- if (exitOrError) {
170
- // eslint-disable-next-line no-console
171
- console.log('\nCleaning up');
172
- await this.cleanUp(pathDir);
173
- // eslint-disable-next-line no-console
174
- console.log('done');
175
- // eslint-disable-next-line no-process-exit
176
-
177
- if (exitOrError instanceof Promise) {
178
- exitOrError.catch((error) => {
179
- console.log((error && error.message) || '');
180
- });
181
- } else if (exitOrError.message) {
182
- console.log(exitOrError.message);
183
- } else if (exitOrError.errorMessage) {
184
- console.log(exitOrError.message);
185
- }
186
-
187
- if (exitOrError === true) process.exit();
188
- }
189
- };
190
-
191
- exceptions.forEach((event) => process.on(event, cleanUp));
192
- interrupt.forEach((signal) => process.on(signal, () => cleanUp(true)));
193
- }
194
- }
195
-
196
- StackCloneCommand.description = `Clone data (structure/content or both) of a stack into another stack
197
- Use this plugin to automate the process of cloning a stack in few steps.
198
- `;
199
-
200
- StackCloneCommand.examples = [
201
- 'csdx cm:stacks:clone',
202
- 'csdx cm:stacks:clone --source-branch <source-branch-name> --target-branch <target-branch-name> --yes',
203
- 'csdx cm:stacks:clone --source-stack-api-key <apiKey> --destination-stack-api-key <apiKey>',
204
- 'csdx cm:stacks:clone --source-management-token-alias <management token alias> --destination-management-token-alias <management token alias>',
205
- 'csdx cm:stacks:clone --source-branch --target-branch --source-management-token-alias <management token alias> --destination-management-token-alias <management token alias>',
206
- '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>',
207
- ];
208
-
209
- StackCloneCommand.aliases = ['cm:stack-clone'];
210
-
211
- StackCloneCommand.flags = {
212
- 'source-branch': flags.string({
213
- required: false,
214
- multiple: false,
215
- description: 'Branch of the source stack.',
216
- exclusive: ['source-branch-alias']
217
- }),
218
- 'source-branch-alias': flags.string({
219
- required: false,
220
- multiple: false,
221
- description: 'Alias of Branch of the source stack.',
222
- exclusive: ['source-branch']
223
- }),
224
- 'target-branch': flags.string({
225
- required: false,
226
- multiple: false,
227
- description: 'Branch of the target stack.',
228
- exclusive: ['target-branch-alias']
229
- }),
230
- 'target-branch-alias': flags.string({
231
- required: false,
232
- multiple: false,
233
- description: 'Alias of Branch of the target stack.',
234
- exclusive: ['target-branch']
235
- }),
236
- 'source-management-token-alias': flags.string({
237
- required: false,
238
- multiple: false,
239
- description: 'Source management token alias.',
240
- }),
241
- 'destination-management-token-alias': flags.string({
242
- required: false,
243
- multiple: false,
244
- description: 'Destination management token alias.',
245
- }),
246
- 'stack-name': flags.string({
247
- char: 'n',
248
- required: false,
249
- multiple: false,
250
- description: 'Provide a name for the new stack to store the cloned content.',
251
- }),
252
- type: flags.string({
253
- required: false,
254
- multiple: false,
255
- options: ['a', 'b'],
256
- description: ` Type of data to clone. You can select option a or b.
257
- a) Structure (all modules except entries & assets).
258
- b) Structure with content (all modules including entries & assets).
259
- `,
260
- }),
261
- 'source-stack-api-key': flags.string({
262
- description: 'Source stack API key',
263
- }),
264
- 'destination-stack-api-key': flags.string({
265
- description: 'Destination stack API key',
266
- }),
267
- 'import-webhook-status': flags.string({
268
- description: '[default: disable] (optional) The status of the import webhook. <options: disable|current>',
269
- options: ['disable', 'current'],
270
- required: false,
271
- default: 'disable',
272
- }),
273
- yes: flags.boolean({
274
- char: 'y',
275
- required: false,
276
- description: 'Force override all Marketplace prompts.',
277
- }),
278
- 'skip-audit': flags.boolean({
279
- description: ' (optional) Skips the audit fix that occurs during an import operation.',
280
- }),
281
- config: flags.string({
282
- char: 'c',
283
- required: false,
284
- description: 'Path for the external configuration',
285
- }),
286
- };
287
-
288
- StackCloneCommand.usage =
289
- '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]';
290
-
291
- module.exports = StackCloneCommand;
@@ -1,67 +0,0 @@
1
- const CloneCommand = function (execute, undo, params, parentContext) {
2
- this.execute = execute.bind(parentContext);
3
- this.undo = undo && undo.bind(parentContext);
4
- this.params = params;
5
- };
6
-
7
- const HandleOrgCommand = function (params, parentContext) {
8
- return new CloneCommand(parentContext.handleOrgSelection, null, params, parentContext);
9
- };
10
-
11
- const HandleStackCommand = function (params, parentContext) {
12
- return new CloneCommand(parentContext.handleStackSelection, parentContext.execute, params, parentContext);
13
- };
14
-
15
- const HandleBranchCommand = function (params, parentContext, backStepHandler) {
16
- return new CloneCommand(parentContext.handleBranchSelection, backStepHandler, params, parentContext);
17
- };
18
-
19
- const HandleDestinationStackCommand = function (params, parentContext) {
20
- return new CloneCommand(parentContext.handleStackSelection, parentContext.executeDestination, params, parentContext);
21
- };
22
-
23
- const HandleExportCommand = function (params, parentContext) {
24
- return new CloneCommand(parentContext.cmdExport, null, params, parentContext);
25
- };
26
-
27
- const SetBranchCommand = function (params, parentContext) {
28
- return new CloneCommand(parentContext.setBranch, null, params, parentContext);
29
- };
30
-
31
- const CreateNewStackCommand = function (params, parentContext) {
32
- return new CloneCommand(parentContext.createNewStack, parentContext.executeDestination, params, parentContext);
33
- };
34
-
35
- const CloneTypeSelectionCommand = function (params, parentContext) {
36
- return new CloneCommand(parentContext.cloneTypeSelection, null, params, parentContext);
37
- };
38
-
39
- const Clone = function () {
40
- const commands = [];
41
-
42
- return {
43
- execute: async function (command) {
44
- commands.push(command);
45
- const result = await command.execute(command.params);
46
- return result;
47
- },
48
- undo: async function () {
49
- if (commands.length) {
50
- const command = commands.pop();
51
- command.undo && await command.undo(command.params);
52
- }
53
- },
54
- };
55
- };
56
-
57
- module.exports = {
58
- HandleOrgCommand,
59
- HandleStackCommand,
60
- HandleBranchCommand,
61
- HandleDestinationStackCommand,
62
- HandleExportCommand,
63
- SetBranchCommand,
64
- CreateNewStackCommand,
65
- CloneTypeSelectionCommand,
66
- Clone,
67
- };
@@ -1,49 +0,0 @@
1
- 'use strict';
2
-
3
- const { EventEmitter } = require('events');
4
-
5
- class CustomAbortSignal {
6
- constructor() {
7
- this.eventEmitter = new EventEmitter();
8
- this.onabort = null;
9
- this.aborted = false;
10
- }
11
- toString() {
12
- return '[object CustomAbortSignal]';
13
- }
14
- get [Symbol.toStringTag]() {
15
- return 'CustomAbortSignal';
16
- }
17
- removeEventListener(name, handler) {
18
- this.eventEmitter.removeListener(name, handler);
19
- }
20
- addEventListener(name, handler) {
21
- this.eventEmitter.on(name, handler);
22
- }
23
- dispatchEvent(type) {
24
- const event = { type, target: this };
25
- const handlerName = `on${type}`;
26
-
27
- if (typeof this[handlerName] === 'function') this[handlerName](event);
28
- }
29
- }
30
-
31
- class CustomAbortController {
32
- constructor() {
33
- this.signal = new CustomAbortSignal();
34
- }
35
- abort() {
36
- if (this.signal.aborted) return;
37
-
38
- this.signal.aborted = true;
39
- this.signal.dispatchEvent('abort');
40
- }
41
- toString() {
42
- return '[object CustomAbortController]';
43
- }
44
- get [Symbol.toStringTag]() {
45
- return 'CustomAbortController';
46
- }
47
- }
48
-
49
- module.exports = { CustomAbortController, CustomAbortSignal };