@hubspot/cli 7.7.15-experimental.0 → 7.7.16-experimental.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +4 -0
- package/bin/hs +1 -1
- package/commands/getStarted.d.ts +9 -0
- package/commands/getStarted.js +227 -0
- package/commands/init.js +6 -1
- package/commands/mcp/setup.d.ts +4 -10
- package/commands/mcp/setup.js +28 -220
- package/commands/mcp/start.d.ts +3 -9
- package/commands/mcp/start.js +18 -15
- package/commands/mcp.js +2 -1
- package/commands/project/deploy.d.ts +1 -0
- package/commands/project/deploy.js +29 -3
- package/commands/project/upload.d.ts +2 -2
- package/commands/project/upload.js +18 -23
- package/commands/project/validate.d.ts +6 -0
- package/commands/project/validate.js +82 -0
- package/commands/project.js +2 -0
- package/commands/testAccount/create.d.ts +6 -0
- package/commands/testAccount/create.js +110 -0
- package/commands/testAccount/createConfig.d.ts +10 -0
- package/commands/testAccount/createConfig.js +98 -0
- package/commands/testAccount/delete.d.ts +6 -0
- package/commands/testAccount/delete.js +48 -0
- package/commands/testAccount.d.ts +3 -0
- package/commands/testAccount.js +28 -0
- package/lang/en.d.ts +144 -29
- package/lang/en.js +144 -32
- package/lang/en.lyaml +9 -14
- package/lib/app/migrate.js +15 -3
- package/lib/commonOpts.d.ts +2 -0
- package/lib/commonOpts.js +21 -9
- package/lib/constants.d.ts +5 -0
- package/lib/constants.js +6 -1
- package/lib/doctor/Doctor.js +1 -1
- package/lib/errorHandlers/index.js +7 -0
- package/lib/mcp/setup.d.ts +21 -0
- package/lib/mcp/setup.js +218 -0
- package/lib/projectProfiles.d.ts +1 -0
- package/lib/projectProfiles.js +18 -0
- package/lib/projects/buildAndDeploy.js +1 -1
- package/lib/projects/localDev/AppDevModeInterface.d.ts +3 -0
- package/lib/projects/localDev/AppDevModeInterface.js +45 -16
- package/lib/projects/localDev/LocalDevManager.js +1 -1
- package/lib/projects/upload.d.ts +3 -0
- package/lib/projects/upload.js +56 -22
- package/lib/projects/urls.d.ts +2 -0
- package/lib/projects/urls.js +10 -0
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +17 -0
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +96 -0
- package/lib/prompts/installAppPrompt.d.ts +2 -1
- package/lib/prompts/installAppPrompt.js +12 -2
- package/lib/prompts/promptUtils.d.ts +1 -0
- package/lib/prompts/promptUtils.js +2 -0
- package/lib/ui/logger.d.ts +1 -0
- package/lib/ui/logger.js +1 -0
- package/lib/yargsUtils.d.ts +1 -0
- package/lib/yargsUtils.js +3 -0
- package/mcp-server/tools/index.js +2 -0
- package/mcp-server/tools/project/AddFeatureToProject.js +6 -29
- package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/CreateProjectTool.js +12 -31
- package/mcp-server/tools/project/DeployProject.js +4 -11
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +3 -16
- package/mcp-server/tools/project/UploadProjectTools.js +3 -7
- package/mcp-server/tools/project/ValidateProjectTool.d.ts +17 -0
- package/mcp-server/tools/project/ValidateProjectTool.js +35 -0
- package/mcp-server/utils/content.d.ts +3 -0
- package/mcp-server/utils/content.js +21 -0
- package/package.json +10 -9
- package/types/LocalDev.d.ts +1 -0
- package/types/Yargs.d.ts +4 -0
package/lib/commonOpts.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.addOverwriteOptions = addOverwriteOptions;
|
|
|
10
10
|
exports.addCmsPublishModeOptions = addCmsPublishModeOptions;
|
|
11
11
|
exports.addTestingOptions = addTestingOptions;
|
|
12
12
|
exports.addUseEnvironmentOptions = addUseEnvironmentOptions;
|
|
13
|
+
exports.addJSONOutputOptions = addJSONOutputOptions;
|
|
13
14
|
exports.addCustomHelpOutput = addCustomHelpOutput;
|
|
14
15
|
exports.setLogLevel = setLogLevel;
|
|
15
16
|
exports.getCommandName = getCommandName;
|
|
@@ -19,16 +20,16 @@ const yargs_parser_1 = __importDefault(require("yargs-parser"));
|
|
|
19
20
|
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
20
21
|
const files_1 = require("@hubspot/local-dev-lib/constants/files");
|
|
21
22
|
const config_1 = require("@hubspot/local-dev-lib/config");
|
|
22
|
-
const lang_1 = require("./lang");
|
|
23
23
|
const errorHandlers_1 = require("./errorHandlers");
|
|
24
24
|
const exitCodes_1 = require("./enums/exitCodes");
|
|
25
25
|
const ui_1 = require("./ui");
|
|
26
|
+
const lang_1 = require("./lang");
|
|
26
27
|
function addGlobalOptions(yargs) {
|
|
27
28
|
yargs.version(false);
|
|
28
29
|
yargs.option('debug', {
|
|
29
30
|
alias: 'd',
|
|
30
31
|
default: false,
|
|
31
|
-
describe: (0, lang_1.i18n)(
|
|
32
|
+
describe: (0, lang_1.i18n)('lib.commonOpts.options.debug.describe'),
|
|
32
33
|
type: 'boolean',
|
|
33
34
|
});
|
|
34
35
|
yargs.option('network-debug', {
|
|
@@ -41,21 +42,21 @@ function addGlobalOptions(yargs) {
|
|
|
41
42
|
function addAccountOptions(yargs) {
|
|
42
43
|
return yargs.option('account', {
|
|
43
44
|
alias: 'a',
|
|
44
|
-
describe: (0, lang_1.i18n)(
|
|
45
|
+
describe: (0, lang_1.i18n)('lib.commonOpts.options.account.describe'),
|
|
45
46
|
type: 'string',
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
49
|
function addConfigOptions(yargs) {
|
|
49
50
|
return yargs.option('config', {
|
|
50
51
|
alias: 'c',
|
|
51
|
-
describe: (0, lang_1.i18n)(
|
|
52
|
+
describe: (0, lang_1.i18n)('lib.commonOpts.options.config.describe'),
|
|
52
53
|
type: 'string',
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
56
|
function addOverwriteOptions(yargs) {
|
|
56
57
|
return yargs.option('overwrite', {
|
|
57
58
|
alias: 'o',
|
|
58
|
-
describe: (0, lang_1.i18n)(
|
|
59
|
+
describe: (0, lang_1.i18n)('lib.commonOpts.options.overwrite.describe'),
|
|
59
60
|
type: 'boolean',
|
|
60
61
|
default: false,
|
|
61
62
|
});
|
|
@@ -70,7 +71,7 @@ function addCmsPublishModeOptions(yargs, { read, write }) {
|
|
|
70
71
|
}
|
|
71
72
|
function addTestingOptions(yargs) {
|
|
72
73
|
return yargs.option('qa', {
|
|
73
|
-
describe: (0, lang_1.i18n)(
|
|
74
|
+
describe: (0, lang_1.i18n)('lib.commonOpts.options.qa.describe'),
|
|
74
75
|
type: 'boolean',
|
|
75
76
|
default: false,
|
|
76
77
|
hidden: true,
|
|
@@ -78,12 +79,20 @@ function addTestingOptions(yargs) {
|
|
|
78
79
|
}
|
|
79
80
|
function addUseEnvironmentOptions(yargs) {
|
|
80
81
|
yargs.option('use-env', {
|
|
81
|
-
describe: (0, lang_1.i18n)(
|
|
82
|
+
describe: (0, lang_1.i18n)('lib.commonOpts.options.useEnv.describe'),
|
|
82
83
|
type: 'boolean',
|
|
83
84
|
});
|
|
84
85
|
yargs.conflicts('use-env', 'account');
|
|
85
86
|
return yargs;
|
|
86
87
|
}
|
|
88
|
+
function addJSONOutputOptions(yargs) {
|
|
89
|
+
return yargs.option('json', {
|
|
90
|
+
alias: 'format-output-as-json',
|
|
91
|
+
describe: (0, lang_1.i18n)('lib.commonOpts.options.jsonOutput.describe'),
|
|
92
|
+
type: 'boolean',
|
|
93
|
+
hidden: true,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
87
96
|
async function addCustomHelpOutput(yargs, command, describe) {
|
|
88
97
|
try {
|
|
89
98
|
const parsedArgv = (0, yargs_parser_1.default)(process.argv.slice(2));
|
|
@@ -125,8 +134,11 @@ async function addCustomHelpOutput(yargs, command, describe) {
|
|
|
125
134
|
}
|
|
126
135
|
}
|
|
127
136
|
function setLogLevel(options) {
|
|
128
|
-
const { debug, networkDebug } = options;
|
|
129
|
-
if (
|
|
137
|
+
const { debug, networkDebug, json } = options;
|
|
138
|
+
if (json) {
|
|
139
|
+
(0, logger_1.setLogLevel)(logger_1.LOG_LEVEL.NONE);
|
|
140
|
+
}
|
|
141
|
+
else if (debug) {
|
|
130
142
|
(0, logger_1.setLogLevel)(logger_1.LOG_LEVEL.DEBUG);
|
|
131
143
|
}
|
|
132
144
|
else {
|
package/lib/constants.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ export declare const PROJECT_ERROR_TYPES: {
|
|
|
49
49
|
readonly BUILD_NOT_IN_PROGRESS: "BuildPipelineErrorType.BUILD_NOT_IN_PROGRESS";
|
|
50
50
|
readonly SUBBUILD_FAILED: "BuildPipelineErrorType.DEPENDENT_SUBBUILD_FAILED";
|
|
51
51
|
readonly SUBDEPLOY_FAILED: "DeployPipelineErrorType.DEPENDENT_SUBDEPLOY_FAILED";
|
|
52
|
+
readonly DEPLOY_CONTAINS_REMOVALS: "DeployPipelineErrorType.WARNING_DEPLOY_CONTAINS_REMOVALS";
|
|
52
53
|
};
|
|
53
54
|
export declare const PROJECT_TASK_TYPES: {
|
|
54
55
|
[key: string]: string;
|
|
@@ -98,6 +99,10 @@ export declare const oAuth = "oauth";
|
|
|
98
99
|
export declare const privateDistribution = "private";
|
|
99
100
|
export declare const marketplaceDistribution = "marketplace";
|
|
100
101
|
export declare const appComponent = "app";
|
|
102
|
+
export declare const GET_STARTED_OPTIONS: {
|
|
103
|
+
readonly APP: "APP";
|
|
104
|
+
readonly CMS: "CMS";
|
|
105
|
+
};
|
|
101
106
|
export declare const LOCAL_DEV_SERVER_MESSAGE_TYPES: {
|
|
102
107
|
readonly INITIAL: "INITIAL";
|
|
103
108
|
readonly WEBSOCKET_SERVER_CONNECTED: "WEBSOCKET_SERVER_CONNECTED";
|
package/lib/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LOCAL_DEV_SERVER_MESSAGE_TYPES = exports.appComponent = exports.marketplaceDistribution = exports.privateDistribution = exports.oAuth = exports.staticAuth = exports.APP_INSTALLATION_STATES = exports.LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES = exports.LOCAL_DEV_UI_MESSAGE_SEND_TYPES = exports.FEATURES = exports.APP_AUTH_TYPES = exports.APP_DISTRIBUTION_TYPES = exports.IR_COMPONENT_TYPES = exports.PLATFORM_VERSION_ERROR_TYPES = exports.PROJECT_COMPONENT_TYPES = exports.PROJECT_TASK_TYPES = exports.PROJECT_ERROR_TYPES = exports.PROJECT_DEPLOY_TEXT = exports.PROJECT_BUILD_TEXT = exports.PROJECT_DEPLOY_STATES = exports.PROJECT_BUILD_STATES = exports.PROJECT_CONFIG_FILE = exports.DEFAULT_POLLING_DELAY = exports.MARKETPLACE_FOLDER = exports.HUBSPOT_FOLDER = exports.FEEDBACK_INTERVAL = exports.DEFAULT_PROJECT_TEMPLATE_BRANCH = exports.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH = void 0;
|
|
3
|
+
exports.LOCAL_DEV_SERVER_MESSAGE_TYPES = exports.GET_STARTED_OPTIONS = exports.appComponent = exports.marketplaceDistribution = exports.privateDistribution = exports.oAuth = exports.staticAuth = exports.APP_INSTALLATION_STATES = exports.LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES = exports.LOCAL_DEV_UI_MESSAGE_SEND_TYPES = exports.FEATURES = exports.APP_AUTH_TYPES = exports.APP_DISTRIBUTION_TYPES = exports.IR_COMPONENT_TYPES = exports.PLATFORM_VERSION_ERROR_TYPES = exports.PROJECT_COMPONENT_TYPES = exports.PROJECT_TASK_TYPES = exports.PROJECT_ERROR_TYPES = exports.PROJECT_DEPLOY_TEXT = exports.PROJECT_BUILD_TEXT = exports.PROJECT_DEPLOY_STATES = exports.PROJECT_BUILD_STATES = exports.PROJECT_CONFIG_FILE = exports.DEFAULT_POLLING_DELAY = exports.MARKETPLACE_FOLDER = exports.HUBSPOT_FOLDER = exports.FEEDBACK_INTERVAL = exports.DEFAULT_PROJECT_TEMPLATE_BRANCH = exports.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH = void 0;
|
|
4
4
|
exports.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH = 'HubSpot/hubspot-project-components';
|
|
5
5
|
exports.DEFAULT_PROJECT_TEMPLATE_BRANCH = 'main';
|
|
6
6
|
exports.FEEDBACK_INTERVAL = 10;
|
|
@@ -41,6 +41,7 @@ exports.PROJECT_ERROR_TYPES = {
|
|
|
41
41
|
BUILD_NOT_IN_PROGRESS: 'BuildPipelineErrorType.BUILD_NOT_IN_PROGRESS',
|
|
42
42
|
SUBBUILD_FAILED: 'BuildPipelineErrorType.DEPENDENT_SUBBUILD_FAILED',
|
|
43
43
|
SUBDEPLOY_FAILED: 'DeployPipelineErrorType.DEPENDENT_SUBDEPLOY_FAILED',
|
|
44
|
+
DEPLOY_CONTAINS_REMOVALS: 'DeployPipelineErrorType.WARNING_DEPLOY_CONTAINS_REMOVALS',
|
|
44
45
|
};
|
|
45
46
|
exports.PROJECT_TASK_TYPES = {
|
|
46
47
|
PRIVATE_APP: 'private app',
|
|
@@ -93,6 +94,10 @@ exports.oAuth = 'oauth';
|
|
|
93
94
|
exports.privateDistribution = 'private';
|
|
94
95
|
exports.marketplaceDistribution = 'marketplace';
|
|
95
96
|
exports.appComponent = 'app';
|
|
97
|
+
exports.GET_STARTED_OPTIONS = {
|
|
98
|
+
APP: 'APP',
|
|
99
|
+
CMS: 'CMS',
|
|
100
|
+
};
|
|
96
101
|
exports.LOCAL_DEV_SERVER_MESSAGE_TYPES = {
|
|
97
102
|
INITIAL: 'INITIAL',
|
|
98
103
|
WEBSOCKET_SERVER_CONNECTED: 'WEBSOCKET_SERVER_CONNECTED',
|
package/lib/doctor/Doctor.js
CHANGED
|
@@ -15,6 +15,10 @@ const util_1 = __importDefault(require("util"));
|
|
|
15
15
|
const ui_1 = require("../ui");
|
|
16
16
|
function logError(error, context) {
|
|
17
17
|
debugError(error, context);
|
|
18
|
+
if (isProjectValidationError(error)) {
|
|
19
|
+
logger_1.logger.error(error.message);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
18
22
|
if ((0, suppressError_1.shouldSuppressError)(error, context)) {
|
|
19
23
|
return;
|
|
20
24
|
}
|
|
@@ -89,6 +93,9 @@ class ApiErrorContext {
|
|
|
89
93
|
}
|
|
90
94
|
}
|
|
91
95
|
exports.ApiErrorContext = ApiErrorContext;
|
|
96
|
+
function isProjectValidationError(error) {
|
|
97
|
+
return error instanceof Error && error.name === 'ProjectValidationError';
|
|
98
|
+
}
|
|
92
99
|
function isErrorWithMessageOrReason(error) {
|
|
93
100
|
return (typeof error === 'object' &&
|
|
94
101
|
error !== null &&
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const supportedTools: ({
|
|
2
|
+
name: "Claude Code";
|
|
3
|
+
value: string;
|
|
4
|
+
} | {
|
|
5
|
+
name: "Cursor";
|
|
6
|
+
value: string;
|
|
7
|
+
} | {
|
|
8
|
+
name: "Windsurf";
|
|
9
|
+
value: string;
|
|
10
|
+
})[];
|
|
11
|
+
interface McpCommand {
|
|
12
|
+
command: string;
|
|
13
|
+
args: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare function addMintlifyMcpServer(installTargets: string[]): Promise<void>;
|
|
16
|
+
export declare function setupMintlify(derivedTargets?: string[]): Promise<boolean>;
|
|
17
|
+
export declare function addMcpServerToConfig(targets: string[] | undefined): Promise<string[]>;
|
|
18
|
+
export declare function setupClaudeCode(mcpCommand?: McpCommand): Promise<boolean>;
|
|
19
|
+
export declare function setupCursor(mcpCommand?: McpCommand): boolean;
|
|
20
|
+
export declare function setupWindsurf(mcpCommand?: McpCommand): boolean;
|
|
21
|
+
export {};
|
package/lib/mcp/setup.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.supportedTools = void 0;
|
|
7
|
+
exports.addMintlifyMcpServer = addMintlifyMcpServer;
|
|
8
|
+
exports.setupMintlify = setupMintlify;
|
|
9
|
+
exports.addMcpServerToConfig = addMcpServerToConfig;
|
|
10
|
+
exports.setupClaudeCode = setupClaudeCode;
|
|
11
|
+
exports.setupCursor = setupCursor;
|
|
12
|
+
exports.setupWindsurf = setupWindsurf;
|
|
13
|
+
const logger_1 = require("../ui/logger");
|
|
14
|
+
const en_1 = require("../../lang/en");
|
|
15
|
+
const promptUtils_1 = require("../prompts/promptUtils");
|
|
16
|
+
const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
|
|
17
|
+
const errorHandlers_1 = require("../errorHandlers");
|
|
18
|
+
const command_1 = require("../../mcp-server/utils/command");
|
|
19
|
+
const child_process_1 = require("child_process");
|
|
20
|
+
const path_1 = __importDefault(require("path"));
|
|
21
|
+
const os_1 = __importDefault(require("os"));
|
|
22
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
23
|
+
const fs_1 = require("fs");
|
|
24
|
+
const mcpServerName = 'hubspot-cli-mcp';
|
|
25
|
+
const claudeCode = 'claude';
|
|
26
|
+
const windsurf = 'windsurf';
|
|
27
|
+
const cursor = 'cursor';
|
|
28
|
+
const supportedMintlifyClients = [windsurf, cursor];
|
|
29
|
+
exports.supportedTools = [
|
|
30
|
+
{ name: en_1.commands.mcp.setup.claudeCode, value: claudeCode },
|
|
31
|
+
{ name: en_1.commands.mcp.setup.cursor, value: cursor },
|
|
32
|
+
{ name: en_1.commands.mcp.setup.windsurf, value: windsurf },
|
|
33
|
+
];
|
|
34
|
+
const defaultMcpCommand = {
|
|
35
|
+
command: 'hs',
|
|
36
|
+
args: ['mcp', 'start'],
|
|
37
|
+
};
|
|
38
|
+
async function addMintlifyMcpServer(installTargets) {
|
|
39
|
+
await runSetupFunction(() => setupMintlify(installTargets));
|
|
40
|
+
}
|
|
41
|
+
async function setupMintlify(derivedTargets = supportedMintlifyClients) {
|
|
42
|
+
logger_1.uiLogger.info(en_1.commands.mcp.setup.installingDocSearch);
|
|
43
|
+
logger_1.uiLogger.log('');
|
|
44
|
+
return new Promise(resolve => {
|
|
45
|
+
const subcommands = ['mint-mcp', 'add', 'hubspot-migration'];
|
|
46
|
+
const docsSearchClients = derivedTargets.filter(target => supportedMintlifyClients.includes(target));
|
|
47
|
+
const childProcess = (0, child_process_1.spawn)(`npx`, docsSearchClients && docsSearchClients.length
|
|
48
|
+
? [...subcommands, '--client', ...docsSearchClients]
|
|
49
|
+
: subcommands, {
|
|
50
|
+
stdio: 'inherit',
|
|
51
|
+
});
|
|
52
|
+
childProcess.on('exit', code => {
|
|
53
|
+
if (code !== 0) {
|
|
54
|
+
resolve(false);
|
|
55
|
+
}
|
|
56
|
+
resolve(true);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async function addMcpServerToConfig(targets) {
|
|
61
|
+
try {
|
|
62
|
+
let derivedTargets = [];
|
|
63
|
+
if (!targets || targets.length === 0) {
|
|
64
|
+
const { selectedTargets } = await (0, promptUtils_1.promptUser)({
|
|
65
|
+
name: 'selectedTargets',
|
|
66
|
+
type: 'checkbox',
|
|
67
|
+
message: en_1.commands.mcp.setup.prompts.targets,
|
|
68
|
+
choices: exports.supportedTools,
|
|
69
|
+
validate: (choices) => {
|
|
70
|
+
return choices.length === 0
|
|
71
|
+
? en_1.commands.mcp.setup.prompts.targetsRequired
|
|
72
|
+
: true;
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
derivedTargets = selectedTargets;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
derivedTargets = targets;
|
|
79
|
+
}
|
|
80
|
+
SpinniesManager_1.default.init();
|
|
81
|
+
if (derivedTargets.includes(claudeCode)) {
|
|
82
|
+
await runSetupFunction(setupClaudeCode);
|
|
83
|
+
}
|
|
84
|
+
if (derivedTargets.includes(cursor)) {
|
|
85
|
+
await runSetupFunction(setupCursor);
|
|
86
|
+
}
|
|
87
|
+
if (derivedTargets.includes(windsurf)) {
|
|
88
|
+
await runSetupFunction(setupWindsurf);
|
|
89
|
+
}
|
|
90
|
+
logger_1.uiLogger.info(en_1.commands.mcp.setup.success(derivedTargets));
|
|
91
|
+
return derivedTargets;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
SpinniesManager_1.default.fail('mcpSetup', {
|
|
95
|
+
text: en_1.commands.mcp.setup.spinners.failedToConfigure,
|
|
96
|
+
});
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function runSetupFunction(func) {
|
|
101
|
+
const result = await func();
|
|
102
|
+
if (!result) {
|
|
103
|
+
throw new Error();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function setupMcpConfigFile(config) {
|
|
107
|
+
try {
|
|
108
|
+
SpinniesManager_1.default.add('spinner', {
|
|
109
|
+
text: config.configuringMessage,
|
|
110
|
+
});
|
|
111
|
+
if (!(0, fs_1.existsSync)(config.configPath)) {
|
|
112
|
+
fs_extra_1.default.writeFileSync(config.configPath, JSON.stringify({}, null, 2));
|
|
113
|
+
}
|
|
114
|
+
let mcpConfig = {};
|
|
115
|
+
try {
|
|
116
|
+
const configContent = fs_extra_1.default.readFileSync(config.configPath, 'utf8');
|
|
117
|
+
mcpConfig = JSON.parse(configContent);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
SpinniesManager_1.default.fail('spinner', {
|
|
121
|
+
text: config.failedMessage,
|
|
122
|
+
});
|
|
123
|
+
(0, errorHandlers_1.logError)(error);
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
// Initialize mcpServers if it doesn't exist
|
|
127
|
+
if (!mcpConfig.mcpServers) {
|
|
128
|
+
mcpConfig.mcpServers = {};
|
|
129
|
+
}
|
|
130
|
+
// Add or update HubSpot CLI MCP server
|
|
131
|
+
mcpConfig.mcpServers[mcpServerName] = {
|
|
132
|
+
...config.mcpCommand,
|
|
133
|
+
};
|
|
134
|
+
// Write the updated config
|
|
135
|
+
fs_extra_1.default.writeFileSync(config.configPath, JSON.stringify(mcpConfig, null, 2));
|
|
136
|
+
SpinniesManager_1.default.succeed('spinner', {
|
|
137
|
+
text: config.configuredMessage,
|
|
138
|
+
});
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
SpinniesManager_1.default.fail('spinner', {
|
|
143
|
+
text: config.failedMessage,
|
|
144
|
+
});
|
|
145
|
+
(0, errorHandlers_1.logError)(error);
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function setupClaudeCode(mcpCommand = defaultMcpCommand) {
|
|
150
|
+
try {
|
|
151
|
+
SpinniesManager_1.default.add('claudeCode', {
|
|
152
|
+
text: en_1.commands.mcp.setup.spinners.configuringClaudeCode,
|
|
153
|
+
});
|
|
154
|
+
try {
|
|
155
|
+
// Check if claude command is available
|
|
156
|
+
await (0, command_1.execAsync)('claude --version');
|
|
157
|
+
// Run claude mcp add command
|
|
158
|
+
const mcpConfig = JSON.stringify({
|
|
159
|
+
type: 'stdio',
|
|
160
|
+
...mcpCommand,
|
|
161
|
+
});
|
|
162
|
+
const { stdout } = await (0, command_1.execAsync)('claude mcp list');
|
|
163
|
+
if (stdout.includes(mcpServerName)) {
|
|
164
|
+
SpinniesManager_1.default.update('claudeCode', {
|
|
165
|
+
text: en_1.commands.mcp.setup.spinners.alreadyInstalled,
|
|
166
|
+
});
|
|
167
|
+
await (0, command_1.execAsync)(`claude mcp remove "${mcpServerName}" --scope user`);
|
|
168
|
+
}
|
|
169
|
+
await (0, command_1.execAsync)(`claude mcp add-json "${mcpServerName}" '${mcpConfig}' --scope user`);
|
|
170
|
+
SpinniesManager_1.default.succeed('claudeCode', {
|
|
171
|
+
text: en_1.commands.mcp.setup.spinners.configuredClaudeCode,
|
|
172
|
+
});
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (error instanceof Error &&
|
|
177
|
+
error.message.includes('claude: command not found')) {
|
|
178
|
+
SpinniesManager_1.default.fail('claudeCode', {
|
|
179
|
+
text: en_1.commands.mcp.setup.spinners.claudeCodeNotFound,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
SpinniesManager_1.default.fail('claudeCode', {
|
|
184
|
+
text: en_1.commands.mcp.setup.spinners.claudeCodeInstallFailed,
|
|
185
|
+
});
|
|
186
|
+
(0, errorHandlers_1.logError)(error);
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
SpinniesManager_1.default.fail('claudeCode', {
|
|
193
|
+
text: en_1.commands.mcp.setup.spinners.claudeCodeInstallFailed,
|
|
194
|
+
});
|
|
195
|
+
(0, errorHandlers_1.logError)(error);
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function setupCursor(mcpCommand = defaultMcpCommand) {
|
|
200
|
+
const cursorConfigPath = path_1.default.join(os_1.default.homedir(), '.cursor', 'mcp.json');
|
|
201
|
+
return setupMcpConfigFile({
|
|
202
|
+
configPath: cursorConfigPath,
|
|
203
|
+
configuringMessage: en_1.commands.mcp.setup.spinners.configuringCursor,
|
|
204
|
+
configuredMessage: en_1.commands.mcp.setup.spinners.configuredCursor,
|
|
205
|
+
failedMessage: en_1.commands.mcp.setup.spinners.failedToConfigureCursor,
|
|
206
|
+
mcpCommand,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function setupWindsurf(mcpCommand = defaultMcpCommand) {
|
|
210
|
+
const windsurfConfigPath = path_1.default.join(os_1.default.homedir(), '.codeium', 'windsurf', 'mcp_config.json');
|
|
211
|
+
return setupMcpConfigFile({
|
|
212
|
+
configPath: windsurfConfigPath,
|
|
213
|
+
configuringMessage: en_1.commands.mcp.setup.spinners.configuringWindsurf,
|
|
214
|
+
configuredMessage: en_1.commands.mcp.setup.spinners.configuredWindsurf,
|
|
215
|
+
failedMessage: en_1.commands.mcp.setup.spinners.failedToConfigureWindsurf,
|
|
216
|
+
mcpCommand,
|
|
217
|
+
});
|
|
218
|
+
}
|
package/lib/projectProfiles.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare function logProfileHeader(profileName: string): void;
|
|
|
4
4
|
export declare function logProfileFooter(profile: HsProfileFile, includeVariables?: boolean): void;
|
|
5
5
|
export declare function loadProfile(projectConfig: ProjectConfig | null, projectDir: string | null, profileName: string): HsProfileFile | undefined;
|
|
6
6
|
export declare function exitIfUsingProfiles(projectConfig: ProjectConfig | null, projectDir: string | null): Promise<void>;
|
|
7
|
+
export declare function loadAndValidateProfile(projectConfig: ProjectConfig | null, projectDir: string | null, argsProfile: string | undefined): Promise<number | undefined>;
|
package/lib/projectProfiles.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.logProfileHeader = logProfileHeader;
|
|
|
7
7
|
exports.logProfileFooter = logProfileFooter;
|
|
8
8
|
exports.loadProfile = loadProfile;
|
|
9
9
|
exports.exitIfUsingProfiles = exitIfUsingProfiles;
|
|
10
|
+
exports.loadAndValidateProfile = loadAndValidateProfile;
|
|
10
11
|
const path_1 = __importDefault(require("path"));
|
|
11
12
|
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
12
13
|
const en_1 = require("../lang/en");
|
|
@@ -63,3 +64,20 @@ async function exitIfUsingProfiles(projectConfig, projectDir) {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
}
|
|
67
|
+
async function loadAndValidateProfile(projectConfig, projectDir, argsProfile) {
|
|
68
|
+
if (argsProfile) {
|
|
69
|
+
logProfileHeader(argsProfile);
|
|
70
|
+
const profile = loadProfile(projectConfig, projectDir, argsProfile);
|
|
71
|
+
if (!profile) {
|
|
72
|
+
(0, ui_1.uiLine)();
|
|
73
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
74
|
+
}
|
|
75
|
+
logProfileFooter(profile, true);
|
|
76
|
+
return profile.accountId;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// A profile must be specified if this project has profiles configured
|
|
80
|
+
await exitIfUsingProfiles(projectConfig, projectDir);
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
@@ -228,7 +228,7 @@ function makePollTaskStatusFunc({ statusFn, structureFn, statusText, statusStrin
|
|
|
228
228
|
}
|
|
229
229
|
function pollBuildAutodeployStatus(accountId, taskName, buildId) {
|
|
230
230
|
return new Promise((resolve, reject) => {
|
|
231
|
-
let maxIntervals = (
|
|
231
|
+
let maxIntervals = (15 * 1000) / constants_1.DEFAULT_POLLING_DELAY; // Num of intervals in ~15s
|
|
232
232
|
const pollInterval = setInterval(async () => {
|
|
233
233
|
let build;
|
|
234
234
|
try {
|
|
@@ -14,9 +14,12 @@ declare class AppDevModeInterface {
|
|
|
14
14
|
private get appNode();
|
|
15
15
|
private get appData();
|
|
16
16
|
private set appData(value);
|
|
17
|
+
private isAutomaticallyInstallable;
|
|
17
18
|
private getAppInstallUrl;
|
|
18
19
|
private fetchAppData;
|
|
19
20
|
private checkMarketplaceAppInstalls;
|
|
21
|
+
private autoInstallStaticAuthApp;
|
|
22
|
+
private installAppOrOpenInstallUrl;
|
|
20
23
|
private checkTestAccountAppInstallation;
|
|
21
24
|
private setUpLocalDevServerMessageListeners;
|
|
22
25
|
setup(args: any): Promise<void>;
|
|
@@ -4,6 +4,7 @@ const localDevAuth_1 = require("@hubspot/local-dev-lib/api/localDevAuth");
|
|
|
4
4
|
const appsDev_1 = require("@hubspot/local-dev-lib/api/appsDev");
|
|
5
5
|
const ui_extensions_dev_server_1 = require("@hubspot/ui-extensions-dev-server");
|
|
6
6
|
const portManager_1 = require("@hubspot/local-dev-lib/portManager");
|
|
7
|
+
const config_1 = require("@hubspot/local-dev-lib/config");
|
|
7
8
|
const constants_1 = require("../../constants");
|
|
8
9
|
const exitCodes_1 = require("../../enums/exitCodes");
|
|
9
10
|
const structure_1 = require("../../projects/structure");
|
|
@@ -14,6 +15,7 @@ const promptUtils_1 = require("../../prompts/promptUtils");
|
|
|
14
15
|
const en_1 = require("../../../lang/en");
|
|
15
16
|
const logger_1 = require("../../ui/logger");
|
|
16
17
|
const urls_1 = require("../../app/urls");
|
|
18
|
+
const accountTypes_1 = require("../../accountTypes");
|
|
17
19
|
class AppDevModeInterface {
|
|
18
20
|
localDevState;
|
|
19
21
|
localDevLogger;
|
|
@@ -22,15 +24,6 @@ class AppDevModeInterface {
|
|
|
22
24
|
constructor(options) {
|
|
23
25
|
this.localDevState = options.localDevState;
|
|
24
26
|
this.localDevLogger = options.localDevLogger;
|
|
25
|
-
// Static auth apps are currently only installable in the portal that the project resides in
|
|
26
|
-
// This limitation will eventually be removed, but in the meantime we need this check or the install
|
|
27
|
-
// will always fail with a confusing message
|
|
28
|
-
if (this.appNode?.config.auth.type === constants_1.APP_AUTH_TYPES.STATIC &&
|
|
29
|
-
this.localDevState.targetTestingAccountId !==
|
|
30
|
-
this.localDevState.targetProjectAccountId) {
|
|
31
|
-
logger_1.uiLogger.error(en_1.lib.LocalDevManager.staticAuthAccountsMustMatch);
|
|
32
|
-
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
33
|
-
}
|
|
34
27
|
if (!this.localDevState.targetProjectAccountId ||
|
|
35
28
|
!this.localDevState.projectConfig ||
|
|
36
29
|
!this.localDevState.projectDir) {
|
|
@@ -59,6 +52,19 @@ class AppDevModeInterface {
|
|
|
59
52
|
}
|
|
60
53
|
this.localDevState.setAppDataForUid(this.appNode.uid, appData);
|
|
61
54
|
}
|
|
55
|
+
isAutomaticallyInstallable() {
|
|
56
|
+
const targetTestingAccount = (0, config_1.getAccountConfig)(this.localDevState.targetTestingAccountId);
|
|
57
|
+
if (!targetTestingAccount) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
const isTestAccount = (0, accountTypes_1.isDeveloperTestAccount)(targetTestingAccount) ||
|
|
61
|
+
(0, accountTypes_1.isSandbox)(targetTestingAccount);
|
|
62
|
+
const hasCorrectParent = targetTestingAccount.parentAccountId ===
|
|
63
|
+
this.localDevState.targetProjectAccountId;
|
|
64
|
+
return (isTestAccount &&
|
|
65
|
+
hasCorrectParent &&
|
|
66
|
+
this.appNode?.config.auth.type === constants_1.APP_AUTH_TYPES.STATIC);
|
|
67
|
+
}
|
|
62
68
|
async getAppInstallUrl() {
|
|
63
69
|
if (this.appNode?.config.auth.type === constants_1.APP_AUTH_TYPES.OAUTH) {
|
|
64
70
|
return (0, urls_1.getOauthAppInstallUrl)({
|
|
@@ -72,7 +78,7 @@ class AppDevModeInterface {
|
|
|
72
78
|
const { data: { results }, } = await (0, appsDev_1.fetchPublicAppsForPortal)(this.localDevState.targetProjectAccountId);
|
|
73
79
|
const app = results.find(app => app.sourceId === this.appNode?.uid);
|
|
74
80
|
if (!app) {
|
|
75
|
-
logger_1.uiLogger.error(en_1.lib.LocalDevManager.
|
|
81
|
+
logger_1.uiLogger.error(en_1.lib.LocalDevManager.appNotFound(this.localDevState.targetProjectAccountId, this.appNode?.uid));
|
|
76
82
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
77
83
|
}
|
|
78
84
|
return (0, urls_1.getStaticAuthAppInstallUrl)({
|
|
@@ -93,6 +99,7 @@ class AppDevModeInterface {
|
|
|
93
99
|
clientId: appData.clientId,
|
|
94
100
|
name: appData.name,
|
|
95
101
|
installationState: constants_1.APP_INSTALLATION_STATES.NOT_INSTALLED,
|
|
102
|
+
scopeGroupIds: appData.scopeGroupIds,
|
|
96
103
|
};
|
|
97
104
|
this.marketplaceAppInstalls = uniquePortalInstallCount;
|
|
98
105
|
}
|
|
@@ -110,9 +117,31 @@ class AppDevModeInterface {
|
|
|
110
117
|
}
|
|
111
118
|
this.localDevLogger.addUploadWarning(en_1.lib.AppDevModeInterface.defaultMarketplaceAppWarning(this.marketplaceAppInstalls));
|
|
112
119
|
}
|
|
120
|
+
async autoInstallStaticAuthApp() {
|
|
121
|
+
const shouldInstall = await (0, installAppPrompt_1.installAppAutoPrompt)();
|
|
122
|
+
if (!shouldInstall) {
|
|
123
|
+
logger_1.uiLogger.log(en_1.lib.AppDevModeInterface.autoInstallDeclined);
|
|
124
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
125
|
+
}
|
|
126
|
+
await (0, appsDev_1.installStaticAuthAppOnTestAccount)(this.appData.id, this.localDevState.targetTestingAccountId, this.appData.scopeGroupIds);
|
|
127
|
+
}
|
|
128
|
+
async installAppOrOpenInstallUrl(isReinstall) {
|
|
129
|
+
if (this.isAutomaticallyInstallable()) {
|
|
130
|
+
try {
|
|
131
|
+
await this.autoInstallStaticAuthApp();
|
|
132
|
+
logger_1.uiLogger.success(en_1.lib.AppDevModeInterface.autoInstallSuccess(this.appData.name, this.localDevState.targetTestingAccountId));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
logger_1.uiLogger.error(en_1.lib.AppDevModeInterface.autoInstallError(this.appData.name, this.localDevState.targetTestingAccountId));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const installUrl = await this.getAppInstallUrl();
|
|
140
|
+
await (0, installAppPrompt_1.installAppBrowserPrompt)(installUrl, isReinstall);
|
|
141
|
+
}
|
|
113
142
|
async checkTestAccountAppInstallation() {
|
|
114
143
|
if (!this.appNode || !this.appData) {
|
|
115
|
-
return;
|
|
144
|
+
return {};
|
|
116
145
|
}
|
|
117
146
|
const { data: { isInstalledWithScopeGroups, previouslyAuthorizedScopeGroups }, } = await (0, localDevAuth_1.fetchAppInstallationData)(this.localDevState.targetTestingAccountId, this.localDevState.projectId, this.appNode.uid, this.appNode.config.auth.requiredScopes, this.appNode.config.auth.optionalScopes);
|
|
118
147
|
const isReinstall = previouslyAuthorizedScopeGroups.length > 0;
|
|
@@ -128,10 +157,7 @@ class AppDevModeInterface {
|
|
|
128
157
|
installationState: constants_1.APP_INSTALLATION_STATES.INSTALLED_WITH_OUTDATED_SCOPES,
|
|
129
158
|
};
|
|
130
159
|
}
|
|
131
|
-
|
|
132
|
-
const installUrl = await this.getAppInstallUrl();
|
|
133
|
-
await (0, installAppPrompt_1.installAppPrompt)(installUrl, isReinstall);
|
|
134
|
-
}
|
|
160
|
+
return { needsInstall: !isInstalledWithScopeGroups, isReinstall };
|
|
135
161
|
}
|
|
136
162
|
setUpLocalDevServerMessageListeners() {
|
|
137
163
|
this.localDevState.addListener('devServerMessage', message => {
|
|
@@ -151,7 +177,10 @@ class AppDevModeInterface {
|
|
|
151
177
|
if (this.appNode.config.distribution === constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE) {
|
|
152
178
|
await this.checkMarketplaceAppInstalls();
|
|
153
179
|
}
|
|
154
|
-
await this.checkTestAccountAppInstallation();
|
|
180
|
+
const { needsInstall, isReinstall } = await this.checkTestAccountAppInstallation();
|
|
181
|
+
if (needsInstall) {
|
|
182
|
+
await this.installAppOrOpenInstallUrl(isReinstall || false);
|
|
183
|
+
}
|
|
155
184
|
}
|
|
156
185
|
catch (e) {
|
|
157
186
|
(0, index_1.logError)(e);
|
|
@@ -195,7 +195,7 @@ class LocalDevManager {
|
|
|
195
195
|
scopes: this.activeApp.config.auth.requiredScopes,
|
|
196
196
|
redirectUrls: this.activeApp.config.auth.redirectUrls,
|
|
197
197
|
});
|
|
198
|
-
await (0, installAppPrompt_1.
|
|
198
|
+
await (0, installAppPrompt_1.installAppBrowserPrompt)(installUrl, isReinstall);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
updateKeypressListeners() {
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -18,4 +18,7 @@ type HandleProjectUploadArg<T> = {
|
|
|
18
18
|
profile?: string;
|
|
19
19
|
};
|
|
20
20
|
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
|
|
21
|
+
export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig): void;
|
|
22
|
+
export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
23
|
+
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<unknown>;
|
|
21
24
|
export {};
|