@hubspot/cli 8.0.1-experimental.0 → 8.0.3-experimental.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/bin/cli.js +8 -5
- package/commands/__tests__/getStarted.test.js +12 -0
- package/commands/__tests__/project.test.js +30 -0
- package/commands/account/auth.js +8 -97
- package/commands/account/use.js +19 -4
- package/commands/cms/module/marketplace-validate.js +23 -5
- package/commands/cms/theme/marketplace-validate.js +25 -6
- package/commands/getStarted.d.ts +2 -1
- package/commands/getStarted.js +38 -15
- package/commands/mcp/__tests__/start.test.js +1 -67
- package/commands/mcp/setup.js +1 -2
- package/commands/mcp/start.js +1 -19
- package/commands/mcp.js +1 -2
- package/commands/project.js +22 -1
- package/lang/en.d.ts +53 -7
- package/lang/en.js +59 -13
- package/lib/CLIWebSocketServer.d.ts +28 -0
- package/lib/CLIWebSocketServer.js +91 -0
- package/lib/__tests__/CLIWebSocketServer.test.d.ts +1 -0
- package/lib/__tests__/CLIWebSocketServer.test.js +252 -0
- package/lib/__tests__/accountAuth.test.d.ts +1 -0
- package/lib/__tests__/accountAuth.test.js +258 -0
- package/lib/__tests__/commandSuggestion.test.d.ts +1 -0
- package/lib/__tests__/commandSuggestion.test.js +119 -0
- package/lib/accountAuth.d.ts +10 -0
- package/lib/accountAuth.js +105 -0
- package/lib/app/urls.d.ts +1 -0
- package/lib/app/urls.js +4 -0
- package/lib/commandSuggestion.d.ts +3 -0
- package/lib/commandSuggestion.js +45 -0
- package/lib/constants.d.ts +0 -1
- package/lib/constants.js +0 -1
- package/lib/errors/ProjectErrors.d.ts +15 -0
- package/lib/errors/ProjectErrors.js +30 -0
- package/lib/getStarted/getStartedV2.d.ts +7 -0
- package/lib/getStarted/getStartedV2.js +18 -0
- package/lib/getStartedV2Actions.d.ts +37 -0
- package/lib/getStartedV2Actions.js +146 -0
- package/lib/marketplaceValidate.d.ts +1 -1
- package/lib/marketplaceValidate.js +23 -41
- package/lib/mcp/__tests__/setup.test.js +0 -17
- package/lib/mcp/setup.d.ts +0 -1
- package/lib/mcp/setup.js +59 -103
- package/lib/projects/ProjectLogsManager.d.ts +12 -3
- package/lib/projects/ProjectLogsManager.js +70 -12
- package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +43 -175
- package/lib/projects/__tests__/ProjectLogsManager.test.js +131 -18
- package/lib/projects/__tests__/platformVersion.test.js +37 -1
- package/lib/projects/__tests__/projects.test.js +6 -2
- package/lib/projects/components.d.ts +6 -0
- package/lib/projects/components.js +1 -1
- package/lib/projects/config.js +9 -2
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +2 -7
- package/lib/projects/localDev/LocalDevWebsocketServer.js +51 -98
- package/lib/projects/localDev/helpers/project.d.ts +4 -1
- package/lib/projects/localDev/helpers/project.js +13 -8
- package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +8 -7
- package/lib/projects/platformVersion.d.ts +8 -0
- package/lib/projects/platformVersion.js +31 -2
- package/lib/prompts/accountsPrompt.d.ts +2 -1
- package/lib/prompts/accountsPrompt.js +10 -2
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +20 -3
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +6 -10
- package/mcp-server/tools/project/CreateProjectTool.d.ts +24 -4
- package/mcp-server/tools/project/CreateProjectTool.js +5 -10
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +5 -8
- package/mcp-server/tools/project/GetBuildLogsTool.d.ts +2 -2
- package/mcp-server/tools/project/GetBuildLogsTool.js +3 -4
- package/mcp-server/tools/project/GetBuildStatusTool.d.ts +1 -1
- package/mcp-server/tools/project/GetBuildStatusTool.js +3 -4
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +6 -1
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -6
- package/mcp-server/tools/project/constants.d.ts +12 -1
- package/mcp-server/tools/project/constants.js +12 -16
- package/mcp-server/utils/__tests__/project.test.js +0 -125
- package/mcp-server/utils/project.js +0 -8
- package/package.json +10 -5
- package/types/LocalDev.d.ts +0 -4
- package/ui/components/ActionSection.d.ts +12 -0
- package/ui/components/ActionSection.js +25 -0
- package/ui/components/BoxWithTitle.d.ts +4 -2
- package/ui/components/BoxWithTitle.js +2 -2
- package/ui/components/FullScreen.d.ts +6 -0
- package/ui/components/FullScreen.js +13 -0
- package/ui/components/InputField.d.ts +10 -0
- package/ui/components/InputField.js +10 -0
- package/ui/components/SelectInput.d.ts +11 -0
- package/ui/components/SelectInput.js +59 -0
- package/ui/components/StatusIcon.d.ts +9 -0
- package/ui/components/StatusIcon.js +17 -0
- package/ui/components/getStarted/GetStartedFlow.d.ts +8 -0
- package/ui/components/getStarted/GetStartedFlow.js +136 -0
- package/ui/components/getStarted/reducer.d.ts +59 -0
- package/ui/components/getStarted/reducer.js +72 -0
- package/ui/components/getStarted/screens/ProjectSetupScreen.d.ts +16 -0
- package/ui/components/getStarted/screens/ProjectSetupScreen.js +39 -0
- package/ui/components/getStarted/screens/UploadScreen.d.ts +7 -0
- package/ui/components/getStarted/screens/UploadScreen.js +43 -0
- package/ui/components/getStarted/selectors.d.ts +2 -0
- package/ui/components/getStarted/selectors.js +1 -0
- package/ui/constants.d.ts +6 -0
- package/ui/constants.js +6 -0
- package/ui/lib/constants.d.ts +16 -0
- package/ui/lib/constants.js +16 -0
- package/ui/playground/fixtures.js +47 -0
- package/ui/render.d.ts +4 -0
- package/ui/render.js +31 -0
- package/ui/styles.d.ts +3 -0
- package/ui/styles.js +3 -0
package/bin/cli.js
CHANGED
|
@@ -33,6 +33,7 @@ import mcpCommand from '../commands/mcp.js';
|
|
|
33
33
|
import upgradeCommand from '../commands/upgrade.js';
|
|
34
34
|
import { uiLogger } from '../lib/ui/logger.js';
|
|
35
35
|
import { initializeSpinniesManager } from '../lib/middleware/spinniesMiddleware.js';
|
|
36
|
+
import { addCommandSuggestions } from '../lib/commandSuggestion.js';
|
|
36
37
|
function getTerminalWidth() {
|
|
37
38
|
const width = yargs().terminalWidth();
|
|
38
39
|
if (width >= 100)
|
|
@@ -114,20 +115,22 @@ const argv = yargs(process.argv.slice(2))
|
|
|
114
115
|
.command(completionCommand)
|
|
115
116
|
.command(doctorCommand)
|
|
116
117
|
.command(mcpCommand)
|
|
117
|
-
.command(upgradeCommand)
|
|
118
|
+
.command(upgradeCommand);
|
|
119
|
+
const argvWithSuggestions = addCommandSuggestions(argv)
|
|
118
120
|
.help()
|
|
119
121
|
.alias('h', 'help')
|
|
120
122
|
.recommendCommands()
|
|
121
123
|
.demandCommand(1, '')
|
|
122
124
|
.wrap(getTerminalWidth())
|
|
123
125
|
.strict().argv;
|
|
124
|
-
if ('help' in
|
|
126
|
+
if ('help' in argvWithSuggestions && argvWithSuggestions.help !== undefined) {
|
|
125
127
|
(async () => {
|
|
126
|
-
await trackHelpUsage(getCommandName(
|
|
128
|
+
await trackHelpUsage(getCommandName(argvWithSuggestions));
|
|
127
129
|
})();
|
|
128
130
|
}
|
|
129
|
-
if ('convertFields' in
|
|
131
|
+
if ('convertFields' in argvWithSuggestions &&
|
|
132
|
+
argvWithSuggestions.convertFields !== undefined) {
|
|
130
133
|
(async () => {
|
|
131
|
-
await trackConvertFieldsUsage(getCommandName(
|
|
134
|
+
await trackConvertFieldsUsage(getCommandName(argvWithSuggestions));
|
|
132
135
|
})();
|
|
133
136
|
}
|
|
@@ -9,6 +9,8 @@ import { getProjectPackageJsonLocations, installPackages, } from '../../lib/depe
|
|
|
9
9
|
import { GET_STARTED_OPTIONS } from '../../lib/constants.js';
|
|
10
10
|
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
11
11
|
import open from 'open';
|
|
12
|
+
import { renderInteractive } from '../../ui/render.js';
|
|
13
|
+
import { getGetStartedFlow } from '../../ui/components/getStarted/GetStartedFlow.js';
|
|
12
14
|
vi.mock('../../lib/prompts/promptUtils');
|
|
13
15
|
vi.mock('../../lib/prompts/projectNameAndDestPrompt');
|
|
14
16
|
vi.mock('../../lib/projects/config');
|
|
@@ -16,6 +18,8 @@ vi.mock('../../lib/errorHandlers');
|
|
|
16
18
|
vi.mock('@hubspot/local-dev-lib/github');
|
|
17
19
|
vi.mock('../../lib/dependencyManagement');
|
|
18
20
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
21
|
+
vi.mock('../../ui/render');
|
|
22
|
+
vi.mock('../../ui/components/getStarted/GetStartedFlow');
|
|
19
23
|
vi.mock('open');
|
|
20
24
|
vi.mock('fs-extra', () => ({
|
|
21
25
|
default: {
|
|
@@ -103,6 +107,14 @@ describe('commands/get-started', () => {
|
|
|
103
107
|
await getStartedCommand.handler(mockArgs);
|
|
104
108
|
expect(open).toHaveBeenCalledWith(expect.stringContaining('design-manager'), { url: true });
|
|
105
109
|
});
|
|
110
|
+
it('should use Ink flow when v2 flag is enabled', async () => {
|
|
111
|
+
getGetStartedFlow.mockImplementation(() => null);
|
|
112
|
+
renderInteractive.mockResolvedValue(undefined);
|
|
113
|
+
await getStartedCommand.handler({ ...mockArgs, v2: true });
|
|
114
|
+
expect(renderInteractive).toHaveBeenCalled();
|
|
115
|
+
expect(promptUser).not.toHaveBeenCalled();
|
|
116
|
+
expect(process.exit).toHaveBeenCalledWith(EXIT_CODES.SUCCESS);
|
|
117
|
+
});
|
|
106
118
|
});
|
|
107
119
|
describe('App flow', () => {
|
|
108
120
|
beforeEach(() => {
|
|
@@ -17,6 +17,9 @@ import validate from '../project/validate.js';
|
|
|
17
17
|
import profileCommands from '../project/profile.js';
|
|
18
18
|
import list from '../project/list.js';
|
|
19
19
|
import projectCommand from '../project.js';
|
|
20
|
+
import * as projectConfigLib from '../../lib/projects/config.js';
|
|
21
|
+
import * as platformVersionLib from '../../lib/projects/platformVersion.js';
|
|
22
|
+
import { uiLogger } from '../../lib/ui/logger.js';
|
|
20
23
|
vi.mock('../project/deploy');
|
|
21
24
|
vi.mock('../project/create');
|
|
22
25
|
vi.mock('../project/upload');
|
|
@@ -40,13 +43,24 @@ vi.mock('../project/installDeps');
|
|
|
40
43
|
vi.mock('../project/lint');
|
|
41
44
|
vi.mock('../project/profile');
|
|
42
45
|
vi.mock('../../lib/commonOpts');
|
|
46
|
+
vi.mock('../../lib/projects/config.js');
|
|
47
|
+
vi.mock('../../lib/projects/platformVersion.js');
|
|
43
48
|
const commandSpy = vi
|
|
44
49
|
.spyOn(yargs, 'command')
|
|
45
50
|
.mockReturnValue(yargs);
|
|
46
51
|
const demandCommandSpy = vi
|
|
47
52
|
.spyOn(yargs, 'demandCommand')
|
|
48
53
|
.mockReturnValue(yargs);
|
|
54
|
+
const getProjectConfigSpy = vi.spyOn(projectConfigLib, 'getProjectConfig');
|
|
55
|
+
const isUnsupportedPlatformVersionSpy = vi.spyOn(platformVersionLib, 'isUnsupportedPlatformVersion');
|
|
56
|
+
const processExitSpy = vi.spyOn(process, 'exit');
|
|
57
|
+
const uiLoggerErrorSpy = vi.spyOn(uiLogger, 'error');
|
|
49
58
|
describe('commands/project', () => {
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
vi.clearAllMocks();
|
|
61
|
+
// @ts-expect-error Mock implementation
|
|
62
|
+
processExitSpy.mockImplementation(() => { });
|
|
63
|
+
});
|
|
50
64
|
describe('command', () => {
|
|
51
65
|
it('should have the correct command structure', () => {
|
|
52
66
|
expect(projectCommand.command).toEqual(['project', 'projects']);
|
|
@@ -92,4 +106,20 @@ describe('commands/project', () => {
|
|
|
92
106
|
expect(commandSpy).toHaveBeenCalledWith(module);
|
|
93
107
|
});
|
|
94
108
|
});
|
|
109
|
+
describe('middleware - validatePlatformVersion', () => {
|
|
110
|
+
it('should have platform version validation functions available', () => {
|
|
111
|
+
// Verify the necessary functions are available for middleware
|
|
112
|
+
expect(getProjectConfigSpy).toBeDefined();
|
|
113
|
+
expect(isUnsupportedPlatformVersionSpy).toBeDefined();
|
|
114
|
+
expect(uiLoggerErrorSpy).toBeDefined();
|
|
115
|
+
expect(processExitSpy).toBeDefined();
|
|
116
|
+
});
|
|
117
|
+
it('should register middleware when building', async () => {
|
|
118
|
+
// Verify middleware is registered during builder execution
|
|
119
|
+
await projectCommand.builder(yargs);
|
|
120
|
+
// The middleware should be registered (we can't easily test async middleware execution)
|
|
121
|
+
// but we verify the builder completes successfully
|
|
122
|
+
expect(projectCommand.builder).toBeDefined();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
95
125
|
});
|
package/commands/account/auth.js
CHANGED
|
@@ -1,96 +1,21 @@
|
|
|
1
|
-
import { updateConfigAccount, createEmptyConfigFile, deleteConfigFileIfEmpty, getConfigFilePath, localConfigFileExists, globalConfigFileExists, } from '@hubspot/local-dev-lib/config';
|
|
2
|
-
import { getAccessToken, updateConfigWithAccessToken, } from '@hubspot/local-dev-lib/personalAccessKey';
|
|
3
1
|
import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
|
|
4
|
-
import { toKebabCase } from '@hubspot/local-dev-lib/text';
|
|
5
2
|
import { PERSONAL_ACCESS_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
|
|
6
|
-
import {
|
|
3
|
+
import { deleteConfigFileIfEmpty } from '@hubspot/local-dev-lib/config';
|
|
7
4
|
import { handleExit } from '../../lib/process.js';
|
|
8
|
-
import { debugError } from '../../lib/errorHandlers/index.js';
|
|
9
5
|
import { trackCommandUsage, trackAuthAction } from '../../lib/usageTracking.js';
|
|
10
|
-
import { personalAccessKeyPrompt } from '../../lib/prompts/personalAccessKeyPrompt.js';
|
|
11
|
-
import { cliAccountNamePrompt } from '../../lib/prompts/accountNamePrompt.js';
|
|
12
|
-
import { setAsDefaultAccountPrompt } from '../../lib/prompts/setAsDefaultAccountPrompt.js';
|
|
13
|
-
import { logError } from '../../lib/errorHandlers/index.js';
|
|
14
6
|
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
15
7
|
import { uiFeatureHighlight } from '../../lib/ui/index.js';
|
|
16
8
|
import { parseStringToNumber } from '../../lib/parsing.js';
|
|
17
9
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
18
10
|
import { commands } from '../../lang/en.js';
|
|
19
11
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
12
|
+
import { authenticateNewAccount } from '../../lib/accountAuth.js';
|
|
20
13
|
const TRACKING_STATUS = {
|
|
21
14
|
STARTED: 'started',
|
|
22
15
|
ERROR: 'error',
|
|
23
16
|
COMPLETE: 'complete',
|
|
24
17
|
};
|
|
25
18
|
const authType = PERSONAL_ACCESS_KEY_AUTH_METHOD.value;
|
|
26
|
-
async function updateConfigWithNewAccount(env, configAlreadyExists, providedPersonalAccessKey, accountId) {
|
|
27
|
-
try {
|
|
28
|
-
const { personalAccessKey } = providedPersonalAccessKey
|
|
29
|
-
? { personalAccessKey: providedPersonalAccessKey }
|
|
30
|
-
: await personalAccessKeyPrompt({
|
|
31
|
-
env,
|
|
32
|
-
account: accountId,
|
|
33
|
-
});
|
|
34
|
-
const token = await getAccessToken(personalAccessKey, env);
|
|
35
|
-
const defaultAccountName = token.hubName
|
|
36
|
-
? toKebabCase(token.hubName)
|
|
37
|
-
: undefined;
|
|
38
|
-
const accountName = configAlreadyExists
|
|
39
|
-
? undefined
|
|
40
|
-
: (await cliAccountNamePrompt(defaultAccountName)).name;
|
|
41
|
-
const updatedConfig = await updateConfigWithAccessToken(token, personalAccessKey, env, accountName, !configAlreadyExists);
|
|
42
|
-
if (!updatedConfig)
|
|
43
|
-
return null;
|
|
44
|
-
// Can happen if the user is re-authenticating an account with no name
|
|
45
|
-
if (configAlreadyExists && !updatedConfig.name) {
|
|
46
|
-
updatedConfig.name = (await cliAccountNamePrompt(defaultAccountName)).name;
|
|
47
|
-
updateConfigAccount({
|
|
48
|
-
...updatedConfig,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return updatedConfig;
|
|
52
|
-
}
|
|
53
|
-
catch (e) {
|
|
54
|
-
debugError(e);
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function handleConfigMigration() {
|
|
59
|
-
const deprecatedConfigExists = localConfigFileExists();
|
|
60
|
-
const globalConfigExists = globalConfigFileExists();
|
|
61
|
-
// No deprecated config exists, so no migration is needed
|
|
62
|
-
if (!deprecatedConfigExists) {
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
// Global config exists, so we need to merge the deprecated config with the global config
|
|
66
|
-
if (globalConfigExists) {
|
|
67
|
-
try {
|
|
68
|
-
const mergeConfirmed = await handleMerge();
|
|
69
|
-
if (!mergeConfirmed) {
|
|
70
|
-
uiLogger.log('');
|
|
71
|
-
uiLogger.log(commands.account.subcommands.auth.errors.mergeNotConfirmed);
|
|
72
|
-
}
|
|
73
|
-
return mergeConfirmed;
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
logError(error);
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Global config does not exist, so we only need to migrate the deprecated config
|
|
81
|
-
try {
|
|
82
|
-
const migrationConfirmed = await handleMigration();
|
|
83
|
-
if (!migrationConfirmed) {
|
|
84
|
-
uiLogger.log('');
|
|
85
|
-
uiLogger.log(commands.account.subcommands.auth.errors.migrationNotConfirmed);
|
|
86
|
-
}
|
|
87
|
-
return migrationConfirmed;
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
logError(error);
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
19
|
const describe = commands.account.subcommands.auth.describe;
|
|
95
20
|
const command = 'auth';
|
|
96
21
|
async function handler(args) {
|
|
@@ -109,33 +34,19 @@ async function handler(args) {
|
|
|
109
34
|
trackCommandUsage('account-auth', {}, parsedUserProvidedAccountId);
|
|
110
35
|
await trackAuthAction('account-auth', authType, TRACKING_STATUS.STARTED);
|
|
111
36
|
}
|
|
112
|
-
const configMigrationSuccess = await handleConfigMigration();
|
|
113
|
-
if (!configMigrationSuccess) {
|
|
114
|
-
await trackAuthAction('account-auth', authType, TRACKING_STATUS.ERROR);
|
|
115
|
-
process.exit(EXIT_CODES.ERROR);
|
|
116
|
-
}
|
|
117
|
-
const configAlreadyExists = globalConfigFileExists();
|
|
118
|
-
if (!configAlreadyExists) {
|
|
119
|
-
createEmptyConfigFile(true);
|
|
120
|
-
}
|
|
121
37
|
handleExit(deleteConfigFileIfEmpty);
|
|
122
|
-
const updatedConfig = await
|
|
38
|
+
const updatedConfig = await authenticateNewAccount({
|
|
39
|
+
env: args.qa ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD,
|
|
40
|
+
providedPersonalAccessKey,
|
|
41
|
+
accountId: parsedUserProvidedAccountId,
|
|
42
|
+
});
|
|
123
43
|
if (!updatedConfig) {
|
|
124
44
|
if (!disableTracking) {
|
|
125
45
|
await trackAuthAction('account-auth', authType, TRACKING_STATUS.ERROR);
|
|
126
46
|
}
|
|
127
|
-
uiLogger.error(commands.account.subcommands.auth.errors.failedToUpdateConfig);
|
|
128
47
|
return process.exit(EXIT_CODES.ERROR);
|
|
129
48
|
}
|
|
130
|
-
const { accountId
|
|
131
|
-
if (!configAlreadyExists) {
|
|
132
|
-
uiLogger.log('');
|
|
133
|
-
uiLogger.success(commands.account.subcommands.auth.success.configFileCreated(getConfigFilePath()));
|
|
134
|
-
uiLogger.success(commands.account.subcommands.auth.success.configFileUpdated(accountId));
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
await setAsDefaultAccountPrompt(name);
|
|
138
|
-
}
|
|
49
|
+
const { accountId } = updatedConfig;
|
|
139
50
|
uiFeatureHighlight([
|
|
140
51
|
'getStartedCommand',
|
|
141
52
|
'helpCommand',
|
package/commands/account/use.js
CHANGED
|
@@ -1,24 +1,39 @@
|
|
|
1
|
-
import { getConfigFilePath, setConfigAccountAsDefault, getConfigAccountIfExists, getConfigAccountByName, getConfigAccountById, getAllConfigAccounts, } from '@hubspot/local-dev-lib/config';
|
|
1
|
+
import { getConfigFilePath, setConfigAccountAsDefault, getConfigAccountIfExists, getConfigAccountByName, getConfigAccountById, globalConfigFileExists, getAllConfigAccounts, } from '@hubspot/local-dev-lib/config';
|
|
2
2
|
import { getDefaultAccountOverrideAccountId, getDefaultAccountOverrideFilePath, } from '@hubspot/local-dev-lib/config/defaultAccountOverride';
|
|
3
|
+
import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
|
|
3
4
|
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
4
5
|
import { commands } from '../../lang/en.js';
|
|
5
6
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
6
|
-
import { selectAccountFromConfig } from '../../lib/prompts/accountsPrompt.js';
|
|
7
|
+
import { selectAccountFromConfig, AUTHENTICATE_NEW_ACCOUNT_VALUE, } from '../../lib/prompts/accountsPrompt.js';
|
|
7
8
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
9
|
+
import { authenticateNewAccount } from '../../lib/accountAuth.js';
|
|
10
|
+
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
8
11
|
const command = 'use [account]';
|
|
9
12
|
const describe = commands.account.subcommands.use.describe;
|
|
10
13
|
async function handler(args) {
|
|
11
14
|
let newDefaultAccount = args.account;
|
|
15
|
+
const usingGlobalConfig = globalConfigFileExists();
|
|
12
16
|
if (!newDefaultAccount) {
|
|
13
|
-
newDefaultAccount = await selectAccountFromConfig();
|
|
17
|
+
newDefaultAccount = await selectAccountFromConfig('', usingGlobalConfig);
|
|
14
18
|
}
|
|
15
19
|
else {
|
|
16
20
|
const account = getConfigAccountIfExists(newDefaultAccount);
|
|
17
21
|
if (!account) {
|
|
18
22
|
uiLogger.error(commands.account.subcommands.use.errors.accountNotFound(newDefaultAccount, getConfigFilePath()));
|
|
19
|
-
newDefaultAccount = await selectAccountFromConfig();
|
|
23
|
+
newDefaultAccount = await selectAccountFromConfig('', usingGlobalConfig);
|
|
20
24
|
}
|
|
21
25
|
}
|
|
26
|
+
if (newDefaultAccount === AUTHENTICATE_NEW_ACCOUNT_VALUE) {
|
|
27
|
+
const updatedConfig = await authenticateNewAccount({
|
|
28
|
+
env: args.qa ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD,
|
|
29
|
+
setAsDefaultAccount: true,
|
|
30
|
+
});
|
|
31
|
+
if (!updatedConfig) {
|
|
32
|
+
process.exit(EXIT_CODES.ERROR);
|
|
33
|
+
}
|
|
34
|
+
trackCommandUsage('accounts-use', undefined, updatedConfig.accountId);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
22
37
|
let account;
|
|
23
38
|
if (!isNaN(Number(newDefaultAccount))) {
|
|
24
39
|
account = getConfigAccountById(Number(newDefaultAccount));
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import SpinniesManager from '../../../lib/ui/SpinniesManager.js';
|
|
2
2
|
import { trackCommandUsage } from '../../../lib/usageTracking.js';
|
|
3
|
-
import { kickOffValidation, pollForValidationFinish, fetchValidationResults,
|
|
3
|
+
import { kickOffValidation, pollForValidationFinish, fetchValidationResults, hasProcessValidationErrors, displayValidationResults, } from '../../../lib/marketplaceValidate.js';
|
|
4
4
|
import { commands } from '../../../lang/en.js';
|
|
5
5
|
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
6
6
|
import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
|
|
7
|
+
import { logError } from '../../../lib/errorHandlers/index.js';
|
|
7
8
|
const command = 'marketplace-validate <src>';
|
|
8
9
|
const describe = commands.cms.subcommands.module.subcommands.marketplaceValidate.describe;
|
|
9
10
|
async function handler(args) {
|
|
@@ -13,12 +14,29 @@ async function handler(args) {
|
|
|
13
14
|
text: commands.cms.subcommands.module.subcommands.marketplaceValidate.logs.validatingModule(src),
|
|
14
15
|
});
|
|
15
16
|
const assetType = 'MODULE';
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
let validationId;
|
|
18
|
+
try {
|
|
19
|
+
validationId = await kickOffValidation(derivedAccountId, assetType, src);
|
|
20
|
+
await pollForValidationFinish(derivedAccountId, validationId);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
logError(e);
|
|
24
|
+
process.exit(EXIT_CODES.ERROR);
|
|
25
|
+
}
|
|
18
26
|
SpinniesManager.remove('marketplaceValidation');
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
let validationResults;
|
|
28
|
+
try {
|
|
29
|
+
validationResults = await fetchValidationResults(derivedAccountId, validationId);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
logError(e);
|
|
33
|
+
process.exit(EXIT_CODES.ERROR);
|
|
34
|
+
}
|
|
35
|
+
const hasErrors = hasProcessValidationErrors(commands.cms.subcommands.module.subcommands.marketplaceValidate.errors
|
|
21
36
|
.invalidPath, validationResults);
|
|
37
|
+
if (hasErrors) {
|
|
38
|
+
process.exit(EXIT_CODES.ERROR);
|
|
39
|
+
}
|
|
22
40
|
displayValidationResults(commands.cms.subcommands.module.subcommands.marketplaceValidate.results, validationResults);
|
|
23
41
|
process.exit(EXIT_CODES.SUCCESS);
|
|
24
42
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import SpinniesManager from '../../../lib/ui/SpinniesManager.js';
|
|
2
2
|
import { trackCommandUsage } from '../../../lib/usageTracking.js';
|
|
3
|
-
import { kickOffValidation, pollForValidationFinish, fetchValidationResults,
|
|
3
|
+
import { kickOffValidation, pollForValidationFinish, fetchValidationResults, hasProcessValidationErrors, displayValidationResults, } from '../../../lib/marketplaceValidate.js';
|
|
4
4
|
import { commands } from '../../../lang/en.js';
|
|
5
5
|
import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
|
|
6
|
+
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
7
|
+
import { logError } from '../../../lib/errorHandlers/index.js';
|
|
6
8
|
const command = 'marketplace-validate <path>';
|
|
7
9
|
const describe = commands.cms.subcommands.theme.subcommands.marketplaceValidate.describe;
|
|
8
10
|
async function handler(args) {
|
|
@@ -12,14 +14,31 @@ async function handler(args) {
|
|
|
12
14
|
text: commands.cms.subcommands.theme.subcommands.marketplaceValidate.logs.validatingTheme(path),
|
|
13
15
|
});
|
|
14
16
|
const assetType = 'THEME';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
let validationId;
|
|
18
|
+
try {
|
|
19
|
+
validationId = await kickOffValidation(derivedAccountId, assetType, path);
|
|
20
|
+
await pollForValidationFinish(derivedAccountId, validationId);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
logError(e);
|
|
24
|
+
process.exit(EXIT_CODES.ERROR);
|
|
25
|
+
}
|
|
17
26
|
SpinniesManager.remove('marketplaceValidation');
|
|
18
|
-
|
|
19
|
-
|
|
27
|
+
let validationResults;
|
|
28
|
+
try {
|
|
29
|
+
validationResults = await fetchValidationResults(derivedAccountId, validationId);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
logError(e);
|
|
33
|
+
process.exit(EXIT_CODES.ERROR);
|
|
34
|
+
}
|
|
35
|
+
const hasErrors = hasProcessValidationErrors(commands.cms.subcommands.theme.subcommands.marketplaceValidate.errors
|
|
20
36
|
.invalidPath, validationResults);
|
|
37
|
+
if (hasErrors) {
|
|
38
|
+
process.exit(EXIT_CODES.ERROR);
|
|
39
|
+
}
|
|
21
40
|
displayValidationResults(commands.cms.subcommands.theme.subcommands.marketplaceValidate.results, validationResults);
|
|
22
|
-
process.exit();
|
|
41
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
23
42
|
}
|
|
24
43
|
function themeValidateBuilder(yargs) {
|
|
25
44
|
yargs.positional('path', {
|
package/commands/getStarted.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { AccountArgs,
|
|
1
|
+
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, YargsCommandModule } from '../types/Yargs.js';
|
|
2
2
|
type GetStartedArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
|
|
3
3
|
name?: string;
|
|
4
4
|
dest?: string;
|
|
5
|
+
v2?: boolean;
|
|
5
6
|
};
|
|
6
7
|
declare const getStartedCommand: YargsCommandModule<unknown, GetStartedArgs>;
|
|
7
8
|
export default getStartedCommand;
|
package/commands/getStarted.js
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
|
+
import { cloneGithubRepo } from '@hubspot/local-dev-lib/github';
|
|
2
|
+
import { getCwd } from '@hubspot/local-dev-lib/path';
|
|
1
3
|
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
4
|
import open from 'open';
|
|
4
|
-
import
|
|
5
|
-
import { cloneGithubRepo } from '@hubspot/local-dev-lib/github';
|
|
5
|
+
import path from 'path';
|
|
6
6
|
import { commands } from '../lang/en.js';
|
|
7
|
-
import {
|
|
7
|
+
import { GET_STARTED_OPTIONS, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_CONFIG_FILE, } from '../lib/constants.js';
|
|
8
8
|
import { EXIT_CODES } from '../lib/enums/exitCodes.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { debugError, logError } from '../lib/errorHandlers/index.js';
|
|
10
|
+
import { getProjectConfig, validateProjectConfig, writeProjectConfig, } from '../lib/projects/config.js';
|
|
11
|
+
import { handleProjectUpload } from '../lib/projects/upload.js';
|
|
11
12
|
import { projectNameAndDestPrompt } from '../lib/prompts/projectNameAndDestPrompt.js';
|
|
13
|
+
import { promptUser } from '../lib/prompts/promptUtils.js';
|
|
12
14
|
import { uiAccountDescription, uiFeatureHighlight, uiInfoSection, } from '../lib/ui/index.js';
|
|
13
15
|
import { uiLogger } from '../lib/ui/logger.js';
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import { handleProjectUpload } from '../lib/projects/upload.js';
|
|
17
|
-
import { PROJECT_CONFIG_FILE, GET_STARTED_OPTIONS, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, } from '../lib/constants.js';
|
|
18
|
-
import { writeProjectConfig, getProjectConfig, validateProjectConfig, } from '../lib/projects/config.js';
|
|
19
|
-
import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
|
|
16
|
+
import { trackCommandMetadataUsage, trackCommandUsage, } from '../lib/usageTracking.js';
|
|
17
|
+
import { makeYargsBuilder } from '../lib/yargsUtils.js';
|
|
20
18
|
import { isV2Project } from '../lib/projects/platformVersion.js';
|
|
21
|
-
import {
|
|
22
|
-
import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
|
|
23
|
-
import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
|
|
19
|
+
import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
|
|
24
20
|
import { fetchPublicAppsForPortal } from '@hubspot/local-dev-lib/api/appsDev';
|
|
21
|
+
import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
|
|
22
|
+
import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
|
|
23
|
+
import ProjectValidationError from '../lib/errors/ProjectValidationError.js';
|
|
24
|
+
import { openLink } from '../lib/links.js';
|
|
25
|
+
import { runGetStartedV2 } from '../lib/getStarted/getStartedV2.js';
|
|
25
26
|
const command = 'get-started';
|
|
26
27
|
const describe = commands.getStarted.describe;
|
|
27
28
|
async function handler(args) {
|
|
@@ -29,6 +30,22 @@ async function handler(args) {
|
|
|
29
30
|
const env = getConfigAccountEnvironment(derivedAccountId);
|
|
30
31
|
await trackCommandUsage('get-started', {}, derivedAccountId);
|
|
31
32
|
const accountName = uiAccountDescription(derivedAccountId);
|
|
33
|
+
if (args.v2) {
|
|
34
|
+
try {
|
|
35
|
+
await runGetStartedV2({
|
|
36
|
+
...args,
|
|
37
|
+
name: args.name,
|
|
38
|
+
dest: args.dest,
|
|
39
|
+
});
|
|
40
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
logError(error);
|
|
45
|
+
process.exit(EXIT_CODES.ERROR);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
32
49
|
uiInfoSection(commands.getStarted.startTitle, () => {
|
|
33
50
|
uiLogger.log(commands.getStarted.startDescription);
|
|
34
51
|
uiLogger.log(commands.getStarted.guideOverview(accountName));
|
|
@@ -277,6 +294,12 @@ function getStartedBuilder(yargs) {
|
|
|
277
294
|
describe: commands.getStarted.options.dest.describe,
|
|
278
295
|
type: 'string',
|
|
279
296
|
},
|
|
297
|
+
v2: {
|
|
298
|
+
describe: commands.getStarted.options.v2.describe,
|
|
299
|
+
type: 'boolean',
|
|
300
|
+
default: false,
|
|
301
|
+
hidden: true,
|
|
302
|
+
},
|
|
280
303
|
'template-source': {
|
|
281
304
|
describe: commands.getStarted.options.templateSource.describe,
|
|
282
305
|
type: 'string',
|
|
@@ -7,20 +7,14 @@ import * as errorHandlers from '../../../lib/errorHandlers/index.js';
|
|
|
7
7
|
import * as usageTrackingLib from '../../../lib/usageTracking.js';
|
|
8
8
|
import * as processLib from '../../../lib/process.js';
|
|
9
9
|
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
10
|
-
|
|
11
|
-
const execAsyncMock = vi.fn();
|
|
10
|
+
import startCommand from '../start.js';
|
|
12
11
|
vi.mock('yargs');
|
|
13
12
|
vi.mock('../../../lib/commonOpts');
|
|
14
13
|
vi.mock('node:child_process');
|
|
15
|
-
vi.mock('node:util', () => ({
|
|
16
|
-
promisify: vi.fn(() => execAsyncMock),
|
|
17
|
-
}));
|
|
18
14
|
vi.mock('fs');
|
|
19
15
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
20
16
|
vi.mock('../../../lib/errorHandlers/index.js');
|
|
21
17
|
vi.mock('../../../lib/process.js');
|
|
22
|
-
// Import after mocks are set up
|
|
23
|
-
const startCommand = await import('../start.js').then(m => m.default);
|
|
24
18
|
const spawnSpy = vi.mocked(spawn);
|
|
25
19
|
const existsSyncSpy = vi.spyOn(fs, 'existsSync');
|
|
26
20
|
const trackCommandUsageSpy = vi.spyOn(usageTrackingLib, 'trackCommandUsage');
|
|
@@ -42,7 +36,6 @@ describe('commands/mcp/start', () => {
|
|
|
42
36
|
processExitSpy.mockImplementation(() => { });
|
|
43
37
|
// Mock config to prevent reading actual config file in CI
|
|
44
38
|
getConfigAccountIfExistsSpy.mockReturnValue(undefined);
|
|
45
|
-
execAsyncMock.mockClear();
|
|
46
39
|
});
|
|
47
40
|
describe('command', () => {
|
|
48
41
|
it('should have the correct command structure', () => {
|
|
@@ -140,64 +133,5 @@ describe('commands/mcp/start', () => {
|
|
|
140
133
|
expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('Failed to start'));
|
|
141
134
|
expect(logErrorSpy).toHaveBeenCalledWith(error);
|
|
142
135
|
});
|
|
143
|
-
it('should fetch CLI version in standalone mode', async () => {
|
|
144
|
-
const originalEnv = process.env.HUBSPOT_MCP_STANDALONE;
|
|
145
|
-
process.env.HUBSPOT_MCP_STANDALONE = 'true';
|
|
146
|
-
execAsyncMock.mockResolvedValue({
|
|
147
|
-
stdout: '8.0.0',
|
|
148
|
-
stderr: '',
|
|
149
|
-
});
|
|
150
|
-
await startCommand.handler(args);
|
|
151
|
-
expect(execAsyncMock).toHaveBeenCalledWith('npm view @hubspot/cli version');
|
|
152
|
-
expect(spawnSpy).toHaveBeenCalledWith('node', expect.any(Array), expect.objectContaining({
|
|
153
|
-
env: expect.objectContaining({
|
|
154
|
-
HUBSPOT_CLI_VERSION: '8.0.0',
|
|
155
|
-
}),
|
|
156
|
-
}));
|
|
157
|
-
// Restore original env
|
|
158
|
-
if (originalEnv === undefined) {
|
|
159
|
-
delete process.env.HUBSPOT_MCP_STANDALONE;
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
process.env.HUBSPOT_MCP_STANDALONE = originalEnv;
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
it('should not fetch CLI version when not in standalone mode', async () => {
|
|
166
|
-
const originalEnv = process.env.HUBSPOT_MCP_STANDALONE;
|
|
167
|
-
delete process.env.HUBSPOT_MCP_STANDALONE;
|
|
168
|
-
await startCommand.handler(args);
|
|
169
|
-
expect(execAsyncMock).not.toHaveBeenCalled();
|
|
170
|
-
expect(spawnSpy).toHaveBeenCalledWith('node', expect.any(Array), expect.objectContaining({
|
|
171
|
-
env: expect.not.objectContaining({
|
|
172
|
-
HUBSPOT_CLI_VERSION: expect.anything(),
|
|
173
|
-
}),
|
|
174
|
-
}));
|
|
175
|
-
// Restore original env
|
|
176
|
-
if (originalEnv !== undefined) {
|
|
177
|
-
process.env.HUBSPOT_MCP_STANDALONE = originalEnv;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
it('should handle version fetch errors gracefully', async () => {
|
|
181
|
-
const originalEnv = process.env.HUBSPOT_MCP_STANDALONE;
|
|
182
|
-
process.env.HUBSPOT_MCP_STANDALONE = 'true';
|
|
183
|
-
const error = new Error('Version fetch failed');
|
|
184
|
-
execAsyncMock.mockRejectedValue(error);
|
|
185
|
-
await startCommand.handler(args);
|
|
186
|
-
expect(execAsyncMock).toHaveBeenCalledWith('npm view @hubspot/cli version');
|
|
187
|
-
expect(uiLogger.warn).toHaveBeenCalledWith(expect.stringContaining('Failed to get CLI version'));
|
|
188
|
-
expect(logErrorSpy).toHaveBeenCalledWith(error);
|
|
189
|
-
expect(spawnSpy).toHaveBeenCalledWith('node', expect.any(Array), expect.objectContaining({
|
|
190
|
-
env: expect.not.objectContaining({
|
|
191
|
-
HUBSPOT_CLI_VERSION: expect.anything(),
|
|
192
|
-
}),
|
|
193
|
-
}));
|
|
194
|
-
// Restore original env
|
|
195
|
-
if (originalEnv === undefined) {
|
|
196
|
-
delete process.env.HUBSPOT_MCP_STANDALONE;
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
process.env.HUBSPOT_MCP_STANDALONE = originalEnv;
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
136
|
});
|
|
203
137
|
});
|
package/commands/mcp/setup.js
CHANGED
|
@@ -6,9 +6,8 @@ import { addMcpServerToConfig, supportedTools } from '../../lib/mcp/setup.js';
|
|
|
6
6
|
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
7
7
|
import { hasFeature } from '../../lib/hasFeature.js';
|
|
8
8
|
import { FEATURES } from '../../lib/constants.js';
|
|
9
|
-
import { uiBetaTag } from '../../lib/ui/index.js';
|
|
10
9
|
const command = ['setup'];
|
|
11
|
-
const describe =
|
|
10
|
+
const describe = commands.mcp.setup.describe;
|
|
12
11
|
async function handler(args) {
|
|
13
12
|
const { derivedAccountId } = args;
|
|
14
13
|
const hasMcpAccess = await hasFeature(derivedAccountId, FEATURES.MCP_ACCESS);
|
package/commands/mcp/start.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { spawn
|
|
2
|
-
import { promisify } from 'node:util';
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
3
2
|
import path from 'path';
|
|
4
3
|
import fs from 'fs';
|
|
5
4
|
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
@@ -10,7 +9,6 @@ import { commands } from '../../lang/en.js';
|
|
|
10
9
|
import { handleExit } from '../../lib/process.js';
|
|
11
10
|
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
12
11
|
import { fileURLToPath } from 'url';
|
|
13
|
-
const execAsync = promisify(exec);
|
|
14
12
|
const command = 'start';
|
|
15
13
|
const describe = undefined; // Leave hidden for now
|
|
16
14
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -30,28 +28,12 @@ async function startMcpServer(aiAgent) {
|
|
|
30
28
|
uiLogger.debug(commands.mcp.start.startingServer);
|
|
31
29
|
uiLogger.debug(commands.mcp.start.stopInstructions);
|
|
32
30
|
const args = [serverPath];
|
|
33
|
-
// Get CLI version if running in standalone mode
|
|
34
|
-
let cliVersion;
|
|
35
|
-
if (process.env.HUBSPOT_MCP_STANDALONE === 'true') {
|
|
36
|
-
try {
|
|
37
|
-
// const { stdout } = await execAsync('npm view @hubspot/cli version');
|
|
38
|
-
// // Extract version number from output (e.g., "8.0.0")
|
|
39
|
-
// cliVersion = stdout.trim();
|
|
40
|
-
cliVersion = '8.0.1-experimental.0';
|
|
41
|
-
uiLogger.debug(`Using @hubspot/cli version: ${cliVersion}`);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
uiLogger.warn('Failed to get CLI version, will use latest');
|
|
45
|
-
logError(error);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
31
|
// Start the server using ts-node
|
|
49
32
|
const child = spawn(`node`, args, {
|
|
50
33
|
stdio: 'inherit',
|
|
51
34
|
env: {
|
|
52
35
|
...process.env,
|
|
53
36
|
HUBSPOT_MCP_AI_AGENT: aiAgent || 'unknown',
|
|
54
|
-
...(cliVersion && { HUBSPOT_CLI_VERSION: cliVersion }),
|
|
55
37
|
},
|
|
56
38
|
});
|
|
57
39
|
// Handle server process events
|