@hubspot/cli 4.1.7 → 4.1.8-beta.0
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/commands/accounts/remove.js +84 -0
- package/commands/accounts.js +2 -0
- package/commands/functions/deploy.js +0 -1
- package/commands/functions/list.js +1 -1
- package/commands/list.js +1 -5
- package/commands/sandbox/create.js +29 -2
- package/commands/sandbox/delete.js +24 -8
- package/lib/prompts/accountsPrompt.js +2 -2
- package/lib/prompts/projectsLogsPrompt.js +1 -1
- package/lib/sandboxes.js +25 -0
- package/package.json +4 -4
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const { logger } = require('@hubspot/cli-lib/logger');
|
|
2
|
+
const {
|
|
3
|
+
getConfig,
|
|
4
|
+
getConfigPath,
|
|
5
|
+
deleteAccount,
|
|
6
|
+
getConfigDefaultAccount,
|
|
7
|
+
getAccountId: getAccountIdFromConfig,
|
|
8
|
+
updateDefaultAccount,
|
|
9
|
+
} = require('@hubspot/cli-lib/lib/config');
|
|
10
|
+
|
|
11
|
+
const { trackCommandUsage } = require('../../lib/usageTracking');
|
|
12
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
13
|
+
const { selectAccountFromConfig } = require('../../lib/prompts/accountsPrompt');
|
|
14
|
+
const { loadAndValidateOptions } = require('../../lib/validation');
|
|
15
|
+
|
|
16
|
+
const i18nKey = 'cli.commands.accounts.subcommands.remove';
|
|
17
|
+
|
|
18
|
+
exports.command = 'remove [--account]';
|
|
19
|
+
exports.describe = i18n(`${i18nKey}.describe`);
|
|
20
|
+
|
|
21
|
+
exports.handler = async options => {
|
|
22
|
+
await loadAndValidateOptions(options, false);
|
|
23
|
+
|
|
24
|
+
let config = getConfig();
|
|
25
|
+
|
|
26
|
+
let accountToRemove = options.account;
|
|
27
|
+
|
|
28
|
+
if (accountToRemove && !getAccountIdFromConfig(accountToRemove)) {
|
|
29
|
+
logger.error(
|
|
30
|
+
i18n(`${i18nKey}.errors.accountNotFound`, {
|
|
31
|
+
specifiedAccount: accountToRemove,
|
|
32
|
+
configPath: getConfigPath(),
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!accountToRemove || !getAccountIdFromConfig(accountToRemove)) {
|
|
38
|
+
accountToRemove = await selectAccountFromConfig(
|
|
39
|
+
config,
|
|
40
|
+
i18n(`${i18nKey}.prompts.selectAccountToRemove`)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
trackCommandUsage(
|
|
45
|
+
'accounts-remove',
|
|
46
|
+
null,
|
|
47
|
+
getAccountIdFromConfig(accountToRemove)
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const currentDefaultAccount = getConfigDefaultAccount();
|
|
51
|
+
|
|
52
|
+
await deleteAccount(accountToRemove);
|
|
53
|
+
logger.success(
|
|
54
|
+
i18n(`${i18nKey}.success.accountRemoved`, {
|
|
55
|
+
accountName: accountToRemove,
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// Get updated version of the config
|
|
60
|
+
config = getConfig();
|
|
61
|
+
|
|
62
|
+
if (accountToRemove === currentDefaultAccount) {
|
|
63
|
+
logger.log();
|
|
64
|
+
logger.log(i18n(`${i18nKey}.logs.replaceDefaultAccount`));
|
|
65
|
+
const newDefaultAccount = await selectAccountFromConfig(config);
|
|
66
|
+
updateDefaultAccount(newDefaultAccount);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
exports.builder = yargs => {
|
|
71
|
+
yargs.option('account', {
|
|
72
|
+
describe: i18n(`${i18nKey}.options.account.describe`),
|
|
73
|
+
type: 'string',
|
|
74
|
+
});
|
|
75
|
+
yargs.example([
|
|
76
|
+
['$0 accounts remove', i18n(`${i18nKey}.examples.default`)],
|
|
77
|
+
[
|
|
78
|
+
'$0 accounts remove --account=MyAccount',
|
|
79
|
+
i18n(`${i18nKey}.examples.byName`),
|
|
80
|
+
],
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
return yargs;
|
|
84
|
+
};
|
package/commands/accounts.js
CHANGED
|
@@ -4,6 +4,7 @@ const list = require('./accounts/list');
|
|
|
4
4
|
const rename = require('./accounts/rename');
|
|
5
5
|
const use = require('./accounts/use');
|
|
6
6
|
const info = require('./accounts/info');
|
|
7
|
+
const remove = require('./accounts/remove');
|
|
7
8
|
|
|
8
9
|
const i18nKey = 'cli.commands.accounts';
|
|
9
10
|
|
|
@@ -22,6 +23,7 @@ exports.builder = yargs => {
|
|
|
22
23
|
.command(rename)
|
|
23
24
|
.command(use)
|
|
24
25
|
.command(info)
|
|
26
|
+
.command(remove)
|
|
25
27
|
.demandCommand(1, '');
|
|
26
28
|
|
|
27
29
|
return yargs;
|
|
@@ -36,7 +36,7 @@ exports.handler = async options => {
|
|
|
36
36
|
logger.debug(i18n(`${i18nKey}.debug.gettingFunctions`));
|
|
37
37
|
|
|
38
38
|
const routesResp = await getRoutes(accountId).catch(async e => {
|
|
39
|
-
await logApiErrorInstance(
|
|
39
|
+
await logApiErrorInstance(e, new ApiErrorContext({ accountId }));
|
|
40
40
|
process.exit(EXIT_CODES.SUCCESS);
|
|
41
41
|
});
|
|
42
42
|
|
package/commands/list.js
CHANGED
|
@@ -48,11 +48,7 @@ exports.handler = async options => {
|
|
|
48
48
|
try {
|
|
49
49
|
contentsResp = await getDirectoryContentsByPath(accountId, directoryPath);
|
|
50
50
|
} catch (e) {
|
|
51
|
-
logApiErrorInstance(
|
|
52
|
-
accountId,
|
|
53
|
-
e,
|
|
54
|
-
new ApiErrorContext({ accountId, directoryPath })
|
|
55
|
-
);
|
|
51
|
+
logApiErrorInstance(e, new ApiErrorContext({ accountId, directoryPath }));
|
|
56
52
|
process.exit(EXIT_CODES.SUCCESS);
|
|
57
53
|
}
|
|
58
54
|
|
|
@@ -14,6 +14,8 @@ const { createSandboxPrompt } = require('../../lib/prompts/sandboxesPrompt');
|
|
|
14
14
|
const {
|
|
15
15
|
getSandboxType,
|
|
16
16
|
sandboxCreatePersonalAccessKeyFlow,
|
|
17
|
+
getHasDevelopmentSandboxes,
|
|
18
|
+
getDevSandboxLimit,
|
|
17
19
|
} = require('../../lib/sandboxes');
|
|
18
20
|
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
19
21
|
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
@@ -22,7 +24,7 @@ const {
|
|
|
22
24
|
} = require('@hubspot/cli-lib/errorHandlers/standardErrors');
|
|
23
25
|
const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
|
|
24
26
|
const { EXIT_CODES } = require('../../lib/enums/exitCodes');
|
|
25
|
-
const { getAccountConfig } = require('@hubspot/cli-lib');
|
|
27
|
+
const { getAccountConfig, getEnv } = require('@hubspot/cli-lib');
|
|
26
28
|
const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
|
|
27
29
|
const {
|
|
28
30
|
isMissingScopeError,
|
|
@@ -127,7 +129,32 @@ exports.handler = async options => {
|
|
|
127
129
|
err.error.message
|
|
128
130
|
) {
|
|
129
131
|
logger.log('');
|
|
130
|
-
|
|
132
|
+
const devSandboxLimit = getDevSandboxLimit(err.error);
|
|
133
|
+
const plural = devSandboxLimit !== 1;
|
|
134
|
+
const hasDevelopmentSandboxes = getHasDevelopmentSandboxes(accountConfig);
|
|
135
|
+
if (hasDevelopmentSandboxes) {
|
|
136
|
+
logger.error(
|
|
137
|
+
i18n(
|
|
138
|
+
`${i18nKey}.failure.alreadyInConfig.${plural ? 'other' : 'one'}`,
|
|
139
|
+
{
|
|
140
|
+
accountName: accountConfig.name || accountId,
|
|
141
|
+
limit: devSandboxLimit,
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
);
|
|
145
|
+
} else {
|
|
146
|
+
const baseUrl = getHubSpotWebsiteOrigin(
|
|
147
|
+
getEnv(accountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD
|
|
148
|
+
);
|
|
149
|
+
logger.error(
|
|
150
|
+
i18n(`${i18nKey}.failure.limit.${plural ? 'other' : 'one'}`, {
|
|
151
|
+
accountName: accountConfig.name || accountId,
|
|
152
|
+
limit: devSandboxLimit,
|
|
153
|
+
devSandboxesLink: `${baseUrl}/sandboxes-developer/${accountId}/development`,
|
|
154
|
+
})
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
logger.log('');
|
|
131
158
|
} else {
|
|
132
159
|
logErrorInstance(err);
|
|
133
160
|
}
|
|
@@ -14,7 +14,7 @@ const {
|
|
|
14
14
|
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
15
15
|
const { deleteSandbox } = require('@hubspot/cli-lib/sandboxes');
|
|
16
16
|
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
17
|
-
const { getConfig, getEnv } = require('@hubspot/cli-lib');
|
|
17
|
+
const { getConfig, getEnv, getAccountConfig } = require('@hubspot/cli-lib');
|
|
18
18
|
const { deleteSandboxPrompt } = require('../../lib/prompts/sandboxesPrompt');
|
|
19
19
|
const {
|
|
20
20
|
removeSandboxAccountFromConfig,
|
|
@@ -30,6 +30,8 @@ const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
|
|
|
30
30
|
const {
|
|
31
31
|
isSpecifiedError,
|
|
32
32
|
} = require('@hubspot/cli-lib/errorHandlers/apiErrors');
|
|
33
|
+
const { HubSpotAuthError } = require('@hubspot/cli-lib/lib/models/Errors');
|
|
34
|
+
const { getAccountName } = require('../../lib/sandboxes');
|
|
33
35
|
|
|
34
36
|
const i18nKey = 'cli.commands.sandbox.subcommands.delete';
|
|
35
37
|
|
|
@@ -62,7 +64,7 @@ exports.handler = async options => {
|
|
|
62
64
|
const sandboxAccountId = getAccountId({
|
|
63
65
|
account: account || accountPrompt.account,
|
|
64
66
|
});
|
|
65
|
-
|
|
67
|
+
const accountConfig = getAccountConfig(sandboxAccountId);
|
|
66
68
|
const isDefaultAccount =
|
|
67
69
|
sandboxAccountId === getAccountId(config.defaultPortal);
|
|
68
70
|
|
|
@@ -89,12 +91,13 @@ exports.handler = async options => {
|
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
const parentAccount = getAccountConfig(parentAccountId);
|
|
92
95
|
const url = `${baseUrl}/sandboxes/${parentAccountId}`;
|
|
93
96
|
const command = `hs auth ${
|
|
94
97
|
getEnv(sandboxAccountId) === 'qa' ? '--qa' : ''
|
|
95
98
|
} --account=${parentAccountId}`;
|
|
96
99
|
|
|
97
|
-
if (!getAccountId({ account: parentAccountId })) {
|
|
100
|
+
if (parentAccountId && !getAccountId({ account: parentAccountId })) {
|
|
98
101
|
logger.log('');
|
|
99
102
|
logger.error(
|
|
100
103
|
i18n(`${i18nKey}.failure.noParentPortalAvailable`, {
|
|
@@ -109,14 +112,14 @@ exports.handler = async options => {
|
|
|
109
112
|
|
|
110
113
|
logger.debug(
|
|
111
114
|
i18n(`${i18nKey}.debug.deleting`, {
|
|
112
|
-
account:
|
|
115
|
+
account: getAccountName(accountConfig),
|
|
113
116
|
})
|
|
114
117
|
);
|
|
115
118
|
|
|
116
119
|
if (isDefaultAccount) {
|
|
117
120
|
logger.log(
|
|
118
121
|
i18n(`${i18nKey}.defaultAccountWarning`, {
|
|
119
|
-
account:
|
|
122
|
+
account: getAccountName(accountConfig),
|
|
120
123
|
})
|
|
121
124
|
);
|
|
122
125
|
}
|
|
@@ -128,7 +131,7 @@ exports.handler = async options => {
|
|
|
128
131
|
name: 'confirmSandboxDeletePrompt',
|
|
129
132
|
type: 'confirm',
|
|
130
133
|
message: i18n(`${i18nKey}.confirm`, {
|
|
131
|
-
account:
|
|
134
|
+
account: getAccountName(accountConfig),
|
|
132
135
|
}),
|
|
133
136
|
},
|
|
134
137
|
]);
|
|
@@ -170,7 +173,20 @@ exports.handler = async options => {
|
|
|
170
173
|
sandboxAccountId
|
|
171
174
|
);
|
|
172
175
|
|
|
173
|
-
if (
|
|
176
|
+
if (err instanceof HubSpotAuthError) {
|
|
177
|
+
// Intercept invalid key error
|
|
178
|
+
// This command uses the parent portal PAK to delete a sandbox, so we must specify which account needs a new key
|
|
179
|
+
const regex = /\bYour personal access key is invalid\b/;
|
|
180
|
+
const match = err.message.match(regex);
|
|
181
|
+
if (match && match[0]) {
|
|
182
|
+
logger.log('');
|
|
183
|
+
logger.error(
|
|
184
|
+
i18n(`${i18nKey}.failure.invalidKey`, {
|
|
185
|
+
account: getAccountName(parentAccount),
|
|
186
|
+
})
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
} else if (
|
|
174
190
|
isSpecifiedError(
|
|
175
191
|
err,
|
|
176
192
|
404,
|
|
@@ -181,7 +197,7 @@ exports.handler = async options => {
|
|
|
181
197
|
logger.log('');
|
|
182
198
|
logger.warn(
|
|
183
199
|
i18n(`${i18nKey}.failure.objectNotFound`, {
|
|
184
|
-
account:
|
|
200
|
+
account: getAccountName(accountConfig),
|
|
185
201
|
})
|
|
186
202
|
);
|
|
187
203
|
logger.log('');
|
|
@@ -15,14 +15,14 @@ const mapAccountChoices = portals =>
|
|
|
15
15
|
|
|
16
16
|
const i18nKey = 'cli.commands.accounts.subcommands.use';
|
|
17
17
|
|
|
18
|
-
const selectAccountFromConfig = async config => {
|
|
18
|
+
const selectAccountFromConfig = async (config, prompt) => {
|
|
19
19
|
const { default: selectedDefault } = await promptUser([
|
|
20
20
|
{
|
|
21
21
|
type: 'list',
|
|
22
22
|
look: false,
|
|
23
23
|
name: 'default',
|
|
24
24
|
pageSize: 20,
|
|
25
|
-
message: i18n(`${i18nKey}.promptMessage`),
|
|
25
|
+
message: prompt || i18n(`${i18nKey}.promptMessage`),
|
|
26
26
|
choices: mapAccountChoices(config.portals),
|
|
27
27
|
default: config.defaultPortal,
|
|
28
28
|
},
|
|
@@ -66,7 +66,7 @@ const projectLogsPrompt = (accountId, promptOptions = {}) => {
|
|
|
66
66
|
|
|
67
67
|
if (deployedBuild && deployedBuild.subbuildStatuses) {
|
|
68
68
|
return deployedBuild.subbuildStatuses
|
|
69
|
-
.filter(subbuild => subbuild.buildType === '
|
|
69
|
+
.filter(subbuild => subbuild.buildType === 'PRIVATE_APP')
|
|
70
70
|
.map(subbuild => ({
|
|
71
71
|
name: subbuild.buildName,
|
|
72
72
|
value: subbuild.buildName,
|
package/lib/sandboxes.js
CHANGED
|
@@ -35,6 +35,29 @@ function getAccountName(config) {
|
|
|
35
35
|
return `${config.name} ${isSandbox ? sandboxName : ''}(${config.portalId})`;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function getHasDevelopmentSandboxes(parentAccountConfig) {
|
|
39
|
+
const config = getConfig();
|
|
40
|
+
const parentPortalId = parentAccountConfig.portalId;
|
|
41
|
+
for (const portal of config.portals) {
|
|
42
|
+
if (
|
|
43
|
+
(portal.parentAccountId !== null ||
|
|
44
|
+
portal.parentAccountId !== undefined) &&
|
|
45
|
+
portal.parentAccountId === parentPortalId &&
|
|
46
|
+
portal.sandboxAccountType &&
|
|
47
|
+
portal.sandboxAccountType === 'DEVELOPER'
|
|
48
|
+
) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function getDevSandboxLimit(error) {
|
|
56
|
+
// Error context should contain a limit property with a list of one number. That number is the current limit
|
|
57
|
+
const limit = error.context && error.context.limit && error.context.limit[0];
|
|
58
|
+
return limit ? parseInt(limit, 10) : 1; // Default to 1
|
|
59
|
+
}
|
|
60
|
+
|
|
38
61
|
// Fetches available sync types for a given sandbox portal
|
|
39
62
|
async function getAvailableSyncTypes(parentAccountConfig, config) {
|
|
40
63
|
const parentPortalId = parentAccountConfig.portalId;
|
|
@@ -211,6 +234,8 @@ function pollSyncTaskStatus(accountId, taskId, syncStatusUrl) {
|
|
|
211
234
|
module.exports = {
|
|
212
235
|
getSandboxType,
|
|
213
236
|
getAccountName,
|
|
237
|
+
getHasDevelopmentSandboxes,
|
|
238
|
+
getDevSandboxLimit,
|
|
214
239
|
getAvailableSyncTypes,
|
|
215
240
|
sandboxCreatePersonalAccessKeyFlow,
|
|
216
241
|
pollSyncTaskStatus,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.8-beta.0",
|
|
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.1.
|
|
12
|
-
"@hubspot/serverless-dev-runtime": "4.1.
|
|
11
|
+
"@hubspot/cli-lib": "4.1.8-beta.0",
|
|
12
|
+
"@hubspot/serverless-dev-runtime": "4.1.8-beta.0",
|
|
13
13
|
"archiver": "^5.3.0",
|
|
14
14
|
"chalk": "^4.1.2",
|
|
15
15
|
"cli-progress": "^3.11.2",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "af16182b2c7abd401771d5e0eed3de21e7b0477c"
|
|
42
42
|
}
|