@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
@@ -14,7 +14,7 @@ const SLEEP_TIME = 2000;
14
14
  const kickOffValidation = async (accountId, assetType, src) => {
15
15
  const requestGroup = 'EXTERNAL_DEVELOPER';
16
16
  try {
17
- const requestResult = await requestValidation(accountId, {
17
+ const { data: requestResult } = await requestValidation(accountId, {
18
18
  path: src,
19
19
  assetType,
20
20
  requestGroup,
@@ -29,7 +29,7 @@ const kickOffValidation = async (accountId, assetType, src) => {
29
29
  const pollForValidationFinish = async (accountId, validationId) => {
30
30
  try {
31
31
  const checkValidationStatus = async () => {
32
- const validationStatus = await getValidationStatus(accountId, {
32
+ const { data: validationStatus } = await getValidationStatus(accountId, {
33
33
  validationId,
34
34
  });
35
35
 
@@ -47,7 +47,7 @@ const pollForValidationFinish = async (accountId, validationId) => {
47
47
 
48
48
  const fetchValidationResults = async (accountId, validationId) => {
49
49
  try {
50
- const validationResults = await getValidationResults(accountId, {
50
+ const { data: validationResults } = await getValidationResults(accountId, {
51
51
  validationId,
52
52
  });
53
53
  return validationResults;
package/lib/oauth.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const express = require('express');
2
2
  const open = require('open');
3
3
  const {
4
- default: OAuth2Manager,
4
+ OAuth2Manager,
5
5
  } = require('@hubspot/local-dev-lib/models/OAuth2Manager');
6
6
  const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
7
7
  const { addOauthToAccountConfig } = require('@hubspot/local-dev-lib/oauth');
package/lib/polling.js CHANGED
@@ -4,7 +4,7 @@ const poll = (callback, accountId, taskId) => {
4
4
  return new Promise((resolve, reject) => {
5
5
  const pollInterval = setInterval(async () => {
6
6
  try {
7
- const pollResp = await callback(accountId, taskId);
7
+ const { data: pollResp } = await callback(accountId, taskId);
8
8
  const { status } = pollResp;
9
9
 
10
10
  if (status === POLLING_STATUS.SUCCESS) {
@@ -54,10 +54,9 @@ class ProjectLogsManager {
54
54
  throw new Error(i18n(`${i18nKey}.errors.noProjectConfig`));
55
55
  }
56
56
 
57
- const { topLevelComponentMetadata } = await fetchProjectComponentsMetadata(
58
- this.accountId,
59
- this.projectId
60
- );
57
+ const {
58
+ data: { topLevelComponentMetadata },
59
+ } = await fetchProjectComponentsMetadata(this.accountId, this.projectId);
61
60
 
62
61
  const apps = topLevelComponentMetadata.filter(componentMetadata => {
63
62
  const { type } = componentMetadata;
@@ -2,7 +2,7 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { walk } = require('@hubspot/local-dev-lib/fs');
4
4
  const { logger } = require('@hubspot/local-dev-lib/logger');
5
- const { logErrorInstance } = require('./errorHandlers/standardErrors');
5
+ const { logError } = require('./errorHandlers/index');
6
6
 
7
7
  const COMPONENT_TYPES = Object.freeze({
8
8
  privateApp: 'private-app',
@@ -94,7 +94,7 @@ async function findProjectComponents(projectSourceDir) {
94
94
  try {
95
95
  projectFiles = await walk(projectSourceDir);
96
96
  } catch (e) {
97
- logErrorInstance(e);
97
+ logError(e);
98
98
  }
99
99
 
100
100
  projectFiles.forEach(projectFile => {
package/lib/projects.js CHANGED
@@ -33,10 +33,7 @@ const {
33
33
  fetchBuildWarnLogs,
34
34
  fetchDeployWarnLogs,
35
35
  } = require('@hubspot/local-dev-lib/api/projects');
36
- const {
37
- isSpecifiedError,
38
- isSpecifiedHubSpotAuthError,
39
- } = require('@hubspot/local-dev-lib/errors/apiErrors');
36
+ const { isSpecifiedError } = require('@hubspot/local-dev-lib/errors/index');
40
37
  const { shouldIgnoreFile } = require('@hubspot/local-dev-lib/ignoreRules');
41
38
  const { getCwd, getAbsoluteFilePath } = require('@hubspot/local-dev-lib/path');
42
39
  const { downloadGithubRepoContents } = require('@hubspot/local-dev-lib/github');
@@ -45,10 +42,7 @@ const { EXIT_CODES } = require('./enums/exitCodes');
45
42
  const { uiLine, uiLink, uiAccountDescription } = require('../lib/ui');
46
43
  const { i18n } = require('./lang');
47
44
  const SpinniesManager = require('./ui/SpinniesManager');
48
- const {
49
- logApiErrorInstance,
50
- ApiErrorContext,
51
- } = require('./errorHandlers/apiErrors');
45
+ const { logError, ApiErrorContext } = require('./errorHandlers/index');
52
46
 
53
47
  const i18nKey = 'lib.projects';
54
48
 
@@ -215,11 +209,11 @@ const pollFetchProject = async (accountId, projectName) => {
215
209
  });
216
210
  const pollInterval = setInterval(async () => {
217
211
  try {
218
- const project = await fetchProject(accountId, projectName);
219
- if (project) {
212
+ const response = await fetchProject(accountId, projectName);
213
+ if (response && response.data) {
220
214
  SpinniesManager.remove('pollFetchProject');
221
215
  clearInterval(pollInterval);
222
- resolve(project);
216
+ resolve(response);
223
217
  }
224
218
  } catch (err) {
225
219
  if (
@@ -254,7 +248,7 @@ const ensureProjectExists = async (
254
248
  ) => {
255
249
  const accountIdentifier = uiAccountDescription(accountId);
256
250
  try {
257
- const project = withPolling
251
+ const { data: project } = withPolling
258
252
  ? await pollFetchProject(accountId, projectName)
259
253
  : await fetchProject(accountId, projectName);
260
254
  return { projectExists: !!project, project };
@@ -278,7 +272,7 @@ const ensureProjectExists = async (
278
272
 
279
273
  if (shouldCreateProject) {
280
274
  try {
281
- const project = await createProject(accountId, projectName);
275
+ const { data: project } = await createProject(accountId, projectName);
282
276
  logger.success(
283
277
  i18n(`${i18nKey}.ensureProjectExists.createSuccess`, {
284
278
  projectName,
@@ -287,7 +281,7 @@ const ensureProjectExists = async (
287
281
  );
288
282
  return { projectExists: true, project };
289
283
  } catch (err) {
290
- return logApiErrorInstance(err, new ApiErrorContext({ accountId }));
284
+ return logError(err, new ApiErrorContext({ accountId }));
291
285
  }
292
286
  } else {
293
287
  if (!noLogs) {
@@ -302,14 +296,14 @@ const ensureProjectExists = async (
302
296
  }
303
297
  }
304
298
  if (
305
- isSpecifiedHubSpotAuthError(err, {
299
+ isSpecifiedError(err, {
306
300
  statusCode: 401,
307
301
  })
308
302
  ) {
309
303
  logger.error(err.message);
310
304
  process.exit(EXIT_CODES.ERROR);
311
305
  }
312
- logApiErrorInstance(err, new ApiErrorContext({ accountId }));
306
+ logError(err, new ApiErrorContext({ accountId }));
313
307
  process.exit(EXIT_CODES.ERROR);
314
308
  }
315
309
  };
@@ -364,7 +358,7 @@ const uploadProjectFiles = async (
364
358
  let error;
365
359
 
366
360
  try {
367
- const upload = await uploadProject(
361
+ const { data: upload } = await uploadProject(
368
362
  accountId,
369
363
  projectName,
370
364
  filePath,
@@ -442,7 +436,7 @@ const pollProjectBuildAndDeploy = async (
442
436
  )
443
437
  );
444
438
 
445
- displayWarnLogs(accountId, projectConfig.name, buildId);
439
+ await displayWarnLogs(accountId, projectConfig.name, buildId);
446
440
  }
447
441
 
448
442
  // autoDeployId of 0 indicates a skipped deploy
@@ -501,7 +495,7 @@ const pollProjectBuildAndDeploy = async (
501
495
  }
502
496
 
503
497
  if (result && result.deployResult) {
504
- displayWarnLogs(
498
+ await displayWarnLogs(
505
499
  accountId,
506
500
  projectConfig.name,
507
501
  result.deployResult.deployId,
@@ -636,8 +630,10 @@ const makePollTaskStatusFunc = ({
636
630
  });
637
631
 
638
632
  const [
639
- initialTaskStatus,
640
- { topLevelComponentsWithChildren: taskStructure },
633
+ { data: initialTaskStatus },
634
+ {
635
+ data: { topLevelComponentsWithChildren: taskStructure },
636
+ },
641
637
  ] = await Promise.all([
642
638
  statusFn(accountId, taskName, taskId),
643
639
  structureFn(accountId, taskName, taskId),
@@ -711,9 +707,17 @@ const makePollTaskStatusFunc = ({
711
707
  const pollInterval = setInterval(async () => {
712
708
  let taskStatus;
713
709
  try {
714
- taskStatus = await statusFn(accountId, taskName, taskId);
710
+ const { data } = await statusFn(accountId, taskName, taskId);
711
+ taskStatus = data;
715
712
  } catch (e) {
716
713
  logger.debug(e);
714
+ logError(
715
+ e,
716
+ new ApiErrorContext({
717
+ accountId,
718
+ projectName: taskName,
719
+ })
720
+ );
717
721
  return reject(
718
722
  new Error(
719
723
  i18n(
@@ -981,22 +985,31 @@ const displayWarnLogs = async (
981
985
 
982
986
  if (isDeploy) {
983
987
  try {
984
- result = await fetchDeployWarnLogs(accountId, projectName, taskId);
988
+ const { data } = await fetchDeployWarnLogs(
989
+ accountId,
990
+ projectName,
991
+ taskId
992
+ );
993
+ result = data;
985
994
  } catch (e) {
986
- logApiErrorInstance(e);
995
+ logError(e);
987
996
  }
988
997
  } else {
989
998
  try {
990
- result = await fetchBuildWarnLogs(accountId, projectName, taskId);
999
+ const { data } = await fetchBuildWarnLogs(accountId, projectName, taskId);
1000
+ result = data;
991
1001
  } catch (e) {
992
- logApiErrorInstance(e);
1002
+ logError(e);
993
1003
  }
994
1004
  }
995
1005
 
996
- if (result && result.logs.length) {
997
- result.logs.forEach(log => {
1006
+ if (result && result.logs) {
1007
+ const logLength = result.logs.length;
1008
+ result.logs.forEach((log, i) => {
998
1009
  logger.warn(log.message);
999
- logger.log('');
1010
+ if (i < logLength - 1) {
1011
+ logger.log('');
1012
+ }
1000
1013
  });
1001
1014
  }
1002
1015
  };
@@ -2,10 +2,7 @@ const chokidar = require('chokidar');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
4
  const { default: PQueue } = require('p-queue');
5
- const {
6
- logApiErrorInstance,
7
- ApiErrorContext,
8
- } = require('./errorHandlers/apiErrors');
5
+ const { logError, ApiErrorContext } = require('./errorHandlers/index');
9
6
  const { i18n } = require('./lang');
10
7
  const { logger } = require('@hubspot/local-dev-lib/logger');
11
8
  const { isAllowedExtension } = require('@hubspot/local-dev-lib/path');
@@ -17,7 +14,7 @@ const {
17
14
  deleteFileFromBuild,
18
15
  queueBuild,
19
16
  } = require('@hubspot/local-dev-lib/api/projects');
20
- const { isSpecifiedError } = require('@hubspot/local-dev-lib/errors/apiErrors');
17
+ const { isSpecifiedError } = require('@hubspot/local-dev-lib/errors/index');
21
18
  const { PROJECT_ERROR_TYPES } = require('./constants');
22
19
 
23
20
  const i18nKey = 'commands.project.subcommands.watch';
@@ -85,7 +82,7 @@ const debounceQueueBuild = (accountId, projectName, platformVersion) => {
85
82
  logger.log(i18n(`${i18nKey}.logs.watchCancelledFromUi`));
86
83
  process.exit(0);
87
84
  } else {
88
- logApiErrorInstance(err, new ApiErrorContext({ accountId }));
85
+ logError(err, new ApiErrorContext({ accountId }));
89
86
  }
90
87
 
91
88
  return;
@@ -148,14 +145,12 @@ const queueFileOrFolder = async (
148
145
  const createNewBuild = async (accountId, projectName, platformVersion) => {
149
146
  try {
150
147
  logger.debug(i18n(`${i18nKey}.debug.attemptNewBuild`));
151
- const { buildId } = await provisionBuild(
152
- accountId,
153
- projectName,
154
- platformVersion
155
- );
148
+ const {
149
+ data: { buildId },
150
+ } = await provisionBuild(accountId, projectName, platformVersion);
156
151
  return buildId;
157
152
  } catch (err) {
158
- logApiErrorInstance(err, new ApiErrorContext({ accountId }));
153
+ logError(err, new ApiErrorContext({ accountId }));
159
154
  if (
160
155
  isSpecifiedError(err, { subCategory: PROJECT_ERROR_TYPES.PROJECT_LOCKED })
161
156
  ) {
@@ -60,14 +60,20 @@ const createProjectPrompt = async (
60
60
  skipTemplatePrompt = false
61
61
  ) => {
62
62
  let projectTemplates = [];
63
+ let selectedTemplate;
64
+
63
65
  if (!skipTemplatePrompt) {
64
66
  projectTemplates = await createTemplateOptions(
65
67
  promptOptions.templateSource,
66
68
  githubRef
67
69
  );
70
+
71
+ selectedTemplate =
72
+ promptOptions.template &&
73
+ projectTemplates.find(t => t.name === promptOptions.template);
68
74
  }
69
75
 
70
- return promptUser([
76
+ const result = await promptUser([
71
77
  {
72
78
  name: 'name',
73
79
  message: i18n(`${i18nKey}.enterName`),
@@ -115,10 +121,7 @@ const createProjectPrompt = async (
115
121
  })
116
122
  : i18n(`${i18nKey}.selectTemplate`);
117
123
  },
118
- when:
119
- !skipTemplatePrompt &&
120
- (!promptOptions.template ||
121
- !projectTemplates.find(t => t.name === promptOptions.template)),
124
+ when: !skipTemplatePrompt && !selectedTemplate,
122
125
  type: 'list',
123
126
  choices: projectTemplates.map(template => {
124
127
  return {
@@ -128,6 +131,12 @@ const createProjectPrompt = async (
128
131
  }),
129
132
  },
130
133
  ]);
134
+
135
+ if (selectedTemplate) {
136
+ result.template = selectedTemplate;
137
+ }
138
+
139
+ return result;
131
140
  };
132
141
 
133
142
  module.exports = {
@@ -1,10 +1,7 @@
1
1
  const { promptUser } = require('./promptUtils');
2
2
  const { getAccountId } = require('@hubspot/local-dev-lib/config');
3
3
  const { fetchProjects } = require('@hubspot/local-dev-lib/api/projects');
4
- const {
5
- logApiErrorInstance,
6
- ApiErrorContext,
7
- } = require('../../lib/errorHandlers/apiErrors');
4
+ const { logError, ApiErrorContext } = require('../../lib/errorHandlers/index');
8
5
  const { EXIT_CODES } = require('../enums/exitCodes');
9
6
  const { i18n } = require('../lang');
10
7
 
@@ -12,10 +9,10 @@ const i18nKey = 'lib.prompts.downloadProjectPrompt';
12
9
 
13
10
  const createProjectsList = async accountId => {
14
11
  try {
15
- const projects = await fetchProjects(accountId);
12
+ const { data: projects } = await fetchProjects(accountId);
16
13
  return projects.results;
17
14
  } catch (e) {
18
- logApiErrorInstance(e, new ApiErrorContext({ accountId }));
15
+ logError(e, new ApiErrorContext({ accountId }));
19
16
  process.exit(EXIT_CODES.ERROR);
20
17
  }
21
18
  };
@@ -3,7 +3,9 @@ const { i18n } = require('../lang');
3
3
  const { uiAccountDescription, uiCommandReference } = require('../ui');
4
4
  const { isSandbox } = require('../accountTypes');
5
5
  const { getAccountId } = require('@hubspot/local-dev-lib/config');
6
- const { getSandboxUsageLimits } = require('@hubspot/local-dev-lib/sandboxes');
6
+ const {
7
+ getSandboxUsageLimits,
8
+ } = require('@hubspot/local-dev-lib/api/sandboxHubs');
7
9
  const {
8
10
  HUBSPOT_ACCOUNT_TYPES,
9
11
  HUBSPOT_ACCOUNT_TYPE_STRINGS,
@@ -11,7 +13,7 @@ const {
11
13
  const { logger } = require('@hubspot/local-dev-lib/logger');
12
14
  const {
13
15
  fetchDeveloperTestAccounts,
14
- } = require('@hubspot/local-dev-lib/developerTestAccounts');
16
+ } = require('@hubspot/local-dev-lib/api/developerTestAccounts');
15
17
 
16
18
  const i18nKey = 'lib.prompts.projectDevTargetAccountPrompt';
17
19
 
@@ -38,7 +40,8 @@ const selectSandboxTargetAccountPrompt = async (
38
40
  let choices = [];
39
41
  let sandboxUsage = {};
40
42
  try {
41
- sandboxUsage = await getSandboxUsageLimits(defaultAccountId);
43
+ const { data } = await getSandboxUsageLimits(defaultAccountId);
44
+ sandboxUsage = data.usage;
42
45
  } catch (err) {
43
46
  logger.debug('Unable to fetch sandbox usage limits: ', err);
44
47
  }
@@ -101,9 +104,8 @@ const selectDeveloperTestTargetAccountPrompt = async (
101
104
  const defaultAccountId = getAccountId(defaultAccountConfig.name);
102
105
  let devTestAccountsResponse = undefined;
103
106
  try {
104
- devTestAccountsResponse = await fetchDeveloperTestAccounts(
105
- defaultAccountId
106
- );
107
+ const { data } = await fetchDeveloperTestAccounts(defaultAccountId);
108
+ devTestAccountsResponse = data;
107
109
  } catch (err) {
108
110
  logger.debug('Unable to fetch developer test account usage limits: ', err);
109
111
  }
@@ -1,7 +1,7 @@
1
1
  const { promptUser } = require('./promptUtils');
2
2
  const { i18n } = require('../lang');
3
3
  const { uiLine } = require('../ui');
4
- const { logApiErrorInstance } = require('../errorHandlers/apiErrors');
4
+ const { logError } = require('../errorHandlers/index');
5
5
  const { logger } = require('@hubspot/local-dev-lib/logger');
6
6
  const {
7
7
  fetchPublicAppsForPortal,
@@ -16,7 +16,9 @@ const fetchPublicAppOptions = async (
16
16
  isMigratingApp = false
17
17
  ) => {
18
18
  try {
19
- const publicApps = await fetchPublicAppsForPortal(accountId);
19
+ const {
20
+ data: { results: publicApps },
21
+ } = await fetchPublicAppsForPortal(accountId);
20
22
  const filteredPublicApps = publicApps.filter(
21
23
  app => !app.projectId && !app.sourceId
22
24
  );
@@ -44,7 +46,7 @@ const fetchPublicAppOptions = async (
44
46
  }
45
47
  return filteredPublicApps;
46
48
  } catch (error) {
47
- logApiErrorInstance(error, { accountId });
49
+ logError(error, { accountId });
48
50
  logger.error(i18n(`${i18nKey}.errors.errorFetchingApps`));
49
51
  process.exit(EXIT_CODES.ERROR);
50
52
  }
@@ -3,13 +3,13 @@ const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
3
3
  const { logger } = require('@hubspot/local-dev-lib/logger');
4
4
  const { i18n } = require('./lang');
5
5
  const { getAvailableSyncTypes } = require('./sandboxes');
6
- const { initiateSync } = require('@hubspot/local-dev-lib/sandboxes');
7
- const { debugErrorAndContext } = require('./errorHandlers/standardErrors');
6
+ const { initiateSync } = require('@hubspot/local-dev-lib/api/sandboxSync');
8
7
  const {
9
- logApiErrorInstance,
8
+ debugError,
9
+ logError,
10
10
  ApiErrorContext,
11
- } = require('./errorHandlers/apiErrors');
12
- const { isSpecifiedError } = require('@hubspot/local-dev-lib/errors/apiErrors');
11
+ } = require('./errorHandlers/index');
12
+ const { isSpecifiedError } = require('@hubspot/local-dev-lib/errors/index');
13
13
  const { getSandboxTypeAsString } = require('./sandboxes');
14
14
  const { getAccountId } = require('@hubspot/local-dev-lib/config');
15
15
  const {
@@ -88,7 +88,7 @@ const syncSandbox = async ({
88
88
  ),
89
89
  });
90
90
  } catch (err) {
91
- debugErrorAndContext(err);
91
+ debugError(err);
92
92
 
93
93
  SpinniesManager.fail('sandboxSync', {
94
94
  text: i18n(`${i18nKey}.loading.fail`),
@@ -155,7 +155,7 @@ const syncSandbox = async ({
155
155
  'https://app.hubspot.com/l/docs/guides/crm/project-cli-commands#developer-projects-cli-commands-beta'
156
156
  );
157
157
  } else {
158
- logApiErrorInstance(
158
+ logError(
159
159
  err,
160
160
  new ApiErrorContext({
161
161
  accountId: parentAccountId,
package/lib/sandboxes.js CHANGED
@@ -1,9 +1,9 @@
1
1
  const { i18n } = require('./lang');
2
2
  const { logger } = require('@hubspot/local-dev-lib/logger');
3
3
  const {
4
- fetchTypes,
5
4
  getSandboxUsageLimits,
6
- } = require('@hubspot/local-dev-lib/sandboxes');
5
+ } = require('@hubspot/local-dev-lib/api/sandboxHubs');
6
+ const { fetchTypes } = require('@hubspot/local-dev-lib/api/sandboxSync');
7
7
  const {
8
8
  getConfig,
9
9
  getAccountId,
@@ -19,9 +19,9 @@ const { uiAccountDescription } = require('./ui');
19
19
  const {
20
20
  isMissingScopeError,
21
21
  isSpecifiedError,
22
- } = require('@hubspot/local-dev-lib/errors/apiErrors');
22
+ } = require('@hubspot/local-dev-lib/errors/index');
23
23
  const { getValidEnv } = require('@hubspot/local-dev-lib/environment');
24
- const { logErrorInstance } = require('./errorHandlers/standardErrors');
24
+ const { logError } = require('./errorHandlers/index');
25
25
 
26
26
  const syncTypes = {
27
27
  OBJECT_RECORDS: 'object-records',
@@ -73,7 +73,9 @@ function getSandboxLimit(error) {
73
73
  async function getAvailableSyncTypes(parentAccountConfig, config) {
74
74
  const parentPortalId = getAccountId(parentAccountConfig.portalId);
75
75
  const portalId = getAccountId(config.portalId);
76
- const syncTypes = await fetchTypes(parentPortalId, portalId);
76
+ const {
77
+ data: { results: syncTypes },
78
+ } = await fetchTypes(parentPortalId, portalId);
77
79
  if (!syncTypes) {
78
80
  throw new Error(
79
81
  'Unable to fetch available sandbox sync types. Please try again.'
@@ -126,7 +128,9 @@ const getSyncTypesWithContactRecordsPrompt = async (
126
128
  */
127
129
  const validateSandboxUsageLimits = async (accountConfig, sandboxType, env) => {
128
130
  const accountId = getAccountId(accountConfig.portalId);
129
- const usage = await getSandboxUsageLimits(accountId);
131
+ const {
132
+ data: { usage },
133
+ } = await getSandboxUsageLimits(accountId);
130
134
  if (!usage) {
131
135
  throw new Error('Unable to fetch sandbox usage limits. Please try again.');
132
136
  }
@@ -348,7 +352,7 @@ function handleSandboxCreateError({
348
352
  }
349
353
  logger.log('');
350
354
  } else {
351
- logErrorInstance(err);
355
+ logError(err);
352
356
  }
353
357
  throw err;
354
358
  }
package/lib/schema.js CHANGED
@@ -24,8 +24,8 @@ const logSchemas = schemas => {
24
24
  };
25
25
 
26
26
  const listSchemas = async accountId => {
27
- const response = await fetchObjectSchemas(accountId);
28
- logSchemas(response.results);
27
+ const { data } = await fetchObjectSchemas(accountId);
28
+ logSchemas(data.results);
29
29
  };
30
30
 
31
31
  module.exports = {
@@ -4,13 +4,20 @@ const { handleExit, handleKeypress } = require('./process');
4
4
  const chalk = require('chalk');
5
5
  const { logger } = require('@hubspot/local-dev-lib/logger');
6
6
  const { outputLogs } = require('./ui/serverlessFunctionLogs');
7
- const {
8
- logServerlessFunctionApiErrorInstance,
9
- logApiErrorInstance,
10
- ApiErrorContext,
11
- } = require('./errorHandlers/apiErrors');
7
+ const { logError, ApiErrorContext } = require('./errorHandlers/index');
12
8
 
13
9
  const { EXIT_CODES } = require('../lib/enums/exitCodes');
10
+ const {
11
+ isHubSpotHttpError,
12
+ isMissingScopeError,
13
+ } = require('@hubspot/local-dev-lib/errors/index');
14
+ const {
15
+ SCOPE_GROUPS,
16
+ PERSONAL_ACCESS_KEY_AUTH_METHOD,
17
+ } = require('@hubspot/local-dev-lib/constants/auth');
18
+ const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
19
+ const { fetchScopeData } = require('@hubspot/local-dev-lib/api/localDevAuth');
20
+ const { i18n } = require('./lang');
14
21
 
15
22
  const TAIL_DELAY = 5000;
16
23
 
@@ -38,6 +45,47 @@ const handleUserInput = () => {
38
45
  });
39
46
  };
40
47
 
48
+ async function verifyAccessKeyAndUserAccess(accountId, scopeGroup) {
49
+ const accountConfig = getAccountConfig(accountId);
50
+ // TODO[JOE]: Update this i18n key
51
+ const i18nKey = 'lib.serverless';
52
+ const { authType } = accountConfig;
53
+ if (authType !== PERSONAL_ACCESS_KEY_AUTH_METHOD.value) {
54
+ return;
55
+ }
56
+
57
+ let scopesData;
58
+ try {
59
+ scopesData = await fetchScopeData(accountId, scopeGroup);
60
+ } catch (e) {
61
+ logger.debug(
62
+ i18n(`${i18nKey}.verifyAccessKeyAndUserAccess.fetchScopeDataError`, {
63
+ scopeGroup,
64
+ error: e,
65
+ })
66
+ );
67
+ return;
68
+ }
69
+ const { portalScopesInGroup, userScopesInGroup } = scopesData;
70
+
71
+ if (!portalScopesInGroup.length) {
72
+ logger.error(
73
+ i18n(`${i18nKey}.verifyAccessKeyAndUserAccess.portalMissingScope`)
74
+ );
75
+ return;
76
+ }
77
+
78
+ if (!portalScopesInGroup.every(s => userScopesInGroup.includes(s))) {
79
+ logger.error(
80
+ i18n(`${i18nKey}.verifyAccessKeyAndUserAccess.userMissingScope`)
81
+ );
82
+ } else {
83
+ logger.error(
84
+ i18n(`${i18nKey}.verifyAccessKeyAndUserAccess.genericMissingScope`)
85
+ );
86
+ }
87
+ }
88
+
41
89
  const tailLogs = async ({
42
90
  accountId,
43
91
  compact,
@@ -48,16 +96,19 @@ const tailLogs = async ({
48
96
  let initialAfter;
49
97
 
50
98
  try {
51
- const latestLog = await fetchLatest();
99
+ const { data: latestLog } = await fetchLatest();
52
100
  initialAfter = latestLog && base64EncodeString(latestLog.id);
53
101
  } catch (e) {
54
102
  // A 404 means no latest log exists(never executed)
55
- if (e.response && e.response.status !== 404) {
56
- await logServerlessFunctionApiErrorInstance(
57
- accountId,
58
- e,
59
- new ApiErrorContext({ accountId })
60
- );
103
+ if (isHubSpotHttpError(e) && e.status !== 404) {
104
+ if (isMissingScopeError(e)) {
105
+ await verifyAccessKeyAndUserAccess(
106
+ accountId,
107
+ SCOPE_GROUPS.CMS_FUNCTIONS
108
+ );
109
+ } else {
110
+ await logError(e, new ApiErrorContext({ accountId }));
111
+ }
61
112
  }
62
113
  }
63
114
 
@@ -65,11 +116,12 @@ const tailLogs = async ({
65
116
  let latestLog;
66
117
  let nextAfter;
67
118
  try {
68
- latestLog = await tailCall(after);
119
+ const { data } = await tailCall(after);
120
+ latestLog = data;
69
121
  nextAfter = latestLog.paging.next.after;
70
122
  } catch (e) {
71
- if (e.response && e.response.status !== 404) {
72
- logApiErrorInstance(
123
+ if (isHubSpotHttpError(e) && e.status !== 404) {
124
+ logError(
73
125
  e,
74
126
  new ApiErrorContext({
75
127
  accountId,