@hubspot/cli 4.0.1-beta.3 → 4.0.1-beta.4

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.
package/bin/cli.js CHANGED
@@ -35,6 +35,7 @@ const moduleCommand = require('../commands/module');
35
35
  const configCommand = require('../commands/config');
36
36
  const accountsCommand = require('../commands/accounts');
37
37
  const sandboxesCommand = require('../commands/sandbox');
38
+ const cmsCommand = require('../commands/cms');
38
39
  const { EXIT_CODES } = require('../lib/enums/exitCodes');
39
40
 
40
41
  const notifier = updateNotifier({ pkg: { ...pkg, name: '@hubspot/cli' } });
@@ -129,6 +130,7 @@ const argv = yargs
129
130
  .command(authCommand)
130
131
  .command(initCommand)
131
132
  .command(logsCommand)
133
+ .command(cmsCommand)
132
134
  .command(lintCommand)
133
135
  .command(hubdbCommand)
134
136
  .command(watchCommand)
@@ -5,47 +5,24 @@ const {
5
5
  updateDefaultAccount,
6
6
  getAccountId: getAccountIdFromConfig,
7
7
  } = require('@hubspot/cli-lib/lib/config');
8
- const { loadAndValidateOptions } = require('../../lib/validation');
9
8
 
10
- const { getAccountId } = require('../../lib/commonOpts');
11
9
  const { trackCommandUsage } = require('../../lib/usageTracking');
12
- const { promptUser } = require('../../lib/prompts/promptUtils');
13
10
  const { i18n } = require('@hubspot/cli-lib/lib/lang');
11
+ const { selectAccountFromConfig } = require('../../lib/prompts/accountsPrompt');
12
+ const { loadAndValidateOptions } = require('../../lib/validation');
14
13
 
15
14
  const i18nKey = 'cli.commands.accounts.subcommands.use';
16
15
 
17
- const selectAccountFromConfig = async config => {
18
- const { default: selectedDefault } = await promptUser([
19
- {
20
- type: 'list',
21
- look: false,
22
- name: 'default',
23
- pageSize: 20,
24
- message: i18n(`${i18nKey}.promptMessage`),
25
- choices: config.portals.map(p => ({
26
- name: `${p.name} (${p.portalId})`,
27
- value: p.name || p.portalId,
28
- })),
29
- default: config.defaultPortal,
30
- },
31
- ]);
32
-
33
- return selectedDefault;
34
- };
35
-
36
16
  exports.command = 'use [--account]';
37
17
  exports.describe = i18n(`${i18nKey}.describe`);
38
18
 
39
19
  exports.handler = async options => {
40
- await loadAndValidateOptions({ debug: options.debug });
20
+ await loadAndValidateOptions(options, false);
41
21
 
42
- const accountId = getAccountId(options);
43
22
  const config = getConfig();
44
23
 
45
24
  let newDefaultAccount = options.account;
46
25
 
47
- trackCommandUsage('accounts-use', {}, accountId);
48
-
49
26
  if (!newDefaultAccount) {
50
27
  newDefaultAccount = await selectAccountFromConfig(config);
51
28
  } else if (!getAccountIdFromConfig(newDefaultAccount)) {
@@ -58,6 +35,12 @@ exports.handler = async options => {
58
35
  newDefaultAccount = await selectAccountFromConfig(config);
59
36
  }
60
37
 
38
+ trackCommandUsage(
39
+ 'accounts-use',
40
+ {},
41
+ getAccountIdFromConfig(newDefaultAccount)
42
+ );
43
+
61
44
  updateDefaultAccount(newDefaultAccount);
62
45
 
63
46
  return logger.success(
@@ -0,0 +1,322 @@
1
+ //const chalk = require('chalk');
2
+ const Spinnies = require('spinnies');
3
+ const {
4
+ addAccountOptions,
5
+ addConfigOptions,
6
+ addUseEnvironmentOptions,
7
+ getAccountId,
8
+ } = require('../../lib/commonOpts');
9
+ const { logger } = require('@hubspot/cli-lib/logger');
10
+ const {
11
+ getTableContents,
12
+ getTableHeader,
13
+ } = require('@hubspot/cli-lib/lib/table');
14
+ const { loadAndValidateOptions } = require('../../lib/validation');
15
+ const { promptUser } = require('../../lib/prompts/promptUtils');
16
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
17
+ const { fetchThemes } = require('@hubspot/cli-lib/api/designManager');
18
+ const {
19
+ requestLighthouseScore,
20
+ getLighthouseScoreStatus,
21
+ getLighthouseScore,
22
+ } = require('@hubspot/cli-lib/api/lighthouseScore');
23
+ const {
24
+ HUBSPOT_FOLDER,
25
+ MARKETPLACE_FOLDER,
26
+ } = require('@hubspot/cli-lib/lib/constants');
27
+ const { uiLink } = require('../../lib/ui');
28
+ const { EXIT_CODES } = require('../../lib/enums/exitCodes');
29
+
30
+ const i18nKey = 'cli.commands.cms.subcommands.lighthouseScore';
31
+
32
+ const DEFAULT_TABLE_HEADER = [
33
+ 'Accessibility',
34
+ 'Best practices',
35
+ 'Performace',
36
+ 'PWA',
37
+ 'SEO',
38
+ ];
39
+
40
+ exports.command = 'lighthouse-score [--theme]';
41
+ exports.describe = i18n(`${i18nKey}.describe`);
42
+
43
+ const selectTheme = async accountId => {
44
+ const { theme: selectedTheme } = await promptUser([
45
+ {
46
+ type: 'list',
47
+ look: false,
48
+ name: 'theme',
49
+ message: i18n(`${i18nKey}.info.promptMessage`),
50
+ choices: async () => {
51
+ try {
52
+ const result = await fetchThemes(accountId);
53
+ if (result && result.objects) {
54
+ return result.objects
55
+ .map(({ theme }) => theme.path)
56
+ .filter(
57
+ themePath =>
58
+ !themePath.startsWith(HUBSPOT_FOLDER) &&
59
+ !themePath.startsWith(MARKETPLACE_FOLDER)
60
+ );
61
+ }
62
+ } catch (err) {
63
+ logger.error(i18n(`${i18nKey}.errors.failedToFetchThemes`));
64
+ process.exit(EXIT_CODES.ERROR);
65
+ }
66
+ },
67
+ },
68
+ ]);
69
+
70
+ return selectedTheme;
71
+ };
72
+
73
+ exports.handler = async options => {
74
+ await loadAndValidateOptions(options);
75
+ const accountId = getAccountId(options);
76
+
77
+ const includeDesktopScore = options.target === 'desktop' || !options.verbose;
78
+ const includeMobileScore = options.target === 'mobile' || !options.verbose;
79
+ let themeToCheck = options.theme;
80
+
81
+ if (themeToCheck) {
82
+ let isValidTheme = true;
83
+ try {
84
+ const result = await fetchThemes(accountId, {
85
+ name: encodeURIComponent(themeToCheck),
86
+ });
87
+ isValidTheme = result && result.total;
88
+ } catch (err) {
89
+ isValidTheme = false;
90
+ }
91
+ if (!isValidTheme) {
92
+ logger.error(
93
+ i18n(`${i18nKey}.errors.themeNotFound`, { theme: themeToCheck })
94
+ );
95
+ process.exit(EXIT_CODES.ERROR);
96
+ }
97
+ } else {
98
+ themeToCheck = await selectTheme(accountId);
99
+ logger.log();
100
+ }
101
+
102
+ // Kick off the scoring
103
+ let requestResult;
104
+ try {
105
+ requestResult = await requestLighthouseScore(accountId, {
106
+ themePath: themeToCheck,
107
+ });
108
+ } catch (err) {
109
+ logger.debug(err);
110
+ }
111
+
112
+ if (!requestResult || !requestResult.mobileId || !requestResult.desktopId) {
113
+ logger.error(i18n(`${i18nKey}.errors.failedToGetLighthouseScore`));
114
+ process.exit(EXIT_CODES.ERROR);
115
+ }
116
+
117
+ // Poll till scoring is finished
118
+ try {
119
+ const spinnies = new Spinnies();
120
+
121
+ spinnies.add('lighthouseScore', {
122
+ text: i18n(`${i18nKey}.info.generatingScore`, { theme: themeToCheck }),
123
+ });
124
+
125
+ const checkScoreStatus = async () => {
126
+ const desktopScoreStatus = includeDesktopScore
127
+ ? await getLighthouseScoreStatus(accountId, {
128
+ themeId: requestResult.desktopId,
129
+ })
130
+ : 'COMPLETED';
131
+ const mobileScoreStatus = includeMobileScore
132
+ ? await getLighthouseScoreStatus(accountId, {
133
+ themeId: requestResult.mobileId,
134
+ })
135
+ : 'COMPLETED';
136
+
137
+ if (
138
+ desktopScoreStatus === 'REQUESTED' ||
139
+ mobileScoreStatus === 'REQUESTED'
140
+ ) {
141
+ await new Promise(resolve => setTimeout(resolve, 2000));
142
+ await checkScoreStatus();
143
+ }
144
+ };
145
+
146
+ await checkScoreStatus();
147
+
148
+ spinnies.remove('lighthouseScore');
149
+ } catch (err) {
150
+ logger.debug(err);
151
+ process.exit(EXIT_CODES.ERROR);
152
+ }
153
+
154
+ // Fetch the scoring results
155
+ let desktopScoreResult;
156
+ let mobileScoreResult;
157
+ let verboseViewAverageScoreResult;
158
+ try {
159
+ const params = { isAverage: !options.verbose };
160
+ desktopScoreResult = includeDesktopScore
161
+ ? await getLighthouseScore(accountId, {
162
+ ...params,
163
+ desktopId: requestResult.desktopId,
164
+ })
165
+ : {};
166
+ mobileScoreResult = includeMobileScore
167
+ ? await getLighthouseScore(accountId, {
168
+ ...params,
169
+ mobileId: requestResult.mobileId,
170
+ })
171
+ : {};
172
+ // This is needed to show the average scores above the verbose output
173
+ verboseViewAverageScoreResult = options.verbose
174
+ ? await getLighthouseScore(accountId, {
175
+ ...params,
176
+ isAverage: true,
177
+ desktopId: includeDesktopScore ? requestResult.desktopId : null,
178
+ mobileId: includeMobileScore ? requestResult.mobileId : null,
179
+ })
180
+ : {};
181
+ } catch (err) {
182
+ logger.error(i18n(`${i18nKey}.errors.failedToGetLighthouseScore`));
183
+ process.exit(EXIT_CODES.ERROR);
184
+ }
185
+
186
+ if (options.verbose) {
187
+ logger.log(`${themeToCheck} ${options.target} scores`);
188
+
189
+ const tableHeader = getTableHeader(DEFAULT_TABLE_HEADER);
190
+
191
+ const scores = verboseViewAverageScoreResult.scores
192
+ ? verboseViewAverageScoreResult.scores[0]
193
+ : {};
194
+
195
+ const averageTableData = [
196
+ scores.accessibilityScore,
197
+ scores.bestPracticesScore,
198
+ scores.performanceScore,
199
+ scores.pwaScore,
200
+ scores.seoScore,
201
+ ];
202
+
203
+ logger.log(
204
+ getTableContents([tableHeader, averageTableData], {
205
+ border: { bodyLeft: ' ' },
206
+ })
207
+ );
208
+ logger.log(i18n(`${i18nKey}.info.pageTemplateScoreTitle`));
209
+
210
+ const table2Header = getTableHeader([
211
+ 'Template path',
212
+ ...DEFAULT_TABLE_HEADER,
213
+ ]);
214
+
215
+ const scoreResult =
216
+ options.target === 'desktop' ? desktopScoreResult : mobileScoreResult;
217
+
218
+ const templateTableData = scoreResult.scores.map(score => {
219
+ return [
220
+ score.templatePath,
221
+ score.accessibilityScore,
222
+ score.bestPracticesScore,
223
+ score.performanceScore,
224
+ score.pwaScore,
225
+ score.seoScore,
226
+ ];
227
+ });
228
+
229
+ logger.log(
230
+ getTableContents([table2Header, ...templateTableData], {
231
+ border: { bodyLeft: ' ' },
232
+ })
233
+ );
234
+
235
+ logger.log(i18n(`${i18nKey}.info.lighthouseLinksTitle`));
236
+
237
+ scoreResult.scores.forEach(score => {
238
+ logger.log(' ', uiLink(score.templatePath, score.link));
239
+ });
240
+
241
+ if (scoreResult.failedTemplatePaths.length) {
242
+ logger.log();
243
+ logger.error(i18n(`${i18nKey}.info.failedTemplatePathsTitle`));
244
+ scoreResult.failedTemplatePaths.forEach(failedTemplatePath => {
245
+ logger.log(' ', failedTemplatePath);
246
+ });
247
+ }
248
+
249
+ logger.log();
250
+ logger.info(
251
+ i18n(`${i18nKey}.info.targetDeviceNote`, { target: options.target })
252
+ );
253
+ } else {
254
+ logger.log(`Theme: ${themeToCheck}`);
255
+ const tableHeader = getTableHeader(['Target', ...DEFAULT_TABLE_HEADER]);
256
+
257
+ const getTableData = (target, scoreResult) => {
258
+ const scores = scoreResult.scores ? scoreResult.scores[0] : {};
259
+ return [
260
+ target,
261
+ scores.accessibilityScore,
262
+ scores.bestPracticesScore,
263
+ scores.performanceScore,
264
+ scores.pwaScore,
265
+ scores.seoScore,
266
+ ];
267
+ };
268
+
269
+ const tableData = [
270
+ getTableData('desktop', desktopScoreResult),
271
+ getTableData('mobile', mobileScoreResult),
272
+ ];
273
+
274
+ logger.log(
275
+ getTableContents([tableHeader, ...tableData], {
276
+ border: { bodyLeft: ' ' },
277
+ })
278
+ );
279
+
280
+ logger.info(i18n(`${i18nKey}.info.verboseOptionNote`));
281
+ }
282
+
283
+ logger.log();
284
+ logger.log(
285
+ `Powered by ${uiLink(
286
+ 'Google Lighthouse',
287
+ 'https://developer.chrome.com/docs/lighthouse/overview/'
288
+ )}.`
289
+ );
290
+
291
+ process.exit();
292
+ };
293
+
294
+ exports.builder = yargs => {
295
+ yargs.option('theme', {
296
+ describe: i18n(`${i18nKey}.options.theme.describe`),
297
+ type: 'string',
298
+ });
299
+ yargs.option('target', {
300
+ describe: i18n(`${i18nKey}.options.target.describe`),
301
+ type: 'string',
302
+ choices: ['desktop', 'mobile'],
303
+ default: 'desktop',
304
+ });
305
+ yargs.option('verbose', {
306
+ describe: i18n(`${i18nKey}.options.verbose.describe`),
307
+ boolean: true,
308
+ default: false,
309
+ });
310
+ yargs.example([
311
+ [
312
+ '$0 cms lighthouse-score --theme=my-theme',
313
+ i18n(`${i18nKey}.examples.default`),
314
+ ],
315
+ ]);
316
+
317
+ addConfigOptions(yargs, true);
318
+ addAccountOptions(yargs, true);
319
+ addUseEnvironmentOptions(yargs, true);
320
+
321
+ return yargs;
322
+ };
@@ -0,0 +1,16 @@
1
+ const { addConfigOptions, addAccountOptions } = require('../lib/commonOpts');
2
+ const lighthouseScore = require('./cms/lighthouseScore');
3
+
4
+ // const i18nKey = 'cli.commands.cms';
5
+
6
+ exports.command = 'cms';
7
+ exports.describe = false; // i18n(`${i18nKey}.describe`);
8
+
9
+ exports.builder = yargs => {
10
+ addConfigOptions(yargs, true);
11
+ addAccountOptions(yargs, true);
12
+
13
+ yargs.command(lighthouseScore).demandCommand(1, '');
14
+
15
+ return yargs;
16
+ };
package/commands/fetch.js CHANGED
@@ -76,5 +76,12 @@ exports.builder = yargs => {
76
76
  },
77
77
  });
78
78
 
79
+ yargs.options({
80
+ assetVersion: {
81
+ type: 'number',
82
+ describe: i18n(`${i18nKey}.options.assetVersion.describe`),
83
+ },
84
+ });
85
+
79
86
  return yargs;
80
87
  };
@@ -7,7 +7,7 @@ const {
7
7
  } = require('../../lib/commonOpts');
8
8
  const { trackCommandUsage } = require('../../lib/usageTracking');
9
9
  const { logger } = require('@hubspot/cli-lib/logger');
10
-
10
+ const Spinnies = require('spinnies');
11
11
  const { createSandbox } = require('@hubspot/cli-lib/sandboxes');
12
12
  const { loadAndValidateOptions } = require('../../lib/validation');
13
13
  const { createSandboxPrompt } = require('../../lib/prompts/sandboxesPrompt');
@@ -113,6 +113,10 @@ exports.handler = async options => {
113
113
  const accountId = getAccountId(options);
114
114
  const accountConfig = getAccountConfig(accountId);
115
115
  const env = options.qa ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD;
116
+ const spinnies = new Spinnies({
117
+ succeedColor: 'white',
118
+ });
119
+
116
120
  let namePrompt;
117
121
 
118
122
  trackCommandUsage('sandbox-create', {}, accountId);
@@ -123,26 +127,30 @@ exports.handler = async options => {
123
127
 
124
128
  const sandboxName = name || namePrompt.name;
125
129
 
126
- logger.debug(
127
- i18n(`${i18nKey}.debug.creating`, {
128
- name: sandboxName,
129
- })
130
- );
131
130
  let result;
131
+
132
132
  try {
133
- result = await createSandbox(accountId, sandboxName).then(
134
- ({ name, sandboxHubId }) => {
135
- logger.log('');
136
- logger.success(
137
- i18n(`${i18nKey}.success.create`, {
138
- name,
139
- sandboxHubId,
140
- })
141
- );
142
- return { name, sandboxHubId };
143
- }
144
- );
133
+ spinnies.add('sandboxCreate', {
134
+ text: i18n(`${i18nKey}.loading.add`, {
135
+ sandboxName,
136
+ }),
137
+ });
138
+
139
+ result = await createSandbox(accountId, sandboxName);
140
+
141
+ logger.log('');
142
+ spinnies.succeed('sandboxCreate', {
143
+ text: i18n(`${i18nKey}.loading.succeed`, {
144
+ name: result.name,
145
+ sandboxHubId: result.sandboxHubId,
146
+ }),
147
+ });
145
148
  } catch (err) {
149
+ spinnies.fail('sandboxCreate', {
150
+ text: i18n(`${i18nKey}.loading.fail`, {
151
+ sandboxName,
152
+ }),
153
+ });
146
154
  if (isMissingScopeError(err)) {
147
155
  logger.error(
148
156
  i18n(`${i18nKey}.failure.scopes.message`, {
@@ -167,6 +175,7 @@ exports.handler = async options => {
167
175
  process.exit(EXIT_CODES.SUCCESS);
168
176
  } catch (err) {
169
177
  logErrorInstance(err);
178
+ process.exit(EXIT_CODES.ERROR);
170
179
  }
171
180
  };
172
181
 
@@ -2,22 +2,144 @@ const {
2
2
  addAccountOptions,
3
3
  addConfigOptions,
4
4
  addUseEnvironmentOptions,
5
+ getAccountId,
6
+ addTestingOptions,
5
7
  } = require('../../lib/commonOpts');
6
8
  const { logger } = require('@hubspot/cli-lib/logger');
7
-
9
+ const { trackCommandUsage } = require('../../lib/usageTracking');
8
10
  const { loadAndValidateOptions } = require('../../lib/validation');
11
+
12
+ const { deleteSandbox } = require('@hubspot/cli-lib/sandboxes');
9
13
  const { i18n } = require('@hubspot/cli-lib/lib/lang');
14
+ const { getConfig, getEnv } = require('@hubspot/cli-lib');
15
+ const { deleteSandboxPrompt } = require('../../lib/prompts/sandboxesPrompt');
16
+ const { removeAccountFromConfig } = require('@hubspot/cli-lib/lib/config');
17
+ const {
18
+ selectAndSetAsDefaultAccountPrompt,
19
+ } = require('../../lib/prompts/accountsPrompt');
20
+ const { EXIT_CODES } = require('../../lib/enums/exitCodes');
21
+ const { promptUser } = require('../../lib/prompts/promptUtils');
22
+ const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
23
+ const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
10
24
 
11
25
  const i18nKey = 'cli.commands.sandbox.subcommands.delete';
12
26
 
13
- exports.command = 'delete';
27
+ const SANDBOX_NOT_FOUND = 'SandboxErrors.SANDBOX_NOT_FOUND';
28
+ const OBJECT_NOT_FOUND = 'OBJECT_NOT_FOUND';
29
+
30
+ exports.command = 'delete [--account]';
14
31
  exports.describe = i18n(`${i18nKey}.describe`);
15
32
 
16
33
  exports.handler = async options => {
17
- await loadAndValidateOptions(options);
34
+ await loadAndValidateOptions(options, false);
35
+
36
+ const { account } = options;
37
+ const config = getConfig();
38
+
39
+ let accountPrompt;
40
+ if (!account) {
41
+ accountPrompt = await deleteSandboxPrompt(config);
42
+ }
43
+ const sandboxAccountId = getAccountId({
44
+ account: account || accountPrompt.account,
45
+ });
46
+
47
+ trackCommandUsage('sandbox-delete', {}, sandboxAccountId);
48
+
49
+ let parentAccountId;
50
+ for (const portal of config.portals) {
51
+ if (portal.portalId === sandboxAccountId) {
52
+ if (portal.parentAccountId) {
53
+ parentAccountId = portal.parentAccountId;
54
+ } else {
55
+ const parentAccountPrompt = await deleteSandboxPrompt(config, true);
56
+ parentAccountId = getAccountId({
57
+ account: parentAccountPrompt.account,
58
+ });
59
+ }
60
+ }
61
+ }
62
+
63
+ if (!getAccountId({ account: parentAccountId })) {
64
+ const baseUrl = getHubSpotWebsiteOrigin(
65
+ getEnv(sandboxAccountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD
66
+ );
67
+ const url = `${baseUrl}/sandboxes/${parentAccountId}`;
68
+ const command = `hs auth ${
69
+ getEnv(sandboxAccountId) === 'qa' ? '--qa' : ''
70
+ } --account=${parentAccountId}`;
71
+ logger.log('');
72
+ logger.error(
73
+ i18n(`${i18nKey}.noParentPortalAvailable`, {
74
+ parentAccountId,
75
+ url,
76
+ command,
77
+ })
78
+ );
79
+ logger.log('');
80
+ process.exit(EXIT_CODES.ERROR);
81
+ }
82
+
83
+ logger.debug(
84
+ i18n(`${i18nKey}.debug.deleting`, {
85
+ account: account || accountPrompt.account,
86
+ })
87
+ );
88
+
89
+ try {
90
+ const { confirmSandboxDeletePrompt: confirmed } = await promptUser([
91
+ {
92
+ name: 'confirmSandboxDeletePrompt',
93
+ type: 'confirm',
94
+ message: i18n(`${i18nKey}.confirm`, {
95
+ account: account || accountPrompt.account,
96
+ }),
97
+ },
98
+ ]);
99
+ if (!confirmed) {
100
+ process.exit(EXIT_CODES.SUCCESS);
101
+ }
102
+
103
+ await deleteSandbox(parentAccountId, sandboxAccountId);
104
+
105
+ logger.log('');
106
+ logger.success(
107
+ i18n(`${i18nKey}.success.delete`, {
108
+ account: account || accountPrompt.account,
109
+ sandboxHubId: sandboxAccountId,
110
+ })
111
+ );
112
+ logger.log('');
113
+
114
+ const promptDefaultAccount = removeAccountFromConfig(sandboxAccountId);
115
+ if (promptDefaultAccount) {
116
+ await selectAndSetAsDefaultAccountPrompt(config);
117
+ }
118
+ process.exit(EXIT_CODES.SUCCESS);
119
+ } catch (err) {
120
+ if (
121
+ err.error &&
122
+ err.error.category === OBJECT_NOT_FOUND &&
123
+ err.error.subCategory === SANDBOX_NOT_FOUND
124
+ ) {
125
+ logger.log('');
126
+ logger.warn(
127
+ i18n(`${i18nKey}.objectNotFound`, {
128
+ account: account || accountPrompt.account,
129
+ })
130
+ );
131
+ logger.log('');
18
132
 
19
- logger.log('');
20
- logger.log(i18n(`${i18nKey}.temporaryMessage`));
133
+ const promptDefaultAccount = removeAccountFromConfig(sandboxAccountId);
134
+ if (promptDefaultAccount) {
135
+ await selectAndSetAsDefaultAccountPrompt(config);
136
+ }
137
+ process.exit(EXIT_CODES.SUCCESS);
138
+ } else {
139
+ logger.error(err.error.message);
140
+ }
141
+ process.exit(EXIT_CODES.ERROR);
142
+ }
21
143
  };
22
144
 
23
145
  exports.builder = yargs => {
@@ -36,6 +158,7 @@ exports.builder = yargs => {
36
158
  addConfigOptions(yargs, true);
37
159
  addAccountOptions(yargs, true);
38
160
  addUseEnvironmentOptions(yargs, true);
161
+ addTestingOptions(yargs, true);
39
162
 
40
163
  return yargs;
41
164
  };
@@ -0,0 +1,47 @@
1
+ const { updateDefaultAccount } = require('@hubspot/cli-lib/lib/config');
2
+ const { promptUser } = require('./promptUtils');
3
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
4
+
5
+ const i18nKey = 'cli.commands.accounts.subcommands.use';
6
+
7
+ const selectAccountFromConfig = async config => {
8
+ const { default: selectedDefault } = await promptUser([
9
+ {
10
+ type: 'list',
11
+ look: false,
12
+ name: 'default',
13
+ pageSize: 20,
14
+ message: i18n(`${i18nKey}.promptMessage`),
15
+ choices: config.portals.map(p => ({
16
+ name: `${p.name} (${p.portalId})`,
17
+ value: p.name || p.portalId,
18
+ })),
19
+ default: config.defaultPortal,
20
+ },
21
+ ]);
22
+
23
+ return selectedDefault;
24
+ };
25
+
26
+ const selectAndSetAsDefaultAccountPrompt = async config => {
27
+ const { default: selectedDefault } = await promptUser([
28
+ {
29
+ type: 'list',
30
+ look: false,
31
+ name: 'default',
32
+ pageSize: 20,
33
+ message: i18n(`${i18nKey}.promptMessage`),
34
+ choices: config.portals.map(p => ({
35
+ name: `${p.name} (${p.portalId})`,
36
+ value: p.name || p.portalId,
37
+ })),
38
+ default: config.defaultPortal,
39
+ },
40
+ ]);
41
+ updateDefaultAccount(selectedDefault);
42
+ };
43
+
44
+ module.exports = {
45
+ selectAndSetAsDefaultAccountPrompt,
46
+ selectAccountFromConfig,
47
+ };
@@ -19,6 +19,25 @@ const createSandboxPrompt = () => {
19
19
  ]);
20
20
  };
21
21
 
22
+ const deleteSandboxPrompt = (config, promptParentAccount = false) => {
23
+ return promptUser([
24
+ {
25
+ name: 'account',
26
+ message: i18n(
27
+ promptParentAccount
28
+ ? `${i18nKey}.selectParentAccountName`
29
+ : `${i18nKey}.selectAccountName`
30
+ ),
31
+ type: 'list',
32
+ look: false,
33
+ pageSize: 20,
34
+ choices: config.portals.map(p => p.name || p.portalId),
35
+ default: config.defaultPortal,
36
+ },
37
+ ]);
38
+ };
39
+
22
40
  module.exports = {
23
41
  createSandboxPrompt,
42
+ deleteSandboxPrompt,
24
43
  };
package/lib/validation.js CHANGED
@@ -26,14 +26,19 @@ const fs = require('fs');
26
26
  const path = require('path');
27
27
  const { EXIT_CODES } = require('./enums/exitCodes');
28
28
 
29
- async function loadAndValidateOptions(options) {
29
+ async function loadAndValidateOptions(options, shouldValidateAccount = true) {
30
30
  setLogLevel(options);
31
31
  logDebugInfo(options);
32
32
  const { config: configPath } = options;
33
33
  loadConfig(configPath, options);
34
34
  checkAndWarnGitInclusion(getConfigPath());
35
35
 
36
- if (!(validateConfig() && (await validateAccount(options)))) {
36
+ let validAccount = true;
37
+ if (shouldValidateAccount) {
38
+ validAccount = await validateAccount(options);
39
+ }
40
+
41
+ if (!(validateConfig() && validAccount)) {
37
42
  process.exit(EXIT_CODES.ERROR);
38
43
  }
39
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "4.0.1-beta.3",
3
+ "version": "4.0.1-beta.4",
4
4
  "description": "CLI for working with HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -8,8 +8,8 @@
8
8
  "url": "https://github.com/HubSpot/hubspot-cms-tools"
9
9
  },
10
10
  "dependencies": {
11
- "@hubspot/cli-lib": "4.0.1-beta.3",
12
- "@hubspot/serverless-dev-runtime": "4.0.1-beta.3",
11
+ "@hubspot/cli-lib": "4.0.1-beta.4",
12
+ "@hubspot/serverless-dev-runtime": "4.0.1-beta.4",
13
13
  "archiver": "^5.3.0",
14
14
  "chalk": "^4.1.2",
15
15
  "express": "^4.17.1",
@@ -37,5 +37,5 @@
37
37
  "publishConfig": {
38
38
  "access": "public"
39
39
  },
40
- "gitHead": "e2fac76a5ea9f51f69dfb786a5f285ffcf88a47a"
40
+ "gitHead": "38cd22d1d1a3d8d06d65dfb40ba4d6b3b659e205"
41
41
  }