@hubspot/cli 8.13.0 → 8.14.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/cms/function/server.js +14 -7
- package/commands/project/upload.js +4 -0
- package/commands/project/watch.js +3 -2
- package/lang/en.d.ts +8 -0
- package/lang/en.js +8 -0
- package/lib/cms/serverlessDevRuntime.d.ts +1 -0
- package/lib/cms/serverlessDevRuntime.js +72 -0
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +1 -0
- package/lib/projects/create/v2.js +1 -0
- package/lib/projects/localDev/LocalDevProcess.js +3 -3
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +1 -0
- package/mcp-server/tools/project/CreateProjectTool.d.ts +1 -0
- package/mcp-server/tools/project/constants.d.ts +1 -0
- package/mcp-server/tools/project/constants.js +2 -1
- package/package.json +12 -11
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { uiLogger } from '../../../lib/ui/logger.js';
|
|
2
|
-
// This package is not typed, so we need to use require
|
|
3
|
-
import { start as startTestServer } from '@hubspot/serverless-dev-runtime';
|
|
4
2
|
import { commands } from '../../../lang/en.js';
|
|
3
|
+
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
4
|
+
import { startServerlessDevRuntime } from '../../../lib/cms/serverlessDevRuntime.js';
|
|
5
|
+
import { logError } from '../../../lib/errorHandlers/index.js';
|
|
5
6
|
import { makeWrappedYargsHandler } from '../../../lib/yargs/makeWrappedYargsHandler.js';
|
|
6
7
|
import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
|
|
7
8
|
const command = 'server <path>';
|
|
8
9
|
const describe = undefined;
|
|
9
10
|
async function handler(args) {
|
|
10
|
-
const { path: functionPath, derivedAccountId } = args;
|
|
11
|
+
const { path: functionPath, derivedAccountId, exit } = args;
|
|
11
12
|
uiLogger.debug(commands.cms.subcommands.function.subcommands.server.debug.startingServer(functionPath));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
try {
|
|
14
|
+
await startServerlessDevRuntime({
|
|
15
|
+
accountId: derivedAccountId,
|
|
16
|
+
...args,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
logError(e);
|
|
21
|
+
return exit(EXIT_CODES.ERROR);
|
|
22
|
+
}
|
|
16
23
|
}
|
|
17
24
|
function functionServerBuilder(yargs) {
|
|
18
25
|
yargs.positional('path', {
|
|
@@ -17,6 +17,7 @@ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler
|
|
|
17
17
|
import { UploadSchema, } from '../../lib/jsonOutput.js';
|
|
18
18
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
19
19
|
import { projectProfilePrompt } from '../../lib/prompts/projectProfilePrompt.js';
|
|
20
|
+
import { uiDeprecatedTag } from '../../lib/ui/index.js';
|
|
20
21
|
import { showMcpPromotionNudge } from '../../lib/mcp/promotion.js';
|
|
21
22
|
import { PLATFORM_VERSIONS } from '@hubspot/project-parsing-lib/constants';
|
|
22
23
|
const command = 'upload';
|
|
@@ -37,6 +38,9 @@ async function handlePreview(accountId, projectId, buildId, targetPortalId) {
|
|
|
37
38
|
}
|
|
38
39
|
async function handler(args) {
|
|
39
40
|
const { force = false, forceCreate = false, message, derivedAccountId, skipValidation, skipNpmAudit, skipAutoDeploy, formatOutputAsJson, profile: profileOption, useEnv: useEnvOption, preview, target: targetPortalId, exit, addUsageMetadata, addJsonOutput, } = args;
|
|
41
|
+
if (forceCreate) {
|
|
42
|
+
uiDeprecatedTag(commands.project.upload.logs.forceCreateDeprecated);
|
|
43
|
+
}
|
|
40
44
|
const { projectConfig, projectDir } = await getProjectConfig();
|
|
41
45
|
try {
|
|
42
46
|
validateProjectConfig(projectConfig, projectDir);
|
|
@@ -14,9 +14,9 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
|
14
14
|
import { handleKeypress, handleExit } from '../../lib/process.js';
|
|
15
15
|
import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
|
|
16
16
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
17
|
-
import {
|
|
17
|
+
import { uiCommandRelocatedMessage, uiCommandRenamedDescription, } from '../../lib/ui/index.js';
|
|
18
18
|
const command = 'watch';
|
|
19
|
-
const describe =
|
|
19
|
+
const describe = uiCommandRenamedDescription(commands.project.watch.describe, 'hs project dev');
|
|
20
20
|
async function handleBuildStatus(accountId, projectName, buildId) {
|
|
21
21
|
const { isAutoDeployEnabled, deployStatusTaskLocator } = await pollBuildStatus(accountId, projectName, buildId, null);
|
|
22
22
|
if (isAutoDeployEnabled && deployStatusTaskLocator) {
|
|
@@ -57,6 +57,7 @@ function handleUserInput(accountId, projectName, currentBuildId, exit) {
|
|
|
57
57
|
}
|
|
58
58
|
async function handler(args) {
|
|
59
59
|
const { initialUpload, derivedAccountId, exit } = args;
|
|
60
|
+
uiCommandRelocatedMessage('hs project dev');
|
|
60
61
|
const { projectConfig, projectDir } = await getProjectConfig();
|
|
61
62
|
if (!projectConfig || !projectDir) {
|
|
62
63
|
uiLogger.error(commands.project.watch.errors.projectConfigNotFound);
|
package/lang/en.d.ts
CHANGED
|
@@ -1901,6 +1901,7 @@ export declare const commands: {
|
|
|
1901
1901
|
withPreview: string;
|
|
1902
1902
|
};
|
|
1903
1903
|
logs: {
|
|
1904
|
+
forceCreateDeprecated: string;
|
|
1904
1905
|
buildSucceeded: (buildId: number) => string;
|
|
1905
1906
|
readyToGoLive: string;
|
|
1906
1907
|
runCommand: (command: string) => string;
|
|
@@ -4494,6 +4495,13 @@ export declare const lib: {
|
|
|
4494
4495
|
copyingProjectFilesFailed: string;
|
|
4495
4496
|
};
|
|
4496
4497
|
};
|
|
4498
|
+
cms: {
|
|
4499
|
+
serverlessDevRuntime: {
|
|
4500
|
+
installStarted: (targetVersion: string) => string;
|
|
4501
|
+
installSucceeded: string;
|
|
4502
|
+
installFailed: string;
|
|
4503
|
+
};
|
|
4504
|
+
};
|
|
4497
4505
|
theme: {
|
|
4498
4506
|
cmsDevServerProcess: {
|
|
4499
4507
|
installStarted: (targetVersion: string) => string;
|
package/lang/en.js
CHANGED
|
@@ -1917,6 +1917,7 @@ export const commands = {
|
|
|
1917
1917
|
withPreview: 'Upload and preview the build on a target portal',
|
|
1918
1918
|
},
|
|
1919
1919
|
logs: {
|
|
1920
|
+
forceCreateDeprecated: `The ${uiCommandReference('--force-create')} flag is deprecated. Use ${uiCommandReference('--force')} instead.`,
|
|
1920
1921
|
buildSucceeded: (buildId) => `Build #${buildId} succeeded\n`,
|
|
1921
1922
|
readyToGoLive: '🚀 Ready to take your project live?',
|
|
1922
1923
|
runCommand: (command) => `Run \`${uiCommandReference(command)}\``,
|
|
@@ -4531,6 +4532,13 @@ export const lib = {
|
|
|
4531
4532
|
copyingProjectFilesFailed: 'Unable to copy migrated project files',
|
|
4532
4533
|
},
|
|
4533
4534
|
},
|
|
4535
|
+
cms: {
|
|
4536
|
+
serverlessDevRuntime: {
|
|
4537
|
+
installStarted: (targetVersion) => `Installing serverless-dev-runtime ${targetVersion}...`,
|
|
4538
|
+
installSucceeded: 'serverless-dev-runtime setup complete',
|
|
4539
|
+
installFailed: 'Failed to install serverless-dev-runtime',
|
|
4540
|
+
},
|
|
4541
|
+
},
|
|
4534
4542
|
theme: {
|
|
4535
4543
|
cmsDevServerProcess: {
|
|
4536
4544
|
installStarted: (targetVersion) => `Installing cms-dev-server ${targetVersion}...`,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startServerlessDevRuntime(options: any): Promise<void>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import SpinniesManager from '../ui/SpinniesManager.js';
|
|
7
|
+
import { lib } from '../../lang/en.js';
|
|
8
|
+
const TARGET_SERVERLESS_RUNTIME_VERSION = '7.0.7';
|
|
9
|
+
const CACHE_DIR = path.join(os.homedir(), '.hscli', '.serverless-runtime-cache');
|
|
10
|
+
async function ensureServerlessRuntimeInstalled() {
|
|
11
|
+
const packageJsonPath = path.join(CACHE_DIR, 'node_modules', '@hubspot', 'serverless-dev-runtime', 'package.json');
|
|
12
|
+
let needsInstall = true;
|
|
13
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
14
|
+
try {
|
|
15
|
+
const installed = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
16
|
+
if (installed.version === TARGET_SERVERLESS_RUNTIME_VERSION) {
|
|
17
|
+
needsInstall = false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
needsInstall = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!needsInstall) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
SpinniesManager.init({ succeedColor: 'white' });
|
|
28
|
+
SpinniesManager.add('serverless-runtime-install', {
|
|
29
|
+
text: lib.cms.serverlessDevRuntime.installStarted(TARGET_SERVERLESS_RUNTIME_VERSION),
|
|
30
|
+
});
|
|
31
|
+
fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
32
|
+
const nodeModulesDir = path.join(CACHE_DIR, 'node_modules');
|
|
33
|
+
if (fs.existsSync(nodeModulesDir)) {
|
|
34
|
+
fs.rmSync(nodeModulesDir, { recursive: true, force: true });
|
|
35
|
+
}
|
|
36
|
+
await new Promise((resolve, reject) => {
|
|
37
|
+
const installProcess = spawn('npm', [
|
|
38
|
+
'install',
|
|
39
|
+
`@hubspot/serverless-dev-runtime@${TARGET_SERVERLESS_RUNTIME_VERSION}`,
|
|
40
|
+
'--production',
|
|
41
|
+
'--no-save',
|
|
42
|
+
'--loglevel=error',
|
|
43
|
+
], { cwd: CACHE_DIR, stdio: 'ignore' });
|
|
44
|
+
installProcess.on('close', code => {
|
|
45
|
+
if (code === 0) {
|
|
46
|
+
SpinniesManager.succeed('serverless-runtime-install', {
|
|
47
|
+
text: lib.cms.serverlessDevRuntime.installSucceeded,
|
|
48
|
+
});
|
|
49
|
+
resolve();
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
SpinniesManager.fail('serverless-runtime-install', {
|
|
53
|
+
text: lib.cms.serverlessDevRuntime.installFailed,
|
|
54
|
+
});
|
|
55
|
+
reject(new Error(lib.cms.serverlessDevRuntime.installFailed));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
installProcess.on('error', error => {
|
|
59
|
+
SpinniesManager.fail('serverless-runtime-install', {
|
|
60
|
+
text: lib.cms.serverlessDevRuntime.installFailed,
|
|
61
|
+
});
|
|
62
|
+
reject(error);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
export async function startServerlessDevRuntime(options) {
|
|
68
|
+
await ensureServerlessRuntimeInstalled();
|
|
69
|
+
const requireFromCache = createRequire(path.join(CACHE_DIR, 'package.json'));
|
|
70
|
+
const { start } = requireFromCache('@hubspot/serverless-dev-runtime');
|
|
71
|
+
start(options);
|
|
72
|
+
}
|
package/lib/constants.d.ts
CHANGED
|
@@ -82,6 +82,7 @@ export declare const FEATURES: {
|
|
|
82
82
|
readonly APP_EVENTS: "Developers:UnifiedApps:AppEventsAccess";
|
|
83
83
|
readonly THEME_MIGRATION_2025_2: "Developers:ProjectThemeMigrations:2025.2";
|
|
84
84
|
readonly AGENT_TOOLS: "ThirdPartyAgentTools";
|
|
85
|
+
readonly APP_ACTIONS: "Developers:AppActions";
|
|
85
86
|
};
|
|
86
87
|
export declare const LOCAL_DEV_UI_MESSAGE_SEND_TYPES: {
|
|
87
88
|
UPLOAD_SUCCESS: string;
|
package/lib/constants.js
CHANGED
|
@@ -74,6 +74,7 @@ export const FEATURES = {
|
|
|
74
74
|
APP_EVENTS: 'Developers:UnifiedApps:AppEventsAccess',
|
|
75
75
|
THEME_MIGRATION_2025_2: 'Developers:ProjectThemeMigrations:2025.2',
|
|
76
76
|
AGENT_TOOLS: 'ThirdPartyAgentTools',
|
|
77
|
+
APP_ACTIONS: 'Developers:AppActions',
|
|
77
78
|
};
|
|
78
79
|
export const LOCAL_DEV_UI_MESSAGE_SEND_TYPES = {
|
|
79
80
|
UPLOAD_SUCCESS: 'server:uploadSuccess',
|
|
@@ -48,6 +48,7 @@ export async function createV2App(providedAuth, providedDistribution) {
|
|
|
48
48
|
const componentTypeToGateMap = {
|
|
49
49
|
[AppEventsKey]: FEATURES.APP_EVENTS,
|
|
50
50
|
'workflow-action-tool': FEATURES.AGENT_TOOLS,
|
|
51
|
+
'crm-bulk-action': FEATURES.APP_ACTIONS,
|
|
51
52
|
};
|
|
52
53
|
export async function calculateComponentTemplateChoices(components, authType, distribution, accountId, projectMetadata) {
|
|
53
54
|
const enabledComponents = [];
|
|
@@ -153,14 +153,14 @@ class LocalDevProcess {
|
|
|
153
153
|
return this.state.actions.exit(EXIT_CODES.ERROR);
|
|
154
154
|
}
|
|
155
155
|
this.logger.startupMessage();
|
|
156
|
-
if (isConfigFlagEnabled(CONFIG_FLAGS.AUTO_OPEN_BROWSER, true)) {
|
|
157
|
-
this.openLocalDevUi();
|
|
158
|
-
}
|
|
159
156
|
await this.startDevServers();
|
|
160
157
|
const devSessionRegistered = await this.devSessionManager.registerSession();
|
|
161
158
|
if (!devSessionRegistered) {
|
|
162
159
|
return this.state.actions.exit(EXIT_CODES.ERROR);
|
|
163
160
|
}
|
|
161
|
+
if (isConfigFlagEnabled(CONFIG_FLAGS.AUTO_OPEN_BROWSER, true)) {
|
|
162
|
+
this.openLocalDevUi();
|
|
163
|
+
}
|
|
164
164
|
this.state.devServersStarted = true;
|
|
165
165
|
this.logger.monitorConsoleOutput();
|
|
166
166
|
}
|
|
@@ -20,6 +20,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
20
20
|
settings: "settings";
|
|
21
21
|
"app-event": "app-event";
|
|
22
22
|
"workflow-action-tool": "workflow-action-tool";
|
|
23
|
+
"crm-bulk-action": "crm-bulk-action";
|
|
23
24
|
page: "page";
|
|
24
25
|
webhooks: "webhooks";
|
|
25
26
|
"app-function": "app-function";
|
|
@@ -24,6 +24,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
24
24
|
settings: "settings";
|
|
25
25
|
"app-event": "app-event";
|
|
26
26
|
"workflow-action-tool": "workflow-action-tool";
|
|
27
|
+
"crm-bulk-action": "crm-bulk-action";
|
|
27
28
|
page: "page";
|
|
28
29
|
webhooks: "webhooks";
|
|
29
30
|
"app-function": "app-function";
|
|
@@ -6,6 +6,7 @@ export declare const features: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
|
6
6
|
settings: "settings";
|
|
7
7
|
"app-event": "app-event";
|
|
8
8
|
"workflow-action-tool": "workflow-action-tool";
|
|
9
|
+
"crm-bulk-action": "crm-bulk-action";
|
|
9
10
|
page: "page";
|
|
10
11
|
webhooks: "webhooks";
|
|
11
12
|
"app-function": "app-function";
|
|
@@ -18,8 +18,9 @@ export const features = z
|
|
|
18
18
|
'app-event',
|
|
19
19
|
'scim',
|
|
20
20
|
'page',
|
|
21
|
+
'crm-bulk-action',
|
|
21
22
|
]))
|
|
22
|
-
.describe('The features to include in the project, multiple options can be selected. "app-function" is also known as a private serverless function. "app-function-endpoint" is a serverless functions that is publicly accessible via endpoint. "workflow-action" is also known as a custom workflow action. "workflow-action-tool" is also known as agent tools.')
|
|
23
|
+
.describe('The features to include in the project, multiple options can be selected. "app-function" is also known as a private serverless function. "app-function-endpoint" is a serverless functions that is publicly accessible via endpoint. "workflow-action" is also known as a custom workflow action. "workflow-action-tool" is also known as agent tools. "crm-bulk-action" is an app actions extension that lets users act on multiple CRM records at once.')
|
|
23
24
|
.optional();
|
|
24
25
|
export const docsSearchQuery = z
|
|
25
26
|
.string()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.14.0-beta.0",
|
|
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",
|
|
@@ -10,10 +10,9 @@
|
|
|
10
10
|
"!**/__tests__/**"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@hubspot/local-dev-lib": "5.10.
|
|
14
|
-
"@hubspot/project-parsing-lib": "0.
|
|
15
|
-
"@hubspot/
|
|
16
|
-
"@hubspot/ui-extensions-dev-server": "2.1.0",
|
|
13
|
+
"@hubspot/local-dev-lib": "5.10.3",
|
|
14
|
+
"@hubspot/project-parsing-lib": "0.22.1",
|
|
15
|
+
"@hubspot/ui-extensions-dev-server": "2.1.2",
|
|
17
16
|
"@inquirer/prompts": "7.1.0",
|
|
18
17
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
19
18
|
"archiver": "7.0.1",
|
|
@@ -21,13 +20,13 @@
|
|
|
21
20
|
"chokidar": "3.6.0",
|
|
22
21
|
"cli-cursor": "3.1.0",
|
|
23
22
|
"cli-progress": "3.12.0",
|
|
24
|
-
"express": "4.22.
|
|
23
|
+
"express": "4.22.2",
|
|
25
24
|
"findup-sync": "4.0.0",
|
|
26
25
|
"fs-extra": "8.1.0",
|
|
27
26
|
"ink": "6.6.0",
|
|
28
27
|
"ink-spinner": "5.0.0",
|
|
29
28
|
"ink-text-input": "6.0.0",
|
|
30
|
-
"js-yaml": "4.
|
|
29
|
+
"js-yaml": "4.3.1",
|
|
31
30
|
"minimatch": "10.2.5",
|
|
32
31
|
"moment": "2.30.1",
|
|
33
32
|
"open": "7.4.2",
|
|
@@ -36,9 +35,9 @@
|
|
|
36
35
|
"semver": "7.6.3",
|
|
37
36
|
"strip-ansi": "7.1.0",
|
|
38
37
|
"table": "6.9.0",
|
|
39
|
-
"tmp": "0.2.
|
|
38
|
+
"tmp": "0.2.7",
|
|
40
39
|
"update-notifier": "7.3.1",
|
|
41
|
-
"ws": "8.
|
|
40
|
+
"ws": "8.21.0",
|
|
42
41
|
"yargs": "17.7.2",
|
|
43
42
|
"yargs-parser": "21.1.1",
|
|
44
43
|
"zod": "^4.4.3"
|
|
@@ -61,7 +60,7 @@
|
|
|
61
60
|
"@typescript-eslint/eslint-plugin": "^8.30.1",
|
|
62
61
|
"@typescript-eslint/parser": "^8.11.0",
|
|
63
62
|
"@vitest/coverage-v8": "^2.1.9",
|
|
64
|
-
"axios": "1.
|
|
63
|
+
"axios": "1.19.0",
|
|
65
64
|
"eslint": "^8.56.0",
|
|
66
65
|
"eslint-plugin-import": "^2.31.0",
|
|
67
66
|
"husky": "^4.3.8",
|
|
@@ -125,6 +124,8 @@
|
|
|
125
124
|
},
|
|
126
125
|
"resolutions": {
|
|
127
126
|
"eslint-visitor-keys": "4.2.0",
|
|
128
|
-
"@eslint-community/eslint-utils": "4.9.0"
|
|
127
|
+
"@eslint-community/eslint-utils": "4.9.0",
|
|
128
|
+
"@opentelemetry/core": "2.10.0",
|
|
129
|
+
"axios": "1.19.0"
|
|
129
130
|
}
|
|
130
131
|
}
|