@hubspot/cli 7.7.16-experimental.0 → 7.7.16-experimental.10
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/account/auth.js +3 -3
- package/commands/app/install.d.ts +8 -0
- package/commands/app/install.js +127 -0
- package/commands/app.js +6 -1
- package/commands/auth.js +23 -25
- package/commands/getStarted.d.ts +9 -0
- package/commands/getStarted.js +274 -0
- package/commands/init.js +35 -32
- package/commands/mcp/setup.d.ts +2 -2
- package/commands/mcp/setup.js +2 -0
- package/commands/mcp/start.d.ts +2 -2
- package/commands/mcp/start.js +3 -1
- package/commands/project/cloneApp.js +4 -4
- package/commands/project/create.js +9 -9
- package/commands/project/deploy.d.ts +1 -0
- package/commands/project/deploy.js +29 -3
- package/commands/project/dev/deprecatedFlow.js +4 -4
- package/commands/project/dev/index.js +5 -5
- package/commands/project/dev/unifiedFlow.js +8 -0
- 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/sandbox/delete.js +5 -5
- package/commands/testAccount/create.d.ts +6 -0
- package/commands/testAccount/create.js +160 -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 +201 -35
- package/lang/en.js +201 -38
- package/lang/en.lyaml +9 -14
- package/lib/accountTypes.d.ts +1 -0
- package/lib/accountTypes.js +20 -9
- package/lib/app/migrate.js +15 -3
- package/lib/app/migrate_legacy.js +2 -3
- package/lib/app/urls.d.ts +1 -1
- 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 +9 -0
- package/lib/mcp/setup.js +23 -21
- package/lib/middleware/__test__/configMiddleware.test.js +2 -2
- package/lib/middleware/configMiddleware.js +10 -2
- package/lib/parsing.d.ts +1 -0
- package/lib/parsing.js +11 -0
- package/lib/polling.d.ts +1 -1
- package/lib/polling.js +11 -1
- package/lib/projectProfiles.d.ts +1 -0
- package/lib/projectProfiles.js +18 -0
- package/lib/projects/add/v3AddComponent.js +4 -0
- package/lib/projects/buildAndDeploy.js +1 -1
- package/lib/projects/create/index.d.ts +3 -2
- package/lib/projects/create/index.js +11 -5
- package/lib/projects/create/v3.d.ts +3 -3
- package/lib/projects/create/v3.js +2 -2
- package/lib/projects/localDev/AppDevModeInterface.d.ts +3 -0
- package/lib/projects/localDev/AppDevModeInterface.js +46 -17
- package/lib/projects/localDev/LocalDevManager.js +1 -1
- package/lib/projects/localDev/LocalDevProcess.d.ts +3 -2
- package/lib/projects/localDev/LocalDevProcess.js +16 -12
- package/lib/projects/localDev/LocalDevState.d.ts +10 -5
- package/lib/projects/localDev/LocalDevState.js +18 -20
- package/lib/projects/localDev/LocalDevWatcher.js +1 -1
- package/lib/projects/structure.d.ts +2 -2
- package/lib/projects/upload.d.ts +4 -0
- package/lib/projects/upload.js +57 -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/personalAccessKeyPrompt.js +2 -2
- package/lib/prompts/projectNameAndDestPrompt.d.ts +3 -0
- package/lib/prompts/projectNameAndDestPrompt.js +60 -0
- package/lib/prompts/promptUtils.d.ts +1 -0
- package/lib/prompts/promptUtils.js +2 -0
- package/lib/prompts/selectProjectTemplatePrompt.d.ts +26 -0
- package/lib/prompts/{createProjectPrompt.js → selectProjectTemplatePrompt.js} +6 -55
- package/lib/ui/logger.d.ts +1 -0
- package/lib/ui/logger.js +1 -0
- package/lib/validation.d.ts +1 -1
- package/lib/validation.js +4 -4
- 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/CreateProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/CreateProjectTool.js +5 -1
- package/mcp-server/tools/project/DeployProject.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.js +1 -1
- package/mcp-server/tools/project/ValidateProjectTool.d.ts +17 -0
- package/mcp-server/tools/project/ValidateProjectTool.js +35 -0
- package/package.json +10 -9
- package/types/LocalDev.d.ts +2 -0
- package/types/Yargs.d.ts +5 -1
- package/lib/prompts/createProjectPrompt.d.ts +0 -28
|
@@ -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
|
+
}
|
|
@@ -29,7 +29,7 @@ async function personalAccessKeyPrompt({ env, account, }) {
|
|
|
29
29
|
if (account) {
|
|
30
30
|
url = `${websiteOrigin}/personal-access-key/${account}`;
|
|
31
31
|
}
|
|
32
|
-
const {
|
|
32
|
+
const { personalAccessKeyBrowserOpenPrep: choice } = await (0, promptUtils_1.promptUser)([
|
|
33
33
|
PERSONAL_ACCESS_KEY_BROWSER_OPEN_PREP,
|
|
34
34
|
]);
|
|
35
35
|
if (!choice) {
|
|
@@ -94,7 +94,7 @@ const CLIENT_SECRET = {
|
|
|
94
94
|
},
|
|
95
95
|
};
|
|
96
96
|
const PERSONAL_ACCESS_KEY_BROWSER_OPEN_PREP = {
|
|
97
|
-
name: '
|
|
97
|
+
name: 'personalAccessKeyBrowserOpenPrep',
|
|
98
98
|
type: 'list',
|
|
99
99
|
message: 'Choose your preferred method of authentication',
|
|
100
100
|
choices: Object.values(en_1.lib.prompts.personalAccessKeyPrompt.personalAccessKeyPromptChoices),
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { PromptOptionsArg, ProjectNameAndDestPromptResponse } from './selectProjectTemplatePrompt';
|
|
2
|
+
export declare function projectNameAndDestPrompt(promptOptions: PromptOptionsArg): Promise<ProjectNameAndDestPromptResponse>;
|
|
3
|
+
export declare function validateProjectDirectory(input?: string): string | boolean;
|
|
@@ -0,0 +1,60 @@
|
|
|
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.projectNameAndDestPrompt = projectNameAndDestPrompt;
|
|
7
|
+
exports.validateProjectDirectory = validateProjectDirectory;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const path_2 = require("@hubspot/local-dev-lib/path");
|
|
11
|
+
const en_1 = require("../../lang/en");
|
|
12
|
+
const promptUtils_1 = require("./promptUtils");
|
|
13
|
+
const constants_1 = require("../constants");
|
|
14
|
+
async function projectNameAndDestPrompt(promptOptions) {
|
|
15
|
+
const result = await (0, promptUtils_1.promptUser)([
|
|
16
|
+
{
|
|
17
|
+
name: 'name',
|
|
18
|
+
message: en_1.lib.prompts.projectNameAndDestPrompt.enterName,
|
|
19
|
+
when: !promptOptions.name,
|
|
20
|
+
validate: (input) => {
|
|
21
|
+
if (!input) {
|
|
22
|
+
return en_1.lib.prompts.projectNameAndDestPrompt.errors.nameRequired;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'dest',
|
|
29
|
+
message: en_1.lib.prompts.projectNameAndDestPrompt.enterDest,
|
|
30
|
+
when: !promptOptions.dest,
|
|
31
|
+
default: answers => {
|
|
32
|
+
const projectName = (0, path_2.sanitizeFileName)(promptOptions.name || answers.name);
|
|
33
|
+
return path_1.default.resolve((0, path_2.getCwd)(), projectName);
|
|
34
|
+
},
|
|
35
|
+
validate: validateProjectDirectory,
|
|
36
|
+
filter: input => {
|
|
37
|
+
return (0, path_2.untildify)(input);
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
]);
|
|
41
|
+
if (!result.name) {
|
|
42
|
+
result.name = promptOptions.name;
|
|
43
|
+
}
|
|
44
|
+
if (!result.dest) {
|
|
45
|
+
result.dest = promptOptions.dest;
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
function validateProjectDirectory(input) {
|
|
50
|
+
if (!input) {
|
|
51
|
+
return en_1.lib.prompts.projectNameAndDestPrompt.errors.destRequired;
|
|
52
|
+
}
|
|
53
|
+
if (fs_1.default.existsSync(path_1.default.resolve((0, path_2.getCwd)(), path_1.default.join(input, constants_1.PROJECT_CONFIG_FILE)))) {
|
|
54
|
+
return en_1.lib.prompts.projectNameAndDestPrompt.errors.invalidDest;
|
|
55
|
+
}
|
|
56
|
+
if (!(0, path_2.isValidPath)(input)) {
|
|
57
|
+
return en_1.lib.prompts.projectNameAndDestPrompt.errors.invalidCharacters;
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ComponentTemplate, ComponentTemplateChoice, ProjectTemplate } from '../../types/Projects';
|
|
2
|
+
export type SelectProjectTemplatePromptResponse = {
|
|
3
|
+
projectTemplate?: ProjectTemplate;
|
|
4
|
+
componentTemplates?: ComponentTemplate[];
|
|
5
|
+
};
|
|
6
|
+
type SelectProjectTemplatePromptResponseProjectTemplate = {
|
|
7
|
+
projectTemplate: ProjectTemplate;
|
|
8
|
+
componentTemplates: undefined;
|
|
9
|
+
};
|
|
10
|
+
type SelectProjectTemplatePromptResponseComponentTemplates = {
|
|
11
|
+
projectTemplate?: undefined;
|
|
12
|
+
componentTemplates?: ComponentTemplate[];
|
|
13
|
+
};
|
|
14
|
+
export type ProjectNameAndDestPromptResponse = {
|
|
15
|
+
name: string;
|
|
16
|
+
dest: string;
|
|
17
|
+
};
|
|
18
|
+
export type PromptOptionsArg = {
|
|
19
|
+
name?: string;
|
|
20
|
+
dest?: string;
|
|
21
|
+
template?: string;
|
|
22
|
+
features?: string[];
|
|
23
|
+
};
|
|
24
|
+
export declare function selectProjectTemplatePrompt(promptOptions: PromptOptionsArg, projectTemplates?: ProjectTemplate[], componentTemplates?: undefined): Promise<SelectProjectTemplatePromptResponseProjectTemplate>;
|
|
25
|
+
export declare function selectProjectTemplatePrompt(promptOptions: PromptOptionsArg, projectTemplates?: undefined, componentTemplates?: ComponentTemplateChoice[]): Promise<SelectProjectTemplatePromptResponseComponentTemplates>;
|
|
26
|
+
export {};
|
|
@@ -1,31 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const path_2 = require("@hubspot/local-dev-lib/path");
|
|
3
|
+
exports.selectProjectTemplatePrompt = selectProjectTemplatePrompt;
|
|
10
4
|
const promptUtils_1 = require("./promptUtils");
|
|
11
|
-
const constants_1 = require("../constants");
|
|
12
5
|
const en_1 = require("../../lang/en");
|
|
13
|
-
function validateProjectDirectory(input) {
|
|
14
|
-
if (!input) {
|
|
15
|
-
return en_1.lib.prompts.createProjectPrompt.errors.destRequired;
|
|
16
|
-
}
|
|
17
|
-
if (fs_1.default.existsSync(path_1.default.resolve((0, path_2.getCwd)(), path_1.default.join(input, constants_1.PROJECT_CONFIG_FILE)))) {
|
|
18
|
-
return en_1.lib.prompts.createProjectPrompt.errors.invalidDest;
|
|
19
|
-
}
|
|
20
|
-
if (!(0, path_2.isValidPath)(input)) {
|
|
21
|
-
return en_1.lib.prompts.createProjectPrompt.errors.invalidCharacters;
|
|
22
|
-
}
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
6
|
function findTemplateByNameOrLabel(projectTemplates, templateNameOrLabel) {
|
|
26
7
|
return projectTemplates.find(t => t.name === templateNameOrLabel || t.label === templateNameOrLabel);
|
|
27
8
|
}
|
|
28
|
-
async function
|
|
9
|
+
async function selectProjectTemplatePrompt(promptOptions, projectTemplates, componentTemplates) {
|
|
29
10
|
const createProjectFromTemplate = !!projectTemplates && projectTemplates.length > 0;
|
|
30
11
|
const createProjectFromComponents = Array.isArray(componentTemplates) && componentTemplates?.length > 0;
|
|
31
12
|
const selectedComponents = [];
|
|
@@ -46,36 +27,12 @@ async function createProjectPrompt(promptOptions, projectTemplates, componentTem
|
|
|
46
27
|
!!promptOptions.template &&
|
|
47
28
|
!!findTemplateByNameOrLabel(projectTemplates, promptOptions.template);
|
|
48
29
|
const result = await (0, promptUtils_1.promptUser)([
|
|
49
|
-
{
|
|
50
|
-
name: 'name',
|
|
51
|
-
message: en_1.lib.prompts.createProjectPrompt.enterName,
|
|
52
|
-
when: !promptOptions.name,
|
|
53
|
-
validate: (input) => {
|
|
54
|
-
if (!input) {
|
|
55
|
-
return en_1.lib.prompts.createProjectPrompt.errors.nameRequired;
|
|
56
|
-
}
|
|
57
|
-
return true;
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'dest',
|
|
62
|
-
message: en_1.lib.prompts.createProjectPrompt.enterDest,
|
|
63
|
-
when: !promptOptions.dest,
|
|
64
|
-
default: answers => {
|
|
65
|
-
const projectName = (0, path_2.sanitizeFileName)(promptOptions.name || answers.name);
|
|
66
|
-
return path_1.default.resolve((0, path_2.getCwd)(), projectName);
|
|
67
|
-
},
|
|
68
|
-
validate: validateProjectDirectory,
|
|
69
|
-
filter: input => {
|
|
70
|
-
return (0, path_2.untildify)(input);
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
30
|
{
|
|
74
31
|
name: 'projectTemplate',
|
|
75
32
|
message: () => {
|
|
76
33
|
return promptOptions.template && !providedTemplateIsValid
|
|
77
|
-
? en_1.lib.prompts.
|
|
78
|
-
: en_1.lib.prompts.
|
|
34
|
+
? en_1.lib.prompts.selectProjectTemplatePrompt.errors.invalidTemplate(promptOptions.template)
|
|
35
|
+
: en_1.lib.prompts.selectProjectTemplatePrompt.selectTemplate;
|
|
79
36
|
},
|
|
80
37
|
when: createProjectFromTemplate && !providedTemplateIsValid,
|
|
81
38
|
type: 'list',
|
|
@@ -90,7 +47,7 @@ async function createProjectPrompt(promptOptions, projectTemplates, componentTem
|
|
|
90
47
|
},
|
|
91
48
|
{
|
|
92
49
|
name: 'componentTemplates',
|
|
93
|
-
message: en_1.lib.prompts.
|
|
50
|
+
message: en_1.lib.prompts.selectProjectTemplatePrompt.features,
|
|
94
51
|
when: !promptOptions.features &&
|
|
95
52
|
createProjectFromComponents &&
|
|
96
53
|
selectedComponents.length === 0,
|
|
@@ -98,12 +55,6 @@ async function createProjectPrompt(promptOptions, projectTemplates, componentTem
|
|
|
98
55
|
choices: componentTemplates,
|
|
99
56
|
},
|
|
100
57
|
]);
|
|
101
|
-
if (!result.name) {
|
|
102
|
-
result.name = promptOptions.name;
|
|
103
|
-
}
|
|
104
|
-
if (!result.dest) {
|
|
105
|
-
result.dest = promptOptions.dest;
|
|
106
|
-
}
|
|
107
58
|
if (!result.componentTemplates) {
|
|
108
59
|
result.componentTemplates = selectedComponents;
|
|
109
60
|
}
|
|
@@ -112,7 +63,7 @@ async function createProjectPrompt(promptOptions, projectTemplates, componentTem
|
|
|
112
63
|
}
|
|
113
64
|
if (projectTemplates && projectTemplates.length > 0) {
|
|
114
65
|
if (!result.projectTemplate) {
|
|
115
|
-
throw new Error(en_1.lib.prompts.
|
|
66
|
+
throw new Error(en_1.lib.prompts.selectProjectTemplatePrompt.errors.projectTemplateRequired);
|
|
116
67
|
}
|
|
117
68
|
return result;
|
|
118
69
|
}
|
package/lib/ui/logger.d.ts
CHANGED
package/lib/ui/logger.js
CHANGED
package/lib/validation.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare function validateAccount(options: Arguments<{
|
|
|
4
4
|
account?: string;
|
|
5
5
|
accountId?: string;
|
|
6
6
|
derivedAccountId?: number;
|
|
7
|
-
|
|
7
|
+
userProvidedAccount?: string;
|
|
8
8
|
}>): Promise<boolean>;
|
|
9
9
|
export declare function validateCmsPublishMode(options: Arguments<{
|
|
10
10
|
cmsPublishMode?: CmsPublishMode;
|
package/lib/validation.js
CHANGED
|
@@ -50,18 +50,18 @@ const path_1 = require("@hubspot/local-dev-lib/path");
|
|
|
50
50
|
const commonOpts_1 = require("./commonOpts");
|
|
51
51
|
const index_1 = require("./errorHandlers/index");
|
|
52
52
|
async function validateAccount(options) {
|
|
53
|
-
const { derivedAccountId,
|
|
53
|
+
const { derivedAccountId, userProvidedAccount } = options;
|
|
54
54
|
const accountId = (0, config_1.getAccountId)(derivedAccountId);
|
|
55
55
|
if (!accountId) {
|
|
56
|
-
if (
|
|
57
|
-
logger_1.logger.error(`The account "${
|
|
56
|
+
if (userProvidedAccount) {
|
|
57
|
+
logger_1.logger.error(`The account "${userProvidedAccount}" could not be found in the config`);
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
60
60
|
logger_1.logger.error('An account needs to be supplied either via "--account" or through setting a "defaultPortal"');
|
|
61
61
|
}
|
|
62
62
|
return false;
|
|
63
63
|
}
|
|
64
|
-
if (
|
|
64
|
+
if (userProvidedAccount && (0, config_1.loadConfigFromEnvironment)()) {
|
|
65
65
|
throw new Error('Cannot specify an account when environment variables are supplied. Please unset the environment variables or do not use the "--account" flag.');
|
|
66
66
|
}
|
|
67
67
|
const accountConfig = (0, config_1.getAccountConfig)(accountId);
|
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
|
}
|
|
@@ -3,28 +3,28 @@ 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;
|
|
18
17
|
distribution?: "marketplace" | "private" | undefined;
|
|
19
18
|
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
19
|
+
name?: string | 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;
|
|
26
25
|
distribution?: "marketplace" | "private" | undefined;
|
|
27
26
|
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
27
|
+
name?: string | undefined;
|
|
28
28
|
}>;
|
|
29
29
|
export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
30
30
|
export declare class CreateProjectTool extends Tool<CreateProjectInputSchema> {
|
|
@@ -13,7 +13,8 @@ const inputSchema = {
|
|
|
13
13
|
absoluteCurrentWorkingDirectory: constants_2.absoluteCurrentWorkingDirectory,
|
|
14
14
|
name: zod_1.z
|
|
15
15
|
.string()
|
|
16
|
-
.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(),
|
|
17
18
|
destination: zod_1.z
|
|
18
19
|
.string()
|
|
19
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.'),
|
|
@@ -56,6 +57,9 @@ class CreateProjectTool extends types_1.Tool {
|
|
|
56
57
|
if (name) {
|
|
57
58
|
command = (0, command_1.addFlag)(command, 'name', name);
|
|
58
59
|
}
|
|
60
|
+
else {
|
|
61
|
+
content.push((0, content_1.formatTextContent)(`Ask the user what they would like to name the project.`));
|
|
62
|
+
}
|
|
59
63
|
if (destination) {
|
|
60
64
|
command = (0, command_1.addFlag)(command, 'dest', destination);
|
|
61
65
|
}
|
|
@@ -42,7 +42,7 @@ class DeployProject extends types_1.Tool {
|
|
|
42
42
|
register() {
|
|
43
43
|
return this.mcpServer.registerTool('deploy-hubspot-project', {
|
|
44
44
|
title: 'Deploy a build of HubSpot Project',
|
|
45
|
-
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.',
|
|
46
46
|
inputSchema,
|
|
47
47
|
}, this.handler);
|
|
48
48
|
}
|
|
@@ -27,7 +27,7 @@ class UploadProjectTools extends types_1.Tool {
|
|
|
27
27
|
register() {
|
|
28
28
|
return this.mcpServer.registerTool('upload-hubspot-project', {
|
|
29
29
|
title: 'Upload HubSpot Project',
|
|
30
|
-
description: 'Uploads the HubSpot project in current working directory. If the project does not exist, it will be created. MUST be ran from within the project directory.',
|
|
30
|
+
description: 'Uploads the HubSpot project in current working directory. If the project does not exist, it will be created. MUST be ran from within the project directory. DO NOT run this tool unless the user specifies they would like to upload the project, it is potentially destructive',
|
|
31
31
|
inputSchema,
|
|
32
32
|
}, this.handler);
|
|
33
33
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TextContentResponse, Tool } from '../../types';
|
|
2
|
+
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteProjectPath: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
absoluteProjectPath: string;
|
|
8
|
+
}, {
|
|
9
|
+
absoluteProjectPath: string;
|
|
10
|
+
}>;
|
|
11
|
+
export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
12
|
+
export declare class ValidateProjectTool extends Tool<CreateProjectInputSchema> {
|
|
13
|
+
constructor(mcpServer: McpServer);
|
|
14
|
+
handler({ absoluteProjectPath, }: CreateProjectInputSchema): Promise<TextContentResponse>;
|
|
15
|
+
register(): RegisteredTool;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValidateProjectTool = void 0;
|
|
4
|
+
const types_1 = require("../../types");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const constants_1 = require("./constants");
|
|
7
|
+
const project_1 = require("../../utils/project");
|
|
8
|
+
const content_1 = require("../../utils/content");
|
|
9
|
+
const inputSchema = {
|
|
10
|
+
absoluteProjectPath: constants_1.absoluteProjectPath,
|
|
11
|
+
};
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
13
|
+
const inputSchemaZodObject = zod_1.z.object({ ...inputSchema });
|
|
14
|
+
class ValidateProjectTool extends types_1.Tool {
|
|
15
|
+
constructor(mcpServer) {
|
|
16
|
+
super(mcpServer);
|
|
17
|
+
}
|
|
18
|
+
async handler({ absoluteProjectPath, }) {
|
|
19
|
+
try {
|
|
20
|
+
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, 'hs project validate');
|
|
21
|
+
return (0, content_1.formatTextContents)(stdout, stderr);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
return (0, content_1.formatTextContents)(error instanceof Error ? error.message : `${error}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
register() {
|
|
28
|
+
return this.mcpServer.registerTool('validate-hubspot-project', {
|
|
29
|
+
title: 'Validate HubSpot Project',
|
|
30
|
+
description: 'Validates the HubSpot project and its configuration files. This tool does not need to be ran before uploading the project',
|
|
31
|
+
inputSchema,
|
|
32
|
+
}, this.handler);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.ValidateProjectTool = ValidateProjectTool;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "7.7.16-experimental.
|
|
3
|
+
"version": "7.7.16-experimental.10",
|
|
4
4
|
"description": "The official CLI for developing on HubSpot",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": "https://github.com/HubSpot/hubspot-cli",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@hubspot/local-dev-lib": "3.
|
|
9
|
-
"@hubspot/project-parsing-lib": "0.
|
|
8
|
+
"@hubspot/local-dev-lib": "3.13.0",
|
|
9
|
+
"@hubspot/project-parsing-lib": "0.5.1",
|
|
10
10
|
"@hubspot/serverless-dev-runtime": "7.0.6",
|
|
11
11
|
"@hubspot/theme-preview-dev-server": "0.0.10",
|
|
12
12
|
"@hubspot/ui-extensions-dev-server": "0.9.2",
|
|
@@ -66,22 +66,23 @@
|
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
68
|
"build": "ts-node ./scripts/build.ts",
|
|
69
|
+
"build-docker": "docker image build --tag hs-cli-image . && docker image prune -f",
|
|
70
|
+
"circular-deps": "yarn madge --circular .",
|
|
69
71
|
"debug-mcp": "yarn build && npx @modelcontextprotocol/inspector node dist/mcp-server/server.js",
|
|
72
|
+
"hs": "yarn build && node ./dist/bin/hs",
|
|
73
|
+
"hs-debug": "yarn build && NODE_DEBUG=http* node --inspect-brk ./dist/bin/hs",
|
|
70
74
|
"lint": "echo 'Linting is disabled for Blazar'",
|
|
71
75
|
"lint:local": "eslint . && prettier --list-different './**/*.{ts,js,json}'",
|
|
72
76
|
"list-all-commands": "yarn ts-node ./scripts/get-all-commands.ts",
|
|
73
77
|
"local-link": "yarn ts-node ./scripts/linking.ts",
|
|
78
|
+
"mcp-local": "yarn ts-node ./scripts/mcp-local.ts",
|
|
74
79
|
"prettier:write": "prettier --write './**/*.{ts,js,json}'",
|
|
80
|
+
"release": "yarn ts-node ./scripts/release.ts release",
|
|
75
81
|
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js",
|
|
76
82
|
"test-cli": "yarn build && yarn --cwd 'acceptance-tests' test-ci",
|
|
77
83
|
"test-cli-debug": "yarn build && yarn --cwd 'acceptance-tests' test-debug",
|
|
78
|
-
"test-cli-qa": "yarn build && yarn --cwd 'acceptance-tests' test-qa",
|
|
79
84
|
"test-cli-latest": "yarn build && yarn build-docker && docker container run -it --rm --name=hs-cli-container hs-cli-image yarn --cwd 'acceptance-tests' test-latest",
|
|
80
|
-
"
|
|
81
|
-
"circular-deps": "yarn madge --circular .",
|
|
82
|
-
"release": "yarn ts-node ./scripts/release.ts release",
|
|
83
|
-
"hs": "yarn build && node ./dist/bin/hs",
|
|
84
|
-
"hs-debug": "yarn build && NODE_DEBUG=http* node --inspect-brk ./dist/bin/hs",
|
|
85
|
+
"test-cli-qa": "yarn build && yarn --cwd 'acceptance-tests' test-qa",
|
|
85
86
|
"update-ldl": "yarn add --exact @hubspot/local-dev-lib@latest",
|
|
86
87
|
"view-unreleased-changes": "node ./scripts/unreleasedChanges.js"
|
|
87
88
|
},
|
package/types/LocalDev.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { APP_INSTALLATION_STATES, LOCAL_DEV_SERVER_MESSAGE_TYPES } from '../lib/
|
|
|
8
8
|
export type LocalDevStateConstructorOptions = {
|
|
9
9
|
targetProjectAccountId: number;
|
|
10
10
|
targetTestingAccountId: number;
|
|
11
|
+
profile?: string;
|
|
11
12
|
projectConfig: ProjectConfig;
|
|
12
13
|
projectDir: string;
|
|
13
14
|
projectId: number;
|
|
@@ -30,5 +31,6 @@ export type AppLocalDevData = {
|
|
|
30
31
|
clientId: string;
|
|
31
32
|
name: string;
|
|
32
33
|
installationState: ValueOf<typeof APP_INSTALLATION_STATES>;
|
|
34
|
+
scopeGroupIds: number[];
|
|
33
35
|
};
|
|
34
36
|
export type LocalDevServerMessage = ValueOf<typeof LOCAL_DEV_SERVER_MESSAGE_TYPES>;
|