@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/lib/prompts.js CHANGED
@@ -7,6 +7,9 @@ const {
7
7
  const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
8
8
  const { logger } = require('@hubspot/cli-lib/logger');
9
9
  const { API_KEY_REGEX, STRING_WITH_NO_SPACES_REGEX } = require('./regex');
10
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
11
+
12
+ const i18nKey = 'cli.lib.prompts';
10
13
 
11
14
  const promptUser = async promptConfig => {
12
15
  const prompt = inquirer.createPromptModule();
@@ -18,14 +21,14 @@ const promptUser = async promptConfig => {
18
21
  * then opens their browser to the personal-access-key shortlink
19
22
  */
20
23
  const personalAccessKeyPrompt = async ({ env } = {}) => {
21
- await promptUser([PERSONAL_ACCESS_KEY_BROWSER_OPEN_PREP]);
22
24
  const websiteOrigin = getHubSpotWebsiteOrigin(env);
23
25
  const url = `${websiteOrigin}/l/personal-access-key`;
24
26
  if (process.env.BROWSER !== 'none') {
27
+ await promptUser([PERSONAL_ACCESS_KEY_BROWSER_OPEN_PREP]);
25
28
  open(url, { url: true });
26
29
  }
27
30
 
28
- logger.log(`Opening ${url} in your web browser`);
31
+ logger.log(i18n(`${i18nKey}.logs.openingWebBrowser`, { url }));
29
32
  const { personalAccessKey } = await promptUser(PERSONAL_ACCESS_KEY);
30
33
 
31
34
  return {
@@ -36,25 +39,24 @@ const personalAccessKeyPrompt = async ({ env } = {}) => {
36
39
 
37
40
  const ACCOUNT_ID = {
38
41
  name: 'accountId',
39
- message:
40
- 'Enter the account ID for your account (the number under the DOMAIN column at https://app.hubspot.com/myaccounts-beta ):',
42
+ message: i18n(`${i18nKey}.accountId`),
41
43
  type: 'number',
42
44
  validate(val) {
43
45
  if (!Number.isNaN(val) && val > 0) {
44
46
  return true;
45
47
  }
46
- return 'You did not enter a valid account ID. Please try again.';
48
+ return i18n(`${i18nKey}.errors.invalidAccountId`);
47
49
  },
48
50
  };
49
51
 
50
52
  const CLIENT_ID = {
51
53
  name: 'clientId',
52
- message: 'Enter your OAuth2 client ID:',
54
+ message: i18n(`${i18nKey}.clientId`),
53
55
  validate(val) {
54
56
  if (typeof val !== 'string') {
55
- return 'You entered an invalid OAuth2 client ID. Please try again.';
57
+ return i18n(`${i18nKey}.errors.invalidOauthClientId`);
56
58
  } else if (val.length !== 36) {
57
- return 'The OAuth2 client ID must be 36 characters long. Please try again.';
59
+ return i18n(`${i18nKey}.errors.invalidOauthClientIdLength`);
58
60
  }
59
61
  return true;
60
62
  },
@@ -62,14 +64,14 @@ const CLIENT_ID = {
62
64
 
63
65
  const CLIENT_SECRET = {
64
66
  name: 'clientSecret',
65
- message: 'Enter your OAuth2 client secret:',
67
+ message: i18n(`${i18nKey}.clientSecret`),
66
68
  validate(val) {
67
69
  if (typeof val !== 'string') {
68
- return 'You entered an invalid OAuth2 client secret. Please try again.';
70
+ return i18n(`${i18nKey}.errors.invalidOauthClientSecret`);
69
71
  } else if (val.length !== 36) {
70
- return 'The OAuth2 client secret must be 36 characters long. Please try again.';
72
+ return i18n(`${i18nKey}.errors.invalidOauthClientSecretLength`);
71
73
  } else if (val[0] === '*') {
72
- return 'Please copy the actual OAuth2 client secret rather than the asterisks that mask it.';
74
+ return i18n(`${i18nKey}.errors.invalidOauthClientSecretCopy`);
73
75
  }
74
76
  return true;
75
77
  },
@@ -77,14 +79,14 @@ const CLIENT_SECRET = {
77
79
 
78
80
  const ACCOUNT_NAME = {
79
81
  name: 'name',
80
- message: 'Enter a unique name to reference your account:',
82
+ message: i18n(`${i18nKey}.accountName`),
81
83
  validate(val) {
82
84
  if (typeof val !== 'string') {
83
- return 'You entered an invalid name. Please try again.';
85
+ return i18n(`${i18nKey}.errors.invalidName`);
84
86
  } else if (!val.length) {
85
- return 'The name may not be blank. Please try again.';
87
+ return i18n(`${i18nKey}.errors.nameRequired`);
86
88
  } else if (!STRING_WITH_NO_SPACES_REGEX.test(val)) {
87
- return 'The name may not contain spaces. Please try again.';
89
+ return i18n(`${i18nKey}.errors.spacesInName`);
88
90
  }
89
91
  return true;
90
92
  },
@@ -92,11 +94,10 @@ const ACCOUNT_NAME = {
92
94
 
93
95
  const ACCOUNT_API_KEY = {
94
96
  name: 'apiKey',
95
- message:
96
- 'Enter the API key for your account (found at https://app.hubspot.com/l/api-key):',
97
+ message: i18n(`${i18nKey}.apiKey`),
97
98
  validate(val) {
98
99
  if (!API_KEY_REGEX.test(val)) {
99
- return 'You did not enter a valid API key. Please try again.';
100
+ return i18n(`${i18nKey}.errors.invalidAPIKey`);
100
101
  }
101
102
  return true;
102
103
  },
@@ -104,18 +105,17 @@ const ACCOUNT_API_KEY = {
104
105
 
105
106
  const PERSONAL_ACCESS_KEY_BROWSER_OPEN_PREP = {
106
107
  name: 'personalAcessKeyBrowserOpenPrep',
107
- message:
108
- "When you're ready, we'll open a secure page in your default browser where you can view and copy your personal access key, which you'll need to complete the next step.\n<Press enter to open the page and generate your personal access key>",
108
+ message: i18n(`${i18nKey}.personalAccessKeyBrowserOpenPrep`),
109
109
  };
110
110
 
111
111
  const PERSONAL_ACCESS_KEY = {
112
112
  name: 'personalAccessKey',
113
- message: 'Enter your personal access key:',
113
+ message: i18n(`${i18nKey}.personalAccessKey`),
114
114
  validate(val) {
115
115
  if (typeof val !== 'string') {
116
- return 'You did not enter a valid access key. Please try again.';
116
+ return i18n(`${i18nKey}.errors.invalidPersonalAccessKey`);
117
117
  } else if (val[0] === '•') {
118
- return 'Please copy the actual access key rather than the bullets that mask it.';
118
+ return i18n(`${i18nKey}.errors.invalidPersonalAccessKeyCopy`);
119
119
  }
120
120
  return true;
121
121
  },
@@ -124,8 +124,7 @@ const PERSONAL_ACCESS_KEY = {
124
124
  const SCOPES = {
125
125
  type: 'checkbox',
126
126
  name: 'scopes',
127
- message:
128
- 'Select access scopes (see https://developers.hubspot.com/docs/methods/oauth2/initiate-oauth-integration#scopes)',
127
+ message: i18n(`${i18nKey}.scopes`),
129
128
  default: DEFAULT_OAUTH_SCOPES,
130
129
  choices: OAUTH_SCOPES,
131
130
  };
@@ -137,7 +136,7 @@ const folderOverwritePrompt = folderName => {
137
136
  return promptUser({
138
137
  type: 'confirm',
139
138
  name: 'overwrite',
140
- message: `The folder with name '${folderName}' already exists. Overwrite?`,
139
+ message: i18n(`${i18nKey}.folderOverwrite`, { folderName }),
141
140
  default: false,
142
141
  });
143
142
  };
@@ -9,6 +9,7 @@ const {
9
9
  ApiErrorContext,
10
10
  } = require('@hubspot/cli-lib/errorHandlers');
11
11
  const { base64EncodeString } = require('@hubspot/cli-lib/lib/encoding');
12
+ const { EXIT_CODES } = require('../lib/enums/exitCodes');
12
13
 
13
14
  const TAIL_DELAY = 5000;
14
15
 
@@ -17,7 +18,7 @@ const handleKeypressToExit = exit => {
17
18
  process.stdin.setRawMode(true);
18
19
  process.stdin.on('keypress', (str, key) => {
19
20
  if (key && ((key.ctrl && key.name == 'c') || key.name === 'escape')) {
20
- exit();
21
+ exit(key.name === 'escape' ? 'esc' : 'ctrl+c');
21
22
  }
22
23
  });
23
24
  };
@@ -25,17 +26,15 @@ const handleKeypressToExit = exit => {
25
26
  const tailLogs = async ({
26
27
  accountId,
27
28
  compact,
28
- spinner,
29
+ spinnies,
29
30
  fetchLatest,
30
31
  tailCall,
31
32
  }) => {
32
33
  let initialAfter;
33
34
 
34
- spinner.start();
35
-
36
35
  try {
37
36
  const latestLog = await fetchLatest();
38
- initialAfter = base64EncodeString(latestLog.id);
37
+ initialAfter = latestLog && base64EncodeString(latestLog.id);
39
38
  } catch (e) {
40
39
  // A 404 means no latest log exists(never executed)
41
40
  if (e.statusCode !== 404) {
@@ -54,8 +53,7 @@ const tailLogs = async ({
54
53
  latestLog = await tailCall(after);
55
54
  nextAfter = latestLog.paging.next.after;
56
55
  } catch (e) {
57
- logger.info('Stopped polling due to error.');
58
- spinner.clear();
56
+ spinnies.fail('tailLogs', { text: 'Stopped polling due to error.' });
59
57
  if (e.statusCode !== 404) {
60
58
  logApiErrorInstance(
61
59
  e,
@@ -64,11 +62,10 @@ const tailLogs = async ({
64
62
  })
65
63
  );
66
64
  }
67
- process.exit();
65
+ process.exit(EXIT_CODES.SUCCESS);
68
66
  }
69
67
 
70
68
  if (latestLog && latestLog.results.length) {
71
- spinner.clear();
72
69
  outputLogs(latestLog, {
73
70
  compact,
74
71
  });
@@ -79,9 +76,11 @@ const tailLogs = async ({
79
76
  }, TAIL_DELAY);
80
77
  };
81
78
 
82
- handleKeypressToExit(() => {
83
- spinner.stop();
84
- process.exit();
79
+ handleKeypressToExit(exitKey => {
80
+ spinnies.succeed('tailLogs', {
81
+ text: `Stopped polling because "${exitKey}" was pressed.`,
82
+ });
83
+ process.exit(EXIT_CODES.SUCCESS);
85
84
  });
86
85
  await tail(initialAfter);
87
86
  };
package/lib/ui.js ADDED
@@ -0,0 +1,48 @@
1
+ const chalk = require('chalk');
2
+ const supportsHyperlinks = require('supports-hyperlinks');
3
+ const { getAccountConfig } = require('@hubspot/cli-lib/lib/config');
4
+ const { logger } = require('@hubspot/cli-lib/logger');
5
+
6
+ /**
7
+ * Outputs horizontal line
8
+ *
9
+ * @returns
10
+ */
11
+ const uiLine = () => {
12
+ logger.log('-'.repeat(50));
13
+ };
14
+
15
+ /**
16
+ * Returns a hyperlink or link and description
17
+ *
18
+ * @param {string} linkText
19
+ * @param {string} url
20
+ * @param {object} options
21
+ * @returns {string}
22
+ */
23
+ const uiLink = (linkText, url, options = {}) => {
24
+ if (supportsHyperlinks.stdout) {
25
+ return ['\u001B]8;;', url, '\u0007', linkText, '\u001B]8;;\u0007'].join('');
26
+ } else {
27
+ return options.fallback ? `${linkText}: ${url}` : linkText;
28
+ }
29
+ };
30
+
31
+ /**
32
+ * Returns formatted account name and ID
33
+ *
34
+ * @param {number} accountId
35
+ * @returns {string}
36
+ */
37
+ const uiAccountDescription = accountId => {
38
+ const account = getAccountConfig(accountId);
39
+ return chalk.bold(
40
+ account.name ? `${account.name} (${account.portalId})` : account.portalId
41
+ );
42
+ };
43
+
44
+ module.exports = {
45
+ uiLine,
46
+ uiLink,
47
+ uiAccountDescription,
48
+ };
package/lib/validation.js CHANGED
@@ -24,6 +24,7 @@ const { getAccountId, getMode, setLogLevel } = require('./commonOpts');
24
24
  const { logDebugInfo } = require('./debugInfo');
25
25
  const fs = require('fs');
26
26
  const path = require('path');
27
+ const { EXIT_CODES } = require('./enums/exitCodes');
27
28
 
28
29
  async function loadAndValidateOptions(options) {
29
30
  setLogLevel(options);
@@ -33,7 +34,7 @@ async function loadAndValidateOptions(options) {
33
34
  checkAndWarnGitInclusion();
34
35
 
35
36
  if (!(validateConfig() && (await validateAccount(options)))) {
36
- process.exit(1);
37
+ process.exit(EXIT_CODES.ERROR);
37
38
  }
38
39
  }
39
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "3.0.9",
3
+ "version": "3.0.10-beta.11",
4
4
  "description": "CLI for working with HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -8,20 +8,22 @@
8
8
  "url": "https://github.com/HubSpot/hubspot-cms-tools"
9
9
  },
10
10
  "dependencies": {
11
- "@hubspot/cli-lib": "^3.0.9",
12
- "@hubspot/serverless-dev-runtime": "^3.0.9",
11
+ "@hubspot/cli-lib": "^3.0.10-beta.10",
12
+ "@hubspot/serverless-dev-runtime": "^3.0.10-beta.11",
13
13
  "archiver": "^5.3.0",
14
- "chalk": "^4.1.0",
14
+ "chalk": "^4.1.2",
15
15
  "express": "^4.17.1",
16
16
  "findup-sync": "^4.0.0",
17
17
  "fs-extra": "^8.1.0",
18
- "inquirer": "^6.3.1",
18
+ "inquirer": "^8.2.0",
19
+ "moment": "^2.29.1",
19
20
  "open": "^7.0.3",
20
21
  "ora": "^4.0.3",
21
22
  "shelljs": "0.8.3",
22
23
  "spinnies": "^0.5.1",
24
+ "supports-hyperlinks": "^2.2.0",
23
25
  "tmp": "^0.2.1",
24
- "update-notifier": "3.0.1",
26
+ "update-notifier": "^5.1.0",
25
27
  "yargs": "15.4.1"
26
28
  },
27
29
  "devDependencies": {
@@ -37,5 +39,5 @@
37
39
  "publishConfig": {
38
40
  "access": "public"
39
41
  },
40
- "gitHead": "172b7c424c13c0ac21eb730e7d7a403a5787c00e"
42
+ "gitHead": "52da01961c90b30b6fc9f30bffac2527d937a032"
41
43
  }
@@ -1,108 +0,0 @@
1
- const {
2
- addAccountOptions,
3
- addConfigOptions,
4
- setLogLevel,
5
- getAccountId,
6
- addUseEnvironmentOptions,
7
- } = require('../../lib/commonOpts');
8
- const { trackCommandUsage } = require('../../lib/usageTracking');
9
- const { logDebugInfo } = require('../../lib/debugInfo');
10
- const {
11
- loadConfig,
12
- validateConfig,
13
- checkAndWarnGitInclusion,
14
- } = require('@hubspot/cli-lib');
15
- const {
16
- logApiErrorInstance,
17
- ApiErrorContext,
18
- } = require('@hubspot/cli-lib/errorHandlers');
19
- const { logger } = require('@hubspot/cli-lib/logger');
20
- const { createProject } = require('@hubspot/cli-lib/api/dfs');
21
- const { validateAccount } = require('../../lib/validation');
22
- const { getCwd } = require('@hubspot/cli-lib/path');
23
- const path = require('path');
24
- const {
25
- getOrCreateProjectConfig,
26
- showWelcomeMessage,
27
- } = require('../../lib/projects');
28
-
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
- };
40
-
41
- exports.command = 'init [path]';
42
- exports.describe = false;
43
-
44
- exports.handler = async options => {
45
- loadAndValidateOptions(options);
46
-
47
- const { path: projectPath } = options;
48
- const accountId = getAccountId(options);
49
-
50
- trackCommandUsage('project-init', { projectPath }, accountId);
51
-
52
- const cwd = projectPath ? path.resolve(getCwd(), projectPath) : getCwd();
53
- const projectConfig = await getOrCreateProjectConfig(cwd);
54
-
55
- logger.log(`Initializing project: ${projectConfig.name}`);
56
-
57
- try {
58
- await createProject(accountId, projectConfig.name);
59
-
60
- logger.success(
61
- `"${projectConfig.name}" creation succeeded in account ${accountId}`
62
- );
63
- } catch (e) {
64
- if (e.statusCode === 409) {
65
- logger.log(
66
- `Project ${projectConfig.name} already exists in ${accountId}.`
67
- );
68
- } else {
69
- return logApiErrorInstance(
70
- e,
71
- new ApiErrorContext({ accountId, projectPath })
72
- );
73
- }
74
- }
75
-
76
- showWelcomeMessage(projectConfig.name, accountId);
77
- };
78
-
79
- exports.builder = yargs => {
80
- yargs.positional('path', {
81
- describe: 'Path to a project folder',
82
- type: 'string',
83
- });
84
- // TODO: These are not currently used
85
- yargs.options({
86
- name: {
87
- describe: 'Project name (cannot be changed)',
88
- type: 'string',
89
- },
90
- srcDir: {
91
- describe: 'Directory of project',
92
- type: 'string',
93
- },
94
- });
95
-
96
- yargs.example([
97
- [
98
- '$0 project init myProjectFolder',
99
- 'Initialize a project within the myProjectFolder folder',
100
- ],
101
- ]);
102
-
103
- addConfigOptions(yargs, true);
104
- addAccountOptions(yargs, true);
105
- addUseEnvironmentOptions(yargs, true);
106
-
107
- return yargs;
108
- };