@hubspot/cli 4.0.1-beta.3 → 4.0.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.
- package/bin/cli.js +2 -0
- package/commands/accounts/use.js +9 -26
- package/commands/cms/lighthouseScore.js +325 -0
- package/commands/cms.js +16 -0
- package/commands/fetch.js +7 -0
- package/commands/init.js +3 -0
- package/commands/sandbox/create.js +43 -23
- package/commands/sandbox/delete.js +141 -5
- package/lib/projects.js +33 -18
- 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,325 @@
|
|
|
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
|
+
limit: 500,
|
|
54
|
+
sorting: 'MOST_USED',
|
|
55
|
+
});
|
|
56
|
+
if (result && result.objects) {
|
|
57
|
+
return result.objects
|
|
58
|
+
.map(({ theme }) => theme.path)
|
|
59
|
+
.filter(
|
|
60
|
+
themePath =>
|
|
61
|
+
!themePath.startsWith(HUBSPOT_FOLDER) &&
|
|
62
|
+
!themePath.startsWith(MARKETPLACE_FOLDER)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
} catch (err) {
|
|
66
|
+
logger.error(i18n(`${i18nKey}.errors.failedToFetchThemes`));
|
|
67
|
+
process.exit(EXIT_CODES.ERROR);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
return selectedTheme;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
exports.handler = async options => {
|
|
77
|
+
await loadAndValidateOptions(options);
|
|
78
|
+
const accountId = getAccountId(options);
|
|
79
|
+
|
|
80
|
+
const includeDesktopScore = options.target === 'desktop' || !options.verbose;
|
|
81
|
+
const includeMobileScore = options.target === 'mobile' || !options.verbose;
|
|
82
|
+
let themeToCheck = options.theme;
|
|
83
|
+
|
|
84
|
+
if (themeToCheck) {
|
|
85
|
+
let isValidTheme = true;
|
|
86
|
+
try {
|
|
87
|
+
const result = await fetchThemes(accountId, {
|
|
88
|
+
name: encodeURIComponent(themeToCheck),
|
|
89
|
+
});
|
|
90
|
+
isValidTheme = result && result.total;
|
|
91
|
+
} catch (err) {
|
|
92
|
+
isValidTheme = false;
|
|
93
|
+
}
|
|
94
|
+
if (!isValidTheme) {
|
|
95
|
+
logger.error(
|
|
96
|
+
i18n(`${i18nKey}.errors.themeNotFound`, { theme: themeToCheck })
|
|
97
|
+
);
|
|
98
|
+
process.exit(EXIT_CODES.ERROR);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
themeToCheck = await selectTheme(accountId);
|
|
102
|
+
logger.log();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Kick off the scoring
|
|
106
|
+
let requestResult;
|
|
107
|
+
try {
|
|
108
|
+
requestResult = await requestLighthouseScore(accountId, {
|
|
109
|
+
themePath: themeToCheck,
|
|
110
|
+
});
|
|
111
|
+
} catch (err) {
|
|
112
|
+
logger.debug(err);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!requestResult || !requestResult.mobileId || !requestResult.desktopId) {
|
|
116
|
+
logger.error(i18n(`${i18nKey}.errors.failedToGetLighthouseScore`));
|
|
117
|
+
process.exit(EXIT_CODES.ERROR);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Poll till scoring is finished
|
|
121
|
+
try {
|
|
122
|
+
const spinnies = new Spinnies();
|
|
123
|
+
|
|
124
|
+
spinnies.add('lighthouseScore', {
|
|
125
|
+
text: i18n(`${i18nKey}.info.generatingScore`, { theme: themeToCheck }),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const checkScoreStatus = async () => {
|
|
129
|
+
const desktopScoreStatus = includeDesktopScore
|
|
130
|
+
? await getLighthouseScoreStatus(accountId, {
|
|
131
|
+
themeId: requestResult.desktopId,
|
|
132
|
+
})
|
|
133
|
+
: 'COMPLETED';
|
|
134
|
+
const mobileScoreStatus = includeMobileScore
|
|
135
|
+
? await getLighthouseScoreStatus(accountId, {
|
|
136
|
+
themeId: requestResult.mobileId,
|
|
137
|
+
})
|
|
138
|
+
: 'COMPLETED';
|
|
139
|
+
|
|
140
|
+
if (
|
|
141
|
+
desktopScoreStatus === 'REQUESTED' ||
|
|
142
|
+
mobileScoreStatus === 'REQUESTED'
|
|
143
|
+
) {
|
|
144
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
145
|
+
await checkScoreStatus();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
await checkScoreStatus();
|
|
150
|
+
|
|
151
|
+
spinnies.remove('lighthouseScore');
|
|
152
|
+
} catch (err) {
|
|
153
|
+
logger.debug(err);
|
|
154
|
+
process.exit(EXIT_CODES.ERROR);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Fetch the scoring results
|
|
158
|
+
let desktopScoreResult;
|
|
159
|
+
let mobileScoreResult;
|
|
160
|
+
let verboseViewAverageScoreResult;
|
|
161
|
+
try {
|
|
162
|
+
const params = { isAverage: !options.verbose };
|
|
163
|
+
desktopScoreResult = includeDesktopScore
|
|
164
|
+
? await getLighthouseScore(accountId, {
|
|
165
|
+
...params,
|
|
166
|
+
desktopId: requestResult.desktopId,
|
|
167
|
+
})
|
|
168
|
+
: {};
|
|
169
|
+
mobileScoreResult = includeMobileScore
|
|
170
|
+
? await getLighthouseScore(accountId, {
|
|
171
|
+
...params,
|
|
172
|
+
mobileId: requestResult.mobileId,
|
|
173
|
+
})
|
|
174
|
+
: {};
|
|
175
|
+
// This is needed to show the average scores above the verbose output
|
|
176
|
+
verboseViewAverageScoreResult = options.verbose
|
|
177
|
+
? await getLighthouseScore(accountId, {
|
|
178
|
+
...params,
|
|
179
|
+
isAverage: true,
|
|
180
|
+
desktopId: includeDesktopScore ? requestResult.desktopId : null,
|
|
181
|
+
mobileId: includeMobileScore ? requestResult.mobileId : null,
|
|
182
|
+
})
|
|
183
|
+
: {};
|
|
184
|
+
} catch (err) {
|
|
185
|
+
logger.error(i18n(`${i18nKey}.errors.failedToGetLighthouseScore`));
|
|
186
|
+
process.exit(EXIT_CODES.ERROR);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (options.verbose) {
|
|
190
|
+
logger.log(`${themeToCheck} ${options.target} scores`);
|
|
191
|
+
|
|
192
|
+
const tableHeader = getTableHeader(DEFAULT_TABLE_HEADER);
|
|
193
|
+
|
|
194
|
+
const scores = verboseViewAverageScoreResult.scores
|
|
195
|
+
? verboseViewAverageScoreResult.scores[0]
|
|
196
|
+
: {};
|
|
197
|
+
|
|
198
|
+
const averageTableData = [
|
|
199
|
+
scores.accessibilityScore,
|
|
200
|
+
scores.bestPracticesScore,
|
|
201
|
+
scores.performanceScore,
|
|
202
|
+
scores.pwaScore,
|
|
203
|
+
scores.seoScore,
|
|
204
|
+
];
|
|
205
|
+
|
|
206
|
+
logger.log(
|
|
207
|
+
getTableContents([tableHeader, averageTableData], {
|
|
208
|
+
border: { bodyLeft: ' ' },
|
|
209
|
+
})
|
|
210
|
+
);
|
|
211
|
+
logger.log(i18n(`${i18nKey}.info.pageTemplateScoreTitle`));
|
|
212
|
+
|
|
213
|
+
const table2Header = getTableHeader([
|
|
214
|
+
'Template path',
|
|
215
|
+
...DEFAULT_TABLE_HEADER,
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
const scoreResult =
|
|
219
|
+
options.target === 'desktop' ? desktopScoreResult : mobileScoreResult;
|
|
220
|
+
|
|
221
|
+
const templateTableData = scoreResult.scores.map(score => {
|
|
222
|
+
return [
|
|
223
|
+
score.templatePath,
|
|
224
|
+
score.accessibilityScore,
|
|
225
|
+
score.bestPracticesScore,
|
|
226
|
+
score.performanceScore,
|
|
227
|
+
score.pwaScore,
|
|
228
|
+
score.seoScore,
|
|
229
|
+
];
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
logger.log(
|
|
233
|
+
getTableContents([table2Header, ...templateTableData], {
|
|
234
|
+
border: { bodyLeft: ' ' },
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
logger.log(i18n(`${i18nKey}.info.lighthouseLinksTitle`));
|
|
239
|
+
|
|
240
|
+
scoreResult.scores.forEach(score => {
|
|
241
|
+
logger.log(' ', uiLink(score.templatePath, score.link));
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
if (scoreResult.failedTemplatePaths.length) {
|
|
245
|
+
logger.log();
|
|
246
|
+
logger.error(i18n(`${i18nKey}.info.failedTemplatePathsTitle`));
|
|
247
|
+
scoreResult.failedTemplatePaths.forEach(failedTemplatePath => {
|
|
248
|
+
logger.log(' ', failedTemplatePath);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
logger.log();
|
|
253
|
+
logger.info(
|
|
254
|
+
i18n(`${i18nKey}.info.targetDeviceNote`, { target: options.target })
|
|
255
|
+
);
|
|
256
|
+
} else {
|
|
257
|
+
logger.log(`Theme: ${themeToCheck}`);
|
|
258
|
+
const tableHeader = getTableHeader(['Target', ...DEFAULT_TABLE_HEADER]);
|
|
259
|
+
|
|
260
|
+
const getTableData = (target, scoreResult) => {
|
|
261
|
+
const scores = scoreResult.scores ? scoreResult.scores[0] : {};
|
|
262
|
+
return [
|
|
263
|
+
target,
|
|
264
|
+
scores.accessibilityScore,
|
|
265
|
+
scores.bestPracticesScore,
|
|
266
|
+
scores.performanceScore,
|
|
267
|
+
scores.pwaScore,
|
|
268
|
+
scores.seoScore,
|
|
269
|
+
];
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const tableData = [
|
|
273
|
+
getTableData('desktop', desktopScoreResult),
|
|
274
|
+
getTableData('mobile', mobileScoreResult),
|
|
275
|
+
];
|
|
276
|
+
|
|
277
|
+
logger.log(
|
|
278
|
+
getTableContents([tableHeader, ...tableData], {
|
|
279
|
+
border: { bodyLeft: ' ' },
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
logger.info(i18n(`${i18nKey}.info.verboseOptionNote`));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
logger.log();
|
|
287
|
+
logger.log(
|
|
288
|
+
`Powered by ${uiLink(
|
|
289
|
+
'Google Lighthouse',
|
|
290
|
+
'https://developer.chrome.com/docs/lighthouse/overview/'
|
|
291
|
+
)}.`
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
process.exit();
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
exports.builder = yargs => {
|
|
298
|
+
yargs.option('theme', {
|
|
299
|
+
describe: i18n(`${i18nKey}.options.theme.describe`),
|
|
300
|
+
type: 'string',
|
|
301
|
+
});
|
|
302
|
+
yargs.option('target', {
|
|
303
|
+
describe: i18n(`${i18nKey}.options.target.describe`),
|
|
304
|
+
type: 'string',
|
|
305
|
+
choices: ['desktop', 'mobile'],
|
|
306
|
+
default: 'desktop',
|
|
307
|
+
});
|
|
308
|
+
yargs.option('verbose', {
|
|
309
|
+
describe: i18n(`${i18nKey}.options.verbose.describe`),
|
|
310
|
+
boolean: true,
|
|
311
|
+
default: false,
|
|
312
|
+
});
|
|
313
|
+
yargs.example([
|
|
314
|
+
[
|
|
315
|
+
'$0 cms lighthouse-score --theme=my-theme',
|
|
316
|
+
i18n(`${i18nKey}.examples.default`),
|
|
317
|
+
],
|
|
318
|
+
]);
|
|
319
|
+
|
|
320
|
+
addConfigOptions(yargs, true);
|
|
321
|
+
addAccountOptions(yargs, true);
|
|
322
|
+
addUseEnvironmentOptions(yargs, true);
|
|
323
|
+
|
|
324
|
+
return yargs;
|
|
325
|
+
};
|
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
package/commands/init.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
} = require('@hubspot/cli-lib/lib/config');
|
|
9
9
|
const { addConfigOptions } = require('../lib/commonOpts');
|
|
10
10
|
const { handleExit } = require('@hubspot/cli-lib/lib/process');
|
|
11
|
+
const { checkAndUpdateGitignore } = require('@hubspot/cli-lib/lib/git');
|
|
11
12
|
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
12
13
|
const {
|
|
13
14
|
DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
@@ -116,6 +117,8 @@ exports.handler = async options => {
|
|
|
116
117
|
);
|
|
117
118
|
const configPath = getConfigPath();
|
|
118
119
|
|
|
120
|
+
checkAndUpdateGitignore(configPath);
|
|
121
|
+
|
|
119
122
|
logger.log('');
|
|
120
123
|
logger.success(
|
|
121
124
|
i18n(`${i18nKey}.success.configFileCreated`, {
|
|
@@ -7,12 +7,15 @@ 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');
|
|
14
14
|
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
15
15
|
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
16
|
+
const {
|
|
17
|
+
debugErrorAndContext,
|
|
18
|
+
} = require('@hubspot/cli-lib/errorHandlers/standardErrors');
|
|
16
19
|
const {
|
|
17
20
|
ENVIRONMENTS,
|
|
18
21
|
PERSONAL_ACCESS_KEY_AUTH_METHOD,
|
|
@@ -103,7 +106,7 @@ const personalAccessKeyFlow = async (env, account, name) => {
|
|
|
103
106
|
]);
|
|
104
107
|
};
|
|
105
108
|
|
|
106
|
-
exports.command = 'create [name]';
|
|
109
|
+
exports.command = 'create [--name]';
|
|
107
110
|
exports.describe = i18n(`${i18nKey}.describe`);
|
|
108
111
|
|
|
109
112
|
exports.handler = async options => {
|
|
@@ -113,36 +116,49 @@ exports.handler = async options => {
|
|
|
113
116
|
const accountId = getAccountId(options);
|
|
114
117
|
const accountConfig = getAccountConfig(accountId);
|
|
115
118
|
const env = options.qa ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD;
|
|
116
|
-
|
|
119
|
+
const spinnies = new Spinnies({
|
|
120
|
+
succeedColor: 'white',
|
|
121
|
+
});
|
|
117
122
|
|
|
118
123
|
trackCommandUsage('sandbox-create', {}, accountId);
|
|
119
124
|
|
|
125
|
+
let namePrompt;
|
|
126
|
+
|
|
120
127
|
if (!name) {
|
|
121
128
|
namePrompt = await createSandboxPrompt();
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
const sandboxName = name || namePrompt.name;
|
|
125
132
|
|
|
126
|
-
logger.debug(
|
|
127
|
-
i18n(`${i18nKey}.debug.creating`, {
|
|
128
|
-
name: sandboxName,
|
|
129
|
-
})
|
|
130
|
-
);
|
|
131
133
|
let result;
|
|
134
|
+
|
|
132
135
|
try {
|
|
133
|
-
|
|
134
|
-
({
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
136
|
+
spinnies.add('sandboxCreate', {
|
|
137
|
+
text: i18n(`${i18nKey}.loading.add`, {
|
|
138
|
+
sandboxName,
|
|
139
|
+
}),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
result = await createSandbox(accountId, sandboxName);
|
|
143
|
+
|
|
144
|
+
logger.log('');
|
|
145
|
+
spinnies.succeed('sandboxCreate', {
|
|
146
|
+
text: i18n(`${i18nKey}.loading.succeed`, {
|
|
147
|
+
name: result.name,
|
|
148
|
+
sandboxHubId: result.sandboxHubId,
|
|
149
|
+
}),
|
|
150
|
+
});
|
|
145
151
|
} catch (err) {
|
|
152
|
+
debugErrorAndContext(err);
|
|
153
|
+
|
|
154
|
+
trackCommandUsage('sandbox-create', { success: false }, accountId);
|
|
155
|
+
|
|
156
|
+
spinnies.fail('sandboxCreate', {
|
|
157
|
+
text: i18n(`${i18nKey}.loading.fail`, {
|
|
158
|
+
sandboxName,
|
|
159
|
+
}),
|
|
160
|
+
});
|
|
161
|
+
|
|
146
162
|
if (isMissingScopeError(err)) {
|
|
147
163
|
logger.error(
|
|
148
164
|
i18n(`${i18nKey}.failure.scopes.message`, {
|
|
@@ -167,17 +183,21 @@ exports.handler = async options => {
|
|
|
167
183
|
process.exit(EXIT_CODES.SUCCESS);
|
|
168
184
|
} catch (err) {
|
|
169
185
|
logErrorInstance(err);
|
|
186
|
+
process.exit(EXIT_CODES.ERROR);
|
|
170
187
|
}
|
|
171
188
|
};
|
|
172
189
|
|
|
173
190
|
exports.builder = yargs => {
|
|
174
|
-
yargs.
|
|
175
|
-
describe: i18n(`${i18nKey}.
|
|
191
|
+
yargs.option('name', {
|
|
192
|
+
describe: i18n(`${i18nKey}.options.name.describe`),
|
|
176
193
|
type: 'string',
|
|
177
194
|
});
|
|
178
195
|
|
|
179
196
|
yargs.example([
|
|
180
|
-
[
|
|
197
|
+
[
|
|
198
|
+
'$0 sandbox create --name=MySandboxAccount',
|
|
199
|
+
i18n(`${i18nKey}.examples.default`),
|
|
200
|
+
],
|
|
181
201
|
]);
|
|
182
202
|
|
|
183
203
|
addConfigOptions(yargs, true);
|
|
@@ -2,22 +2,157 @@ 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
|
+
const {
|
|
12
|
+
debugErrorAndContext,
|
|
13
|
+
} = require('@hubspot/cli-lib/errorHandlers/standardErrors');
|
|
14
|
+
|
|
15
|
+
const { deleteSandbox } = require('@hubspot/cli-lib/sandboxes');
|
|
9
16
|
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
17
|
+
const { getConfig, getEnv } = require('@hubspot/cli-lib');
|
|
18
|
+
const { deleteSandboxPrompt } = require('../../lib/prompts/sandboxesPrompt');
|
|
19
|
+
const {
|
|
20
|
+
removeSandboxAccountFromConfig,
|
|
21
|
+
} = require('@hubspot/cli-lib/lib/config');
|
|
22
|
+
const {
|
|
23
|
+
selectAndSetAsDefaultAccountPrompt,
|
|
24
|
+
} = require('../../lib/prompts/accountsPrompt');
|
|
25
|
+
const { EXIT_CODES } = require('../../lib/enums/exitCodes');
|
|
26
|
+
const { promptUser } = require('../../lib/prompts/promptUtils');
|
|
27
|
+
const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
|
|
28
|
+
const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
|
|
10
29
|
|
|
11
30
|
const i18nKey = 'cli.commands.sandbox.subcommands.delete';
|
|
12
31
|
|
|
13
|
-
|
|
32
|
+
const SANDBOX_NOT_FOUND = 'SandboxErrors.SANDBOX_NOT_FOUND';
|
|
33
|
+
const OBJECT_NOT_FOUND = 'OBJECT_NOT_FOUND';
|
|
34
|
+
|
|
35
|
+
exports.command = 'delete [--account]';
|
|
14
36
|
exports.describe = i18n(`${i18nKey}.describe`);
|
|
15
37
|
|
|
16
38
|
exports.handler = async options => {
|
|
17
|
-
await loadAndValidateOptions(options);
|
|
39
|
+
await loadAndValidateOptions(options, false);
|
|
40
|
+
|
|
41
|
+
const { account } = options;
|
|
42
|
+
const config = getConfig();
|
|
43
|
+
|
|
44
|
+
let accountPrompt;
|
|
45
|
+
if (!account) {
|
|
46
|
+
accountPrompt = await deleteSandboxPrompt(config);
|
|
47
|
+
}
|
|
48
|
+
const sandboxAccountId = getAccountId({
|
|
49
|
+
account: account || accountPrompt.account,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
trackCommandUsage('sandbox-delete', {}, sandboxAccountId);
|
|
53
|
+
|
|
54
|
+
let parentAccountId;
|
|
55
|
+
for (const portal of config.portals) {
|
|
56
|
+
if (portal.portalId === sandboxAccountId) {
|
|
57
|
+
if (portal.parentAccountId) {
|
|
58
|
+
parentAccountId = portal.parentAccountId;
|
|
59
|
+
} else {
|
|
60
|
+
const parentAccountPrompt = await deleteSandboxPrompt(config, true);
|
|
61
|
+
parentAccountId = getAccountId({
|
|
62
|
+
account: parentAccountPrompt.account,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!getAccountId({ account: parentAccountId })) {
|
|
69
|
+
const baseUrl = getHubSpotWebsiteOrigin(
|
|
70
|
+
getEnv(sandboxAccountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD
|
|
71
|
+
);
|
|
72
|
+
const url = `${baseUrl}/sandboxes/${parentAccountId}`;
|
|
73
|
+
const command = `hs auth ${
|
|
74
|
+
getEnv(sandboxAccountId) === 'qa' ? '--qa' : ''
|
|
75
|
+
} --account=${parentAccountId}`;
|
|
76
|
+
logger.log('');
|
|
77
|
+
logger.error(
|
|
78
|
+
i18n(`${i18nKey}.noParentPortalAvailable`, {
|
|
79
|
+
parentAccountId,
|
|
80
|
+
url,
|
|
81
|
+
command,
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
logger.log('');
|
|
85
|
+
process.exit(EXIT_CODES.ERROR);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
logger.debug(
|
|
89
|
+
i18n(`${i18nKey}.debug.deleting`, {
|
|
90
|
+
account: account || accountPrompt.account,
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const { confirmSandboxDeletePrompt: confirmed } = await promptUser([
|
|
96
|
+
{
|
|
97
|
+
name: 'confirmSandboxDeletePrompt',
|
|
98
|
+
type: 'confirm',
|
|
99
|
+
message: i18n(`${i18nKey}.confirm`, {
|
|
100
|
+
account: account || accountPrompt.account,
|
|
101
|
+
}),
|
|
102
|
+
},
|
|
103
|
+
]);
|
|
104
|
+
if (!confirmed) {
|
|
105
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
await deleteSandbox(parentAccountId, sandboxAccountId);
|
|
109
|
+
|
|
110
|
+
logger.log('');
|
|
111
|
+
logger.success(
|
|
112
|
+
i18n(`${i18nKey}.success.delete`, {
|
|
113
|
+
account: account || accountPrompt.account,
|
|
114
|
+
sandboxHubId: sandboxAccountId,
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
|
+
logger.log('');
|
|
118
|
+
|
|
119
|
+
const promptDefaultAccount = removeSandboxAccountFromConfig(
|
|
120
|
+
sandboxAccountId
|
|
121
|
+
);
|
|
122
|
+
if (promptDefaultAccount) {
|
|
123
|
+
await selectAndSetAsDefaultAccountPrompt(config);
|
|
124
|
+
}
|
|
125
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
debugErrorAndContext(err);
|
|
128
|
+
|
|
129
|
+
trackCommandUsage('sandbox-delete', { success: false }, sandboxAccountId);
|
|
130
|
+
|
|
131
|
+
if (
|
|
132
|
+
err.error &&
|
|
133
|
+
err.error.category === OBJECT_NOT_FOUND &&
|
|
134
|
+
err.error.subCategory === SANDBOX_NOT_FOUND
|
|
135
|
+
) {
|
|
136
|
+
logger.log('');
|
|
137
|
+
logger.warn(
|
|
138
|
+
i18n(`${i18nKey}.objectNotFound`, {
|
|
139
|
+
account: account || accountPrompt.account,
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
logger.log('');
|
|
18
143
|
|
|
19
|
-
|
|
20
|
-
|
|
144
|
+
const promptDefaultAccount = removeSandboxAccountFromConfig(
|
|
145
|
+
sandboxAccountId
|
|
146
|
+
);
|
|
147
|
+
if (promptDefaultAccount) {
|
|
148
|
+
await selectAndSetAsDefaultAccountPrompt(config);
|
|
149
|
+
}
|
|
150
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
151
|
+
} else {
|
|
152
|
+
logger.error(err.error.message);
|
|
153
|
+
}
|
|
154
|
+
process.exit(EXIT_CODES.ERROR);
|
|
155
|
+
}
|
|
21
156
|
};
|
|
22
157
|
|
|
23
158
|
exports.builder = yargs => {
|
|
@@ -36,6 +171,7 @@ exports.builder = yargs => {
|
|
|
36
171
|
addConfigOptions(yargs, true);
|
|
37
172
|
addAccountOptions(yargs, true);
|
|
38
173
|
addUseEnvironmentOptions(yargs, true);
|
|
174
|
+
addTestingOptions(yargs, true);
|
|
39
175
|
|
|
40
176
|
return yargs;
|
|
41
177
|
};
|
package/lib/projects.js
CHANGED
|
@@ -224,6 +224,13 @@ const getProjectBuildDetailUrl = (projectName, buildId, accountId) => {
|
|
|
224
224
|
return `${getProjectDetailUrl(projectName, accountId)}/build/${buildId}`;
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
+
const getProjectDeployDetailUrl = (projectName, deployId, accountId) => {
|
|
228
|
+
if (!projectName || !deployId || !accountId) return;
|
|
229
|
+
return `${getProjectDetailUrl(
|
|
230
|
+
projectName,
|
|
231
|
+
accountId
|
|
232
|
+
)}/activity/deploy/${deployId}`;
|
|
233
|
+
};
|
|
227
234
|
const uploadProjectFiles = async (accountId, projectName, filePath) => {
|
|
228
235
|
const i18nKey = 'cli.commands.project.subcommands.upload';
|
|
229
236
|
const spinnies = new Spinnies({
|
|
@@ -343,10 +350,13 @@ const makePollTaskStatusFunc = ({
|
|
|
343
350
|
}
|
|
344
351
|
};
|
|
345
352
|
|
|
346
|
-
return async (accountId, taskName, taskId) => {
|
|
347
|
-
|
|
353
|
+
return async (accountId, taskName, taskId, deployedBuildId = null) => {
|
|
354
|
+
const displayId = deployedBuildId || taskId;
|
|
355
|
+
|
|
348
356
|
if (linkToHubSpot) {
|
|
349
|
-
logger.log(
|
|
357
|
+
logger.log(
|
|
358
|
+
`\n${linkToHubSpot(accountId, taskName, taskId, deployedBuildId)}\n`
|
|
359
|
+
);
|
|
350
360
|
}
|
|
351
361
|
|
|
352
362
|
const spinnies = new Spinnies({
|
|
@@ -372,7 +382,7 @@ const makePollTaskStatusFunc = ({
|
|
|
372
382
|
const subTaskName = subTask[statusText.SUBTASK_NAME_KEY];
|
|
373
383
|
|
|
374
384
|
spinnies.add(subTaskName, {
|
|
375
|
-
text: `${chalk.bold(subTaskName)} #${
|
|
385
|
+
text: `${chalk.bold(subTaskName)} #${displayId} ${
|
|
376
386
|
statusText.STATUS_TEXT[statusText.STATES.ENQUEUED]
|
|
377
387
|
}\n`,
|
|
378
388
|
indent: 2,
|
|
@@ -395,7 +405,7 @@ const makePollTaskStatusFunc = ({
|
|
|
395
405
|
return;
|
|
396
406
|
}
|
|
397
407
|
|
|
398
|
-
const updatedText = `${chalk.bold(subTaskName)} #${
|
|
408
|
+
const updatedText = `${chalk.bold(subTaskName)} #${displayId} ${
|
|
399
409
|
statusText.STATUS_TEXT[subTask.status]
|
|
400
410
|
}\n`;
|
|
401
411
|
|
|
@@ -413,17 +423,17 @@ const makePollTaskStatusFunc = ({
|
|
|
413
423
|
});
|
|
414
424
|
|
|
415
425
|
if (isTaskComplete(taskStatus)) {
|
|
416
|
-
subTaskStatus.forEach(subTask => {
|
|
417
|
-
|
|
418
|
-
});
|
|
426
|
+
// subTaskStatus.forEach(subTask => {
|
|
427
|
+
// spinnies.remove(subTask[statusText.SUBTASK_NAME_KEY]);
|
|
428
|
+
// });
|
|
419
429
|
|
|
420
430
|
if (status === statusText.STATES.SUCCESS) {
|
|
421
431
|
spinnies.succeed('overallTaskStatus', {
|
|
422
|
-
text:
|
|
432
|
+
text: statusStrings.SUCCESS(taskName),
|
|
423
433
|
});
|
|
424
434
|
} else if (status === statusText.STATES.FAILURE) {
|
|
425
435
|
spinnies.fail('overallTaskStatus', {
|
|
426
|
-
text:
|
|
436
|
+
text: statusStrings.FAIL(taskName),
|
|
427
437
|
});
|
|
428
438
|
|
|
429
439
|
const failedSubtask = subTaskStatus.filter(
|
|
@@ -433,7 +443,7 @@ const makePollTaskStatusFunc = ({
|
|
|
433
443
|
uiLine();
|
|
434
444
|
logger.log(
|
|
435
445
|
`${statusStrings.SUBTASK_FAIL(
|
|
436
|
-
|
|
446
|
+
displayId,
|
|
437
447
|
failedSubtask.length === 1
|
|
438
448
|
? failedSubtask[0][statusText.SUBTASK_NAME_KEY]
|
|
439
449
|
: failedSubtask.length + ' components'
|
|
@@ -470,10 +480,10 @@ const makePollTaskStatusFunc = ({
|
|
|
470
480
|
};
|
|
471
481
|
|
|
472
482
|
const pollBuildStatus = makePollTaskStatusFunc({
|
|
473
|
-
linkToHubSpot: (
|
|
483
|
+
linkToHubSpot: (accountId, taskName, taskId) =>
|
|
474
484
|
uiLink(
|
|
475
|
-
`View build #${
|
|
476
|
-
getProjectBuildDetailUrl(
|
|
485
|
+
`View build #${taskId} in HubSpot`,
|
|
486
|
+
getProjectBuildDetailUrl(taskName, taskId, accountId)
|
|
477
487
|
),
|
|
478
488
|
statusFn: getBuildStatus,
|
|
479
489
|
statusText: PROJECT_BUILD_TEXT,
|
|
@@ -481,22 +491,27 @@ const pollBuildStatus = makePollTaskStatusFunc({
|
|
|
481
491
|
INITIALIZE: name => `Building ${chalk.bold(name)}`,
|
|
482
492
|
SUCCESS: name => `Built ${chalk.bold(name)}`,
|
|
483
493
|
FAIL: name => `Failed to build ${chalk.bold(name)}`,
|
|
484
|
-
SUBTASK_FAIL: (
|
|
485
|
-
`Build #${
|
|
494
|
+
SUBTASK_FAIL: (buildId, name) =>
|
|
495
|
+
`Build #${buildId} failed because there was a problem\nbuilding ${chalk.bold(
|
|
486
496
|
name
|
|
487
497
|
)}`,
|
|
488
498
|
},
|
|
489
499
|
});
|
|
490
500
|
|
|
491
501
|
const pollDeployStatus = makePollTaskStatusFunc({
|
|
502
|
+
linkToHubSpot: (accountId, taskName, taskId, deployedBuildId) =>
|
|
503
|
+
uiLink(
|
|
504
|
+
`View deploy of build #${deployedBuildId} in HubSpot`,
|
|
505
|
+
getProjectDeployDetailUrl(taskName, taskId, accountId)
|
|
506
|
+
),
|
|
492
507
|
statusFn: getDeployStatus,
|
|
493
508
|
statusText: PROJECT_DEPLOY_TEXT,
|
|
494
509
|
statusStrings: {
|
|
495
510
|
INITIALIZE: name => `Deploying ${chalk.bold(name)}`,
|
|
496
511
|
SUCCESS: name => `Deployed ${chalk.bold(name)}`,
|
|
497
512
|
FAIL: name => `Failed to deploy ${chalk.bold(name)}`,
|
|
498
|
-
SUBTASK_FAIL: (
|
|
499
|
-
`Deploy for build #${
|
|
513
|
+
SUBTASK_FAIL: (deployedBuildId, name) =>
|
|
514
|
+
`Deploy for build #${deployedBuildId} failed because there was a\nproblem deploying ${chalk.bold(
|
|
500
515
|
name
|
|
501
516
|
)}`,
|
|
502
517
|
},
|
|
@@ -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
|
|
3
|
+
"version": "4.0.1",
|
|
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
|
|
12
|
-
"@hubspot/serverless-dev-runtime": "4.0.1
|
|
11
|
+
"@hubspot/cli-lib": "4.0.1",
|
|
12
|
+
"@hubspot/serverless-dev-runtime": "4.0.1",
|
|
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": "416585f18c9b856b4da3ef502d1eccaded9281d5"
|
|
41
41
|
}
|