@hubspot/cli 5.2.1-beta.1 → 5.2.1-beta.10

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 (142) hide show
  1. package/bin/cli.js +1 -1
  2. package/bin/hs +1 -1
  3. package/commands/accounts/clean.js +7 -7
  4. package/commands/accounts/info.js +3 -3
  5. package/commands/accounts/list.js +7 -18
  6. package/commands/accounts/remove.js +1 -1
  7. package/commands/accounts/rename.js +3 -3
  8. package/commands/accounts/use.js +1 -1
  9. package/commands/accounts.js +3 -3
  10. package/commands/auth.js +7 -9
  11. package/commands/cms/convertFields.js +1 -1
  12. package/commands/cms/lighthouseScore.js +4 -4
  13. package/commands/cms/reactModules.js +1 -1
  14. package/commands/cms.js +3 -3
  15. package/commands/config/set/allowUsageTracking.js +1 -2
  16. package/commands/config/set/defaultMode.js +1 -1
  17. package/commands/config/set/httpTimeout.js +1 -1
  18. package/commands/config/set.js +1 -1
  19. package/commands/config.js +3 -3
  20. package/commands/create/api-sample.js +1 -1
  21. package/commands/create/module.js +1 -1
  22. package/commands/create/template.js +1 -1
  23. package/commands/create.js +1 -1
  24. package/commands/customObject/create.js +1 -1
  25. package/commands/customObject/schema/create.js +2 -3
  26. package/commands/customObject/schema/delete.js +1 -2
  27. package/commands/customObject/schema/fetch-all.js +1 -2
  28. package/commands/customObject/schema/fetch.js +1 -2
  29. package/commands/customObject/schema/list.js +1 -1
  30. package/commands/customObject/schema/update.js +2 -3
  31. package/commands/customObject/schema.js +1 -1
  32. package/commands/customObject.js +3 -3
  33. package/commands/feedback.js +4 -6
  34. package/commands/fetch.js +6 -6
  35. package/commands/filemanager/fetch.js +4 -4
  36. package/commands/filemanager/upload.js +4 -4
  37. package/commands/filemanager.js +4 -4
  38. package/commands/functions/deploy.js +7 -23
  39. package/commands/functions/list.js +4 -4
  40. package/commands/functions/server.js +4 -4
  41. package/commands/functions.js +3 -3
  42. package/commands/hubdb/clear.js +4 -4
  43. package/commands/hubdb/create.js +4 -4
  44. package/commands/hubdb/delete.js +4 -4
  45. package/commands/hubdb/fetch.js +4 -4
  46. package/commands/hubdb.js +3 -3
  47. package/commands/init.js +6 -8
  48. package/commands/lint.js +3 -3
  49. package/commands/list.js +4 -4
  50. package/commands/logs.js +4 -4
  51. package/commands/module/marketplace-validate.js +5 -5
  52. package/commands/module.js +3 -3
  53. package/commands/mv.js +4 -4
  54. package/commands/open.js +4 -4
  55. package/commands/project/add.js +1 -1
  56. package/commands/project/create.js +4 -4
  57. package/commands/project/deploy.js +4 -4
  58. package/commands/project/dev.js +70 -27
  59. package/commands/project/download.js +11 -7
  60. package/commands/project/listBuilds.js +4 -4
  61. package/commands/project/logs.js +4 -4
  62. package/commands/project/migrateApp.js +227 -0
  63. package/commands/project/open.js +12 -8
  64. package/commands/project/upload.js +13 -8
  65. package/commands/project/watch.js +4 -4
  66. package/commands/project.js +5 -3
  67. package/commands/remove.js +4 -4
  68. package/commands/sandbox/create.js +16 -16
  69. package/commands/sandbox/delete.js +5 -5
  70. package/commands/sandbox/sync.js +6 -6
  71. package/commands/sandbox.js +3 -3
  72. package/commands/secrets/addSecret.js +4 -4
  73. package/commands/secrets/deleteSecret.js +4 -4
  74. package/commands/secrets/listSecrets.js +4 -4
  75. package/commands/secrets/updateSecret.js +4 -4
  76. package/commands/secrets.js +3 -3
  77. package/commands/theme/generate-selectors.js +1 -1
  78. package/commands/theme/marketplace-validate.js +5 -5
  79. package/commands/theme/preview.js +52 -17
  80. package/commands/theme.js +1 -1
  81. package/commands/upload.js +5 -5
  82. package/commands/watch.js +61 -18
  83. package/jest.config.js +1 -0
  84. package/lang/en.lyaml +1425 -1371
  85. package/lib/DevServerManager.js +3 -2
  86. package/lib/LocalDevManager.js +165 -7
  87. package/lib/__tests__/{commonOpts.js → commonOpts.test.js} +3 -0
  88. package/lib/__tests__/downloadProjectPrompt.test.js +31 -0
  89. package/lib/__tests__/projects.test.js +13 -17
  90. package/lib/__tests__/{serverlessLogs.js → serverlessLogs.test.js} +1 -0
  91. package/lib/buildAccount.js +197 -0
  92. package/lib/commonOpts.js +1 -1
  93. package/lib/constants.js +10 -0
  94. package/lib/developerTestAccounts.js +52 -4
  95. package/lib/errorHandlers/apiErrors.js +1 -1
  96. package/lib/errorHandlers/overrideErrors.js +1 -1
  97. package/lib/errorHandlers/standardErrors.js +1 -1
  98. package/lib/generate-selectors.js +1 -1
  99. package/lib/localDev.js +102 -52
  100. package/lib/marketplace-validate.js +11 -3
  101. package/lib/polling.js +26 -0
  102. package/lib/process.js +1 -1
  103. package/lib/projectStructure.js +5 -2
  104. package/lib/projects.js +65 -12
  105. package/lib/projectsWatch.js +1 -1
  106. package/lib/prompts/accountNamePrompt.js +81 -0
  107. package/lib/prompts/accountsPrompt.js +1 -1
  108. package/lib/prompts/activeInstallConfirmationPrompt.js +20 -0
  109. package/lib/prompts/buildIdPrompt.js +1 -1
  110. package/lib/prompts/cleanUploadPrompt.js +1 -1
  111. package/lib/prompts/cmsFieldPrompt.js +1 -1
  112. package/lib/prompts/createApiSamplePrompt.js +1 -1
  113. package/lib/prompts/createFunctionPrompt.js +1 -1
  114. package/lib/prompts/createModulePrompt.js +1 -1
  115. package/lib/prompts/createProjectPrompt.js +32 -10
  116. package/lib/prompts/createTemplatePrompt.js +1 -1
  117. package/lib/prompts/downloadProjectPrompt.js +5 -6
  118. package/lib/prompts/feedbackPrompt.js +1 -1
  119. package/lib/prompts/folderOverwritePrompt.js +1 -1
  120. package/lib/prompts/installPublicAppPrompt.js +42 -0
  121. package/lib/prompts/personalAccessKeyPrompt.js +3 -3
  122. package/lib/prompts/previewPrompt.js +19 -1
  123. package/lib/prompts/projectAddPrompt.js +1 -1
  124. package/lib/prompts/projectDevTargetAccountPrompt.js +48 -6
  125. package/lib/prompts/projectNamePrompt.js +2 -2
  126. package/lib/prompts/projectsLogsPrompt.js +1 -1
  127. package/lib/prompts/sandboxesPrompt.js +13 -42
  128. package/lib/prompts/secretPrompt.js +1 -1
  129. package/lib/prompts/selectPublicAppPrompt.js +69 -0
  130. package/lib/prompts/setAsDefaultAccountPrompt.js +1 -1
  131. package/lib/prompts/uploadPrompt.js +1 -1
  132. package/lib/sandboxSync.js +1 -1
  133. package/lib/sandboxes.js +167 -14
  134. package/lib/ui/git.js +1 -1
  135. package/lib/ui/index.js +5 -22
  136. package/lib/ui/serverlessFunctionLogs.js +1 -1
  137. package/package.json +6 -6
  138. package/lib/developerTestAccountCreate.js +0 -186
  139. package/lib/prompts/developerTestAccountNamePrompt.js +0 -29
  140. package/lib/prompts/enterAccountNamePrompt.js +0 -33
  141. package/lib/sandboxCreate.js +0 -319
  142. /package/lib/__tests__/{validation.js → validation.test.js} +0 -0
@@ -1,186 +0,0 @@
1
- const SpinniesManager = require('./ui/SpinniesManager');
2
- const {
3
- getAccountId,
4
- accountNameExistsInConfig,
5
- updateAccountConfig,
6
- writeConfig,
7
- } = require('@hubspot/local-dev-lib/config');
8
- const { logger } = require('@hubspot/local-dev-lib/logger');
9
- const {
10
- createDeveloperTestAccount,
11
- } = require('@hubspot/local-dev-lib/developerTestAccounts');
12
- const { i18n } = require('./lang');
13
- const {
14
- debugErrorAndContext,
15
- logErrorInstance,
16
- } = require('./errorHandlers/standardErrors');
17
- const {
18
- isMissingScopeError,
19
- isSpecifiedError,
20
- } = require('@hubspot/local-dev-lib/errors/apiErrors');
21
- const {
22
- getAccessToken,
23
- updateConfigWithAccessToken,
24
- } = require('@hubspot/local-dev-lib/personalAccessKey');
25
- const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
26
- const { uiAccountDescription } = require('./ui');
27
- const {
28
- personalAccessKeyPrompt,
29
- } = require('./prompts/personalAccessKeyPrompt');
30
- const { enterAccountNamePrompt } = require('./prompts/enterAccountNamePrompt');
31
-
32
- const i18nKey = 'cli.lib.developerTestAccount';
33
-
34
- const saveDevTestAccountToConfig = async (env, result, force = false) => {
35
- let personalAccessKey = result.personalAccessKey;
36
- if (!personalAccessKey) {
37
- const configData = await personalAccessKeyPrompt({
38
- env,
39
- account: result.id,
40
- });
41
- personalAccessKey = configData.personalAccessKey;
42
- }
43
-
44
- const token = await getAccessToken(personalAccessKey, env);
45
- const updatedConfig = await updateConfigWithAccessToken(
46
- token,
47
- personalAccessKey,
48
- env
49
- );
50
-
51
- let validName = updatedConfig.name;
52
- if (!updatedConfig.name) {
53
- const nameForConfig = result.accountName
54
- .toLowerCase()
55
- .split(' ')
56
- .join('-');
57
- validName = nameForConfig;
58
- const invalidAccountName = accountNameExistsInConfig(nameForConfig);
59
- if (invalidAccountName) {
60
- if (!force) {
61
- logger.log('');
62
- logger.warn(
63
- i18n(
64
- `cli.lib.prompts.enterAccountNamePrompt.errors.accountNameExists`,
65
- { name: nameForConfig }
66
- )
67
- );
68
- const { name: promptName } = await enterAccountNamePrompt(
69
- nameForConfig + `_${result.id}`
70
- );
71
- validName = promptName;
72
- } else {
73
- // Basic invalid name handling when force flag is passed
74
- validName = nameForConfig + `_${result.id}`;
75
- }
76
- }
77
- }
78
-
79
- updateAccountConfig({
80
- ...updatedConfig,
81
- environment: updatedConfig.env,
82
- tokenInfo: updatedConfig.auth.tokenInfo,
83
- name: validName,
84
- });
85
- writeConfig();
86
-
87
- logger.log('');
88
- return validName;
89
- };
90
-
91
- const buildDeveloperTestAccount = async ({
92
- name,
93
- accountConfig,
94
- env,
95
- maxTestPortals,
96
- force = false,
97
- }) => {
98
- SpinniesManager.init({
99
- succeedColor: 'white',
100
- });
101
- const accountId = getAccountId(accountConfig.portalId);
102
-
103
- let result;
104
- const spinniesI18nKey = `${i18nKey}.create.loading`;
105
-
106
- try {
107
- logger.log('');
108
- SpinniesManager.add('devTestAcctCreate', {
109
- text: i18n(`${spinniesI18nKey}.add`, {
110
- accountName: name,
111
- }),
112
- });
113
- result = await createDeveloperTestAccount(accountId, name);
114
-
115
- SpinniesManager.succeed('devTestAcctCreate', {
116
- text: i18n(`${spinniesI18nKey}.succeed`, {
117
- name: result.accountName,
118
- accountId: result.id,
119
- }),
120
- });
121
- } catch (err) {
122
- debugErrorAndContext(err);
123
-
124
- SpinniesManager.fail('devTestAcctCreate', {
125
- text: i18n(`${spinniesI18nKey}.fail`, {
126
- accountName: name,
127
- }),
128
- });
129
-
130
- if (isMissingScopeError(err)) {
131
- logger.error(
132
- i18n(`${i18nKey}.create.failure.scopes.message`, {
133
- accountName: uiAccountDescription(accountId),
134
- })
135
- );
136
- const websiteOrigin = getHubSpotWebsiteOrigin(env);
137
- const url = `${websiteOrigin}/personal-access-key/${accountId}`;
138
- logger.info(
139
- i18n(`${i18nKey}.create.failure.scopes.instructions`, {
140
- accountName: uiAccountDescription(accountId),
141
- url,
142
- })
143
- );
144
- } else if (
145
- isSpecifiedError(err, {
146
- statusCode: 400,
147
- errorType: 'TEST_PORTAL_LIMIT_REACHED',
148
- })
149
- ) {
150
- logger.log('');
151
- logger.error(
152
- i18n(`${i18nKey}.create.failure.limit`, {
153
- accountName: uiAccountDescription(accountId),
154
- limit: maxTestPortals,
155
- })
156
- );
157
- logger.log('');
158
- } else {
159
- logErrorInstance(err);
160
- }
161
- throw err;
162
- }
163
-
164
- let devTestAcctConfigName;
165
-
166
- try {
167
- // Response contains PAK, save to config here
168
- devTestAcctConfigName = await saveDevTestAccountToConfig(
169
- env,
170
- result,
171
- force
172
- );
173
- } catch (err) {
174
- logErrorInstance(err);
175
- throw err;
176
- }
177
-
178
- return {
179
- devTestAcctConfigName,
180
- result,
181
- };
182
- };
183
-
184
- module.exports = {
185
- buildDeveloperTestAccount,
186
- };
@@ -1,29 +0,0 @@
1
- const { promptUser } = require('./promptUtils');
2
- const { i18n } = require('../lang');
3
- const { accountNameExistsInConfig } = require('@hubspot/local-dev-lib/config');
4
-
5
- const i18nKey = 'cli.lib.prompts.developerTestAccountPrompt';
6
-
7
- const developerTestAccountNamePrompt = currentPortalCount => {
8
- return promptUser([
9
- {
10
- name: 'name',
11
- message: i18n(`${i18nKey}.name.message`),
12
- validate(val) {
13
- if (typeof val !== 'string') {
14
- return i18n(`${i18nKey}.name.errors.invalidName`);
15
- } else if (!val.length) {
16
- return i18n(`${i18nKey}.name.errors.nameRequired`);
17
- }
18
- return accountNameExistsInConfig(val)
19
- ? i18n(`${i18nKey}.name.errors.accountNameExists`, { name: val })
20
- : true;
21
- },
22
- default: `Developer test account ${currentPortalCount + 1}`,
23
- },
24
- ]);
25
- };
26
-
27
- module.exports = {
28
- developerTestAccountNamePrompt,
29
- };
@@ -1,33 +0,0 @@
1
- const { accountNameExistsInConfig } = require('@hubspot/local-dev-lib/config');
2
- const { STRING_WITH_NO_SPACES_REGEX } = require('../regex');
3
- const { promptUser } = require('./promptUtils');
4
- const { i18n } = require('../lang');
5
-
6
- const i18nKey = 'cli.lib.prompts.enterAccountNamePrompt';
7
-
8
- const accountNamePrompt = defaultName => ({
9
- name: 'name',
10
- message: i18n(`${i18nKey}.enterAccountName`),
11
- default: defaultName,
12
- validate(val) {
13
- if (typeof val !== 'string') {
14
- return i18n(`${i18nKey}.errors.invalidName`);
15
- } else if (!val.length) {
16
- return i18n(`${i18nKey}.errors.nameRequired`);
17
- } else if (!STRING_WITH_NO_SPACES_REGEX.test(val)) {
18
- return i18n(`${i18nKey}.errors.spacesInName`);
19
- }
20
- return accountNameExistsInConfig(val)
21
- ? i18n(`${i18nKey}.errors.accountNameExists`, { name: val })
22
- : true;
23
- },
24
- });
25
-
26
- const enterAccountNamePrompt = defaultName => {
27
- return promptUser(accountNamePrompt(defaultName));
28
- };
29
-
30
- module.exports = {
31
- accountNamePrompt,
32
- enterAccountNamePrompt,
33
- };
@@ -1,319 +0,0 @@
1
- const SpinniesManager = require('./ui/SpinniesManager');
2
- const {
3
- getSandboxLimit,
4
- getHasSandboxesByType,
5
- sandboxApiTypeMap,
6
- } = require('./sandboxes');
7
- const { i18n } = require('./lang');
8
- const { logger } = require('@hubspot/local-dev-lib/logger');
9
- const {
10
- debugErrorAndContext,
11
- logErrorInstance,
12
- } = require('./errorHandlers/standardErrors');
13
- const {
14
- isMissingScopeError,
15
- isSpecifiedError,
16
- } = require('@hubspot/local-dev-lib/errors/apiErrors');
17
- const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
18
- const { getEnv, getAccountId } = require('@hubspot/local-dev-lib/config');
19
- const { createSandbox } = require('@hubspot/local-dev-lib/sandboxes');
20
- const { getValidEnv } = require('@hubspot/local-dev-lib/environment');
21
- const {
22
- getAccessToken,
23
- updateConfigWithAccessToken,
24
- } = require('@hubspot/local-dev-lib/personalAccessKey');
25
- const { uiAccountDescription } = require('./ui');
26
- const {
27
- personalAccessKeyPrompt,
28
- } = require('./prompts/personalAccessKeyPrompt');
29
- const { enterAccountNamePrompt } = require('./prompts/enterAccountNamePrompt');
30
- const {
31
- accountNameExistsInConfig,
32
- writeConfig,
33
- updateAccountConfig,
34
- } = require('@hubspot/local-dev-lib/config');
35
- const {
36
- HUBSPOT_ACCOUNT_TYPES,
37
- } = require('@hubspot/local-dev-lib/constants/config');
38
-
39
- const i18nKey = 'cli.lib.sandbox.create';
40
-
41
- /**
42
- * @param {String} env - Environment (QA/Prod)
43
- * @param {Object} result - Sandbox instance returned from API
44
- * @param {Boolean} force - Force flag to skip prompt
45
- * @returns {String} validName saved into config
46
- */
47
- const saveSandboxToConfig = async (env, result, force = false) => {
48
- let personalAccessKey = result.personalAccessKey;
49
- if (!personalAccessKey) {
50
- const configData = await personalAccessKeyPrompt({
51
- env,
52
- account: result.sandbox.sandboxHubId,
53
- });
54
- personalAccessKey = configData.personalAccessKey;
55
- }
56
-
57
- let updatedConfig;
58
-
59
- try {
60
- const token = await getAccessToken(personalAccessKey, env);
61
- updatedConfig = await updateConfigWithAccessToken(
62
- token,
63
- personalAccessKey,
64
- env
65
- );
66
- } catch (e) {
67
- logErrorInstance(e);
68
- }
69
-
70
- if (!updatedConfig) {
71
- throw new Error('Failed to update config with personal access key.');
72
- }
73
-
74
- let validName = updatedConfig.name;
75
- if (!updatedConfig.name) {
76
- const nameForConfig = result.sandbox.name
77
- .toLowerCase()
78
- .split(' ')
79
- .join('-');
80
- validName = nameForConfig;
81
- const invalidAccountName = accountNameExistsInConfig(nameForConfig);
82
- if (invalidAccountName) {
83
- if (!force) {
84
- logger.log('');
85
- logger.warn(
86
- i18n(
87
- `cli.lib.prompts.enterAccountNamePrompt.errors.accountNameExists`,
88
- { name: nameForConfig }
89
- )
90
- );
91
- const { name: promptName } = await enterAccountNamePrompt(
92
- nameForConfig + `_${result.sandbox.sandboxHubId}`
93
- );
94
- validName = promptName;
95
- } else {
96
- // Basic invalid name handling when force flag is passed
97
- validName = nameForConfig + `_${result.sandbox.sandboxHubId}`;
98
- }
99
- }
100
- }
101
- updateAccountConfig({
102
- ...updatedConfig,
103
- environment: updatedConfig.env,
104
- tokenInfo: updatedConfig.auth.tokenInfo,
105
- name: validName,
106
- });
107
- writeConfig();
108
-
109
- logger.log('');
110
- return validName;
111
- };
112
-
113
- /**
114
- * @param {String} name - Name of sandbox
115
- * @param {String} type - Sandbox type to be created (STANDARD_SANDBOX/DEVELOPMENT_SANDBOX)
116
- * @param {Object} accountConfig - Account config of parent portal
117
- * @param {String} env - Environment (QA/Prod)
118
- * @returns {Object} Object containing sandboxConfigName string and sandbox instance from API
119
- */
120
- const buildSandbox = async ({
121
- name,
122
- type,
123
- accountConfig,
124
- env,
125
- force = false,
126
- }) => {
127
- SpinniesManager.init({
128
- succeedColor: 'white',
129
- });
130
- const accountId = getAccountId(accountConfig.portalId);
131
-
132
- let result;
133
- const loadingLangKey =
134
- type === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX
135
- ? 'developer'
136
- : 'standard';
137
- const spinniesI18nKey = `${i18nKey}.loading.${loadingLangKey}`;
138
-
139
- try {
140
- logger.log('');
141
- SpinniesManager.add('sandboxCreate', {
142
- text: i18n(`${spinniesI18nKey}.add`, {
143
- sandboxName: name,
144
- }),
145
- });
146
- const sandboxApiType = sandboxApiTypeMap[type]; // API expects sandbox type as 1 or 2
147
- result = await createSandbox(accountId, name, sandboxApiType);
148
-
149
- SpinniesManager.succeed('sandboxCreate', {
150
- text: i18n(`${spinniesI18nKey}.succeed`, {
151
- name: result.sandbox.name,
152
- sandboxHubId: result.sandbox.sandboxHubId,
153
- }),
154
- });
155
- } catch (err) {
156
- debugErrorAndContext(err);
157
-
158
- SpinniesManager.fail('sandboxCreate', {
159
- text: i18n(`${spinniesI18nKey}.fail`, {
160
- sandboxName: name,
161
- }),
162
- });
163
-
164
- if (isMissingScopeError(err)) {
165
- logger.error(
166
- i18n(`${i18nKey}.failure.scopes.message`, {
167
- accountName: uiAccountDescription(accountId),
168
- })
169
- );
170
- const websiteOrigin = getHubSpotWebsiteOrigin(env);
171
- const url = `${websiteOrigin}/personal-access-key/${accountId}`;
172
- logger.info(
173
- i18n(`${i18nKey}.failure.scopes.instructions`, {
174
- accountName: uiAccountDescription(accountId),
175
- url,
176
- })
177
- );
178
- } else if (
179
- isSpecifiedError(err, {
180
- statusCode: 403,
181
- category: 'BANNED',
182
- subCategory: 'SandboxErrors.USER_ACCESS_NOT_ALLOWED',
183
- })
184
- ) {
185
- logger.log('');
186
- logger.error(
187
- i18n(`${i18nKey}.failure.invalidUser`, {
188
- accountName: name,
189
- parentAccountName: uiAccountDescription(accountId),
190
- })
191
- );
192
- logger.log('');
193
- } else if (
194
- isSpecifiedError(err, {
195
- statusCode: 403,
196
- category: 'BANNED',
197
- subCategory: 'SandboxErrors.DEVELOPMENT_SANDBOX_ACCESS_NOT_ALLOWED',
198
- })
199
- ) {
200
- logger.log('');
201
- logger.error(
202
- i18n(`${i18nKey}.failure.403Gating`, {
203
- accountName: name,
204
- parentAccountName: uiAccountDescription(accountId),
205
- accountId,
206
- })
207
- );
208
- logger.log('');
209
- } else if (
210
- isSpecifiedError(err, {
211
- statusCode: 400,
212
- category: 'VALIDATION_ERROR',
213
- subCategory:
214
- 'SandboxErrors.NUM_DEVELOPMENT_SANDBOXES_LIMIT_EXCEEDED_ERROR',
215
- }) &&
216
- err.error &&
217
- err.error.message
218
- ) {
219
- logger.log('');
220
- const devSandboxLimit = getSandboxLimit(err.error);
221
- const plural = devSandboxLimit !== 1;
222
- const hasDevelopmentSandboxes = getHasSandboxesByType(
223
- accountConfig,
224
- HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX
225
- );
226
- if (hasDevelopmentSandboxes) {
227
- logger.error(
228
- i18n(
229
- `${i18nKey}.failure.alreadyInConfig.developer.${
230
- plural ? 'other' : 'one'
231
- }`,
232
- {
233
- accountName: uiAccountDescription(accountId),
234
- limit: devSandboxLimit,
235
- }
236
- )
237
- );
238
- } else {
239
- const baseUrl = getHubSpotWebsiteOrigin(getValidEnv(getEnv(accountId)));
240
- logger.error(
241
- i18n(
242
- `${i18nKey}.failure.limit.developer.${plural ? 'other' : 'one'}`,
243
- {
244
- accountName: uiAccountDescription(accountId),
245
- limit: devSandboxLimit,
246
- link: `${baseUrl}/sandboxes-developer/${accountId}/development`,
247
- }
248
- )
249
- );
250
- }
251
- logger.log('');
252
- } else if (
253
- isSpecifiedError(err, {
254
- statusCode: 400,
255
- category: 'VALIDATION_ERROR',
256
- subCategory:
257
- 'SandboxErrors.NUM_STANDARD_SANDBOXES_LIMIT_EXCEEDED_ERROR',
258
- }) &&
259
- err.error &&
260
- err.error.message
261
- ) {
262
- logger.log('');
263
- const standardSandboxLimit = getSandboxLimit(err.error);
264
- const plural = standardSandboxLimit !== 1;
265
- const hasStandardSandboxes = getHasSandboxesByType(
266
- accountConfig,
267
- HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX
268
- );
269
- if (hasStandardSandboxes) {
270
- logger.error(
271
- i18n(
272
- `${i18nKey}.failure.alreadyInConfig.standard.${
273
- plural ? 'other' : 'one'
274
- }`,
275
- {
276
- accountName: uiAccountDescription(accountId),
277
- limit: standardSandboxLimit,
278
- }
279
- )
280
- );
281
- } else {
282
- const baseUrl = getHubSpotWebsiteOrigin(getValidEnv(getEnv(accountId)));
283
- logger.error(
284
- i18n(
285
- `${i18nKey}.failure.limit.standard.${plural ? 'other' : 'one'}`,
286
- {
287
- accountName: uiAccountDescription(accountId),
288
- limit: standardSandboxLimit,
289
- link: `${baseUrl}/sandboxes-developer/${accountId}/standard`,
290
- }
291
- )
292
- );
293
- }
294
- logger.log('');
295
- } else {
296
- logErrorInstance(err);
297
- }
298
- throw err;
299
- }
300
-
301
- let sandboxConfigName;
302
-
303
- try {
304
- // Response contains PAK, save to config here
305
- sandboxConfigName = await saveSandboxToConfig(env, result, force);
306
- } catch (err) {
307
- logErrorInstance(err);
308
- throw err;
309
- }
310
-
311
- return {
312
- sandboxConfigName,
313
- result,
314
- };
315
- };
316
-
317
- module.exports = {
318
- buildSandbox,
319
- };