@hubspot/cli 3.0.9 → 3.0.10-beta.11

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 (76) hide show
  1. package/README.md +6 -0
  2. package/bin/cli.js +3 -2
  3. package/commands/accounts/list.js +18 -26
  4. package/commands/accounts/rename.js +13 -24
  5. package/commands/accounts.js +4 -1
  6. package/commands/app/deploy.js +22 -28
  7. package/commands/auth.js +30 -13
  8. package/commands/config/set/allowUsageTracking.js +15 -31
  9. package/commands/config/set/defaultAccount.js +22 -32
  10. package/commands/config/set/defaultMode.js +23 -42
  11. package/commands/config/set/httpTimeout.js +10 -28
  12. package/commands/config/set.js +4 -1
  13. package/commands/config.js +4 -1
  14. package/commands/create/api-sample.js +14 -12
  15. package/commands/create/module.js +19 -6
  16. package/commands/create/project.js +8 -1
  17. package/commands/create/template.js +19 -4
  18. package/commands/create.js +23 -8
  19. package/commands/customObject/create.js +22 -24
  20. package/commands/customObject/schema/create.js +30 -28
  21. package/commands/customObject/schema/delete.js +20 -20
  22. package/commands/customObject/schema/fetch-all.js +17 -24
  23. package/commands/customObject/schema/fetch.js +29 -24
  24. package/commands/customObject/schema/list.js +8 -17
  25. package/commands/customObject/schema/update.js +31 -29
  26. package/commands/customObject/schema.js +4 -1
  27. package/commands/customObject.js +10 -21
  28. package/commands/fetch.js +15 -30
  29. package/commands/filemanager/fetch.js +13 -25
  30. package/commands/filemanager/upload.js +47 -35
  31. package/commands/filemanager.js +4 -1
  32. package/commands/functions/deploy.js +34 -37
  33. package/commands/functions/list.js +9 -24
  34. package/commands/functions/server.js +13 -29
  35. package/commands/functions.js +4 -1
  36. package/commands/hubdb/clear.js +25 -21
  37. package/commands/hubdb/create.js +25 -22
  38. package/commands/hubdb/delete.js +19 -20
  39. package/commands/hubdb/fetch.js +15 -20
  40. package/commands/hubdb.js +4 -1
  41. package/commands/init.js +23 -11
  42. package/commands/lint.js +14 -23
  43. package/commands/list.js +19 -25
  44. package/commands/logs.js +41 -135
  45. package/commands/mv.js +21 -25
  46. package/commands/open.js +7 -5
  47. package/commands/project/create.js +111 -0
  48. package/commands/project/deploy.js +30 -34
  49. package/commands/project/listBuilds.js +160 -0
  50. package/commands/project/logs.js +192 -0
  51. package/commands/project/upload.js +108 -55
  52. package/commands/project.js +7 -8
  53. package/commands/remove.js +12 -20
  54. package/commands/sandbox/create.js +16 -11
  55. package/commands/secrets/addSecret.js +18 -21
  56. package/commands/secrets/deleteSecret.js +18 -21
  57. package/commands/secrets/listSecrets.js +10 -19
  58. package/commands/secrets/updateSecret.js +18 -21
  59. package/commands/secrets.js +4 -1
  60. package/commands/server.js +13 -5
  61. package/commands/{marketplaceValidate/validateTheme.js → theme/marketplace-validate.js} +26 -24
  62. package/commands/theme.js +5 -3
  63. package/commands/upload.js +66 -45
  64. package/commands/watch.js +33 -55
  65. package/lib/__tests__/serverlessLogs.js +8 -9
  66. package/lib/commonOpts.js +14 -11
  67. package/lib/enums/exitCodes.js +14 -0
  68. package/lib/projects.js +246 -235
  69. package/lib/prompts/projects.js +8 -5
  70. package/lib/prompts/sandboxes.js +5 -2
  71. package/lib/prompts.js +26 -27
  72. package/lib/serverlessLogs.js +11 -12
  73. package/lib/ui.js +48 -0
  74. package/lib/validation.js +2 -1
  75. package/package.json +9 -7
  76. package/commands/project/init.js +0 -108
package/commands/mv.js CHANGED
@@ -1,9 +1,4 @@
1
1
  const { moveFile } = require('@hubspot/cli-lib/api/fileMapper');
2
- const {
3
- loadConfig,
4
- validateConfig,
5
- checkAndWarnGitInclusion,
6
- } = require('@hubspot/cli-lib');
7
2
  const { logger } = require('@hubspot/cli-lib/logger');
8
3
  const {
9
4
  logApiErrorInstance,
@@ -14,25 +9,14 @@ const {
14
9
  addConfigOptions,
15
10
  addAccountOptions,
16
11
  addUseEnvironmentOptions,
17
- setLogLevel,
18
12
  getAccountId,
19
13
  } = require('../lib/commonOpts');
20
- const { logDebugInfo } = require('../lib/debugInfo');
21
- const { validateAccount } = require('../lib/validation');
22
14
  const { trackCommandUsage } = require('../lib/usageTracking');
23
15
  const { isPathFolder } = require('../lib/filesystem');
16
+ const { loadAndValidateOptions } = require('../lib/validation');
17
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
24
18
 
25
- const loadAndValidateOptions = async options => {
26
- setLogLevel(options);
27
- logDebugInfo(options);
28
- const { config: configPath } = options;
29
- loadConfig(configPath, options);
30
- checkAndWarnGitInclusion();
31
-
32
- if (!(validateConfig() && (await validateAccount(options)))) {
33
- process.exit(1);
34
- }
35
- };
19
+ const i18nKey = 'cli.commands.mv';
36
20
 
37
21
  const getCorrectedDestPath = (srcPath, destPath) => {
38
22
  if (!isPathFolder(srcPath)) {
@@ -44,11 +28,10 @@ const getCorrectedDestPath = (srcPath, destPath) => {
44
28
  };
45
29
 
46
30
  exports.command = 'mv <srcPath> <destPath>';
47
- exports.describe =
48
- 'Move a remote file or folder in HubSpot. This feature is currently in beta and the CLI contract is subject to change';
31
+ exports.describe = i18n(`${i18nKey}.describe`);
49
32
 
50
33
  exports.handler = async options => {
51
- loadAndValidateOptions(options);
34
+ await loadAndValidateOptions(options);
52
35
 
53
36
  const { srcPath, destPath } = options;
54
37
  const accountId = getAccountId(options);
@@ -58,14 +41,27 @@ exports.handler = async options => {
58
41
  try {
59
42
  await moveFile(accountId, srcPath, getCorrectedDestPath(srcPath, destPath));
60
43
  logger.success(
61
- `Moved "${srcPath}" to "${destPath}" in account ${accountId}`
44
+ i18n(`${i18nKey}.move`, {
45
+ accountId,
46
+ destPath,
47
+ srcPath,
48
+ })
62
49
  );
63
50
  } catch (error) {
64
51
  logger.error(
65
- `Moving "${srcPath}" to "${destPath}" in account ${accountId} failed`
52
+ i18n(`${i18nKey}.errors.moveFailed`, {
53
+ accountId,
54
+ destPath,
55
+ srcPath,
56
+ })
66
57
  );
67
58
  if (error.statusCode === 409) {
68
- logger.error(`The folder "${srcPath}" already exists in "${destPath}".`);
59
+ logger.error(
60
+ i18n(`${i18nKey}.errors.sourcePathExists`, {
61
+ destPath,
62
+ srcPath,
63
+ })
64
+ );
69
65
  } else {
70
66
  logApiErrorInstance(
71
67
  error,
package/commands/open.js CHANGED
@@ -7,6 +7,9 @@ const {
7
7
  const { trackCommandUsage } = require('../lib/usageTracking');
8
8
  const { logSiteLinks, getSiteLinksAsArray, openLink } = require('../lib/links');
9
9
  const inquirer = require('inquirer');
10
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
11
+
12
+ const i18nKey = 'cli.commands.open';
10
13
 
11
14
  const separator = ' => ';
12
15
  const createListPrompt = async accountId =>
@@ -16,7 +19,7 @@ const createListPrompt = async accountId =>
16
19
  look: false,
17
20
  name: 'open',
18
21
  pageSize: 20,
19
- message: 'Select a link to open',
22
+ message: i18n(`${i18nKey}.selectLink`),
20
23
  choices: getSiteLinksAsArray(accountId).map(
21
24
  l => `${l.shortcut}${separator}${l.url}`
22
25
  ),
@@ -25,8 +28,7 @@ const createListPrompt = async accountId =>
25
28
  ]);
26
29
 
27
30
  exports.command = 'open [shortcut]';
28
- exports.describe =
29
- 'Open a HubSpot page in your browser. Run ‘hs open list’ to see all available shortcuts.';
31
+ exports.describe = i18n(`${i18nKey}.describe`);
30
32
 
31
33
  exports.handler = async options => {
32
34
  const { shortcut, list } = options;
@@ -47,13 +49,13 @@ exports.handler = async options => {
47
49
 
48
50
  exports.builder = yargs => {
49
51
  yargs.positional('[shortcut]', {
50
- describe: "Shortcut of the link you'd like to open",
52
+ describe: i18n(`${i18nKey}.positionals.shortcut.describe`),
51
53
  type: 'string',
52
54
  });
53
55
 
54
56
  yargs.option('list', {
55
57
  alias: 'l',
56
- describe: 'List all supported shortcuts',
58
+ describe: i18n(`${i18nKey}.options.list.describe`),
57
59
  type: 'boolean',
58
60
  });
59
61
 
@@ -0,0 +1,111 @@
1
+ const {
2
+ addAccountOptions,
3
+ addConfigOptions,
4
+ getAccountId,
5
+ addUseEnvironmentOptions,
6
+ } = require('../../lib/commonOpts');
7
+ const { trackCommandUsage } = require('../../lib/usageTracking');
8
+ const { loadAndValidateOptions } = require('../../lib/validation');
9
+ const { getCwd } = require('@hubspot/cli-lib/path');
10
+ const path = require('path');
11
+ const { prompt } = require('inquirer');
12
+ const { createProjectConfig } = require('../../lib/projects');
13
+ const { PROJECT_TEMPLATES } = require('@hubspot/cli-lib/lib/constants');
14
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
15
+
16
+ const i18nKey = 'cli.commands.project.subcommands.create';
17
+
18
+ exports.command = 'create';
19
+ exports.describe = false;
20
+
21
+ exports.handler = async options => {
22
+ await loadAndValidateOptions(options);
23
+
24
+ const accountId = getAccountId(options);
25
+
26
+ const { name, template, location } = await prompt([
27
+ {
28
+ name: 'name',
29
+ message: '[--name] Give your project a name:',
30
+ when: !options.name,
31
+ validate: input => {
32
+ if (!input) {
33
+ return 'A project name is required';
34
+ }
35
+ return true;
36
+ },
37
+ },
38
+ {
39
+ name: 'location',
40
+ message: '[--location] Where should the project be created?',
41
+ when: !options.location,
42
+ default: answers => {
43
+ return path.resolve(getCwd(), answers.name || options.name);
44
+ },
45
+ validate: input => {
46
+ if (!input) {
47
+ return 'A project location is required';
48
+ }
49
+ return true;
50
+ },
51
+ },
52
+ {
53
+ name: 'template',
54
+ message: () => {
55
+ return options.template &&
56
+ !PROJECT_TEMPLATES.find(t => t.name === options.template)
57
+ ? `[--template] Could not find template ${options.template}. Please choose an available template.`
58
+ : '[--template] Start from a template?';
59
+ },
60
+ when:
61
+ !options.template ||
62
+ !PROJECT_TEMPLATES.find(t => t.name === options.template),
63
+ type: 'list',
64
+ choices: [
65
+ {
66
+ name: 'No template',
67
+ value: 'none',
68
+ },
69
+ ...PROJECT_TEMPLATES.map(template => {
70
+ return {
71
+ name: template.label,
72
+ value: template.name,
73
+ };
74
+ }),
75
+ ],
76
+ },
77
+ ]);
78
+
79
+ trackCommandUsage('project-create', { projectName: name }, accountId);
80
+
81
+ await createProjectConfig(
82
+ path.resolve(getCwd(), options.location || location),
83
+ options.name || name,
84
+ options.template || template
85
+ );
86
+ };
87
+
88
+ exports.builder = yargs => {
89
+ yargs.options({
90
+ name: {
91
+ describe: i18n(`${i18nKey}.options.name.describe`),
92
+ type: 'string',
93
+ },
94
+ location: {
95
+ describe: i18n(`${i18nKey}.options.location.describe`),
96
+ type: 'string',
97
+ },
98
+ template: {
99
+ describe: i18n(`${i18nKey}.options.template.describe`),
100
+ type: 'string',
101
+ },
102
+ });
103
+
104
+ yargs.example([['$0 project create', i18n(`${i18nKey}.examples.default`)]]);
105
+
106
+ addConfigOptions(yargs, true);
107
+ addAccountOptions(yargs, true);
108
+ addUseEnvironmentOptions(yargs, true);
109
+
110
+ return yargs;
111
+ };
@@ -1,65 +1,57 @@
1
- const path = require('path');
2
1
  const {
3
2
  addAccountOptions,
4
3
  addConfigOptions,
5
- setLogLevel,
6
4
  getAccountId,
7
5
  addUseEnvironmentOptions,
8
6
  } = require('../../lib/commonOpts');
9
7
  const { trackCommandUsage } = require('../../lib/usageTracking');
10
- const { logDebugInfo } = require('../../lib/debugInfo');
11
- const {
12
- loadConfig,
13
- validateConfig,
14
- checkAndWarnGitInclusion,
15
- } = require('@hubspot/cli-lib');
16
8
  const {
17
9
  logApiErrorInstance,
18
10
  ApiErrorContext,
19
11
  } = require('@hubspot/cli-lib/errorHandlers');
20
12
  const { logger } = require('@hubspot/cli-lib/logger');
21
13
  const { deployProject, fetchProject } = require('@hubspot/cli-lib/api/dfs');
22
- const { getCwd } = require('@hubspot/cli-lib/path');
23
- const { validateAccount } = require('../../lib/validation');
14
+ const { loadAndValidateOptions } = require('../../lib/validation');
24
15
  const {
25
- getOrCreateProjectConfig,
16
+ getProjectConfig,
26
17
  pollDeployStatus,
18
+ validateProjectConfig,
27
19
  } = require('../../lib/projects');
20
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
28
21
 
29
- const loadAndValidateOptions = async options => {
30
- setLogLevel(options);
31
- logDebugInfo(options);
32
- const { config: configPath } = options;
33
- loadConfig(configPath, options);
34
- checkAndWarnGitInclusion();
35
-
36
- if (!(validateConfig() && (await validateAccount(options)))) {
37
- process.exit(1);
38
- }
39
- };
22
+ const i18nKey = 'cli.commands.project.subcommands.deploy';
23
+ const { EXIT_CODES } = require('../../lib/enums/exitCodes');
40
24
 
41
25
  exports.command = 'deploy [path]';
42
26
  exports.describe = false;
43
27
 
44
28
  exports.handler = async options => {
45
- loadAndValidateOptions(options);
29
+ await loadAndValidateOptions(options);
46
30
 
47
31
  const { path: projectPath, buildId } = options;
48
32
  const accountId = getAccountId(options);
49
33
 
50
34
  trackCommandUsage('project-deploy', { projectPath }, accountId);
51
35
 
52
- const cwd = projectPath ? path.resolve(getCwd(), projectPath) : getCwd();
53
- const projectConfig = await getOrCreateProjectConfig(cwd);
36
+ const { projectConfig, projectDir } = await getProjectConfig(projectPath);
37
+
38
+ validateProjectConfig(projectConfig, projectDir);
39
+
40
+ logger.debug(
41
+ i18n(`${i18nKey}.debug.deploying`, {
42
+ path: projectPath,
43
+ })
44
+ );
54
45
 
55
- logger.debug(`Deploying project at path: ${projectPath}`);
46
+ let exitCode = EXIT_CODES.SUCCESS;
56
47
 
57
48
  const getBuildId = async () => {
58
49
  const { latestBuild } = await fetchProject(accountId, projectConfig.name);
59
50
  if (latestBuild && latestBuild.buildId) {
60
51
  return latestBuild.buildId;
61
52
  }
62
- logger.error('No latest build ID was found.');
53
+ logger.error(i18n(`${i18nKey}.errors.noBuildId`));
54
+ exitCode = EXIT_CODES.ERROR;
63
55
  return;
64
56
  };
65
57
 
@@ -73,7 +65,12 @@ exports.handler = async options => {
73
65
  );
74
66
 
75
67
  if (deployResp.error) {
76
- logger.error(`Deploy error: ${deployResp.error.message}`);
68
+ logger.error(
69
+ i18n(`${i18nKey}.errors.deploy`, {
70
+ details: deployResp.error.message,
71
+ })
72
+ );
73
+ exitCode = EXIT_CODES.ERROR;
77
74
  return;
78
75
  }
79
76
 
@@ -89,27 +86,26 @@ exports.handler = async options => {
89
86
  } else {
90
87
  logApiErrorInstance(e, new ApiErrorContext({ accountId, projectPath }));
91
88
  }
89
+ exitCode = 1;
92
90
  }
91
+ process.exit(exitCode);
93
92
  };
94
93
 
95
94
  exports.builder = yargs => {
96
95
  yargs.positional('path', {
97
- describe: 'Path to a project folder',
96
+ describe: i18n(`${i18nKey}.positionals.path.describe`),
98
97
  type: 'string',
99
98
  });
100
99
 
101
100
  yargs.options({
102
101
  buildId: {
103
- describe: 'Project build ID to be deployed',
102
+ describe: i18n(`${i18nKey}.options.buildId.describe`),
104
103
  type: 'number',
105
104
  },
106
105
  });
107
106
 
108
107
  yargs.example([
109
- [
110
- '$0 project deploy myProjectFolder',
111
- 'Deploy a project within the myProjectFolder folder',
112
- ],
108
+ ['$0 project deploy myProjectFolder', i18n(`${i18nKey}.examples.default`)],
113
109
  ]);
114
110
 
115
111
  addConfigOptions(yargs, true);
@@ -0,0 +1,160 @@
1
+ const path = require('path');
2
+
3
+ const {
4
+ addAccountOptions,
5
+ addConfigOptions,
6
+ getAccountId,
7
+ addUseEnvironmentOptions,
8
+ } = require('../../lib/commonOpts');
9
+ const { trackCommandUsage } = require('../../lib/usageTracking');
10
+ const {
11
+ logApiErrorInstance,
12
+ ApiErrorContext,
13
+ } = require('@hubspot/cli-lib/errorHandlers');
14
+ const { logger } = require('@hubspot/cli-lib/logger');
15
+ const {
16
+ fetchProject,
17
+ fetchProjectBuilds,
18
+ } = require('@hubspot/cli-lib/api/dfs');
19
+ const {
20
+ getTableContents,
21
+ getTableHeader,
22
+ } = require('@hubspot/cli-lib/lib/table');
23
+ const { getCwd } = require('@hubspot/cli-lib/path');
24
+ const { uiLink } = require('../../lib/ui');
25
+ const { loadAndValidateOptions } = require('../../lib/validation');
26
+ const {
27
+ getProjectConfig,
28
+ getProjectDetailUrl,
29
+ validateProjectConfig,
30
+ } = require('../../lib/projects');
31
+ const moment = require('moment');
32
+ const { prompt } = require('inquirer');
33
+
34
+ exports.command = 'list-builds [path]';
35
+ exports.describe = false;
36
+
37
+ exports.handler = async options => {
38
+ await loadAndValidateOptions(options);
39
+
40
+ const { path: projectPath, limit } = options;
41
+ const accountId = getAccountId(options);
42
+
43
+ trackCommandUsage('project-list-builds', { projectPath }, accountId);
44
+
45
+ const cwd = projectPath ? path.resolve(getCwd(), projectPath) : getCwd();
46
+ const { projectConfig, projectDir } = await getProjectConfig(cwd);
47
+
48
+ validateProjectConfig(projectConfig, projectDir);
49
+
50
+ logger.debug(`Fetching builds for project at path: ${projectPath}`);
51
+
52
+ const fetchAndDisplayBuilds = async (project, options) => {
53
+ const { results, paging } = await fetchProjectBuilds(
54
+ accountId,
55
+ project.name,
56
+ options
57
+ );
58
+ const currentDeploy = project.deployedBuildId;
59
+ if (options && options.after) {
60
+ logger.log(
61
+ `Showing the next ${results.length} builds for ${project.name}`
62
+ );
63
+ } else {
64
+ logger.log(
65
+ `Showing the ${results.length} most recent builds for ${project.name}. ` +
66
+ uiLink(
67
+ 'View all builds in project details.',
68
+ getProjectDetailUrl(project.name, accountId)
69
+ )
70
+ );
71
+ }
72
+
73
+ if (results.length === 0) {
74
+ logger.log('No builds found.');
75
+ } else {
76
+ const builds = results.map(build => {
77
+ const isCurrentlyDeployed = build.buildId === currentDeploy;
78
+
79
+ return [
80
+ isCurrentlyDeployed
81
+ ? `#${build.buildId} [deployed]`
82
+ : `#${build.buildId}`,
83
+ build.status,
84
+ moment(build.finishedAt).format('MM/DD/YY, hh:mm:ssa'),
85
+ Math.round(
86
+ moment
87
+ .duration(moment(build.finishedAt).diff(moment(build.enqueuedAt)))
88
+ .asSeconds()
89
+ ) + 's',
90
+ build.subbuildStatuses
91
+ .filter(subbuild => subbuild.status === 'FAILURE')
92
+ .map(subbuild => `${subbuild.buildName} failed`)
93
+ .join(', '),
94
+ ];
95
+ });
96
+ builds.unshift(
97
+ getTableHeader([
98
+ 'Build ID',
99
+ 'Status',
100
+ 'Completed',
101
+ 'Duration',
102
+ 'Details',
103
+ ])
104
+ );
105
+ logger.log(
106
+ getTableContents(builds, {
107
+ columnDefault: {
108
+ paddingLeft: 3,
109
+ },
110
+ })
111
+ );
112
+ }
113
+ if (paging && paging.next) {
114
+ await prompt({
115
+ name: 'more',
116
+ message: 'Press <enter> to load more, or ctrl+c to exit',
117
+ });
118
+ await fetchAndDisplayBuilds(project, { limit, after: paging.next.after });
119
+ }
120
+ };
121
+
122
+ try {
123
+ const project = await fetchProject(accountId, projectConfig.name);
124
+
125
+ await fetchAndDisplayBuilds(project, { limit });
126
+ } catch (e) {
127
+ if (e.statusCode === 404) {
128
+ logger.error(`Project ${projectConfig.name} not found. `);
129
+ } else {
130
+ logApiErrorInstance(e, new ApiErrorContext({ accountId }));
131
+ }
132
+ }
133
+ };
134
+
135
+ exports.builder = yargs => {
136
+ yargs.positional('path', {
137
+ describe: 'Path to a project folder',
138
+ type: 'string',
139
+ });
140
+
141
+ yargs.options({
142
+ limit: {
143
+ describe: 'Max number of builds to load',
144
+ type: 'string',
145
+ },
146
+ });
147
+
148
+ yargs.example([
149
+ [
150
+ '$0 project list-builds myProjectFolder',
151
+ 'Fetch a list of builds for a project within the myProjectFolder folder',
152
+ ],
153
+ ]);
154
+
155
+ addConfigOptions(yargs, true);
156
+ addAccountOptions(yargs, true);
157
+ addUseEnvironmentOptions(yargs, true);
158
+
159
+ return yargs;
160
+ };