@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 +2 -0
- package/commands/accounts/use.js +9 -26
- package/commands/cms/lighthouseScore.js +322 -0
- package/commands/cms.js +16 -0
- package/commands/fetch.js +7 -0
- package/commands/sandbox/create.js +27 -18
- package/commands/sandbox/delete.js +128 -5
- package/lib/prompts/accountsPrompt.js +47 -0
- package/lib/prompts/sandboxesPrompt.js +19 -0
- package/lib/validation.js +7 -2
- package/package.json +4 -4
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)
|
package/commands/accounts/use.js
CHANGED
|
@@ -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(
|
|
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
|
+
};
|
package/commands/cms.js
ADDED
|
@@ -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
|
@@ -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
|
-
|
|
134
|
-
({
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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
|
+
"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.
|
|
12
|
-
"@hubspot/serverless-dev-runtime": "4.0.1-beta.
|
|
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": "
|
|
40
|
+
"gitHead": "38cd22d1d1a3d8d06d65dfb40ba4d6b3b659e205"
|
|
41
41
|
}
|