@hubspot/cli 6.1.1 → 6.2.1

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 (86) hide show
  1. package/bin/cli.js +2 -2
  2. package/commands/accounts/clean.js +5 -7
  3. package/commands/auth.js +5 -5
  4. package/commands/cms/convertFields.js +2 -2
  5. package/commands/cms/lighthouseScore.js +47 -36
  6. package/commands/create/api-sample.js +2 -4
  7. package/commands/create/function.js +2 -2
  8. package/commands/create/module.js +2 -2
  9. package/commands/create/template.js +2 -2
  10. package/commands/create.js +3 -5
  11. package/commands/customObject/create.js +2 -2
  12. package/commands/customObject/schema/create.js +4 -4
  13. package/commands/customObject/schema/delete.js +2 -3
  14. package/commands/customObject/schema/fetch-all.js +2 -5
  15. package/commands/customObject/schema/fetch.js +2 -4
  16. package/commands/customObject/schema/list.js +2 -4
  17. package/commands/customObject/schema/update.js +4 -4
  18. package/commands/fetch.js +2 -2
  19. package/commands/filemanager/fetch.js +2 -2
  20. package/commands/filemanager/upload.js +3 -7
  21. package/commands/functions/deploy.js +26 -23
  22. package/commands/functions/list.js +3 -6
  23. package/commands/hubdb/clear.js +5 -3
  24. package/commands/hubdb/create.js +2 -2
  25. package/commands/hubdb/delete.js +2 -2
  26. package/commands/hubdb/fetch.js +2 -2
  27. package/commands/init.js +4 -7
  28. package/commands/lint.js +2 -2
  29. package/commands/list.js +4 -6
  30. package/commands/logs.js +6 -3
  31. package/commands/mv.js +3 -6
  32. package/commands/project/__tests__/deploy.test.js +37 -26
  33. package/commands/project/__tests__/logs.test.js +4 -5
  34. package/commands/project/add.js +2 -2
  35. package/commands/project/cloneApp.js +11 -9
  36. package/commands/project/create.js +2 -6
  37. package/commands/project/deploy.js +9 -12
  38. package/commands/project/dev.js +6 -5
  39. package/commands/project/download.js +7 -9
  40. package/commands/project/listBuilds.js +8 -12
  41. package/commands/project/logs.js +2 -2
  42. package/commands/project/migrateApp.js +20 -15
  43. package/commands/project/upload.js +4 -10
  44. package/commands/project/watch.js +8 -13
  45. package/commands/remove.js +2 -5
  46. package/commands/sandbox/create.js +4 -6
  47. package/commands/sandbox/delete.js +6 -12
  48. package/commands/secrets/addSecret.js +2 -5
  49. package/commands/secrets/deleteSecret.js +2 -5
  50. package/commands/secrets/listSecrets.js +5 -6
  51. package/commands/secrets/updateSecret.js +2 -5
  52. package/commands/theme/preview.js +2 -5
  53. package/commands/upload.js +3 -7
  54. package/commands/watch.js +3 -7
  55. package/lang/en.lyaml +14 -18
  56. package/lib/LocalDevManager.js +8 -6
  57. package/lib/__tests__/downloadProjectPrompt.test.js +1 -1
  58. package/lib/__tests__/projectLogsManager.test.js +19 -17
  59. package/lib/__tests__/serverlessLogs.test.js +13 -9
  60. package/lib/buildAccount.js +10 -10
  61. package/lib/developerTestAccounts.js +27 -27
  62. package/lib/errorHandlers/index.js +101 -0
  63. package/lib/errorHandlers/{overrideErrors.js → suppressError.js} +7 -7
  64. package/lib/hasFeature.js +15 -0
  65. package/lib/localDev.js +32 -19
  66. package/lib/marketplace-validate.js +3 -3
  67. package/lib/oauth.js +1 -1
  68. package/lib/polling.js +1 -1
  69. package/lib/projectLogsManager.js +3 -4
  70. package/lib/projectStructure.js +2 -2
  71. package/lib/projects.js +42 -29
  72. package/lib/projectsWatch.js +7 -12
  73. package/lib/prompts/createProjectPrompt.js +14 -5
  74. package/lib/prompts/downloadProjectPrompt.js +3 -6
  75. package/lib/prompts/projectDevTargetAccountPrompt.js +8 -6
  76. package/lib/prompts/selectPublicAppPrompt.js +5 -3
  77. package/lib/sandboxSync.js +7 -7
  78. package/lib/sandboxes.js +11 -7
  79. package/lib/schema.js +2 -2
  80. package/lib/serverlessLogs.js +67 -15
  81. package/lib/upload.js +2 -2
  82. package/lib/validation.js +2 -2
  83. package/package.json +8 -9
  84. package/lib/errorHandlers/apiErrors.js +0 -145
  85. package/lib/errorHandlers/fileSystemErrors.js +0 -20
  86. package/lib/errorHandlers/standardErrors.js +0 -103
package/lang/en.lyaml CHANGED
@@ -183,8 +183,6 @@ en:
183
183
  noSamples: "Currently there are no samples available, please, try again later."
184
184
  info:
185
185
  sampleChosen: "You've chosen {{ sampleType }} sample written on {{ sampleLanguage }} language"
186
- loading:
187
- apiSamples: "Loading available API samples"
188
186
  success:
189
187
  sampleCreated: "Please, follow {{ filePath }}/README.md to find out how to run the sample"
190
188
  module:
@@ -335,7 +333,8 @@ en:
335
333
  notFunctionsFolder: "Specified path {{ functionPath }} is not a .functions folder."
336
334
  examples:
337
335
  default: "Build and deploy a new bundle for all functions within the myFunctionFolder.functions folder"
338
- loading: "Building and deploying bundle for \"{{ functionPath }}\" on account \"{{ accountId }}\".\n"
336
+ loading: "Building and deploying bundle for \"{{ functionPath }}\" on {{ account }}"
337
+ loadingFailed: "Failed to build and deploy bundle for \"{{ functionPath }}\" on {{ account }}"
339
338
  positionals:
340
339
  path:
341
340
  describe: "Path to .functions folder"
@@ -1008,7 +1007,9 @@ en:
1008
1007
  localDev:
1009
1008
  confirmDefaultAccountIsTarget:
1010
1009
  declineDefaultAccountExplanation: "To develop on a different account, run {{ useCommand }} to change your default account, then re-run {{ devCommand }}."
1011
- checkIfAppDevloperAccount: "This project contains a public app. Local development of public apps is only supported on developer accounts and developer test accounts. Change your default account using {{ useCommand }}, or link a new account with {{ authCommand }}."
1010
+ checkIfDefaultAccountIsSupported:
1011
+ publicApp: "This project contains a public app. Local development of public apps is only supported on developer accounts and developer test accounts. Change your default account using {{ useCommand }}, or link a new account with {{ authCommand }}."
1012
+ privateApp: "This project contains a private app. Local development of private apps is not supported in developer accounts. Change your default account using {{ useCommand }}, or link a new account with {{ authCommand }}."
1012
1013
  validateAccountOption:
1013
1014
  invalidPublicAppAccount: "This project contains a public app. The \"--account\" flag must point to a developer test account to develop this project locally. Alternatively, change your default account to an App Developer Account using {{ useCommand }} and run {{ devCommand }} to set up a new Developer Test Account."
1014
1015
  invalidPrivateAppAccount: "This project contains a private app. The account specified with the \"--account\" flag points to a developer account, which do not support the local development of private apps. Update the \"--account\" flag to point to a standard, sandbox, or developer test account, or change your default account by running {{ useCommand }}."
@@ -1401,23 +1402,12 @@ en:
1401
1402
  notSuperAdmin: "Couldn't run the sync because you are not a super admin in {{ account }}. Ask the account owner for super admin access to the sandbox."
1402
1403
  objectNotFound: "Couldn't sync the sandbox because {{#bold}}{{ account }}{{/bold}} may have been deleted through the UI. Run {{#bold}}hs sandbox delete{{/bold}} to remove this account from the config. "
1403
1404
  errorHandlers:
1404
- standardErrors:
1405
+ index:
1405
1406
  errorOccurred: "Error: {{ error }}"
1406
1407
  errorContext: "Context: {{ context }}"
1407
1408
  errorCause: "Cause: {{ cause }}"
1408
- systemErrorOccurred: "A system error has occurred: {{ errorMessage }}"
1409
- genericErrorOccurred: "A {{ name }} has occurred."
1410
- unknownErrorOccurred: "An unknown error has occurred"
1411
- fileSystemErrors:
1412
- errorOccurred: "An error occurred while {{ fileAction }} {{ filepath }}."
1413
- errorExplanation: "This is the result of a system error: {{ errorMessage }}"
1414
- apiErrors:
1415
- verifyAccessKeyAndUserAccess:
1416
- fetchScopeDataError: "Error verifying access of scopeGroup {{ scopeGroup }}: {{ error }}"
1417
- portalMissingScope: "Your account does not have access to this action. Talk to an account admin to request it."
1418
- userMissingScope: "You don't have access to this action. Ask an account admin to change your permissions in Users & Teams settings."
1419
- genericMissingScope: "Your access key does not allow this action. Please generate a new access key by running `hs auth personalaccesskey`."
1420
- overrideErrors:
1409
+ unknownErrorOccurred: "An unknown error has occurred."
1410
+ suppressErrors:
1421
1411
  platformVersionErrors:
1422
1412
  header: "Platform version update required"
1423
1413
  unspecifiedPlatformVersion: "Projects with an {{#bold}}{{platformVersion}}{{/bold}} are no longer supported."
@@ -1427,3 +1417,9 @@ en:
1427
1417
  docsLink: "Projects platform versioning (BETA)"
1428
1418
  betaLink: "For more info, see {{ docsLink }}."
1429
1419
  missingScopeError: "Couldn't execute the {{ request }} because the access key for {{ accountName }} is missing required scopes. To update scopes, run {{ authCommand }}. Then deactivate the existing key and generate a new one that includes the missing scopes."
1420
+ serverless:
1421
+ verifyAccessKeyAndUserAccess:
1422
+ fetchScopeDataError: "Error verifying access of scopeGroup {{ scopeGroup }}: {{ error }}"
1423
+ portalMissingScope: "Your account does not have access to this action. Talk to an account admin to request it."
1424
+ userMissingScope: "You don't have access to this action. Ask an account admin to change your permissions in Users & Teams settings."
1425
+ genericMissingScope: "Your access key does not allow this action. Please generate a new access key by running `hs auth personalaccesskey`."
@@ -34,7 +34,7 @@ const {
34
34
  uiLink,
35
35
  uiLine,
36
36
  } = require('./ui');
37
- const { logErrorInstance } = require('./errorHandlers/standardErrors');
37
+ const { logError } = require('./errorHandlers/index');
38
38
  const { installPublicAppPrompt } = require('./prompts/installPublicAppPrompt');
39
39
  const {
40
40
  activeInstallConfirmationPrompt,
@@ -99,7 +99,7 @@ class LocalDevManager {
99
99
  await this.checkActivePublicAppInstalls();
100
100
  await this.checkPublicAppInstallation();
101
101
  } catch (e) {
102
- logErrorInstance(e);
102
+ logError(e);
103
103
  }
104
104
  }
105
105
  }
@@ -109,7 +109,7 @@ class LocalDevManager {
109
109
  return;
110
110
  }
111
111
 
112
- const portalPublicApps = await fetchPublicAppsForPortal(
112
+ const { data: portalPublicApps } = await fetchPublicAppsForPortal(
113
113
  this.targetProjectAccountId
114
114
  );
115
115
 
@@ -119,7 +119,7 @@ class LocalDevManager {
119
119
 
120
120
  // TODO: Update to account for new API with { data }
121
121
  const {
122
- uniquePortalInstallCount,
122
+ data: { uniquePortalInstallCount },
123
123
  } = await fetchPublicAppProductionInstallCounts(
124
124
  activePublicAppData.id,
125
125
  this.targetProjectAccountId
@@ -264,14 +264,16 @@ class LocalDevManager {
264
264
  process.exit(EXIT_CODES.SUCCESS);
265
265
  }
266
266
 
267
- getActiveAppInstallationData() {
268
- return fetchAppInstallationData(
267
+ async getActiveAppInstallationData() {
268
+ const { data } = await fetchAppInstallationData(
269
269
  this.targetAccountId,
270
270
  this.projectId,
271
271
  this.activeApp.config.uid,
272
272
  this.activeApp.config.auth.requiredScopes,
273
273
  this.activeApp.config.auth.optionalScopes
274
274
  );
275
+
276
+ return data;
275
277
  }
276
278
 
277
279
  async checkPublicAppInstallation() {
@@ -1,6 +1,6 @@
1
1
  jest.mock('@hubspot/local-dev-lib/api/projects', () => ({
2
2
  fetchProjects: jest.fn().mockResolvedValue({
3
- results: [],
3
+ data: { results: [] },
4
4
  }),
5
5
  }));
6
6
 
@@ -50,24 +50,26 @@ describe('cli/lib/projectLogsManager', () => {
50
50
  getProjectConfig.mockResolvedValue(projectConfig);
51
51
  ensureProjectExists.mockResolvedValue(projectDetails);
52
52
  fetchProjectComponentsMetadata.mockResolvedValue({
53
- topLevelComponentMetadata: [
54
- {
55
- type: {
56
- name: 'PRIVATE_APP',
57
- },
58
- deployOutput: {
59
- appId,
60
- },
61
- featureComponents: [
62
- ...functions,
63
- {
64
- type: {
65
- name: 'NOT_AN_APP_FUNCTION',
66
- },
53
+ data: {
54
+ topLevelComponentMetadata: [
55
+ {
56
+ type: {
57
+ name: 'PRIVATE_APP',
67
58
  },
68
- ],
69
- },
70
- ],
59
+ deployOutput: {
60
+ appId,
61
+ },
62
+ featureComponents: [
63
+ ...functions,
64
+ {
65
+ type: {
66
+ name: 'NOT_AN_APP_FUNCTION',
67
+ },
68
+ },
69
+ ],
70
+ },
71
+ ],
72
+ },
71
73
  });
72
74
  });
73
75
 
@@ -71,14 +71,16 @@ describe('@hubspot/cli/lib/serverlessLogs', () => {
71
71
 
72
72
  const fetchLatest = jest.fn(() => {
73
73
  return Promise.resolve({
74
- id: '1234',
75
- executionTime: 510,
76
- log: 'Log message',
77
- error: null,
78
- status: 'SUCCESS',
79
- createdAt: 1620232011451,
80
- memory: '70/128 MB',
81
- duration: '53.40 ms',
74
+ data: {
75
+ id: '1234',
76
+ executionTime: 510,
77
+ log: 'Log message',
78
+ error: null,
79
+ status: 'SUCCESS',
80
+ createdAt: 1620232011451,
81
+ memory: '70/128 MB',
82
+ duration: '53.40 ms',
83
+ },
82
84
  });
83
85
  });
84
86
  const latestLogResponse = {
@@ -110,7 +112,9 @@ describe('@hubspot/cli/lib/serverlessLogs', () => {
110
112
  },
111
113
  },
112
114
  };
113
- const tailCall = jest.fn(() => Promise.resolve(latestLogResponse));
115
+ const tailCall = jest.fn(() =>
116
+ Promise.resolve({ data: latestLogResponse })
117
+ );
114
118
 
115
119
  await tailLogs({
116
120
  accountId: ACCOUNT_ID,
@@ -15,17 +15,14 @@ const { logger } = require('@hubspot/local-dev-lib/logger');
15
15
  const { i18n } = require('./lang');
16
16
  const { cliAccountNamePrompt } = require('./prompts/accountNamePrompt');
17
17
  const SpinniesManager = require('./ui/SpinniesManager');
18
- const {
19
- debugErrorAndContext,
20
- logErrorInstance,
21
- } = require('./errorHandlers/standardErrors');
18
+ const { debugError, logError } = require('./errorHandlers/index');
22
19
  const {
23
20
  createDeveloperTestAccount,
24
- } = require('@hubspot/local-dev-lib/developerTestAccounts');
21
+ } = require('@hubspot/local-dev-lib/api/developerTestAccounts');
25
22
  const {
26
23
  HUBSPOT_ACCOUNT_TYPES,
27
24
  } = require('@hubspot/local-dev-lib/constants/config');
28
- const { createSandbox } = require('@hubspot/local-dev-lib/sandboxes');
25
+ const { createSandbox } = require('@hubspot/local-dev-lib/api/sandboxHubs');
29
26
  const { sandboxApiTypeMap, handleSandboxCreateError } = require('./sandboxes');
30
27
  const {
31
28
  handleDeveloperTestAccountCreateError,
@@ -134,10 +131,13 @@ async function buildNewAccount({
134
131
  try {
135
132
  if (isSandbox) {
136
133
  const sandboxApiType = sandboxApiTypeMap[accountType]; // API expects sandbox type as 1 or 2.
137
- result = await createSandbox(accountId, name, sandboxApiType);
134
+
135
+ const { data } = await createSandbox(accountId, name, sandboxApiType);
136
+ result = { name, ...data };
138
137
  resultAccountId = result.sandbox.sandboxHubId;
139
138
  } else if (isDeveloperTestAccount) {
140
- result = await createDeveloperTestAccount(accountId, name);
139
+ const { data } = await createDeveloperTestAccount(accountId, name);
140
+ result = data;
141
141
  resultAccountId = result.id;
142
142
  }
143
143
 
@@ -148,7 +148,7 @@ async function buildNewAccount({
148
148
  }),
149
149
  });
150
150
  } catch (err) {
151
- debugErrorAndContext(err);
151
+ debugError(err);
152
152
 
153
153
  SpinniesManager.fail('buildNewAccount', {
154
154
  text: i18n(`${spinniesI18nKey}.fail`, {
@@ -181,7 +181,7 @@ async function buildNewAccount({
181
181
  force,
182
182
  });
183
183
  } catch (err) {
184
- logErrorInstance(err);
184
+ logError(err);
185
185
  throw err;
186
186
  }
187
187
 
@@ -5,15 +5,15 @@ const { getAccountId, getConfig } = require('@hubspot/local-dev-lib/config');
5
5
  const { i18n } = require('./lang');
6
6
  const {
7
7
  fetchDeveloperTestAccounts,
8
- } = require('@hubspot/local-dev-lib/developerTestAccounts');
8
+ } = require('@hubspot/local-dev-lib/api/developerTestAccounts');
9
9
  const {
10
10
  isMissingScopeError,
11
11
  isSpecifiedError,
12
- } = require('@hubspot/local-dev-lib/errors/apiErrors');
12
+ } = require('@hubspot/local-dev-lib/errors/index');
13
13
  const { logger } = require('@hubspot/local-dev-lib/logger');
14
14
  const { uiAccountDescription } = require('./ui');
15
15
  const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
16
- const { logErrorInstance } = require('./errorHandlers/standardErrors');
16
+ const { logError } = require('./errorHandlers/index');
17
17
 
18
18
  const getHasDevTestAccounts = appDeveloperAccountConfig => {
19
19
  const config = getConfig();
@@ -32,31 +32,31 @@ const getHasDevTestAccounts = appDeveloperAccountConfig => {
32
32
 
33
33
  const validateDevTestAccountUsageLimits = async accountConfig => {
34
34
  const accountId = getAccountId(accountConfig.portalId);
35
- const response = await fetchDeveloperTestAccounts(accountId);
36
- if (response) {
37
- const limit = response.maxTestPortals;
38
- const count = response.results.length;
39
- if (count >= limit) {
40
- const hasDevTestAccounts = getHasDevTestAccounts(accountConfig);
41
- if (hasDevTestAccounts) {
42
- throw new Error(
43
- i18n('lib.developerTestAccount.create.failure.alreadyInConfig', {
44
- accountName: accountConfig.name || accountId,
45
- limit,
46
- })
47
- );
48
- } else {
49
- throw new Error(
50
- i18n('lib.developerTestAccount.create.failure.limit', {
51
- accountName: accountConfig.name || accountId,
52
- limit,
53
- })
54
- );
55
- }
35
+ const { data } = await fetchDeveloperTestAccounts(accountId);
36
+ if (!data) {
37
+ return null;
38
+ }
39
+ const limit = data.maxTestPortals;
40
+ const count = data.results.length;
41
+ if (count >= limit) {
42
+ const hasDevTestAccounts = getHasDevTestAccounts(accountConfig);
43
+ if (hasDevTestAccounts) {
44
+ throw new Error(
45
+ i18n('lib.developerTestAccount.create.failure.alreadyInConfig', {
46
+ accountName: accountConfig.name || accountId,
47
+ limit,
48
+ })
49
+ );
50
+ } else {
51
+ throw new Error(
52
+ i18n('lib.developerTestAccount.create.failure.limit', {
53
+ accountName: accountConfig.name || accountId,
54
+ limit,
55
+ })
56
+ );
56
57
  }
57
- return response;
58
58
  }
59
- return null;
59
+ return data;
60
60
  };
61
61
 
62
62
  function handleDeveloperTestAccountCreateError({
@@ -94,7 +94,7 @@ function handleDeveloperTestAccountCreateError({
94
94
  );
95
95
  logger.log('');
96
96
  } else {
97
- logErrorInstance(err);
97
+ logError(err);
98
98
  }
99
99
  throw err;
100
100
  }
@@ -0,0 +1,101 @@
1
+ const { logger } = require('@hubspot/local-dev-lib/logger');
2
+ const {
3
+ isHubSpotHttpError,
4
+ isSystemError,
5
+ isFileSystemError,
6
+ isValidationError,
7
+ isMissingScopeError,
8
+ } = require('@hubspot/local-dev-lib/errors/index');
9
+ const { shouldSuppressError } = require('./suppressError');
10
+ const { i18n } = require('../lang');
11
+ const util = require('util');
12
+ const { isAxiosError } = require('axios');
13
+
14
+ const i18nKey = 'lib.errorHandlers.index';
15
+
16
+ function logError(error, context = {}) {
17
+ debugError(error, context);
18
+
19
+ if (
20
+ shouldSuppressError(error, context) ||
21
+ shouldSuppressError(error, error.context)
22
+ ) {
23
+ return;
24
+ }
25
+
26
+ if (isHubSpotHttpError(error) && context) {
27
+ error.updateContext(context);
28
+ }
29
+
30
+ if (isHubSpotHttpError(error) || isFileSystemError(error)) {
31
+ if (isValidationError(error) || isMissingScopeError(error)) {
32
+ logger.error(error.formattedValidationErrors());
33
+ } else {
34
+ logger.error(error.message);
35
+ }
36
+ } else if (isSystemError(error)) {
37
+ logger.error(error.message);
38
+ } else if (error.message || error.reason) {
39
+ const message = [];
40
+
41
+ [error.message, error.reason].forEach(msg => {
42
+ if (msg) {
43
+ message.push(msg);
44
+ }
45
+ });
46
+ logger.error(message.join(' '));
47
+ } else {
48
+ // Unknown errors
49
+ logger.error(i18n(`${i18nKey}.unknownErrorOccurred`));
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Logs (debug) the error and context objects.
55
+ *
56
+ * @param {Error} error
57
+ * @param {ApiErrorContext} context
58
+ */
59
+ function debugError(error, context = {}) {
60
+ if (isHubSpotHttpError(error)) {
61
+ logger.debug(error.toString());
62
+ } else {
63
+ logger.debug(i18n(`${i18nKey}.errorOccurred`, { error }));
64
+ }
65
+
66
+ if (error.cause) {
67
+ logger.debug(
68
+ i18n(`${i18nKey}.errorCause`, {
69
+ cause: isAxiosError(error.cause)
70
+ ? error.cause
71
+ : util.inspect(error.cause, false, null, true),
72
+ })
73
+ );
74
+ }
75
+ if (context) {
76
+ logger.debug(
77
+ i18n(`${i18nKey}.errorContext`, {
78
+ context: util.inspect(context, false, null, true),
79
+ })
80
+ );
81
+ }
82
+ }
83
+
84
+ class ApiErrorContext {
85
+ constructor(props = {}) {
86
+ /** @type {number} */
87
+ this.accountId = props.accountId;
88
+ /** @type {string} */
89
+ this.request = props.request || '';
90
+ /** @type {string} */
91
+ this.payload = props.payload || '';
92
+ /** @type {string} */
93
+ this.projectName = props.projectName || '';
94
+ }
95
+ }
96
+
97
+ module.exports = {
98
+ logError,
99
+ debugError,
100
+ ApiErrorContext,
101
+ };
@@ -1,7 +1,7 @@
1
1
  const {
2
2
  isSpecifiedError,
3
3
  isMissingScopeError,
4
- } = require('@hubspot/local-dev-lib/errors/apiErrors');
4
+ } = require('@hubspot/local-dev-lib/errors/index');
5
5
  const { logger } = require('@hubspot/local-dev-lib/logger');
6
6
  const { PLATFORM_VERSION_ERROR_TYPES } = require('../constants');
7
7
  const { i18n } = require('../lang');
@@ -12,7 +12,7 @@ const {
12
12
  uiCommandReference,
13
13
  } = require('../ui');
14
14
 
15
- const i18nKey = 'lib.errorHandlers.overrideErrors';
15
+ const i18nKey = 'lib.errorHandlers.suppressErrors';
16
16
 
17
17
  function createPlatformVersionError(err, subCategory) {
18
18
  let translationKey = 'unspecifiedPlatformVersion';
@@ -58,7 +58,7 @@ function createPlatformVersionError(err, subCategory) {
58
58
  uiLine();
59
59
  }
60
60
 
61
- function overrideErrors(err, context) {
61
+ function shouldSuppressError(err, context = {}) {
62
62
  if (isMissingScopeError(err)) {
63
63
  logger.error(
64
64
  i18n(`${i18nKey}.missingScopeError`, {
@@ -78,7 +78,7 @@ function overrideErrors(err, context) {
78
78
  })
79
79
  ) {
80
80
  createPlatformVersionError(
81
- err,
81
+ err.data,
82
82
  PLATFORM_VERSION_ERROR_TYPES.PLATFORM_VERSION_NOT_SPECIFIED
83
83
  );
84
84
  return true;
@@ -90,7 +90,7 @@ function overrideErrors(err, context) {
90
90
  })
91
91
  ) {
92
92
  createPlatformVersionError(
93
- err,
93
+ err.data,
94
94
  PLATFORM_VERSION_ERROR_TYPES.PLATFORM_VERSION_RETIRED
95
95
  );
96
96
  return true;
@@ -103,7 +103,7 @@ function overrideErrors(err, context) {
103
103
  })
104
104
  ) {
105
105
  createPlatformVersionError(
106
- err,
106
+ err.data,
107
107
  PLATFORM_VERSION_ERROR_TYPES.PLATFORM_VERSION_SPECIFIED_DOES_NOT_EXIST
108
108
  );
109
109
  return true;
@@ -112,5 +112,5 @@ function overrideErrors(err, context) {
112
112
  }
113
113
 
114
114
  module.exports = {
115
- overrideErrors,
115
+ shouldSuppressError,
116
116
  };
@@ -0,0 +1,15 @@
1
+ const {
2
+ fetchEnabledFeatures,
3
+ } = require('@hubspot/local-dev-lib/api/localDevAuth');
4
+
5
+ const hasFeature = async (accountId, feature) => {
6
+ const {
7
+ data: { enabledFeatures },
8
+ } = await fetchEnabledFeatures(accountId);
9
+
10
+ return enabledFeatures[feature];
11
+ };
12
+
13
+ module.exports = {
14
+ hasFeature,
15
+ };
package/lib/localDev.js CHANGED
@@ -6,7 +6,7 @@ const {
6
6
  const {
7
7
  isMissingScopeError,
8
8
  isSpecifiedError,
9
- } = require('@hubspot/local-dev-lib/errors/apiErrors');
9
+ } = require('@hubspot/local-dev-lib/errors/index');
10
10
  const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
11
11
  const { getAccountConfig, getEnv } = require('@hubspot/local-dev-lib/config');
12
12
  const { createProject } = require('@hubspot/local-dev-lib/api/projects');
@@ -28,7 +28,6 @@ const { syncSandbox } = require('./sandboxSync');
28
28
  const {
29
29
  validateDevTestAccountUsageLimits,
30
30
  } = require('./developerTestAccounts');
31
- const { logErrorInstance } = require('./errorHandlers/standardErrors');
32
31
  const { uiCommandReference, uiLine, uiAccountDescription } = require('./ui');
33
32
  const SpinniesManager = require('./ui/SpinniesManager');
34
33
  const { i18n } = require('./lang');
@@ -47,10 +46,7 @@ const {
47
46
  PROJECT_BUILD_TEXT,
48
47
  PROJECT_DEPLOY_TEXT,
49
48
  } = require('./constants');
50
- const {
51
- logApiErrorInstance,
52
- ApiErrorContext,
53
- } = require('./errorHandlers/apiErrors');
49
+ const { logError, ApiErrorContext } = require('./errorHandlers/index');
54
50
  const {
55
51
  PERSONAL_ACCESS_KEY_AUTH_METHOD,
56
52
  } = require('@hubspot/local-dev-lib/constants/auth');
@@ -82,11 +78,25 @@ const confirmDefaultAccountIsTarget = async accountConfig => {
82
78
  }
83
79
  };
84
80
 
85
- // Confirm the default account is a developer account if developing public apps
86
- const checkIfAppDeveloperAccount = accountConfig => {
87
- if (!isAppDeveloperAccount(accountConfig)) {
81
+ // Confirm the default account is supported for the type of apps being developed
82
+ const checkIfDefaultAccountIsSupported = (accountConfig, hasPublicApps) => {
83
+ if (
84
+ hasPublicApps &&
85
+ !(
86
+ isAppDeveloperAccount(accountConfig) ||
87
+ isDeveloperTestAccount(accountConfig)
88
+ )
89
+ ) {
88
90
  logger.error(
89
- i18n(`${i18nKey}.checkIfAppDevloperAccount`, {
91
+ i18n(`${i18nKey}.checkIfDefaultAccountIsSupported.publicApp`, {
92
+ useCommand: uiCommandReference('hs accounts use'),
93
+ authCommand: uiCommandReference('hs auth'),
94
+ })
95
+ );
96
+ process.exit(EXIT_CODES.SUCCESS);
97
+ } else if (!hasPublicApps && isAppDeveloperAccount(accountConfig)) {
98
+ logger.error(
99
+ i18n(`${i18nKey}.checkIfDefaultAccountIsSupported.privateApp`, {
90
100
  useCommand: uiCommandReference('hs accounts use'),
91
101
  authCommand: uiCommandReference('hs auth'),
92
102
  })
@@ -111,7 +121,7 @@ const checkIfParentAccountIsAuthed = accountConfig => {
111
121
  };
112
122
 
113
123
  // Confirm the default account is a developer account if developing public apps
114
- const validateAccountOption = (accountConfig, hasPublicApps) => {
124
+ const checkIfAccountFlagIsSupported = (accountConfig, hasPublicApps) => {
115
125
  if (hasPublicApps) {
116
126
  if (!isDeveloperTestAccount) {
117
127
  logger.error(
@@ -184,7 +194,7 @@ const createSandboxForLocalDev = async (accountId, accountConfig, env) => {
184
194
  })
185
195
  );
186
196
  } else {
187
- logErrorInstance(err);
197
+ logError(err);
188
198
  }
189
199
  process.exit(EXIT_CODES.ERROR);
190
200
  }
@@ -223,7 +233,7 @@ const createSandboxForLocalDev = async (accountId, accountConfig, env) => {
223
233
  });
224
234
  return targetAccountId;
225
235
  } catch (err) {
226
- logErrorInstance(err);
236
+ logError(err);
227
237
  process.exit(EXIT_CODES.ERROR);
228
238
  }
229
239
  };
@@ -262,7 +272,7 @@ const createDeveloperTestAccountForLocalDev = async (
262
272
  })
263
273
  );
264
274
  } else {
265
- logErrorInstance(err);
275
+ logError(err);
266
276
  }
267
277
  process.exit(EXIT_CODES.ERROR);
268
278
  }
@@ -288,7 +298,7 @@ const createDeveloperTestAccountForLocalDev = async (
288
298
 
289
299
  return result.id;
290
300
  } catch (err) {
291
- logErrorInstance(err);
301
+ logError(err);
292
302
  process.exit(EXIT_CODES.ERROR);
293
303
  }
294
304
  };
@@ -367,7 +377,10 @@ const createNewProjectForLocalDev = async (
367
377
  });
368
378
 
369
379
  try {
370
- const project = await createProject(targetAccountId, projectConfig.name);
380
+ const { data: project } = await createProject(
381
+ targetAccountId,
382
+ projectConfig.name
383
+ );
371
384
  SpinniesManager.succeed('createProject', {
372
385
  text: i18n(`${i18nKey}.createNewProjectForLocalDev.createdProject`, {
373
386
  accountIdentifier: uiAccountDescription(targetAccountId),
@@ -420,7 +433,7 @@ const createInitialBuildForNewProject = async (
420
433
  );
421
434
  logger.log();
422
435
  } else {
423
- logApiErrorInstance(
436
+ logError(
424
437
  initialUploadResult.uploadError,
425
438
  new ApiErrorContext({
426
439
  accountId: targetAccountId,
@@ -465,8 +478,8 @@ const getAccountHomeUrl = accountId => {
465
478
 
466
479
  module.exports = {
467
480
  confirmDefaultAccountIsTarget,
468
- checkIfAppDeveloperAccount,
469
- validateAccountOption,
481
+ checkIfDefaultAccountIsSupported,
482
+ checkIfAccountFlagIsSupported,
470
483
  suggestRecommendedNestedAccount,
471
484
  createSandboxForLocalDev,
472
485
  createDeveloperTestAccountForLocalDev,