@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/projects/upload.js
CHANGED
|
@@ -4,22 +4,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.handleProjectUpload = handleProjectUpload;
|
|
7
|
+
exports.validateSourceDirectory = validateSourceDirectory;
|
|
8
|
+
exports.validateNoHSMetaMismatch = validateNoHSMetaMismatch;
|
|
9
|
+
exports.handleTranslate = handleTranslate;
|
|
7
10
|
const archiver_1 = __importDefault(require("archiver"));
|
|
8
11
|
const tmp_1 = __importDefault(require("tmp"));
|
|
9
12
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
13
|
const path_1 = __importDefault(require("path"));
|
|
11
14
|
const projects_1 = require("@hubspot/local-dev-lib/api/projects");
|
|
12
15
|
const ignoreRules_1 = require("@hubspot/local-dev-lib/ignoreRules");
|
|
16
|
+
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
13
17
|
const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
|
|
14
18
|
const ui_1 = require("../ui");
|
|
15
|
-
const exitCodes_1 = require("../enums/exitCodes");
|
|
16
|
-
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
17
19
|
const errorHandlers_1 = require("../errorHandlers");
|
|
18
20
|
const node_util_1 = __importDefault(require("node:util"));
|
|
19
21
|
const en_1 = require("../../lang/en");
|
|
20
22
|
const ensureProjectExists_1 = require("./ensureProjectExists");
|
|
21
23
|
const logger_1 = require("../ui/logger");
|
|
22
24
|
const buildAndDeploy_1 = require("./buildAndDeploy");
|
|
25
|
+
const exitCodes_1 = require("../enums/exitCodes");
|
|
23
26
|
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
|
|
24
27
|
SpinniesManager_1.default.init({});
|
|
25
28
|
const accountIdentifier = (0, ui_1.uiAccountDescription)(accountId);
|
|
@@ -49,14 +52,18 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
|
|
|
49
52
|
}
|
|
50
53
|
async function handleProjectUpload({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage = '', forceCreate = false, isUploadCommand = false, sendIR = false, skipValidation = false, }) {
|
|
51
54
|
const srcDir = path_1.default.resolve(projectDir, projectConfig.srcDir);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
logger_1.uiLogger.log(en_1.lib.projectUpload.handleProjectUpload.emptySource(projectConfig.srcDir));
|
|
55
|
-
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
55
|
+
try {
|
|
56
|
+
validateSourceDirectory(srcDir, projectConfig);
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
catch (e) {
|
|
59
|
+
(0, errorHandlers_1.logError)(e);
|
|
60
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
await validateNoHSMetaMismatch(srcDir, projectConfig);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
(0, errorHandlers_1.logError)(e);
|
|
60
67
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
61
68
|
}
|
|
62
69
|
const tempFile = tmp_1.default.fileSync({ postfix: '.zip' });
|
|
@@ -68,21 +75,11 @@ async function handleProjectUpload({ accountId, projectConfig, projectDir, callb
|
|
|
68
75
|
let intermediateRepresentation;
|
|
69
76
|
if (sendIR) {
|
|
70
77
|
try {
|
|
71
|
-
intermediateRepresentation = await (
|
|
72
|
-
projectSourceDir: path_1.default.join(projectDir, projectConfig.srcDir),
|
|
73
|
-
platformVersion: projectConfig.platformVersion,
|
|
74
|
-
accountId,
|
|
75
|
-
}, { skipValidation, profile });
|
|
76
|
-
logger_1.uiLogger.debug(node_util_1.default.inspect(intermediateRepresentation, false, null, true));
|
|
78
|
+
intermediateRepresentation = await handleTranslate(projectDir, projectConfig, accountId, skipValidation, profile);
|
|
77
79
|
}
|
|
78
80
|
catch (e) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
(0, errorHandlers_1.logError)(e);
|
|
84
|
-
}
|
|
85
|
-
return process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
81
|
+
(0, errorHandlers_1.logError)(e);
|
|
82
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
86
83
|
}
|
|
87
84
|
}
|
|
88
85
|
await (0, ensureProjectExists_1.ensureProjectExists)(accountId, projectConfig.name, {
|
|
@@ -116,3 +113,40 @@ async function handleProjectUpload({ accountId, projectConfig, projectDir, callb
|
|
|
116
113
|
archive.finalize();
|
|
117
114
|
return result;
|
|
118
115
|
}
|
|
116
|
+
function validateSourceDirectory(srcDir, projectConfig) {
|
|
117
|
+
const filenames = fs_extra_1.default.readdirSync(srcDir);
|
|
118
|
+
if (!filenames || filenames.length === 0) {
|
|
119
|
+
const validationError = new Error(en_1.lib.projectUpload.handleProjectUpload.emptySource(projectConfig.srcDir));
|
|
120
|
+
validationError.name = 'ProjectValidationError';
|
|
121
|
+
throw validationError;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function validateNoHSMetaMismatch(srcDir, projectConfig) {
|
|
125
|
+
const hasHsMetaFiles = await (0, project_parsing_lib_1.projectContainsHsMetaFiles)(srcDir);
|
|
126
|
+
if (!(0, buildAndDeploy_1.useV3Api)(projectConfig.platformVersion) && hasHsMetaFiles) {
|
|
127
|
+
const validationError = new Error(en_1.lib.projectUpload.wrongPlatformVersionMetaFiles);
|
|
128
|
+
validationError.name = 'ProjectValidationError';
|
|
129
|
+
throw validationError;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function handleTranslate(projectDir, projectConfig, accountId, skipValidation, profile) {
|
|
133
|
+
try {
|
|
134
|
+
const intermediateRepresentation = await (0, project_parsing_lib_1.translate)({
|
|
135
|
+
projectSourceDir: path_1.default.join(projectDir, projectConfig.srcDir),
|
|
136
|
+
platformVersion: projectConfig.platformVersion,
|
|
137
|
+
accountId,
|
|
138
|
+
}, { skipValidation, profile });
|
|
139
|
+
logger_1.uiLogger.debug(node_util_1.default.inspect(intermediateRepresentation, false, null, true));
|
|
140
|
+
return intermediateRepresentation;
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
if ((0, project_parsing_lib_1.isTranslationError)(e)) {
|
|
144
|
+
const validationError = new Error(e.toString());
|
|
145
|
+
validationError.name = 'ProjectValidationError';
|
|
146
|
+
throw validationError;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
(0, errorHandlers_1.logError)(e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
package/lib/projects/urls.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export declare function getProjectComponentDistributionUrl(projectName: string, componentName: string, accountId: number): string;
|
|
2
|
+
export declare function getDeveloperOverviewUrl(accountId: number): string;
|
|
1
3
|
export declare function getProjectDetailUrl(projectName: string, accountId: number): string | undefined;
|
|
2
4
|
export declare function getProjectSettingsUrl(projectName: string, accountId: number): string | undefined;
|
|
3
5
|
export declare function getProjectActivityUrl(projectName: string, accountId: number): string;
|
package/lib/projects/urls.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getProjectComponentDistributionUrl = getProjectComponentDistributionUrl;
|
|
4
|
+
exports.getDeveloperOverviewUrl = getDeveloperOverviewUrl;
|
|
3
5
|
exports.getProjectDetailUrl = getProjectDetailUrl;
|
|
4
6
|
exports.getProjectSettingsUrl = getProjectSettingsUrl;
|
|
5
7
|
exports.getProjectActivityUrl = getProjectActivityUrl;
|
|
@@ -15,6 +17,14 @@ function getBaseUrl(accountId) {
|
|
|
15
17
|
function getProjectHomeUrl(accountId) {
|
|
16
18
|
return `${getBaseUrl(accountId)}/developer-projects/${accountId}`;
|
|
17
19
|
}
|
|
20
|
+
function getProjectComponentDistributionUrl(projectName, componentName, accountId) {
|
|
21
|
+
const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)((0, config_1.getEnv)(accountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD);
|
|
22
|
+
return `${baseUrl}/developer-projects/${accountId}/project/${projectName}/component/${componentName}/distribution`;
|
|
23
|
+
}
|
|
24
|
+
function getDeveloperOverviewUrl(accountId) {
|
|
25
|
+
const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)((0, config_1.getEnv)(accountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD);
|
|
26
|
+
return `${baseUrl}/developer-overview/${accountId}`;
|
|
27
|
+
}
|
|
18
28
|
function getProjectDetailUrl(projectName, accountId) {
|
|
19
29
|
if (!projectName)
|
|
20
30
|
return;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DeveloperTestAccountConfig } from '@hubspot/local-dev-lib/types/developerTestAccounts';
|
|
2
|
+
declare const hubs: {
|
|
3
|
+
readonly MARKETING: "marketingLevel";
|
|
4
|
+
readonly OPS: "opsLevel";
|
|
5
|
+
readonly SERVICE: "serviceLevel";
|
|
6
|
+
readonly SALES: "salesLevel";
|
|
7
|
+
readonly CONTENT: "contentLevel";
|
|
8
|
+
};
|
|
9
|
+
type HubName = keyof typeof hubs;
|
|
10
|
+
type HubTier = 'STARTER' | 'PROFESSIONAL' | 'ENTERPRISE';
|
|
11
|
+
export type HubConfig = `${HubName}:${HubTier}`;
|
|
12
|
+
export declare function createDeveloperTestAccountConfigPrompt(args?: {
|
|
13
|
+
name?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
tiers?: HubConfig[];
|
|
16
|
+
}): Promise<DeveloperTestAccountConfig>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDeveloperTestAccountConfigPrompt = createDeveloperTestAccountConfigPrompt;
|
|
4
|
+
const en_1 = require("../../lang/en");
|
|
5
|
+
const promptUtils_1 = require("./promptUtils");
|
|
6
|
+
const hubs = {
|
|
7
|
+
MARKETING: 'marketingLevel',
|
|
8
|
+
OPS: 'opsLevel',
|
|
9
|
+
SERVICE: 'serviceLevel',
|
|
10
|
+
SALES: 'salesLevel',
|
|
11
|
+
CONTENT: 'contentLevel',
|
|
12
|
+
};
|
|
13
|
+
const TEST_ACCOUNT_TIERS = [
|
|
14
|
+
{ name: 'Marketing STARTER', value: 'MARKETING:STARTER' },
|
|
15
|
+
{
|
|
16
|
+
name: 'Marketing PROFESSIONAL',
|
|
17
|
+
value: 'MARKETING:PROFESSIONAL',
|
|
18
|
+
},
|
|
19
|
+
{ name: 'Marketing ENTERPRISE', value: 'MARKETING:ENTERPRISE' },
|
|
20
|
+
promptUtils_1.Separator,
|
|
21
|
+
{ name: 'Ops STARTER', value: 'OPS:STARTER' },
|
|
22
|
+
{ name: 'Ops PROFESSIONAL', value: 'OPS:PROFESSIONAL' },
|
|
23
|
+
{ name: 'Ops ENTERPRISE', value: 'OPS:ENTERPRISE' },
|
|
24
|
+
promptUtils_1.Separator,
|
|
25
|
+
{ name: 'Service STARTER', value: 'SERVICE:STARTER' },
|
|
26
|
+
{ name: 'Service PROFESSIONAL', value: 'SERVICE:PROFESSIONAL' },
|
|
27
|
+
{ name: 'Service ENTERPRISE', value: 'SERVICE:ENTERPRISE' },
|
|
28
|
+
promptUtils_1.Separator,
|
|
29
|
+
{ name: 'Sales STARTER', value: 'SALES:STARTER' },
|
|
30
|
+
{ name: 'Sales PROFESSIONAL', value: 'SALES:PROFESSIONAL' },
|
|
31
|
+
{ name: 'Sales ENTERPRISE', value: 'SALES:ENTERPRISE' },
|
|
32
|
+
promptUtils_1.Separator,
|
|
33
|
+
{ name: 'Content STARTER', value: 'CONTENT:STARTER' },
|
|
34
|
+
{ name: 'Content PROFESSIONAL', value: 'CONTENT:PROFESSIONAL' },
|
|
35
|
+
{ name: 'Content ENTERPRISE', value: 'CONTENT:ENTERPRISE' },
|
|
36
|
+
promptUtils_1.Separator,
|
|
37
|
+
];
|
|
38
|
+
async function createDeveloperTestAccountConfigPrompt(args = {}) {
|
|
39
|
+
const { name, description, tiers } = args;
|
|
40
|
+
let accountName = name;
|
|
41
|
+
let accountDescription = description;
|
|
42
|
+
let accountLevelsArray = tiers;
|
|
43
|
+
if (!accountName) {
|
|
44
|
+
const namePromptResult = await (0, promptUtils_1.promptUser)({
|
|
45
|
+
name: 'accountName',
|
|
46
|
+
message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.namePrompt,
|
|
47
|
+
type: 'input',
|
|
48
|
+
});
|
|
49
|
+
accountName = namePromptResult.accountName;
|
|
50
|
+
}
|
|
51
|
+
if (!accountDescription) {
|
|
52
|
+
const descriptionPromptResult = await (0, promptUtils_1.promptUser)({
|
|
53
|
+
name: 'description',
|
|
54
|
+
message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.descriptionPrompt,
|
|
55
|
+
type: 'input',
|
|
56
|
+
});
|
|
57
|
+
accountDescription = descriptionPromptResult.description;
|
|
58
|
+
}
|
|
59
|
+
if (!accountLevelsArray) {
|
|
60
|
+
const accountLevelsPromptResult = await (0, promptUtils_1.promptUser)({
|
|
61
|
+
name: 'testAccountLevels',
|
|
62
|
+
message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.tiersPrompt,
|
|
63
|
+
type: 'checkbox',
|
|
64
|
+
choices: TEST_ACCOUNT_TIERS,
|
|
65
|
+
validate: choices => {
|
|
66
|
+
if (choices?.length > 1) {
|
|
67
|
+
const hubMap = {};
|
|
68
|
+
for (const choice of choices) {
|
|
69
|
+
const hub = choice.split(':')[0];
|
|
70
|
+
if (hubMap[hub]) {
|
|
71
|
+
return en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.errors
|
|
72
|
+
.tiersError;
|
|
73
|
+
}
|
|
74
|
+
hubMap[hub] = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
accountLevelsArray = accountLevelsPromptResult.testAccountLevels;
|
|
81
|
+
}
|
|
82
|
+
if (!accountLevelsArray) {
|
|
83
|
+
accountLevelsArray = [];
|
|
84
|
+
}
|
|
85
|
+
const accountLevels = accountLevelsArray.reduce((acc, level) => {
|
|
86
|
+
const [hubName, hubTier] = level.split(':');
|
|
87
|
+
const hubLevel = hubs[hubName];
|
|
88
|
+
acc[hubLevel] = hubTier;
|
|
89
|
+
return acc;
|
|
90
|
+
}, {});
|
|
91
|
+
return {
|
|
92
|
+
accountName: accountName,
|
|
93
|
+
description: accountDescription,
|
|
94
|
+
...accountLevels,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function installAppBrowserPrompt(installUrl: string, isReinstall?: boolean): Promise<void>;
|
|
2
|
+
export declare function installAppAutoPrompt(): Promise<boolean>;
|
|
@@ -3,13 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.installAppBrowserPrompt = installAppBrowserPrompt;
|
|
7
|
+
exports.installAppAutoPrompt = installAppAutoPrompt;
|
|
7
8
|
const open_1 = __importDefault(require("open"));
|
|
8
9
|
const promptUtils_1 = require("./promptUtils");
|
|
9
10
|
const exitCodes_1 = require("../enums/exitCodes");
|
|
10
11
|
const en_1 = require("../../lang/en");
|
|
11
12
|
const logger_1 = require("../ui/logger");
|
|
12
|
-
async function
|
|
13
|
+
async function installAppBrowserPrompt(installUrl, isReinstall = false) {
|
|
13
14
|
logger_1.uiLogger.log('');
|
|
14
15
|
if (isReinstall) {
|
|
15
16
|
logger_1.uiLogger.log(en_1.lib.prompts.installAppPrompt.reinstallExplanation);
|
|
@@ -33,3 +34,12 @@ async function installAppPrompt(installUrl, isReinstall = false) {
|
|
|
33
34
|
}
|
|
34
35
|
(0, open_1.default)(installUrl);
|
|
35
36
|
}
|
|
37
|
+
async function installAppAutoPrompt() {
|
|
38
|
+
logger_1.uiLogger.log('');
|
|
39
|
+
const { shouldInstall } = await (0, promptUtils_1.promptUser)({
|
|
40
|
+
name: 'shouldInstall',
|
|
41
|
+
type: 'confirm',
|
|
42
|
+
message: en_1.lib.prompts.installAppPrompt.autoPrompt,
|
|
43
|
+
});
|
|
44
|
+
return shouldInstall;
|
|
45
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PromptConfig, GenericPromptResponse, PromptWhen, PromptChoices } from '../../types/Prompts';
|
|
2
|
+
export declare const Separator: any;
|
|
2
3
|
export declare function promptUser<T extends GenericPromptResponse>(config: PromptConfig<T> | PromptConfig<T>[]): Promise<T>;
|
|
3
4
|
export declare function confirmPrompt(message: string, options?: {
|
|
4
5
|
defaultAnswer?: boolean;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Separator = void 0;
|
|
3
4
|
exports.promptUser = promptUser;
|
|
4
5
|
exports.confirmPrompt = confirmPrompt;
|
|
5
6
|
exports.listPrompt = listPrompt;
|
|
6
7
|
exports.inputPrompt = inputPrompt;
|
|
7
8
|
const inquirer = require('inquirer');
|
|
8
9
|
const promptModule = inquirer.createPromptModule();
|
|
10
|
+
exports.Separator = new inquirer.Separator();
|
|
9
11
|
function promptUser(config) {
|
|
10
12
|
return promptModule(config);
|
|
11
13
|
}
|
package/lib/ui/logger.d.ts
CHANGED
package/lib/ui/logger.js
CHANGED
package/lib/yargsUtils.d.ts
CHANGED
package/lib/yargsUtils.js
CHANGED
|
@@ -32,6 +32,9 @@ function makeYargsBuilder(callback, command, describe, options = {}) {
|
|
|
32
32
|
if (options.useTestingOptions) {
|
|
33
33
|
(0, commonOpts_1.addTestingOptions)(yargs);
|
|
34
34
|
}
|
|
35
|
+
if (options.useJSONOutputOptions) {
|
|
36
|
+
(0, commonOpts_1.addJSONOutputOptions)(yargs);
|
|
37
|
+
}
|
|
35
38
|
if (options.useCmsPublishModeOptions) {
|
|
36
39
|
const opts = typeof options.useCmsPublishModeOptions === 'object'
|
|
37
40
|
? options.useCmsPublishModeOptions
|
|
@@ -6,6 +6,7 @@ const CreateProjectTool_1 = require("./project/CreateProjectTool");
|
|
|
6
6
|
const GuidedWalkthroughTool_1 = require("./project/GuidedWalkthroughTool");
|
|
7
7
|
const DeployProject_1 = require("./project/DeployProject");
|
|
8
8
|
const AddFeatureToProject_1 = require("./project/AddFeatureToProject");
|
|
9
|
+
const ValidateProjectTool_1 = require("./project/ValidateProjectTool");
|
|
9
10
|
function registerProjectTools(mcpServer) {
|
|
10
11
|
return [
|
|
11
12
|
new UploadProjectTools_1.UploadProjectTools(mcpServer).register(),
|
|
@@ -13,5 +14,6 @@ function registerProjectTools(mcpServer) {
|
|
|
13
14
|
new GuidedWalkthroughTool_1.GuidedWalkthroughTool(mcpServer).register(),
|
|
14
15
|
new DeployProject_1.DeployProject(mcpServer).register(),
|
|
15
16
|
new AddFeatureToProject_1.AddFeatureToProject(mcpServer).register(),
|
|
17
|
+
new ValidateProjectTool_1.ValidateProjectTool(mcpServer).register(),
|
|
16
18
|
];
|
|
17
19
|
}
|
|
@@ -7,11 +7,12 @@ const constants_1 = require("../../../lib/constants");
|
|
|
7
7
|
const command_1 = require("../../utils/command");
|
|
8
8
|
const constants_2 = require("./constants");
|
|
9
9
|
const project_1 = require("../../utils/project");
|
|
10
|
+
const content_1 = require("../../utils/content");
|
|
10
11
|
const inputSchema = {
|
|
11
12
|
absoluteProjectPath: constants_2.absoluteProjectPath,
|
|
12
13
|
addApp: zod_1.z
|
|
13
14
|
.boolean()
|
|
14
|
-
.describe('Should an app be added? If there is no app in the project,
|
|
15
|
+
.describe('Should an app be added? If there is no app in the project, an app must be added to add a feature'),
|
|
15
16
|
distribution: zod_1.z
|
|
16
17
|
.optional(zod_1.z.union([
|
|
17
18
|
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE),
|
|
@@ -51,19 +52,13 @@ class AddFeatureToProject extends types_1.Tool {
|
|
|
51
52
|
command = (0, command_1.addFlag)(command, 'distribution', distribution);
|
|
52
53
|
}
|
|
53
54
|
else if (addApp) {
|
|
54
|
-
content.push({
|
|
55
|
-
type: 'text',
|
|
56
|
-
text: `Ask the user how they would you like to distribute the application? Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`,
|
|
57
|
-
});
|
|
55
|
+
content.push((0, content_1.formatTextContent)(`Ask the user how they would you like to distribute the application. Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`));
|
|
58
56
|
}
|
|
59
57
|
if (auth) {
|
|
60
58
|
command = (0, command_1.addFlag)(command, 'auth', auth);
|
|
61
59
|
}
|
|
62
60
|
else if (addApp) {
|
|
63
|
-
content.push({
|
|
64
|
-
type: 'text',
|
|
65
|
-
text: `Ask the user which auth type they would like to use? Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`,
|
|
66
|
-
});
|
|
61
|
+
content.push((0, content_1.formatTextContent)(`Ask the user which auth type they would like to use. Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`));
|
|
67
62
|
}
|
|
68
63
|
if (content.length > 0) {
|
|
69
64
|
return {
|
|
@@ -73,28 +68,10 @@ class AddFeatureToProject extends types_1.Tool {
|
|
|
73
68
|
// If features isn't provided, pass an empty array to bypass the prompt
|
|
74
69
|
command = (0, command_1.addFlag)(command, 'features', features || []);
|
|
75
70
|
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, command);
|
|
76
|
-
return
|
|
77
|
-
content: [
|
|
78
|
-
{
|
|
79
|
-
type: 'text',
|
|
80
|
-
text: stdout,
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
type: 'text',
|
|
84
|
-
text: stderr,
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
};
|
|
71
|
+
return (0, content_1.formatTextContents)(stdout, stderr);
|
|
88
72
|
}
|
|
89
73
|
catch (error) {
|
|
90
|
-
return {
|
|
91
|
-
content: [
|
|
92
|
-
{
|
|
93
|
-
type: 'text',
|
|
94
|
-
text: error instanceof Error ? error.message : `${error}`,
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
};
|
|
74
|
+
return (0, content_1.formatTextContents)(error instanceof Error ? error.message : `${error}`);
|
|
98
75
|
}
|
|
99
76
|
}
|
|
100
77
|
register() {
|
|
@@ -3,26 +3,26 @@ import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
5
|
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
|
-
name: z.ZodString
|
|
6
|
+
name: z.ZodOptional<z.ZodString>;
|
|
7
7
|
destination: z.ZodString;
|
|
8
8
|
projectBase: z.ZodUnion<[z.ZodLiteral<"empty">, z.ZodLiteral<"app">]>;
|
|
9
9
|
distribution: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"marketplace">, z.ZodLiteral<"private">]>>;
|
|
10
10
|
auth: z.ZodOptional<z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"static">, z.ZodLiteral<"oauth">]>>>;
|
|
11
11
|
features: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">]>, "many">>;
|
|
12
12
|
}, "strip", z.ZodTypeAny, {
|
|
13
|
-
name: string;
|
|
14
13
|
projectBase: "app" | "empty";
|
|
15
14
|
absoluteCurrentWorkingDirectory: string;
|
|
16
15
|
destination: string;
|
|
17
16
|
auth?: "oauth" | "static" | undefined;
|
|
17
|
+
name?: string | undefined;
|
|
18
18
|
distribution?: "marketplace" | "private" | undefined;
|
|
19
19
|
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
20
20
|
}, {
|
|
21
|
-
name: string;
|
|
22
21
|
projectBase: "app" | "empty";
|
|
23
22
|
absoluteCurrentWorkingDirectory: string;
|
|
24
23
|
destination: string;
|
|
25
24
|
auth?: "oauth" | "static" | undefined;
|
|
25
|
+
name?: string | undefined;
|
|
26
26
|
distribution?: "marketplace" | "private" | undefined;
|
|
27
27
|
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
28
28
|
}>;
|
|
@@ -8,17 +8,19 @@ const command_1 = require("../../utils/command");
|
|
|
8
8
|
const v3_1 = require("../../../lib/projects/create/v3");
|
|
9
9
|
const constants_2 = require("./constants");
|
|
10
10
|
const project_1 = require("../../utils/project");
|
|
11
|
+
const content_1 = require("../../utils/content");
|
|
11
12
|
const inputSchema = {
|
|
12
13
|
absoluteCurrentWorkingDirectory: constants_2.absoluteCurrentWorkingDirectory,
|
|
13
14
|
name: zod_1.z
|
|
14
15
|
.string()
|
|
15
|
-
.describe('The name of the project to be created. This name is how your project will appear in HubSpot.')
|
|
16
|
+
.describe('The name of the project to be created. This name is how your project will appear in HubSpot. If not specified by the user, do not choose for them. Changing this is potentially destructive.')
|
|
17
|
+
.optional(),
|
|
16
18
|
destination: zod_1.z
|
|
17
19
|
.string()
|
|
18
|
-
.describe('Relative path to the directory the project will be created in.
|
|
20
|
+
.describe('Relative path to the directory the project will be created in. DO NOT use the current directory unless the user has explicitly stated to do so.'),
|
|
19
21
|
projectBase: zod_1.z
|
|
20
22
|
.union([zod_1.z.literal(v3_1.EMPTY_PROJECT), zod_1.z.literal(v3_1.PROJECT_WITH_APP)])
|
|
21
|
-
.describe('Empty will create
|
|
23
|
+
.describe('Empty will create an empty project, and app will create a project with an app inside of it.'),
|
|
22
24
|
distribution: zod_1.z
|
|
23
25
|
.optional(zod_1.z.union([
|
|
24
26
|
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE),
|
|
@@ -55,6 +57,9 @@ class CreateProjectTool extends types_1.Tool {
|
|
|
55
57
|
if (name) {
|
|
56
58
|
command = (0, command_1.addFlag)(command, 'name', name);
|
|
57
59
|
}
|
|
60
|
+
else {
|
|
61
|
+
content.push((0, content_1.formatTextContent)(`Ask the user what they would like to name the project.`));
|
|
62
|
+
}
|
|
58
63
|
if (destination) {
|
|
59
64
|
command = (0, command_1.addFlag)(command, 'dest', destination);
|
|
60
65
|
}
|
|
@@ -65,19 +70,13 @@ class CreateProjectTool extends types_1.Tool {
|
|
|
65
70
|
command = (0, command_1.addFlag)(command, 'distribution', distribution);
|
|
66
71
|
}
|
|
67
72
|
else if (projectBase === v3_1.PROJECT_WITH_APP) {
|
|
68
|
-
content.push({
|
|
69
|
-
type: 'text',
|
|
70
|
-
text: `Ask the user how they would you like to distribute the application? Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`,
|
|
71
|
-
});
|
|
73
|
+
content.push((0, content_1.formatTextContent)(`Ask the user how they would you like to distribute the application? Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`));
|
|
72
74
|
}
|
|
73
75
|
if (auth) {
|
|
74
76
|
command = (0, command_1.addFlag)(command, 'auth', auth);
|
|
75
77
|
}
|
|
76
78
|
else if (projectBase === v3_1.PROJECT_WITH_APP) {
|
|
77
|
-
content.push({
|
|
78
|
-
type: 'text',
|
|
79
|
-
text: `Ask the user which auth type they would like to use? Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`,
|
|
80
|
-
});
|
|
79
|
+
content.push((0, content_1.formatTextContent)(`Ask the user which auth type they would like to use? Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`));
|
|
81
80
|
}
|
|
82
81
|
if (content.length > 0) {
|
|
83
82
|
return {
|
|
@@ -88,28 +87,10 @@ class CreateProjectTool extends types_1.Tool {
|
|
|
88
87
|
command = (0, command_1.addFlag)(command, 'features', features || []);
|
|
89
88
|
try {
|
|
90
89
|
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteCurrentWorkingDirectory, command);
|
|
91
|
-
return
|
|
92
|
-
content: [
|
|
93
|
-
{
|
|
94
|
-
type: 'text',
|
|
95
|
-
text: stdout,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
type: 'text',
|
|
99
|
-
text: stderr,
|
|
100
|
-
},
|
|
101
|
-
],
|
|
102
|
-
};
|
|
90
|
+
return (0, content_1.formatTextContents)(stdout, stderr);
|
|
103
91
|
}
|
|
104
92
|
catch (error) {
|
|
105
|
-
return {
|
|
106
|
-
content: [
|
|
107
|
-
{
|
|
108
|
-
type: 'text',
|
|
109
|
-
text: error instanceof Error ? error.message : `${error}`,
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
};
|
|
93
|
+
return (0, content_1.formatTextContents)(error instanceof Error ? error.message : `${error}`);
|
|
113
94
|
}
|
|
114
95
|
}
|
|
115
96
|
register() {
|
|
@@ -6,6 +6,7 @@ const zod_1 = require("zod");
|
|
|
6
6
|
const command_1 = require("../../utils/command");
|
|
7
7
|
const constants_1 = require("./constants");
|
|
8
8
|
const project_1 = require("../../utils/project");
|
|
9
|
+
const content_1 = require("../../utils/content");
|
|
9
10
|
const inputSchema = {
|
|
10
11
|
absoluteProjectPath: constants_1.absoluteProjectPath,
|
|
11
12
|
buildNumber: zod_1.z
|
|
@@ -25,10 +26,7 @@ class DeployProject extends types_1.Tool {
|
|
|
25
26
|
const content = [];
|
|
26
27
|
if (!buildNumber) {
|
|
27
28
|
const { stdout } = await (0, project_1.runCommandInDir)(absoluteProjectPath, `hs project list-builds --limit 100`);
|
|
28
|
-
content.push({
|
|
29
|
-
type: 'text',
|
|
30
|
-
text: `Ask the user which build number they would like to deploy? Build information: ${stdout}`,
|
|
31
|
-
});
|
|
29
|
+
content.push((0, content_1.formatTextContent)(`Ask the user which build number they would like to deploy? Build information: ${stdout}`));
|
|
32
30
|
}
|
|
33
31
|
else {
|
|
34
32
|
command = (0, command_1.addFlag)(command, 'build', buildNumber);
|
|
@@ -39,17 +37,12 @@ class DeployProject extends types_1.Tool {
|
|
|
39
37
|
};
|
|
40
38
|
}
|
|
41
39
|
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, command);
|
|
42
|
-
return
|
|
43
|
-
content: [
|
|
44
|
-
{ type: 'text', text: stdout },
|
|
45
|
-
{ type: 'text', text: stderr },
|
|
46
|
-
],
|
|
47
|
-
};
|
|
40
|
+
return (0, content_1.formatTextContents)(stdout, stderr);
|
|
48
41
|
}
|
|
49
42
|
register() {
|
|
50
43
|
return this.mcpServer.registerTool('deploy-hubspot-project', {
|
|
51
44
|
title: 'Deploy a build of HubSpot Project',
|
|
52
|
-
description: 'Takes a build number and a project name and deploys that build of the project',
|
|
45
|
+
description: 'Takes a build number and a project name and deploys that build of the project. DO NOT run this tool unless the user specifies they would like to deploy the project.',
|
|
53
46
|
inputSchema,
|
|
54
47
|
}, this.handler);
|
|
55
48
|
}
|
|
@@ -4,6 +4,7 @@ exports.GuidedWalkthroughTool = void 0;
|
|
|
4
4
|
const types_1 = require("../../types");
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const command_1 = require("../../utils/command");
|
|
7
|
+
const content_1 = require("../../utils/content");
|
|
7
8
|
const nextCommands = {
|
|
8
9
|
'hs init': 'hs auth',
|
|
9
10
|
'hs auth': 'hs project create',
|
|
@@ -32,23 +33,9 @@ class GuidedWalkthroughTool extends types_1.Tool {
|
|
|
32
33
|
async handler({ command }) {
|
|
33
34
|
if (command) {
|
|
34
35
|
const { stdout } = await (0, command_1.execAsync)(`${command} --help`);
|
|
35
|
-
return {
|
|
36
|
-
content: [
|
|
37
|
-
{
|
|
38
|
-
type: 'text',
|
|
39
|
-
text: `Display this help output for the user amd wait for them to acknowledge: ${stdout}. ${nextCommands[command] ? `Once they are ready, A good command to look at next is ${nextCommands[command]}` : ''}`,
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
};
|
|
36
|
+
return (0, content_1.formatTextContents)(`Display this help output for the user amd wait for them to acknowledge: ${stdout}. ${nextCommands[command] ? `Once they are ready, A good command to look at next is ${nextCommands[command]}` : ''}`);
|
|
43
37
|
}
|
|
44
|
-
return
|
|
45
|
-
content: [
|
|
46
|
-
{
|
|
47
|
-
type: 'text',
|
|
48
|
-
text: 'Is there another command you would like to learn more about?',
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
};
|
|
38
|
+
return (0, content_1.formatTextContents)('Is there another command you would like to learn more about?');
|
|
52
39
|
}
|
|
53
40
|
register() {
|
|
54
41
|
return this.mcpServer.registerTool('guided-walkthrough-hubspot-cli', {
|