@hubspot/cli 8.9.1-beta.0 → 8.10.0-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/account/auth.js +2 -0
- package/commands/app/logs.js +4 -0
- package/commands/getStarted.js +3 -0
- package/commands/init.js +2 -0
- package/commands/mcp/setup.js +2 -2
- package/commands/project/appInstallStatus.js +2 -2
- package/commands/project/create.js +2 -0
- package/commands/project/dev/unifiedFlow.js +3 -1
- 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.d.ts +2 -0
- package/commands/project/upload.js +26 -5
- package/commands/project.js +2 -0
- package/commands/upgrade.js +2 -0
- package/lang/en.d.ts +66 -0
- package/lang/en.js +73 -7
- 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/getStartedV2Actions.js +2 -1
- 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 +283 -0
- package/lib/projects/localDev/AppDevModeInterface.d.ts +0 -3
- package/lib/projects/localDev/AppDevModeInterface.js +22 -44
- package/lib/projects/localDev/LocalDevProcess.js +4 -2
- package/lib/projects/localDev/helpers/project.js +3 -2
- package/lib/projects/ui.d.ts +1 -0
- package/lib/projects/ui.js +14 -0
- package/lib/projects/upload.d.ts +10 -2
- package/lib/projects/upload.js +15 -4
- 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/mcp-server/tools/project/UploadProjectTools.js +1 -1
- package/package.json +5 -5
- 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/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) {
|
|
@@ -206,6 +207,7 @@ async function handler(args) {
|
|
|
206
207
|
isUploadCommand: false,
|
|
207
208
|
sendIR: !isLegacyProject(newProjectConfig.platformVersion),
|
|
208
209
|
skipValidation: false,
|
|
210
|
+
force: true,
|
|
209
211
|
});
|
|
210
212
|
if (uploadError) {
|
|
211
213
|
// Track upload failure
|
|
@@ -275,6 +277,7 @@ async function handler(args) {
|
|
|
275
277
|
return exit(EXIT_CODES.SUCCESS);
|
|
276
278
|
}
|
|
277
279
|
}
|
|
280
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
278
281
|
// Track successful completion of get-started command
|
|
279
282
|
await trackCommandMetadataUsage('get-started', {
|
|
280
283
|
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);
|
|
@@ -28,12 +28,12 @@ async function handler(args) {
|
|
|
28
28
|
}
|
|
29
29
|
let appNode;
|
|
30
30
|
try {
|
|
31
|
-
const {
|
|
31
|
+
const { intermediateRepresentation } = await translateForLocalDev({
|
|
32
32
|
projectSourceDir: path.join(projectDir, projectConfig.srcDir),
|
|
33
33
|
platformVersion: projectConfig.platformVersion,
|
|
34
34
|
accountId: derivedAccountId,
|
|
35
35
|
}, { skipValidation: true });
|
|
36
|
-
appNode = Object.values(intermediateNodesIndexedByUid).find(isAppIRNode);
|
|
36
|
+
appNode = Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).find(isAppIRNode);
|
|
37
37
|
}
|
|
38
38
|
catch (error) {
|
|
39
39
|
debugError(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) {
|
|
@@ -6,6 +6,7 @@ import { isTranslationError, translateForLocalDev, } from '@hubspot/project-pars
|
|
|
6
6
|
import { getConfigAccountEnvironment, getLinkedOrAllConfigAccounts, getConfigAccountById, getConfigAccountIfExists, } from '@hubspot/local-dev-lib/config';
|
|
7
7
|
import { logError } from '../../../lib/errorHandlers/index.js';
|
|
8
8
|
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
9
|
+
import { warnAboutSkippedHsMetaFiles } from '../../../lib/projects/ui.js';
|
|
9
10
|
import { ensureProjectExists } from '../../../lib/projects/ensureProjectExists.js';
|
|
10
11
|
import { createInitialBuildForNewProject, createNewProjectForLocalDev, compareLocalProjectToDeployed, checkAndInstallDependencies, } from '../../../lib/projects/localDev/helpers/project.js';
|
|
11
12
|
import { useExistingDevTestAccount, createDeveloperTestAccountForLocalDev, selectAccountTypePrompt, createSandboxForLocalDev, } from '../../../lib/projects/localDev/helpers/account.js';
|
|
@@ -31,7 +32,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
31
32
|
let projectProfileData;
|
|
32
33
|
// Get IR
|
|
33
34
|
try {
|
|
34
|
-
const intermediateRepresentation = await translateForLocalDev({
|
|
35
|
+
const { intermediateRepresentation, skippedHsMetaFiles } = await translateForLocalDev({
|
|
35
36
|
projectSourceDir: path.join(projectDir, projectConfig.srcDir),
|
|
36
37
|
platformVersion: projectConfig.platformVersion,
|
|
37
38
|
accountId: targetProjectAccountId,
|
|
@@ -39,6 +40,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
39
40
|
projectNodes = intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
40
41
|
projectProfileData = intermediateRepresentation.profileData;
|
|
41
42
|
uiLogger.debug(util.inspect(projectNodes, false, null, true));
|
|
43
|
+
await warnAboutSkippedHsMetaFiles(skippedHsMetaFiles, true, false);
|
|
42
44
|
}
|
|
43
45
|
catch (e) {
|
|
44
46
|
if (isTranslationError(e)) {
|
|
@@ -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, force);
|
|
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)) {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { CommonArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
2
|
export type ProjectUploadArgs = CommonArgs & JSONOutputArgs & {
|
|
3
|
+
force: boolean;
|
|
3
4
|
forceCreate: boolean;
|
|
4
5
|
message: string;
|
|
5
6
|
m: string;
|
|
6
7
|
skipValidation: boolean;
|
|
7
8
|
skipNpmAudit: boolean;
|
|
9
|
+
skipAutoDeploy: boolean;
|
|
8
10
|
profile?: string;
|
|
9
11
|
preview: boolean;
|
|
10
12
|
target?: number;
|
|
@@ -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) {
|
|
@@ -33,7 +34,7 @@ async function handlePreview(accountId, projectId, buildId, targetPortalId) {
|
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
async function handler(args) {
|
|
36
|
-
const { forceCreate, message, derivedAccountId, skipValidation, skipNpmAudit, formatOutputAsJson, profile: profileOption, useEnv: useEnvOption, preview, target: targetPortalId, exit, addUsageMetadata, } = args;
|
|
37
|
+
const { force = false, forceCreate = false, message, derivedAccountId, skipValidation, skipNpmAudit, skipAutoDeploy, formatOutputAsJson, profile: profileOption, useEnv: useEnvOption, preview, target: targetPortalId, exit, addUsageMetadata, } = args;
|
|
37
38
|
const jsonOutput = {};
|
|
38
39
|
const { projectConfig, projectDir } = await getProjectConfig();
|
|
39
40
|
try {
|
|
@@ -71,21 +72,26 @@ async function handler(args) {
|
|
|
71
72
|
assetType: projectConfig.platformVersion,
|
|
72
73
|
});
|
|
73
74
|
try {
|
|
74
|
-
const { result, uploadError, projectId } = await handleProjectUpload({
|
|
75
|
+
const { result, uploadError, projectId, userDeclined } = await handleProjectUpload({
|
|
75
76
|
accountId: targetAccountId,
|
|
76
77
|
projectConfig,
|
|
77
78
|
projectDir,
|
|
78
|
-
callbackFunc: preview
|
|
79
|
+
callbackFunc: preview || skipAutoDeploy
|
|
79
80
|
? (...args) => pollProjectBuildAndDeploy(...args, { skipDeploy: true })
|
|
80
81
|
: pollProjectBuildAndDeploy,
|
|
81
82
|
uploadMessage: message,
|
|
82
|
-
forceCreate,
|
|
83
|
+
forceCreate: forceCreate || force,
|
|
83
84
|
isUploadCommand: true,
|
|
84
85
|
sendIR: !isLegacyProject(projectConfig.platformVersion),
|
|
85
86
|
skipValidation,
|
|
86
87
|
skipNpmAudit,
|
|
88
|
+
skipAutoDeploy,
|
|
87
89
|
profile: profileName,
|
|
90
|
+
force,
|
|
88
91
|
});
|
|
92
|
+
if (userDeclined) {
|
|
93
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
94
|
+
}
|
|
89
95
|
if (uploadError) {
|
|
90
96
|
if (isSpecifiedError(uploadError, {
|
|
91
97
|
subCategory: PROJECT_ERROR_TYPES.PROJECT_LOCKED,
|
|
@@ -104,7 +110,7 @@ async function handler(args) {
|
|
|
104
110
|
}
|
|
105
111
|
if (result &&
|
|
106
112
|
result.succeeded &&
|
|
107
|
-
(!result.buildResult.isAutoDeployEnabled || preview)) {
|
|
113
|
+
(!result.buildResult.isAutoDeployEnabled || preview || skipAutoDeploy)) {
|
|
108
114
|
uiLogger.log(chalk.bold(commands.project.upload.logs.buildSucceeded(result.buildId)));
|
|
109
115
|
if (!preview) {
|
|
110
116
|
uiLogger.log(commands.project.upload.logs.autoDeployDisabled(`hs project deploy --build=${result.buildId}`));
|
|
@@ -144,14 +150,24 @@ async function handler(args) {
|
|
|
144
150
|
if (formatOutputAsJson) {
|
|
145
151
|
uiLogger.json(jsonOutput);
|
|
146
152
|
}
|
|
153
|
+
else {
|
|
154
|
+
await showMcpPromotionNudge(args._.join(' '));
|
|
155
|
+
}
|
|
147
156
|
return exit(EXIT_CODES.SUCCESS);
|
|
148
157
|
}
|
|
149
158
|
function projectUploadBuilder(yargs) {
|
|
150
159
|
yargs.options({
|
|
160
|
+
force: {
|
|
161
|
+
alias: 'f',
|
|
162
|
+
describe: commands.project.upload.options.force.describe,
|
|
163
|
+
type: 'boolean',
|
|
164
|
+
default: false,
|
|
165
|
+
},
|
|
151
166
|
'force-create': {
|
|
152
167
|
describe: commands.project.upload.options.forceCreate.describe,
|
|
153
168
|
type: 'boolean',
|
|
154
169
|
default: false,
|
|
170
|
+
hidden: true,
|
|
155
171
|
},
|
|
156
172
|
message: {
|
|
157
173
|
alias: 'm',
|
|
@@ -169,6 +185,11 @@ function projectUploadBuilder(yargs) {
|
|
|
169
185
|
type: 'boolean',
|
|
170
186
|
default: false,
|
|
171
187
|
},
|
|
188
|
+
'skip-auto-deploy': {
|
|
189
|
+
describe: commands.project.upload.options.skipAutoDeploy.describe,
|
|
190
|
+
type: 'boolean',
|
|
191
|
+
default: false,
|
|
192
|
+
},
|
|
172
193
|
profile: {
|
|
173
194
|
type: 'string',
|
|
174
195
|
alias: 'p',
|
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
|
@@ -1316,6 +1316,9 @@ export declare const commands: {
|
|
|
1316
1316
|
};
|
|
1317
1317
|
mcp: {
|
|
1318
1318
|
describe: string;
|
|
1319
|
+
promotion: {
|
|
1320
|
+
activeNudge: string;
|
|
1321
|
+
};
|
|
1319
1322
|
setup: {
|
|
1320
1323
|
describe: string;
|
|
1321
1324
|
installingDocSearch: string;
|
|
@@ -1885,6 +1888,9 @@ export declare const commands: {
|
|
|
1885
1888
|
targetRequiresPreview: string;
|
|
1886
1889
|
};
|
|
1887
1890
|
options: {
|
|
1891
|
+
force: {
|
|
1892
|
+
describe: string;
|
|
1893
|
+
};
|
|
1888
1894
|
forceCreate: {
|
|
1889
1895
|
describe: string;
|
|
1890
1896
|
};
|
|
@@ -1897,6 +1903,9 @@ export declare const commands: {
|
|
|
1897
1903
|
skipNpmAudit: {
|
|
1898
1904
|
describe: string;
|
|
1899
1905
|
};
|
|
1906
|
+
skipAutoDeploy: {
|
|
1907
|
+
describe: string;
|
|
1908
|
+
};
|
|
1900
1909
|
preview: {
|
|
1901
1910
|
describe: string;
|
|
1902
1911
|
};
|
|
@@ -2168,6 +2177,47 @@ export declare const commands: {
|
|
|
2168
2177
|
force: string;
|
|
2169
2178
|
};
|
|
2170
2179
|
};
|
|
2180
|
+
installApp: {
|
|
2181
|
+
describe: string;
|
|
2182
|
+
verboseDescribe: string;
|
|
2183
|
+
examples: {
|
|
2184
|
+
default: string;
|
|
2185
|
+
withAccount: string;
|
|
2186
|
+
withProfile: string;
|
|
2187
|
+
json: string;
|
|
2188
|
+
};
|
|
2189
|
+
options: {
|
|
2190
|
+
force: string;
|
|
2191
|
+
profile: string;
|
|
2192
|
+
};
|
|
2193
|
+
errors: {
|
|
2194
|
+
noProjectConfig: string;
|
|
2195
|
+
unsupportedPlatformVersion: (platformVersion: string) => string;
|
|
2196
|
+
failedToParseProject: string;
|
|
2197
|
+
noAppInProject: string;
|
|
2198
|
+
unsupportedAuthType: (authType: string) => string;
|
|
2199
|
+
unsupportedDistribution: (distribution: string) => string;
|
|
2200
|
+
invalidAppDeveloperAccount: (accountId: number) => string;
|
|
2201
|
+
projectNotFound: (accountId: number, projectName: string) => string;
|
|
2202
|
+
appNotDeployed: (appName: string, accountId: number) => string;
|
|
2203
|
+
automaticInstallUnavailable: (appName: string, accountId: number) => string;
|
|
2204
|
+
installFailed: (appName: string, accountId: number) => string;
|
|
2205
|
+
};
|
|
2206
|
+
jsonErrors: {
|
|
2207
|
+
automaticInstallUnavailable: string;
|
|
2208
|
+
installFailed: (appName: string, accountId: number) => string;
|
|
2209
|
+
};
|
|
2210
|
+
profileMessage: (profileName: string, accountId: number) => string;
|
|
2211
|
+
appDeveloperAccountNotice: (accountId: number) => string;
|
|
2212
|
+
selectInstallAccountPrompt: string;
|
|
2213
|
+
uploadAndDeployPrompt: (accountId: number) => string;
|
|
2214
|
+
alreadyInstalled: (appName: string, accountId: number) => string;
|
|
2215
|
+
outdatedScopes: (appName: string, accountId: number) => string;
|
|
2216
|
+
reinstallPrompt: string;
|
|
2217
|
+
installPrompt: (appName: string, accountId: number) => string;
|
|
2218
|
+
installFromBrowser: (installUrl: string) => string;
|
|
2219
|
+
success: (appName: string, accountId: number) => string;
|
|
2220
|
+
};
|
|
2171
2221
|
installStatus: {
|
|
2172
2222
|
describe: string;
|
|
2173
2223
|
examples: {
|
|
@@ -3269,6 +3319,11 @@ export declare const lib: {
|
|
|
3269
3319
|
configMiddleWare: {
|
|
3270
3320
|
invalidAccountIdEnvironmentVariable: string;
|
|
3271
3321
|
};
|
|
3322
|
+
accountTargetDiscovery: {
|
|
3323
|
+
errors: {
|
|
3324
|
+
explicitAccountNotFound: (account: string | number) => string;
|
|
3325
|
+
};
|
|
3326
|
+
};
|
|
3272
3327
|
process: {
|
|
3273
3328
|
exitDebug: (signal: string) => string;
|
|
3274
3329
|
};
|
|
@@ -3533,6 +3588,11 @@ export declare const lib: {
|
|
|
3533
3588
|
feedbackHeader: string;
|
|
3534
3589
|
feedbackMessage: string;
|
|
3535
3590
|
};
|
|
3591
|
+
skippedHsMetaFiles: {
|
|
3592
|
+
warning: (files: string[]) => string;
|
|
3593
|
+
uploadWarning: (files: string[]) => string;
|
|
3594
|
+
prompt: string;
|
|
3595
|
+
};
|
|
3536
3596
|
components: {
|
|
3537
3597
|
unableToGetUidFromHsmeta: string;
|
|
3538
3598
|
buildSuccessMessage: {
|
|
@@ -3837,6 +3897,7 @@ export declare const lib: {
|
|
|
3837
3897
|
confirmUseExistingDeveloperTestAccount: (accountName: string) => string;
|
|
3838
3898
|
confirmLinkExistingDeveloperTestAccount: (accountName: string) => string;
|
|
3839
3899
|
noAccountId: string;
|
|
3900
|
+
fetchDeveloperTestAccountsError: string;
|
|
3840
3901
|
};
|
|
3841
3902
|
projectLogsPrompt: {
|
|
3842
3903
|
functionName: (projectName: string) => string;
|
|
@@ -4241,6 +4302,11 @@ export declare const lib: {
|
|
|
4241
4302
|
installed: (npmVersion: string) => string;
|
|
4242
4303
|
unableToDetermine: string;
|
|
4243
4304
|
};
|
|
4305
|
+
mcpChecks: {
|
|
4306
|
+
configured: (clients: string[]) => string;
|
|
4307
|
+
notConfigured: (clients: string[]) => string;
|
|
4308
|
+
notConfiguredSecondary: string;
|
|
4309
|
+
};
|
|
4244
4310
|
hsChecks: {
|
|
4245
4311
|
notLatest: (hsVersion: string) => string;
|
|
4246
4312
|
notLatestSecondary: (command: string, hsVersion: string) => string;
|