@contentstack/cli-migration 0.1.1-beta.3 → 1.0.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -27
  3. package/oclif.manifest.json +1 -1
  4. package/package.json +16 -11
  5. package/src/actions/action-list.js +11 -11
  6. package/src/actions/index.js +33 -34
  7. package/src/commands/cm/{migration.js → stacks/migration.js} +102 -74
  8. package/src/config/api-config.js +8 -9
  9. package/src/config/default-options.js +2 -2
  10. package/src/config/index.js +2 -2
  11. package/src/config/master-locale.js +2 -2
  12. package/src/modules/base.js +33 -33
  13. package/src/modules/content-types.js +76 -76
  14. package/src/modules/fields.js +73 -73
  15. package/src/modules/index.js +2 -2
  16. package/src/modules/locale.js +13 -13
  17. package/src/modules/migration.js +45 -46
  18. package/src/modules/parser.js +65 -52
  19. package/src/services/content-types.js +160 -163
  20. package/src/services/index.js +2 -2
  21. package/src/services/locales.js +33 -35
  22. package/src/utils/auto-retry.js +14 -12
  23. package/src/utils/callsite.js +14 -14
  24. package/src/utils/constants.js +108 -115
  25. package/src/utils/contentstack-sdk.js +42 -43
  26. package/src/utils/error-handler.js +8 -8
  27. package/src/utils/error-helper.js +41 -40
  28. package/src/utils/fs-helper.js +12 -12
  29. package/src/utils/get-batches.js +4 -4
  30. package/src/utils/get-config.js +6 -6
  31. package/src/utils/group-by.js +17 -17
  32. package/src/utils/index.js +2 -2
  33. package/src/utils/logger.js +42 -52
  34. package/src/utils/object-helper.js +7 -7
  35. package/src/utils/safe-promise.js +2 -2
  36. package/src/utils/schema-helper.js +12 -12
  37. package/src/utils/success-handler.js +5 -5
  38. package/src/validators/api-error.js +10 -8
  39. package/src/validators/base-validator.js +14 -14
  40. package/src/validators/create-content-type-validator.js +21 -25
  41. package/src/validators/edit-content-type-validator.js +21 -24
  42. package/src/validators/field-validator.js +10 -8
  43. package/src/validators/index.js +2 -2
  44. package/src/validators/migration-error.js +9 -7
  45. package/src/validators/schema-validator.js +11 -9
  46. package/src/validators/type-error.js +11 -10
@@ -1,33 +1,25 @@
1
1
  /* eslint-disable no-unused-expressions */
2
2
  /* eslint-disable no-warning-comments */
3
3
  /* eslint-disable camelcase */
4
- "use strict";
4
+ 'use strict';
5
5
 
6
6
  // Dependencies
7
- const Listr = require("listr");
8
- const { resolve, extname } = require("path");
9
- const { Command, flags } = require("@contentstack/cli-command");
10
- const { waterfall } = require("async");
11
- const { Parser } = require("../../modules");
12
- const { ActionList } = require("../../actions");
13
- const fs = require("fs");
14
- const chalk = require("chalk");
7
+ const Listr = require('listr');
8
+ const { resolve, extname } = require('path');
9
+ const { Command, flags } = require('@contentstack/cli-command');
10
+ const { waterfall } = require('async');
11
+ const { Parser } = require('../../../modules');
12
+ const { ActionList } = require('../../../actions');
13
+ const fs = require('fs');
14
+ const chalk = require('chalk');
15
+ const { configHandler } = require('@contentstack/cli-utilities');
16
+ const { printFlagDeprecation } = require('@contentstack/cli-utilities');
15
17
 
16
- const {
17
- ApiError,
18
- SchemaValidator,
19
- MigrationError,
20
- FieldValidator,
21
- } = require("../../validators");
18
+ const { ApiError, SchemaValidator, MigrationError, FieldValidator } = require('../../../validators');
22
19
 
23
20
  // Utils
24
- const {
25
- map: _map,
26
- constants,
27
- safePromise,
28
- errorHelper,
29
- } = require("../../utils");
30
- const { success } = require("../../utils/logger");
21
+ const { map: _map, constants, safePromise, errorHelper } = require('../../../utils');
22
+ const { success } = require('../../../utils/logger');
31
23
 
32
24
  // Properties
33
25
  const { get, set, getMapInstance, resetMapInstance } = _map;
@@ -44,41 +36,50 @@ const {
44
36
 
45
37
  class MigrationCommand extends Command {
46
38
  static examples = [
47
- "$ csdx cm:migration -A -n <migration/script/file/path> -k <api-key>",
48
- "$ csdx cm:migration -A -n <migration/script/file/path> -k <api-key> -B <target branch name>",
49
- "$ csdx cm:migration --config <key1>:<value1> <key2>:<value2> ... -n <migration/script/file/path>",
50
- "$ csdx cm:migration --config-file <path/to/json/config/file> -n <migration/script/file/path>",
51
- "$ csdx cm:migration --multi -n <migration/scripts/dir/path> ",
52
- "$ csdx cm:migration -a -n <migration/script/file/path> -k <api-key>",
39
+ '$ csdx cm:migration --file-path <migration/script/file/path> -k <api-key>',
40
+ '$ csdx cm:migration --file-path <migration/script/file/path> -k <api-key> --branch <target branch name>',
41
+ '$ csdx cm:migration --config <key1>:<value1> <key2>:<value2> ... --file-path <migration/script/file/path>',
42
+ '$ csdx cm:migration --config-file <path/to/json/config/file> --file-path <migration/script/file/path>',
43
+ '$ csdx cm:migration --multiple --file-path <migration/scripts/dir/path> ',
44
+ '$ csdx cm:migration --alias --file-path <migration/script/file/path> -k <api-key>',
53
45
  ];
54
46
 
55
47
  async run() {
56
48
  // TODO: filePath validation required.
57
49
  const migrationCommandFlags = this.parse(MigrationCommand).flags;
58
- const { filePath, multi, branch } = migrationCommandFlags;
59
- const authtoken = migrationCommandFlags.authtoken;
60
- const apiKey = migrationCommandFlags["api-key"];
61
- const alias = migrationCommandFlags["management-token-alias"];
62
- const config = migrationCommandFlags["config"];
50
+ const { branch } = migrationCommandFlags;
51
+ const filePath = migrationCommandFlags['file-path'] || migrationCommandFlags.filePath;
52
+ const multi = migrationCommandFlags.multiple || migrationCommandFlags.multi;
53
+ const authtoken = configHandler.get('authtoken');
54
+ const apiKey = migrationCommandFlags['api-key'] || migrationCommandFlags['stack-api-key'];
55
+ const alias = migrationCommandFlags['alias'] || migrationCommandFlags['management-token-alias'];
56
+ const config = migrationCommandFlags['config'];
57
+
58
+ if (!authtoken && !alias) {
59
+ this.log(
60
+ "AuthToken is not present in local drive, Hence use 'csdx auth:login' command for login or provide management token alias",
61
+ );
62
+ this.exit();
63
+ }
63
64
 
64
65
  if (!filePath) {
65
- this.log("Please provide the migration script file path, use -n or --filePath flag");
66
+ this.log('Please provide the migration script file path, use --file-path flag');
66
67
  this.exit();
67
68
  }
68
69
 
69
70
  // Reset map instance
70
71
  const mapInstance = getMapInstance();
71
72
  resetMapInstance(mapInstance);
72
- if (migrationCommandFlags["config-file"]) {
73
- set("config-path", mapInstance, migrationCommandFlags["config-file"]);
73
+ if (migrationCommandFlags['config-file']) {
74
+ set('config-path', mapInstance, migrationCommandFlags['config-file']);
74
75
  }
75
76
 
76
77
  if (Array.isArray(config) && config.length > 0) {
77
78
  let configObj = config.reduce((a, v) => {
78
- let objArr = v.split(":");
79
+ let objArr = v.split(':');
79
80
  return { ...a, [objArr[0]]: objArr[1] };
80
81
  }, {});
81
- set("config", mapInstance, configObj);
82
+ set('config', mapInstance, configObj);
82
83
  }
83
84
 
84
85
  let stackSDKInstance;
@@ -104,9 +105,7 @@ class MigrationCommand extends Command {
104
105
  });
105
106
  }
106
107
  }
107
- }
108
-
109
- if (authtoken) {
108
+ } else if (authtoken) {
110
109
  set(AUTH_TOKEN, mapInstance, authtoken);
111
110
  set(API_KEY, mapInstance, apiKey);
112
111
  this.managementAPIClient = { authtoken: this.authToken };
@@ -162,6 +161,7 @@ class MigrationCommand extends Command {
162
161
  requests.splice(0, requests.length);
163
162
  } catch (error) {
164
163
  // errorHandler(null, null, null, error)
164
+ this.log(error);
165
165
  }
166
166
  }
167
167
 
@@ -170,16 +170,16 @@ class MigrationCommand extends Command {
170
170
  const resolvedMigrationPath = resolve(filePath);
171
171
  try {
172
172
  const files = fs.readdirSync(resolvedMigrationPath);
173
- for (let index = 0; index < files.length; index++) {
174
- const file = files[index];
175
- if (extname(file) === ".js") {
173
+ for (const element of files) {
174
+ const file = element;
175
+ if (extname(file) === '.js') {
176
176
  success(chalk`{white Executing file:} {grey {bold ${file}}}`);
177
177
  // eslint-disable-next-line no-await-in-loop
178
178
  await this.execSingleFile(resolve(filePath, file), mapInstance);
179
179
  }
180
180
  }
181
181
  } catch (error) {
182
- error(error);
182
+ errorHelper(error);
183
183
  }
184
184
  }
185
185
 
@@ -187,8 +187,8 @@ class MigrationCommand extends Command {
187
187
  const _tasks = [];
188
188
  const results = [];
189
189
 
190
- for (let i = 0; i < requests.length; i++) {
191
- let reqObj = requests[i];
190
+ for (const element of requests) {
191
+ let reqObj = element;
192
192
  const { title, failedTitle, successTitle, tasks } = reqObj;
193
193
  const task = {
194
194
  title: title,
@@ -224,48 +224,76 @@ class MigrationCommand extends Command {
224
224
  }
225
225
  }
226
226
 
227
- MigrationCommand.description = "Contentstack migration script.";
227
+ MigrationCommand.description = 'Contentstack migration script.';
228
228
 
229
229
  MigrationCommand.flags = {
230
- "api-key": flags.string({
231
- char: "k",
232
- description: "With this flag add the API key of your stack.",
233
- dependsOn: ["authtoken"],
234
- exclusive: ["management-token-alias"],
230
+ 'api-key': flags.string({
231
+ char: 'k',
232
+ description: 'With this flag add the API key of your stack.',
233
+ dependsOn: ['authtoken'],
234
+ exclusive: ['alias'],
235
+ parse: printFlagDeprecation(['--api-key'], ['-k', '--stack-api-key']),
236
+ hidden: true,
237
+ }),
238
+ 'stack-api-key': flags.string({
239
+ char: 'k',
240
+ description: 'With this flag add the API key of your stack.',
241
+ dependsOn: ['authtoken'],
242
+ exclusive: ['alias'],
235
243
  }),
236
244
  authtoken: flags.boolean({
237
- char: "A",
245
+ char: 'A',
238
246
  description:
239
- "Use this flag to use the auth token of the current session. After logging in CLI, an auth token is generated for each new session.",
240
- dependsOn: ["api-key"],
241
- exclusive: ["management-token-alias"],
247
+ 'Use this flag to use the auth token of the current session. After logging in CLI, an auth token is generated for each new session.',
248
+ dependsOn: ['api-key'],
249
+ exclusive: ['alias'],
250
+ parse: printFlagDeprecation(['-A', '--authtoken']),
251
+ hidden: true,
252
+ }),
253
+ alias: flags.string({
254
+ char: 'a',
255
+ description: 'Use this flag to add the management token alias.',
256
+ exclusive: ['authtoken'],
257
+ }),
258
+ 'management-token-alias': flags.string({
259
+ description: 'alias of the management token',
260
+ exclusive: ['authtoken'],
261
+ hidden: true,
262
+ parse: printFlagDeprecation(['--management-token-alias'], ['-a', '--alias']),
242
263
  }),
243
- "management-token-alias": flags.string({
244
- char: "a",
245
- description: "Use this flag to add the management token alias.",
246
- exclusive: ["authtoken"],
247
- }), // Add a better description
248
264
  filePath: flags.string({
249
- char: "n",
250
- description:
251
- "Use this flag to provide the path of the file of the migration script provided by the user.",
265
+ char: 'n',
266
+ description: 'Use this flag to provide the path of the file of the migration script provided by the user.',
267
+ parse: printFlagDeprecation(['-n', '--filePath'], ['--file-path']),
268
+ hidden: true,
269
+ }),
270
+ 'file-path': flags.string({
271
+ description: 'Use this flag to provide the path of the file of the migration script provided by the user.',
252
272
  }),
253
273
  branch: flags.string({
254
- char: "B",
255
- description:
256
- "Use this flag to add the branch name where you want to perform the migration.",
274
+ char: 'B',
275
+ description: 'Use this flag to add the branch name where you want to perform the migration.',
276
+ parse: printFlagDeprecation(['-B'], ['--branch']),
257
277
  }),
258
- "config-file": flags.string({
259
- description: "[optional] Path of the JSON configuration file",
278
+ 'config-file': flags.string({
279
+ description: '[optional] Path of the JSON configuration file',
260
280
  }),
261
281
  config: flags.string({
262
- description: "[optional] inline configuration, <key1>:<value1>",
282
+ description: '[optional] inline configuration, <key1>:<value1>',
263
283
  multiple: true,
264
284
  }),
265
285
  multi: flags.boolean({
266
- description:
267
- "This flag helps you to migrate multiple content files in a single instance.",
268
- }), // Add a better description
286
+ description: 'This flag helps you to migrate multiple content files in a single instance.',
287
+ parse: printFlagDeprecation(['--multi'], ['--multiple']),
288
+ hidden: true,
289
+ }),
290
+ multiple: flags.boolean({
291
+ description: 'This flag helps you to migrate multiple content files in a single instance.',
292
+ }),
269
293
  };
270
294
 
295
+ MigrationCommand.aliases = ['cm:migration'];
296
+
297
+ MigrationCommand.usage = 'cm:stacks:migration [-k <value>] [-a <value>] [--file-path <value>] [--branch <value>] [--config-file <value>] [--config <value>] [--multiple]';
298
+
271
299
  module.exports = MigrationCommand;
@@ -1,17 +1,16 @@
1
1
  /* eslint-disable camelcase */
2
- "use strict";
2
+ 'use strict';
3
3
 
4
4
  const { CONTENTSTACK_API_KEY, CONTENTSTACK_AUTHTOKEN } = process.env;
5
- const { version } = require("../../package.json");
5
+ const { version } = require('../../package.json');
6
6
  module.exports = {
7
- hostname: "dev9-app.contentstack.com",
8
- // hostname: 'stag-app.contentstack.com',
9
- version: "/v3",
10
- method: "GET", // Default Http method
7
+ hostname: 'api.contentstack.io',
8
+ version: '/v3',
9
+ method: 'GET', // Default Http method
11
10
  headers: {
12
- "Content-Type": "application/json",
13
- "Content-Length": null,
14
- "X-User-Agent": `@contentstack-migration/v${version}`,
11
+ 'Content-Type': 'application/json',
12
+ 'Content-Length': null,
13
+ 'X-User-Agent': `@contentstack-migration/v${version}`,
15
14
  authtoken: CONTENTSTACK_AUTHTOKEN,
16
15
  api_key: CONTENTSTACK_API_KEY,
17
16
  // management_token: CONTENTSTACK_MANAGEMENT_TOKEN
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable camelcase */
2
- 'use strict'
2
+ 'use strict';
3
3
 
4
4
  module.exports = {
5
5
  is_page: true,
6
6
  singleton: false,
7
- }
7
+ };
@@ -1,7 +1,7 @@
1
- 'use strict'
1
+ 'use strict';
2
2
 
3
3
  module.exports = {
4
4
  apiConfig: require('./api-config'),
5
5
  defaultOptions: require('./default-options'),
6
6
  masterLocale: require('./master-locale'),
7
- }
7
+ };
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable camelcase */
2
- 'use strict'
2
+ 'use strict';
3
3
 
4
4
  module.exports = {
5
5
  master_locale: {
@@ -7,4 +7,4 @@ module.exports = {
7
7
  name: 'English - United States',
8
8
  code: 'en-us',
9
9
  },
10
- }
10
+ };
@@ -1,12 +1,12 @@
1
- 'use strict'
1
+ 'use strict';
2
2
 
3
3
  // Utils
4
- const {map: _map, constants} = require('../utils')
4
+ const { map: _map, constants } = require('../utils');
5
5
  // Actions
6
- const {actionCreators} = require('../actions')
6
+ const { actionCreators } = require('../actions');
7
7
  // Utils properties
8
- const {getMapInstance, get} = _map
9
- const {actionMapper} = constants
8
+ const { getMapInstance, get } = _map;
9
+ const { actionMapper } = constants;
10
10
 
11
11
  /**
12
12
  * Base class for module classes
@@ -15,9 +15,9 @@ const {actionMapper} = constants
15
15
  */
16
16
  class Base {
17
17
  constructor(id, action) {
18
- this.id = id
19
- this.action = action
20
- this.actions = []
18
+ this.id = id;
19
+ this.action = action;
20
+ this.actions = [];
21
21
  }
22
22
 
23
23
  /**
@@ -26,14 +26,14 @@ class Base {
26
26
  * @returns {Base} current instance of inherited class
27
27
  */
28
28
  title(value) {
29
- const mapInstance = getMapInstance()
30
- const {id, action} = this
29
+ const mapInstance = getMapInstance();
30
+ const { id, action } = this;
31
31
 
32
- const contentType = get(id, mapInstance)
32
+ const contentType = get(id, mapInstance);
33
33
 
34
- contentType[action].content_type.title = value
34
+ contentType[action].content_type.title = value;
35
35
 
36
- return this
36
+ return this;
37
37
  }
38
38
 
39
39
  /**
@@ -42,11 +42,11 @@ class Base {
42
42
  * @returns {Base} current instance of inherited class
43
43
  */
44
44
  description(value) {
45
- const mapInstance = getMapInstance()
46
- const {id, action} = this
47
- const contentType = get(id, mapInstance)
48
- contentType[action].content_type.description = value
49
- return this
45
+ const mapInstance = getMapInstance();
46
+ const { id, action } = this;
47
+ const contentType = get(id, mapInstance);
48
+ contentType[action].content_type.description = value;
49
+ return this;
50
50
  }
51
51
 
52
52
  /**
@@ -55,14 +55,14 @@ class Base {
55
55
  * @returns {Base} current instance of inherited class
56
56
  */
57
57
  force(value) {
58
- const mapInstance = getMapInstance()
59
- const {id, action} = this
58
+ const mapInstance = getMapInstance();
59
+ const { id, action } = this;
60
60
 
61
- const contentType = get(id, mapInstance)
61
+ const contentType = get(id, mapInstance);
62
62
 
63
- contentType[action].content_type.force = value
63
+ contentType[action].content_type.force = value;
64
64
 
65
- return this
65
+ return this;
66
66
  }
67
67
 
68
68
  /**
@@ -75,21 +75,21 @@ class Base {
75
75
  */
76
76
  dispatch(callsite, id, opts, method) {
77
77
  if (!id && !opts) {
78
- let mapInstance = getMapInstance()
79
- let actions = get(actionMapper, mapInstance) // Returns an array if empty
80
- let action = actionCreators.customTasks(callsite, opts)
81
- actions.push(action)
78
+ let mapInstance = getMapInstance();
79
+ let actions = get(actionMapper, mapInstance); // Returns an array if empty
80
+ let action = actionCreators.customTasks(callsite, opts);
81
+ actions.push(action);
82
82
  } else {
83
- let mapInstance = getMapInstance()
84
- let actions = get(actionMapper, mapInstance) // Returns an array if empty
85
- let action = actionCreators.contentType[method](callsite, id, {...opts, id})
86
- actions.push(action)
83
+ let mapInstance = getMapInstance();
84
+ let actions = get(actionMapper, mapInstance); // Returns an array if empty
85
+ let action = actionCreators.contentType[method](callsite, id, { ...opts, id });
86
+ actions.push(action);
87
87
  }
88
88
  }
89
89
 
90
90
  getActions() {
91
- return this.actions
91
+ return this.actions;
92
92
  }
93
93
  }
94
94
 
95
- module.exports = Base
95
+ module.exports = Base;