@hubspot/cli 8.2.0-experimental.1 → 8.2.0-experimental.2
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/account/auth.js +2 -0
- package/commands/app/logs.js +4 -0
- package/commands/getStarted.js +2 -0
- package/commands/init.js +2 -0
- package/commands/mcp/setup.js +2 -2
- package/commands/project/create.js +2 -0
- package/commands/project/installApp.d.ts +7 -0
- package/commands/project/installApp.js +181 -0
- package/commands/project/installDeps.js +2 -0
- package/commands/project/upload.js +4 -0
- package/commands/project.js +2 -0
- package/commands/upgrade.js +2 -0
- package/lang/en.d.ts +58 -0
- package/lang/en.js +71 -2
- package/lib/accountTargetDiscovery.d.ts +15 -0
- package/lib/accountTargetDiscovery.js +175 -0
- package/lib/app/install.d.ts +22 -0
- package/lib/app/install.js +42 -0
- package/lib/app/logs.js +1 -1
- package/lib/auth/awaitPersonalAccessKeyOverWebsocket.js +3 -2
- package/lib/doctor/Doctor.d.ts +1 -0
- package/lib/doctor/Doctor.js +26 -0
- package/lib/mcp/clients.d.ts +13 -0
- package/lib/mcp/clients.js +55 -0
- package/lib/mcp/promotion.d.ts +3 -0
- package/lib/mcp/promotion.js +109 -0
- package/lib/mcp/setup.d.ts +3 -2
- package/lib/mcp/setup.js +17 -12
- package/lib/projects/installApp.d.ts +58 -0
- package/lib/projects/installApp.js +278 -0
- package/lib/projects/localDev/AppDevModeInterface.d.ts +0 -3
- package/lib/projects/localDev/AppDevModeInterface.js +22 -44
- package/lib/projects/localDev/helpers/project.d.ts +4 -3
- package/lib/projects/localDev/helpers/project.js +46 -12
- package/lib/prompts/projectDevTargetAccountPrompt.js +3 -2
- package/lib/theme/cmsDevServerProcess.js +1 -1
- package/lib/usageTracking.d.ts +1 -0
- package/lib/usageTracking.js +9 -0
- package/mcp-server/tools/project/CreateTestAccountTool.js +1 -1
- package/package.json +4 -4
- package/types/AccountTargets.d.ts +37 -0
- package/types/AccountTargets.js +12 -0
- package/types/LocalDev.d.ts +3 -2
- package/types/ProjectComponents.d.ts +2 -1
- package/types/Projects.d.ts +5 -0
package/commands/account/auth.js
CHANGED
|
@@ -11,6 +11,7 @@ import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
|
11
11
|
import { commands } from '../../lang/en.js';
|
|
12
12
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
13
13
|
import { authenticateNewAccount } from '../../lib/accountAuth.js';
|
|
14
|
+
import { showMcpPromotionNudge } from '../../lib/mcp/promotion.js';
|
|
14
15
|
const TRACKING_STATUS = {
|
|
15
16
|
STARTED: 'started',
|
|
16
17
|
ERROR: 'error',
|
|
@@ -56,6 +57,7 @@ async function handler(args) {
|
|
|
56
57
|
'accountAuthCommand',
|
|
57
58
|
'accountsListCommand',
|
|
58
59
|
]);
|
|
60
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
59
61
|
if (!disableTracking) {
|
|
60
62
|
await trackAuthAction('account-auth', authType, TRACKING_STATUS.COMPLETE, accountId);
|
|
61
63
|
}
|
package/commands/app/logs.js
CHANGED
|
@@ -6,6 +6,7 @@ import { selectAppPrompt } from '../../lib/prompts/selectAppPrompt.js';
|
|
|
6
6
|
import { listPrompt } from '../../lib/prompts/promptUtils.js';
|
|
7
7
|
import { getTypeChoices, handleLogsRequest, SYSTEM_TYPE_CHOICES, tailAppLogs, toSystemType, } from '../../lib/app/logs.js';
|
|
8
8
|
import { logError } from '../../lib/errorHandlers/index.js';
|
|
9
|
+
import { showMcpPromotionNudge } from '../../lib/mcp/promotion.js';
|
|
9
10
|
const command = 'logs';
|
|
10
11
|
const describe = commands.app.subcommands.logs.describe;
|
|
11
12
|
const handler = async (options) => {
|
|
@@ -37,6 +38,9 @@ const handler = async (options) => {
|
|
|
37
38
|
}
|
|
38
39
|
else {
|
|
39
40
|
await handleLogsRequest(derivedAccountId, appId, systemType, options);
|
|
41
|
+
if (!options.json) {
|
|
42
|
+
await showMcpPromotionNudge(options._.join(' '));
|
|
43
|
+
}
|
|
40
44
|
}
|
|
41
45
|
return exit(EXIT_CODES.SUCCESS);
|
|
42
46
|
}
|
package/commands/getStarted.js
CHANGED
|
@@ -24,6 +24,7 @@ import ProjectValidationError from '../lib/errors/ProjectValidationError.js';
|
|
|
24
24
|
import { openLink } from '../lib/links.js';
|
|
25
25
|
import { runGetStartedV2 } from '../lib/getStarted/getStartedV2.js';
|
|
26
26
|
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
27
|
+
import { showMcpPromotionNudge } from '../lib/mcp/promotion.js';
|
|
27
28
|
const command = 'get-started';
|
|
28
29
|
const describe = commands.getStarted.describe;
|
|
29
30
|
async function handler(args) {
|
|
@@ -275,6 +276,7 @@ async function handler(args) {
|
|
|
275
276
|
return exit(EXIT_CODES.SUCCESS);
|
|
276
277
|
}
|
|
277
278
|
}
|
|
279
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
278
280
|
// Track successful completion of get-started command
|
|
279
281
|
await trackCommandMetadataUsage('get-started', {
|
|
280
282
|
successful: true,
|
package/commands/init.js
CHANGED
|
@@ -24,6 +24,7 @@ import { makeWrappedYargsHandler } from '../lib/yargs/makeWrappedYargsHandler.js
|
|
|
24
24
|
import { uiLogger } from '../lib/ui/logger.js';
|
|
25
25
|
import { commands } from '../lang/en.js';
|
|
26
26
|
import { parseStringToNumber } from '../lib/parsing.js';
|
|
27
|
+
import { showMcpPromotionNudge } from '../lib/mcp/promotion.js';
|
|
27
28
|
const TRACKING_STATUS = {
|
|
28
29
|
STARTED: 'started',
|
|
29
30
|
ERROR: 'error',
|
|
@@ -142,6 +143,7 @@ async function handler(args) {
|
|
|
142
143
|
'authCommand',
|
|
143
144
|
'accountsListCommand',
|
|
144
145
|
]);
|
|
146
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
145
147
|
if (!disableTracking) {
|
|
146
148
|
await trackAuthAction('init', authType, TRACKING_STATUS.COMPLETE, accountId);
|
|
147
149
|
}
|
package/commands/mcp/setup.js
CHANGED
|
@@ -2,13 +2,13 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
|
2
2
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
3
3
|
import { commands } from '../../lang/en.js';
|
|
4
4
|
import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
|
|
5
|
-
import {
|
|
5
|
+
import { configureMcpServer, supportedTools } from '../../lib/mcp/setup.js';
|
|
6
6
|
const command = ['setup'];
|
|
7
7
|
const describe = commands.mcp.setup.describe;
|
|
8
8
|
async function handler(args) {
|
|
9
9
|
const { exit } = args;
|
|
10
10
|
try {
|
|
11
|
-
await
|
|
11
|
+
await configureMcpServer(args.client);
|
|
12
12
|
}
|
|
13
13
|
catch (e) {
|
|
14
14
|
return exit(EXIT_CODES.ERROR);
|
|
@@ -17,6 +17,7 @@ import { uiLogger } from '../../lib/ui/logger.js';
|
|
|
17
17
|
import { handleProjectCreationFlow, } from '../../lib/projects/create/index.js';
|
|
18
18
|
import { updateHsMetaFilesWithAutoGeneratedFields } from '../../lib/projects/components.js';
|
|
19
19
|
import SpinniesManager from '../../lib/ui/SpinniesManager.js';
|
|
20
|
+
import { showMcpPromotionNudge } from '../../lib/mcp/promotion.js';
|
|
20
21
|
const command = ['create', 'init'];
|
|
21
22
|
const describe = commands.project.create.describe;
|
|
22
23
|
const BETA_VERSIONS = [
|
|
@@ -107,6 +108,7 @@ async function handler(args) {
|
|
|
107
108
|
if (isProjectEmpty) {
|
|
108
109
|
fs.ensureDirSync(path.join(projectDest, 'src'));
|
|
109
110
|
}
|
|
111
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
110
112
|
return exit(EXIT_CODES.SUCCESS);
|
|
111
113
|
}
|
|
112
114
|
function projectCreateBuilder(yargs) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
+
type ProjectInstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
3
|
+
force: boolean;
|
|
4
|
+
profile?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const projectInstallAppCommand: YargsCommandModule<unknown, ProjectInstallAppArgs>;
|
|
7
|
+
export default projectInstallAppCommand;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { getConfigAccountIfExists } from '@hubspot/local-dev-lib/config';
|
|
2
|
+
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
3
|
+
import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
|
|
4
|
+
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
5
|
+
import { uiLogger } from '../../lib/ui/logger.js';
|
|
6
|
+
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
7
|
+
import { commands } from '../../lang/en.js';
|
|
8
|
+
import { getProjectConfig } from '../../lib/projects/config.js';
|
|
9
|
+
import { APP_INSTALLATION_STATES } from '../../lib/constants.js';
|
|
10
|
+
import { getAppInstallationState } from '../../lib/app/install.js';
|
|
11
|
+
import { confirmInstallAppAction, fetchProjectAppInstallationData, installStaticAuthAppForAccount, loadInstallableAppNode, resolveAppMetadata, resolveProjectId, resolveProjectAccountId, resolveValidInstallAccount, } from '../../lib/projects/installApp.js';
|
|
12
|
+
const command = 'install-app';
|
|
13
|
+
const describe = commands.project.installApp.describe;
|
|
14
|
+
const verboseDescribe = commands.project.installApp.verboseDescribe;
|
|
15
|
+
async function handler(args) {
|
|
16
|
+
const { derivedAccountId, formatOutputAsJson, force, profile: profileOption, useEnv: useEnvOption, exit, } = args;
|
|
17
|
+
const { projectConfig, projectDir } = await getProjectConfig();
|
|
18
|
+
if (!projectConfig || !projectDir) {
|
|
19
|
+
uiLogger.error(commands.project.installApp.errors.noProjectConfig);
|
|
20
|
+
return exit(EXIT_CODES.ERROR);
|
|
21
|
+
}
|
|
22
|
+
if (isLegacyProject(projectConfig.platformVersion)) {
|
|
23
|
+
uiLogger.error(commands.project.installApp.errors.unsupportedPlatformVersion(projectConfig.platformVersion));
|
|
24
|
+
return exit(EXIT_CODES.ERROR);
|
|
25
|
+
}
|
|
26
|
+
const resolvedProjectAccount = await resolveProjectAccountId(derivedAccountId, projectConfig, projectDir, profileOption, !!useEnvOption);
|
|
27
|
+
if (resolvedProjectAccount === null) {
|
|
28
|
+
return exit(EXIT_CODES.ERROR);
|
|
29
|
+
}
|
|
30
|
+
const appNode = await loadInstallableAppNode(projectConfig, projectDir, resolvedProjectAccount.accountId);
|
|
31
|
+
if (!appNode) {
|
|
32
|
+
return exit(EXIT_CODES.ERROR);
|
|
33
|
+
}
|
|
34
|
+
const installAccountId = await resolveValidInstallAccount(resolvedProjectAccount.accountId, force, Boolean(formatOutputAsJson));
|
|
35
|
+
if (installAccountId === null) {
|
|
36
|
+
return exit(EXIT_CODES.ERROR);
|
|
37
|
+
}
|
|
38
|
+
const targetAccountConfig = getConfigAccountIfExists(installAccountId);
|
|
39
|
+
// A profile only applies if we didn't switch away from its account.
|
|
40
|
+
const uploadProfile = installAccountId === resolvedProjectAccount.accountId
|
|
41
|
+
? resolvedProjectAccount.profileName
|
|
42
|
+
: undefined;
|
|
43
|
+
const projectId = await resolveProjectId({
|
|
44
|
+
accountId: installAccountId,
|
|
45
|
+
projectConfig,
|
|
46
|
+
projectDir,
|
|
47
|
+
profile: uploadProfile,
|
|
48
|
+
force,
|
|
49
|
+
formatOutputAsJson: Boolean(formatOutputAsJson),
|
|
50
|
+
});
|
|
51
|
+
if (projectId === null) {
|
|
52
|
+
return exit(EXIT_CODES.ERROR);
|
|
53
|
+
}
|
|
54
|
+
const installationData = await fetchProjectAppInstallationData(installAccountId, projectId, appNode, projectConfig);
|
|
55
|
+
if (installationData === null) {
|
|
56
|
+
return exit(EXIT_CODES.ERROR);
|
|
57
|
+
}
|
|
58
|
+
let appId = installationData.appId;
|
|
59
|
+
const { isInstalledWithScopeGroups, previouslyAuthorizedScopeGroups } = installationData;
|
|
60
|
+
const needsReinstall = !isInstalledWithScopeGroups && previouslyAuthorizedScopeGroups.length > 0;
|
|
61
|
+
const installationState = getAppInstallationState(isInstalledWithScopeGroups, previouslyAuthorizedScopeGroups);
|
|
62
|
+
if (isInstalledWithScopeGroups) {
|
|
63
|
+
if (formatOutputAsJson) {
|
|
64
|
+
uiLogger.json({
|
|
65
|
+
appId,
|
|
66
|
+
appUid: appNode.uid,
|
|
67
|
+
accountId: installAccountId,
|
|
68
|
+
projectId,
|
|
69
|
+
installationState,
|
|
70
|
+
installed: true,
|
|
71
|
+
reinstalled: false,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
uiLogger.success(commands.project.installApp.alreadyInstalled(appNode.config.name, installAccountId));
|
|
76
|
+
}
|
|
77
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
78
|
+
}
|
|
79
|
+
const shouldInstall = await confirmInstallAppAction({
|
|
80
|
+
appName: appNode.config.name,
|
|
81
|
+
targetAccountId: installAccountId,
|
|
82
|
+
force,
|
|
83
|
+
needsReinstall,
|
|
84
|
+
});
|
|
85
|
+
if (!shouldInstall) {
|
|
86
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
87
|
+
}
|
|
88
|
+
const metadata = await resolveAppMetadata({
|
|
89
|
+
appId,
|
|
90
|
+
projectId,
|
|
91
|
+
appUid: appNode.uid,
|
|
92
|
+
appName: appNode.config.name,
|
|
93
|
+
accountId: installAccountId,
|
|
94
|
+
projectConfig,
|
|
95
|
+
projectDir,
|
|
96
|
+
profile: uploadProfile,
|
|
97
|
+
force,
|
|
98
|
+
formatOutputAsJson: Boolean(formatOutputAsJson),
|
|
99
|
+
});
|
|
100
|
+
if (metadata === null) {
|
|
101
|
+
return exit(EXIT_CODES.ERROR);
|
|
102
|
+
}
|
|
103
|
+
appId = metadata.appId;
|
|
104
|
+
const installed = await installStaticAuthAppForAccount({
|
|
105
|
+
appId,
|
|
106
|
+
appNode,
|
|
107
|
+
appName: appNode.config.name,
|
|
108
|
+
targetAccountId: installAccountId,
|
|
109
|
+
targetAccountConfig,
|
|
110
|
+
projectId,
|
|
111
|
+
projectName: projectConfig.name,
|
|
112
|
+
scopeGroupIds: metadata.scopeGroupIds,
|
|
113
|
+
ownerPortalId: metadata.ownerPortalId,
|
|
114
|
+
installationState,
|
|
115
|
+
formatOutputAsJson: Boolean(formatOutputAsJson),
|
|
116
|
+
});
|
|
117
|
+
if (!installed) {
|
|
118
|
+
return exit(EXIT_CODES.ERROR);
|
|
119
|
+
}
|
|
120
|
+
if (formatOutputAsJson) {
|
|
121
|
+
uiLogger.json({
|
|
122
|
+
appId,
|
|
123
|
+
appUid: appNode.uid,
|
|
124
|
+
accountId: installAccountId,
|
|
125
|
+
projectId,
|
|
126
|
+
installationState: APP_INSTALLATION_STATES.INSTALLED,
|
|
127
|
+
installed: true,
|
|
128
|
+
reinstalled: needsReinstall,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
uiLogger.success(commands.project.installApp.success(appNode.config.name, installAccountId));
|
|
133
|
+
}
|
|
134
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
135
|
+
}
|
|
136
|
+
function projectInstallAppBuilder(yargs) {
|
|
137
|
+
yargs.options({
|
|
138
|
+
force: {
|
|
139
|
+
alias: ['f'],
|
|
140
|
+
describe: commands.project.installApp.options.force,
|
|
141
|
+
default: false,
|
|
142
|
+
type: 'boolean',
|
|
143
|
+
},
|
|
144
|
+
profile: {
|
|
145
|
+
alias: 'p',
|
|
146
|
+
describe: commands.project.installApp.options.profile,
|
|
147
|
+
type: 'string',
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
yargs.conflicts('profile', 'account');
|
|
151
|
+
yargs.example([
|
|
152
|
+
['$0 project install-app', commands.project.installApp.examples.default],
|
|
153
|
+
[
|
|
154
|
+
'$0 project install-app --account=12345678',
|
|
155
|
+
commands.project.installApp.examples.withAccount,
|
|
156
|
+
],
|
|
157
|
+
[
|
|
158
|
+
'$0 project install-app --profile=qa',
|
|
159
|
+
commands.project.installApp.examples.withProfile,
|
|
160
|
+
],
|
|
161
|
+
[
|
|
162
|
+
'$0 project install-app --json',
|
|
163
|
+
commands.project.installApp.examples.json,
|
|
164
|
+
],
|
|
165
|
+
]);
|
|
166
|
+
return yargs;
|
|
167
|
+
}
|
|
168
|
+
const builder = makeYargsBuilder(projectInstallAppBuilder, command, verboseDescribe, {
|
|
169
|
+
useGlobalOptions: true,
|
|
170
|
+
useConfigOptions: true,
|
|
171
|
+
useAccountOptions: true,
|
|
172
|
+
useEnvironmentOptions: true,
|
|
173
|
+
useJSONOutputOptions: true,
|
|
174
|
+
});
|
|
175
|
+
const projectInstallAppCommand = {
|
|
176
|
+
command,
|
|
177
|
+
describe,
|
|
178
|
+
handler: makeWrappedYargsHandler('project-install-app', handler),
|
|
179
|
+
builder,
|
|
180
|
+
};
|
|
181
|
+
export default projectInstallAppCommand;
|
|
@@ -9,6 +9,7 @@ import { uiLogger } from '../../lib/ui/logger.js';
|
|
|
9
9
|
import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
|
|
10
10
|
import { logError } from '../../lib/errorHandlers/index.js';
|
|
11
11
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
12
|
+
import { showMcpPromotionNudge } from '../../lib/mcp/promotion.js';
|
|
12
13
|
const command = 'install-deps [packages..]';
|
|
13
14
|
const describe = commands.project.installDeps.help.describe;
|
|
14
15
|
async function handler(args) {
|
|
@@ -48,6 +49,7 @@ async function handler(args) {
|
|
|
48
49
|
packages,
|
|
49
50
|
installLocations,
|
|
50
51
|
});
|
|
52
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
51
53
|
}
|
|
52
54
|
catch (e) {
|
|
53
55
|
if (isPromptExitError(e)) {
|
|
@@ -16,6 +16,7 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
|
16
16
|
import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
|
|
17
17
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
18
18
|
import { projectProfilePrompt } from '../../lib/prompts/projectProfilePrompt.js';
|
|
19
|
+
import { showMcpPromotionNudge } from '../../lib/mcp/promotion.js';
|
|
19
20
|
const command = 'upload';
|
|
20
21
|
const describe = commands.project.upload.describe;
|
|
21
22
|
async function handlePreview(accountId, projectId, buildId, targetPortalId) {
|
|
@@ -144,6 +145,9 @@ async function handler(args) {
|
|
|
144
145
|
if (formatOutputAsJson) {
|
|
145
146
|
uiLogger.json(jsonOutput);
|
|
146
147
|
}
|
|
148
|
+
else {
|
|
149
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
150
|
+
}
|
|
147
151
|
return exit(EXIT_CODES.SUCCESS);
|
|
148
152
|
}
|
|
149
153
|
function projectUploadBuilder(yargs) {
|
package/commands/project.js
CHANGED
|
@@ -21,6 +21,7 @@ import list from './project/list.js';
|
|
|
21
21
|
import info from './project/info.js';
|
|
22
22
|
import deleteProject from './project/delete.js';
|
|
23
23
|
import appInstallStatus from './project/appInstallStatus.js';
|
|
24
|
+
import installApp from './project/installApp.js';
|
|
24
25
|
import { makeYargsBuilder } from '../lib/yargsUtils.js';
|
|
25
26
|
import { getProjectConfig } from '../lib/projects/config.js';
|
|
26
27
|
import { isSupportedPlatformVersion, LATEST_SUPPORTED_PLATFORM_VERSION, } from '@hubspot/project-parsing-lib/projects';
|
|
@@ -70,6 +71,7 @@ function projectBuilder(yargs) {
|
|
|
70
71
|
.command(release)
|
|
71
72
|
.command(projectValidate)
|
|
72
73
|
.command(appInstallStatus)
|
|
74
|
+
.command(installApp)
|
|
73
75
|
.demandCommand(1, '');
|
|
74
76
|
return yargs;
|
|
75
77
|
}
|
package/commands/upgrade.js
CHANGED
|
@@ -11,6 +11,7 @@ import { getLatestCliVersion } from '../lib/cliUpgradeUtils.js';
|
|
|
11
11
|
import { pkg } from '../lib/jsonLoader.js';
|
|
12
12
|
import SpinniesManager from '../lib/ui/SpinniesManager.js';
|
|
13
13
|
import { debugError } from '../lib/errorHandlers/index.js';
|
|
14
|
+
import { showMcpPromotionNudge } from '../lib/mcp/promotion.js';
|
|
14
15
|
const command = ['upgrade [version]', 'update [version]'];
|
|
15
16
|
const describe = commands.upgrade.describe;
|
|
16
17
|
const handler = async (args) => {
|
|
@@ -84,6 +85,7 @@ const handler = async (args) => {
|
|
|
84
85
|
uiLogger.log('');
|
|
85
86
|
uiLogger.log(commands.upgrade.autoUpgradeMessage);
|
|
86
87
|
}
|
|
88
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
87
89
|
return exit(EXIT_CODES.SUCCESS);
|
|
88
90
|
};
|
|
89
91
|
function upgradeBuilder(yargs) {
|
package/lang/en.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HubSpotConfigAccount } from '@hubspot/local-dev-lib/types/Accounts';
|
|
2
|
+
import { LocallyChangedComponents } from '../types/Projects.js';
|
|
2
3
|
export declare const commands: {
|
|
3
4
|
generalErrors: {
|
|
4
5
|
srcIsProject: (src: string, command: string) => string;
|
|
@@ -1315,6 +1316,9 @@ export declare const commands: {
|
|
|
1315
1316
|
};
|
|
1316
1317
|
mcp: {
|
|
1317
1318
|
describe: string;
|
|
1319
|
+
promotion: {
|
|
1320
|
+
activeNudge: string;
|
|
1321
|
+
};
|
|
1318
1322
|
setup: {
|
|
1319
1323
|
describe: string;
|
|
1320
1324
|
installingDocSearch: string;
|
|
@@ -2167,6 +2171,47 @@ export declare const commands: {
|
|
|
2167
2171
|
force: string;
|
|
2168
2172
|
};
|
|
2169
2173
|
};
|
|
2174
|
+
installApp: {
|
|
2175
|
+
describe: string;
|
|
2176
|
+
verboseDescribe: string;
|
|
2177
|
+
examples: {
|
|
2178
|
+
default: string;
|
|
2179
|
+
withAccount: string;
|
|
2180
|
+
withProfile: string;
|
|
2181
|
+
json: string;
|
|
2182
|
+
};
|
|
2183
|
+
options: {
|
|
2184
|
+
force: string;
|
|
2185
|
+
profile: string;
|
|
2186
|
+
};
|
|
2187
|
+
errors: {
|
|
2188
|
+
noProjectConfig: string;
|
|
2189
|
+
unsupportedPlatformVersion: (platformVersion: string) => string;
|
|
2190
|
+
failedToParseProject: string;
|
|
2191
|
+
noAppInProject: string;
|
|
2192
|
+
unsupportedAuthType: (authType: string) => string;
|
|
2193
|
+
unsupportedDistribution: (distribution: string) => string;
|
|
2194
|
+
invalidAppDeveloperAccount: (accountId: number) => string;
|
|
2195
|
+
projectNotFound: (accountId: number, projectName: string) => string;
|
|
2196
|
+
appNotDeployed: (appName: string, accountId: number) => string;
|
|
2197
|
+
automaticInstallUnavailable: (appName: string, accountId: number) => string;
|
|
2198
|
+
installFailed: (appName: string, accountId: number) => string;
|
|
2199
|
+
};
|
|
2200
|
+
jsonErrors: {
|
|
2201
|
+
automaticInstallUnavailable: string;
|
|
2202
|
+
installFailed: (appName: string, accountId: number) => string;
|
|
2203
|
+
};
|
|
2204
|
+
profileMessage: (profileName: string, accountId: number) => string;
|
|
2205
|
+
appDeveloperAccountNotice: (accountId: number) => string;
|
|
2206
|
+
selectInstallAccountPrompt: string;
|
|
2207
|
+
uploadAndDeployPrompt: (accountId: number) => string;
|
|
2208
|
+
alreadyInstalled: (appName: string, accountId: number) => string;
|
|
2209
|
+
outdatedScopes: (appName: string, accountId: number) => string;
|
|
2210
|
+
reinstallPrompt: string;
|
|
2211
|
+
installPrompt: (appName: string, accountId: number) => string;
|
|
2212
|
+
installFromBrowser: (installUrl: string) => string;
|
|
2213
|
+
success: (appName: string, accountId: number) => string;
|
|
2214
|
+
};
|
|
2170
2215
|
installStatus: {
|
|
2171
2216
|
describe: string;
|
|
2172
2217
|
examples: {
|
|
@@ -3268,6 +3313,11 @@ export declare const lib: {
|
|
|
3268
3313
|
configMiddleWare: {
|
|
3269
3314
|
invalidAccountIdEnvironmentVariable: string;
|
|
3270
3315
|
};
|
|
3316
|
+
accountTargetDiscovery: {
|
|
3317
|
+
errors: {
|
|
3318
|
+
explicitAccountNotFound: (account: string | number) => string;
|
|
3319
|
+
};
|
|
3320
|
+
};
|
|
3271
3321
|
process: {
|
|
3272
3322
|
exitDebug: (signal: string) => string;
|
|
3273
3323
|
};
|
|
@@ -3394,7 +3444,9 @@ export declare const lib: {
|
|
|
3394
3444
|
checking: string;
|
|
3395
3445
|
upToDate: string;
|
|
3396
3446
|
notUpToDate: string;
|
|
3447
|
+
changedFiles: (changed: LocallyChangedComponents) => string;
|
|
3397
3448
|
notUpToDateExplanation: (profile?: string) => string;
|
|
3449
|
+
unableToCompare: string;
|
|
3398
3450
|
};
|
|
3399
3451
|
createNewProjectForLocalDev: {
|
|
3400
3452
|
projectMustExistExplanation: (projectName: string, accountId: number) => string;
|
|
@@ -3834,6 +3886,7 @@ export declare const lib: {
|
|
|
3834
3886
|
confirmUseExistingDeveloperTestAccount: (accountName: string) => string;
|
|
3835
3887
|
confirmLinkExistingDeveloperTestAccount: (accountName: string) => string;
|
|
3836
3888
|
noAccountId: string;
|
|
3889
|
+
fetchDeveloperTestAccountsError: string;
|
|
3837
3890
|
};
|
|
3838
3891
|
projectLogsPrompt: {
|
|
3839
3892
|
functionName: (projectName: string) => string;
|
|
@@ -4238,6 +4291,11 @@ export declare const lib: {
|
|
|
4238
4291
|
installed: (npmVersion: string) => string;
|
|
4239
4292
|
unableToDetermine: string;
|
|
4240
4293
|
};
|
|
4294
|
+
mcpChecks: {
|
|
4295
|
+
configured: (clients: string[]) => string;
|
|
4296
|
+
notConfigured: (clients: string[]) => string;
|
|
4297
|
+
notConfiguredSecondary: string;
|
|
4298
|
+
};
|
|
4241
4299
|
hsChecks: {
|
|
4242
4300
|
notLatest: (hsVersion: string) => string;
|
|
4243
4301
|
notLatestSecondary: (command: string, hsVersion: string) => string;
|
package/lang/en.js
CHANGED
|
@@ -1325,8 +1325,11 @@ export const commands = {
|
|
|
1325
1325
|
},
|
|
1326
1326
|
mcp: {
|
|
1327
1327
|
describe: 'Commands for managing HubSpot MCP servers.',
|
|
1328
|
+
promotion: {
|
|
1329
|
+
activeNudge: `${chalk.bold('Tip:')} Work faster with AI coding tools. Run ${uiCommandReference('hs mcp setup')} to connect HubSpot developer context to supported clients.`,
|
|
1330
|
+
},
|
|
1328
1331
|
setup: {
|
|
1329
|
-
describe: '
|
|
1332
|
+
describe: `Run ${uiCommandReference('hs mcp setup')} to connect the HubSpot Dev MCP and work faster with your AI coding tools.`,
|
|
1330
1333
|
installingDocSearch: 'Adding the docs-search mcp server',
|
|
1331
1334
|
codex: 'Codex CLI',
|
|
1332
1335
|
claudeCode: 'Claude Code',
|
|
@@ -2192,6 +2195,47 @@ export const commands = {
|
|
|
2192
2195
|
force: 'skip confirmation prompt',
|
|
2193
2196
|
},
|
|
2194
2197
|
},
|
|
2198
|
+
installApp: {
|
|
2199
|
+
describe: 'Install a static auth app from the current project into the target account',
|
|
2200
|
+
verboseDescribe: `Install a static auth app from the current project into the target account.\n\nRun this command from within the project directory. The project must contain a privately distributed static auth app and must already be uploaded to the target account.`,
|
|
2201
|
+
examples: {
|
|
2202
|
+
default: 'Install the static auth app from the current project',
|
|
2203
|
+
withAccount: 'Install the app into a specific account',
|
|
2204
|
+
withProfile: 'Install the app into the account targeted by a profile',
|
|
2205
|
+
json: 'Output install result as JSON',
|
|
2206
|
+
},
|
|
2207
|
+
options: {
|
|
2208
|
+
force: 'Skip confirmation prompts',
|
|
2209
|
+
profile: 'The profile to target with this install',
|
|
2210
|
+
},
|
|
2211
|
+
errors: {
|
|
2212
|
+
noProjectConfig: `No project config found. Run this command from within a HubSpot project directory, or use ${uiCommandReference('hs project create')} to create a new one.`,
|
|
2213
|
+
unsupportedPlatformVersion: (platformVersion) => `This command is only supported for projects on platform version 2025.2 or later (detected: ${platformVersion}).`,
|
|
2214
|
+
failedToParseProject: 'Failed to parse the project. Check your project configuration is valid and try again.',
|
|
2215
|
+
noAppInProject: 'No app was found in the local project. This command requires a project that contains an app.',
|
|
2216
|
+
unsupportedAuthType: (authType) => `This command only supports static auth apps. Detected auth type: ${authType}.`,
|
|
2217
|
+
unsupportedDistribution: (distribution) => `This command only supports privately distributed apps. Detected distribution: ${distribution}.`,
|
|
2218
|
+
invalidAppDeveloperAccount: (accountId) => `Static auth apps can't be installed into the app developer account ${uiAccountDescription(accountId)}. Switch to a standard, sandbox, or developer test account with ${uiCommandReference('hs account use')}, or pass ${uiCommandReference('--account')}.`,
|
|
2219
|
+
projectNotFound: (accountId, projectName) => `The project ${chalk.bold(projectName)} does not exist in ${uiAccountDescription(accountId)}. Run ${uiCommandReference('hs project upload')} to upload your project files to HubSpot.`,
|
|
2220
|
+
appNotDeployed: (appName, accountId) => `The app ${chalk.bold(appName)} has not been deployed to ${uiAccountDescription(accountId)}. Upload the project with ${uiCommandReference('hs project upload')} and ensure the build succeeds, then try again.`,
|
|
2221
|
+
automaticInstallUnavailable: (appName, accountId) => `${chalk.bold(appName)} could not be installed automatically in ${uiAccountDescription(accountId)}.`,
|
|
2222
|
+
installFailed: (appName, accountId) => `Failed to install ${chalk.bold(appName)} in ${uiAccountDescription(accountId)}.`,
|
|
2223
|
+
},
|
|
2224
|
+
jsonErrors: {
|
|
2225
|
+
automaticInstallUnavailable: 'Automatic install is unavailable for this account.',
|
|
2226
|
+
installFailed: (appName, accountId) => `Failed to install ${appName} in account ${accountId}.`,
|
|
2227
|
+
},
|
|
2228
|
+
profileMessage: (profileName, accountId) => `Installing with ${chalk.bold(profileName)} profile: ${uiAccountDescription(accountId)}`,
|
|
2229
|
+
appDeveloperAccountNotice: (accountId) => `${uiAccountDescription(accountId)} is an app developer account, which can't have apps installed into it.`,
|
|
2230
|
+
selectInstallAccountPrompt: 'Select an account to install the app into',
|
|
2231
|
+
uploadAndDeployPrompt: (accountId) => `The app isn't deployed to ${uiAccountDescription(accountId)} yet. Upload and deploy the project now?`,
|
|
2232
|
+
alreadyInstalled: (appName, accountId) => `${chalk.bold(appName)} is already installed in ${uiAccountDescription(accountId)}.`,
|
|
2233
|
+
outdatedScopes: (appName, accountId) => `${chalk.bold(appName)} is installed in ${uiAccountDescription(accountId)} with outdated scopes.`,
|
|
2234
|
+
reinstallPrompt: 'Reinstall the app to grant the latest scopes?',
|
|
2235
|
+
installPrompt: (appName, accountId) => `Install ${chalk.bold(appName)} in ${uiAccountDescription(accountId)}?`,
|
|
2236
|
+
installFromBrowser: (installUrl) => `Install the app in HubSpot: ${uiLink('Open install page', installUrl)}`,
|
|
2237
|
+
success: (appName, accountId) => `${chalk.bold(appName)} installed in ${uiAccountDescription(accountId)}.`,
|
|
2238
|
+
},
|
|
2195
2239
|
installStatus: {
|
|
2196
2240
|
describe: 'Check whether a static auth app in the current project is installed in the target account. This command must be run from within a HubSpot project directory.',
|
|
2197
2241
|
examples: {
|
|
@@ -2632,7 +2676,7 @@ export const commands = {
|
|
|
2632
2676
|
serviceLevel: 'Service Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
|
|
2633
2677
|
salesLevel: 'Sales Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
|
|
2634
2678
|
contentLevel: 'Content Hub tier. Options: FREE, STARTER, PROFESSIONAL, ENTERPRISE',
|
|
2635
|
-
commerceLevel: '
|
|
2679
|
+
commerceLevel: 'Revenue Hub tier. Options: FREE, PROFESSIONAL, ENTERPRISE',
|
|
2636
2680
|
},
|
|
2637
2681
|
example: (configPath) => `Create a test account from the config file at ${configPath}`,
|
|
2638
2682
|
examples: {
|
|
@@ -3293,6 +3337,11 @@ export const lib = {
|
|
|
3293
3337
|
configMiddleWare: {
|
|
3294
3338
|
invalidAccountIdEnvironmentVariable: 'Unable to parse `HUBSPOT_ACCOUNT_ID` environment variable into a number',
|
|
3295
3339
|
},
|
|
3340
|
+
accountTargetDiscovery: {
|
|
3341
|
+
errors: {
|
|
3342
|
+
explicitAccountNotFound: (account) => `Account ${chalk.bold(String(account))} was not found in your config. Run ${uiCommandReference('hs account list')} to see available accounts.`,
|
|
3343
|
+
},
|
|
3344
|
+
},
|
|
3296
3345
|
process: {
|
|
3297
3346
|
exitDebug: (signal) => `Attempting to gracefully exit. Triggered by ${signal}`,
|
|
3298
3347
|
},
|
|
@@ -3419,7 +3468,21 @@ export const lib = {
|
|
|
3419
3468
|
checking: 'Checking if your deployed build is up to date...',
|
|
3420
3469
|
upToDate: 'Deployed build is up to date.',
|
|
3421
3470
|
notUpToDate: `Your project contains undeployed local changes.`,
|
|
3471
|
+
changedFiles: (changed) => {
|
|
3472
|
+
const sections = [];
|
|
3473
|
+
if (changed.added.length > 0) {
|
|
3474
|
+
sections.push(`${chalk.bold('Features Added:')}\n${changed.added.map(f => ` - ${f}`).join('\n')}`);
|
|
3475
|
+
}
|
|
3476
|
+
if (changed.updated.length > 0) {
|
|
3477
|
+
sections.push(`${chalk.bold('Features Modified:')}\n${changed.updated.map(f => ` - ${f}`).join('\n')}`);
|
|
3478
|
+
}
|
|
3479
|
+
if (changed.removed.length > 0) {
|
|
3480
|
+
sections.push(`${chalk.bold('Features Removed:')}\n${changed.removed.map(f => ` - ${f}`).join('\n')}`);
|
|
3481
|
+
}
|
|
3482
|
+
return sections.join('\n\n');
|
|
3483
|
+
},
|
|
3422
3484
|
notUpToDateExplanation: (profile) => `Run ${uiCommandReference(`hs project upload${profile ? ` --profile ${profile}` : ''}`)} to upload these changes to HubSpot, then re-run ${uiCommandReference(`hs project dev${profile ? ` --profile ${profile}` : ''}`)} to continue local development.`,
|
|
3485
|
+
unableToCompare: `Unable to check if local *-hsmeta.json files match the deployed build. Run ${uiCommandReference('hs project upload')} to upload any local changes before continuing.`,
|
|
3423
3486
|
},
|
|
3424
3487
|
createNewProjectForLocalDev: {
|
|
3425
3488
|
projectMustExistExplanation: (projectName, accountId) => `The project ${projectName} does not exist in the target account ${uiAccountDescription(accountId)}. This command requires the project to exist in the target account.`,
|
|
@@ -3859,6 +3922,7 @@ export const lib = {
|
|
|
3859
3922
|
confirmUseExistingDeveloperTestAccount: (accountName) => `Continue with ${accountName}? This account isn't currently connected to the HubSpot CLI. By continuing, you'll be prompted to generate a personal access key and connect it.`,
|
|
3860
3923
|
confirmLinkExistingDeveloperTestAccount: (accountName) => `${accountName} is not linked to this directory. Would you like to link it?`,
|
|
3861
3924
|
noAccountId: 'No account ID found for the selected account. Please try again.',
|
|
3925
|
+
fetchDeveloperTestAccountsError: 'Unable to fetch developer test accounts. Please try again.',
|
|
3862
3926
|
},
|
|
3863
3927
|
projectLogsPrompt: {
|
|
3864
3928
|
functionName: (projectName) => `[--function] Select function in ${chalk.bold(projectName)} project`,
|
|
@@ -4263,6 +4327,11 @@ export const lib = {
|
|
|
4263
4327
|
installed: (npmVersion) => `npm v${npmVersion} is installed`,
|
|
4264
4328
|
unableToDetermine: 'Unable to determine if npm is installed',
|
|
4265
4329
|
},
|
|
4330
|
+
mcpChecks: {
|
|
4331
|
+
configured: (clients) => `HubSpot MCP server configured in ${clients.join(', ')}`,
|
|
4332
|
+
notConfigured: (clients) => `HubSpot MCP server not configured in ${clients.join(', ')}`,
|
|
4333
|
+
notConfiguredSecondary: `Run ${uiCommandReference('hs mcp setup')} to connect AI coding tools to HubSpot developer context`,
|
|
4334
|
+
},
|
|
4266
4335
|
hsChecks: {
|
|
4267
4336
|
notLatest: (hsVersion) => `Version ${hsVersion} outdated`,
|
|
4268
4337
|
notLatestSecondary: (command, hsVersion) => `Run ${uiCommandReference(command)} to upgrade to the latest version ${hsVersion}`,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DiscoverAccountTargetsOptions, DiscoverAccountTargetsResult } from '../types/AccountTargets.js';
|
|
2
|
+
/**
|
|
3
|
+
* Discovers the candidate target accounts for a command, plus the recommended
|
|
4
|
+
* one to use when a single account is the obvious choice.
|
|
5
|
+
*
|
|
6
|
+
* Profiles take precedence: when the project defines profiles, the candidates
|
|
7
|
+
* are the profile accounts only. Otherwise they are ranked explicit account,
|
|
8
|
+
* then env config, then linked directory, then global default.
|
|
9
|
+
*
|
|
10
|
+
* Takes plain options (not yargs argv) and never prompts or exits, so both the
|
|
11
|
+
* CLI and MCP can call it. `recommended` is omitted when no account is the
|
|
12
|
+
* obvious choice (for example, several profiles). Throws when an explicit
|
|
13
|
+
* account is provided but not found in the config.
|
|
14
|
+
*/
|
|
15
|
+
export declare function discoverAccountTargets(options?: DiscoverAccountTargetsOptions): Promise<DiscoverAccountTargetsResult>;
|