@hubspot/cli 8.2.0-experimental.2 → 8.2.1-experimental.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/account/clean.js +1 -1
- package/commands/account/list.js +1 -1
- package/commands/account/remove.js +1 -1
- package/commands/account/rename.js +1 -1
- package/commands/account/use.js +1 -1
- package/commands/api.d.ts +4 -1
- package/commands/api.js +11 -14
- package/commands/config/set.js +24 -5
- package/commands/customObject/createSchema.js +2 -3
- package/commands/customObject/updateSchema.js +2 -3
- package/commands/getStarted.js +1 -0
- package/commands/hubdb/list.d.ts +1 -1
- package/commands/hubdb/list.js +7 -8
- package/commands/mcp/setup.d.ts +2 -0
- package/commands/mcp/setup.js +29 -1
- package/commands/project/appInstallStatus.d.ts +2 -1
- package/commands/project/appInstallStatus.js +21 -19
- package/commands/project/create.js +0 -1
- package/commands/project/deploy.d.ts +2 -1
- package/commands/project/deploy.js +31 -14
- package/commands/project/dev/index.js +18 -64
- package/commands/project/dev/unifiedFlow.js +3 -1
- package/commands/project/info.d.ts +2 -1
- package/commands/project/info.js +8 -6
- package/commands/project/installApp.d.ts +2 -1
- package/commands/project/installApp.js +26 -27
- package/commands/project/list.js +1 -1
- package/commands/project/listBuilds.d.ts +1 -1
- package/commands/project/listBuilds.js +8 -6
- package/commands/project/logs.js +2 -4
- package/commands/project/profile/add.d.ts +2 -1
- package/commands/project/profile/add.js +22 -1
- package/commands/project/profile/delete.d.ts +1 -1
- package/commands/project/release/create.d.ts +2 -1
- package/commands/project/release/create.js +68 -69
- package/commands/project/release/info.d.ts +2 -1
- package/commands/project/release/info.js +7 -6
- package/commands/project/release/list.d.ts +2 -1
- package/commands/project/release/list.js +15 -7
- package/commands/project/upload.d.ts +4 -1
- package/commands/project/upload.js +48 -21
- package/commands/project/validate.d.ts +1 -1
- package/commands/project/watch.js +3 -2
- package/commands/project.js +2 -2
- package/commands/sandbox/delete.js +2 -3
- package/commands/testAccount/create.d.ts +2 -1
- package/commands/testAccount/create.js +7 -7
- package/commands/testAccount/importData.d.ts +1 -1
- package/lang/en.d.ts +61 -33
- package/lang/en.js +77 -48
- package/lib/app/urls.js +2 -3
- package/lib/commonOpts.js +6 -1
- package/lib/configOptions.d.ts +10 -10
- package/lib/configOptions.js +10 -11
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +2 -0
- package/lib/dependencyManagement.js +7 -7
- package/lib/getStartedV2Actions.js +2 -1
- package/lib/importData.js +3 -4
- package/lib/jsonOutput.d.ts +109 -0
- package/lib/jsonOutput.js +94 -0
- package/lib/links.js +6 -5
- package/lib/mcp/clients.d.ts +1 -1
- package/lib/mcp/clients.js +8 -1
- package/lib/mcp/setup.d.ts +9 -4
- package/lib/mcp/setup.js +115 -35
- package/lib/npm/npmCli.d.ts +1 -0
- package/lib/npm/npmCli.js +13 -0
- package/lib/projects/builds.d.ts +2 -0
- package/lib/projects/builds.js +22 -0
- package/lib/projects/create/v2.js +1 -0
- package/lib/projects/installApp.d.ts +1 -1
- package/lib/projects/installApp.js +8 -3
- package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
- package/lib/projects/localDev/DevSessionManager.js +4 -30
- package/lib/projects/localDev/LocalDevProcess.js +7 -5
- package/lib/projects/localDev/helpers/account.d.ts +0 -7
- package/lib/projects/localDev/helpers/account.js +1 -80
- package/lib/projects/localDev/helpers/project.js +3 -2
- package/lib/projects/release.d.ts +4 -0
- package/lib/projects/release.js +90 -0
- package/lib/projects/ui.d.ts +1 -0
- package/lib/projects/ui.js +14 -0
- package/lib/projects/upload.d.ts +10 -2
- package/lib/projects/upload.js +14 -7
- package/lib/projects/urls.d.ts +0 -1
- package/lib/projects/urls.js +6 -13
- package/lib/yargs/makeWrappedYargsHandler.d.ts +5 -1
- package/lib/yargs/makeWrappedYargsHandler.js +123 -65
- package/mcp-server/Tool.d.ts +8 -3
- package/mcp-server/Tool.js +58 -32
- package/mcp-server/server.js +10 -6
- package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +10 -17
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +12 -18
- package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -10
- package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +9 -9
- package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsListFunctionsTool.js +7 -7
- package/mcp-server/tools/cms/HsListTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsListTool.js +6 -10
- package/mcp-server/tools/index.js +2 -0
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -2
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +8 -9
- package/mcp-server/tools/project/AuthAccountTool.d.ts +18 -0
- package/mcp-server/tools/project/AuthAccountTool.js +78 -0
- package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -2
- package/mcp-server/tools/project/CreateProjectTool.js +13 -12
- package/mcp-server/tools/project/CreateTestAccountTool.d.ts +2 -2
- package/mcp-server/tools/project/CreateTestAccountTool.js +14 -15
- package/mcp-server/tools/project/DeployProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/DeployProjectTool.js +10 -10
- package/mcp-server/tools/project/DocFetchTool.js +1 -1
- package/mcp-server/tools/project/DocsSearchTool.js +8 -7
- package/mcp-server/tools/project/FindProjectsTool.js +1 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +2 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -8
- package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +2 -1
- package/mcp-server/tools/project/GetApplicationInfoTool.js +12 -9
- package/mcp-server/tools/project/GetBuildLogsTool.js +11 -7
- package/mcp-server/tools/project/GetBuildStatusTool.js +11 -7
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +2 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +9 -7
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.d.ts +2 -2
- package/mcp-server/tools/project/UploadProjectTools.js +9 -8
- package/mcp-server/tools/project/ValidateProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/ValidateProjectTool.js +5 -4
- package/mcp-server/tools/project/constants.d.ts +1 -0
- package/mcp-server/tools/project/constants.js +2 -1
- package/mcp-server/utils/command.d.ts +25 -2
- package/mcp-server/utils/command.js +67 -17
- package/mcp-server/utils/config.js +5 -0
- package/mcp-server/utils/logger.d.ts +3 -0
- package/mcp-server/utils/logger.js +30 -0
- package/mcp-server/utils/toolUsageTracking.js +18 -3
- package/package.json +11 -9
- package/types/Yargs.d.ts +3 -1
- package/commands/project/dev/deprecatedFlow.d.ts +0 -11
- package/commands/project/dev/deprecatedFlow.js +0 -180
- package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +0 -43
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +0 -128
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +0 -64
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +0 -394
package/lib/mcp/setup.js
CHANGED
|
@@ -11,29 +11,36 @@ import fs from 'fs-extra';
|
|
|
11
11
|
import { existsSync } from 'fs';
|
|
12
12
|
const mcpServerName = MCP_SERVER_NAME;
|
|
13
13
|
const claudeCode = 'claude';
|
|
14
|
-
const windsurf = 'windsurf';
|
|
15
14
|
const cursor = 'cursor';
|
|
15
|
+
const devin = 'devin';
|
|
16
16
|
const vscode = 'vscode';
|
|
17
17
|
const codex = 'codex';
|
|
18
18
|
const gemini = 'gemini';
|
|
19
|
+
const opencode = 'opencode';
|
|
20
|
+
const OTHER_TOOL = 'other';
|
|
19
21
|
const clientLabels = {
|
|
20
22
|
codex: commands.mcp.setup.codex,
|
|
21
23
|
claude: commands.mcp.setup.claudeCode,
|
|
22
24
|
cursor: commands.mcp.setup.cursor,
|
|
25
|
+
devin: commands.mcp.setup.devin,
|
|
23
26
|
gemini: commands.mcp.setup.gemini,
|
|
27
|
+
opencode: commands.mcp.setup.opencode,
|
|
24
28
|
vscode: commands.mcp.setup.vsCode,
|
|
25
|
-
windsurf: commands.mcp.setup.windsurf,
|
|
26
29
|
};
|
|
27
|
-
export const supportedTools =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
export const supportedTools = [
|
|
31
|
+
...MCP_CLIENTS.map(client => ({
|
|
32
|
+
name: clientLabels[client.id],
|
|
33
|
+
value: client.id,
|
|
34
|
+
})),
|
|
35
|
+
{ name: commands.mcp.setup.other, value: OTHER_TOOL },
|
|
36
|
+
];
|
|
31
37
|
const defaultMcpCommand = {
|
|
32
38
|
command: 'hs',
|
|
33
39
|
args: ['mcp', 'start'],
|
|
34
40
|
};
|
|
35
|
-
export async function configureMcpServer(
|
|
41
|
+
export async function configureMcpServer(options) {
|
|
36
42
|
try {
|
|
43
|
+
const { targets, standalone, cliVersion: cliVersionFlag } = options;
|
|
37
44
|
let derivedTargets = [];
|
|
38
45
|
if (!targets || targets.length === 0) {
|
|
39
46
|
const { selectedTargets } = await promptUser({
|
|
@@ -41,6 +48,7 @@ export async function configureMcpServer(targets) {
|
|
|
41
48
|
type: 'checkbox',
|
|
42
49
|
message: commands.mcp.setup.prompts.targets,
|
|
43
50
|
choices: supportedTools,
|
|
51
|
+
pageSize: supportedTools.length,
|
|
44
52
|
validate: (choices) => {
|
|
45
53
|
return choices.length === 0
|
|
46
54
|
? commands.mcp.setup.prompts.targetsRequired
|
|
@@ -52,23 +60,34 @@ export async function configureMcpServer(targets) {
|
|
|
52
60
|
else {
|
|
53
61
|
derivedTargets = targets;
|
|
54
62
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
63
|
+
const onlyOther = derivedTargets.length === 1 && derivedTargets[0] === OTHER_TOOL;
|
|
64
|
+
let useStandaloneMode = onlyOther ? false : standalone;
|
|
65
|
+
if (useStandaloneMode === undefined) {
|
|
66
|
+
const response = await promptUser({
|
|
67
|
+
name: 'useStandaloneMode',
|
|
68
|
+
type: 'confirm',
|
|
69
|
+
message: commands.mcp.setup.prompts.standaloneMode,
|
|
70
|
+
default: false,
|
|
71
|
+
});
|
|
72
|
+
useStandaloneMode = response.useStandaloneMode;
|
|
73
|
+
}
|
|
74
|
+
let cliVersion = '';
|
|
75
|
+
if (useStandaloneMode) {
|
|
76
|
+
if (cliVersionFlag !== undefined) {
|
|
77
|
+
cliVersion = cliVersionFlag;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const response = await promptUser({
|
|
81
|
+
name: 'cliVersion',
|
|
82
|
+
type: 'input',
|
|
83
|
+
message: commands.mcp.setup.prompts.cliVersion,
|
|
84
|
+
validate: (v) => !v || /^[\d]+\.[\d]+\.[\d]+([-+][\w.]+)?$/.test(v.trim())
|
|
85
|
+
? true
|
|
86
|
+
: 'Please enter a valid semver version (e.g. 8.0.1) or leave blank for latest.',
|
|
87
|
+
});
|
|
88
|
+
cliVersion = response.cliVersion;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
72
91
|
const cliPackage = cliVersion
|
|
73
92
|
? `@hubspot/cli@${cliVersion}`
|
|
74
93
|
: '@hubspot/cli';
|
|
@@ -91,8 +110,8 @@ export async function configureMcpServer(targets) {
|
|
|
91
110
|
if (derivedTargets.includes(cursor)) {
|
|
92
111
|
await runSetupFunction(() => setupCursor(mcpCommand));
|
|
93
112
|
}
|
|
94
|
-
if (derivedTargets.includes(
|
|
95
|
-
await runSetupFunction(() =>
|
|
113
|
+
if (derivedTargets.includes(devin)) {
|
|
114
|
+
await runSetupFunction(() => setupDevin(mcpCommand));
|
|
96
115
|
}
|
|
97
116
|
if (derivedTargets.includes(vscode)) {
|
|
98
117
|
await runSetupFunction(() => setupVsCode(mcpCommand));
|
|
@@ -103,8 +122,17 @@ export async function configureMcpServer(targets) {
|
|
|
103
122
|
if (derivedTargets.includes(gemini)) {
|
|
104
123
|
await runSetupFunction(() => setupGemini(mcpCommand));
|
|
105
124
|
}
|
|
106
|
-
|
|
107
|
-
|
|
125
|
+
if (derivedTargets.includes(opencode)) {
|
|
126
|
+
await runSetupFunction(() => setupOpenCode(mcpCommand));
|
|
127
|
+
}
|
|
128
|
+
if (derivedTargets.includes(OTHER_TOOL)) {
|
|
129
|
+
logOtherToolInstructions(mcpCommand);
|
|
130
|
+
}
|
|
131
|
+
const configuredTargets = derivedTargets.filter(t => t !== OTHER_TOOL);
|
|
132
|
+
if (configuredTargets.length > 0) {
|
|
133
|
+
uiLogger.info(commands.mcp.setup.success(configuredTargets));
|
|
134
|
+
}
|
|
135
|
+
return configuredTargets;
|
|
108
136
|
}
|
|
109
137
|
catch (error) {
|
|
110
138
|
SpinniesManager.fail('mcpSetup', {
|
|
@@ -261,14 +289,14 @@ export function setupCursor(mcpCommand = defaultMcpCommand) {
|
|
|
261
289
|
mcpCommand: buildCommandWithAgentString(mcpCommand, cursor),
|
|
262
290
|
});
|
|
263
291
|
}
|
|
264
|
-
export function
|
|
265
|
-
const
|
|
292
|
+
export function setupDevin(mcpCommand = defaultMcpCommand) {
|
|
293
|
+
const devinConfigPath = path.join(os.homedir(), ...getMcpClientPathSegments(devin));
|
|
266
294
|
return setupMcpConfigFile({
|
|
267
|
-
configPath:
|
|
268
|
-
configuringMessage: commands.mcp.setup.spinners.
|
|
269
|
-
configuredMessage: commands.mcp.setup.spinners.
|
|
270
|
-
failedMessage: commands.mcp.setup.spinners.
|
|
271
|
-
mcpCommand: buildCommandWithAgentString(mcpCommand,
|
|
295
|
+
configPath: devinConfigPath,
|
|
296
|
+
configuringMessage: commands.mcp.setup.spinners.configuringDevin,
|
|
297
|
+
configuredMessage: commands.mcp.setup.spinners.configuredDevin,
|
|
298
|
+
failedMessage: commands.mcp.setup.spinners.failedToConfigureDevin,
|
|
299
|
+
mcpCommand: buildCommandWithAgentString(mcpCommand, devin),
|
|
272
300
|
});
|
|
273
301
|
}
|
|
274
302
|
export async function setupCodex(mcpCommand = defaultMcpCommand) {
|
|
@@ -330,6 +358,58 @@ export async function setupGemini(mcpCommand = defaultMcpCommand) {
|
|
|
330
358
|
return false;
|
|
331
359
|
}
|
|
332
360
|
}
|
|
361
|
+
export async function setupOpenCode(mcpCommand = defaultMcpCommand) {
|
|
362
|
+
try {
|
|
363
|
+
SpinniesManager.add('openCodeSpinner', {
|
|
364
|
+
text: commands.mcp.setup.spinners.configuringOpenCode,
|
|
365
|
+
});
|
|
366
|
+
try {
|
|
367
|
+
await execAsync('opencode --version');
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
SpinniesManager.fail('openCodeSpinner', {
|
|
371
|
+
text: commands.mcp.setup.spinners.openCodeNotFound,
|
|
372
|
+
});
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
const mcpCommandWithAgent = buildCommandWithAgentString(mcpCommand, opencode);
|
|
376
|
+
await execAsync(`opencode mcp add "${mcpServerName}"${buildEnvFlagString(mcpCommand)} -- ${mcpCommandWithAgent.command} ${mcpCommandWithAgent.args.join(' ')}`);
|
|
377
|
+
SpinniesManager.succeed('openCodeSpinner', {
|
|
378
|
+
text: commands.mcp.setup.spinners.configuredOpenCode,
|
|
379
|
+
});
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
SpinniesManager.fail('openCodeSpinner', {
|
|
384
|
+
text: commands.mcp.setup.spinners.openCodeInstallFailed,
|
|
385
|
+
});
|
|
386
|
+
logError(error);
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function logOtherToolInstructions(mcpCommand) {
|
|
391
|
+
const { otherInstructions } = commands.mcp.setup;
|
|
392
|
+
uiLogger.log('');
|
|
393
|
+
uiLogger.log(otherInstructions.header);
|
|
394
|
+
uiLogger.log(otherInstructions.docsNote);
|
|
395
|
+
uiLogger.log('');
|
|
396
|
+
uiLogger.log(` ${otherInstructions.commandLabel}`);
|
|
397
|
+
uiLogger.log(` ${mcpCommand.command} ${mcpCommand.args.join(' ')}`);
|
|
398
|
+
uiLogger.log('');
|
|
399
|
+
uiLogger.log(` ${otherInstructions.jsonLabel}`);
|
|
400
|
+
uiLogger.log('');
|
|
401
|
+
const jsonConfig = {
|
|
402
|
+
mcpServers: {
|
|
403
|
+
[mcpServerName]: mcpCommand,
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
const indented = JSON.stringify(jsonConfig, null, 2)
|
|
407
|
+
.split('\n')
|
|
408
|
+
.map(line => ` ${line}`)
|
|
409
|
+
.join('\n');
|
|
410
|
+
uiLogger.log(indented);
|
|
411
|
+
uiLogger.log('');
|
|
412
|
+
}
|
|
333
413
|
function buildCommandWithAgentString(mcpCommand, agent) {
|
|
334
414
|
const mcpCommandCopy = structuredClone(mcpCommand);
|
|
335
415
|
mcpCommandCopy.args.push('--ai-agent', agent);
|
package/lib/npm/npmCli.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare function getLatestPackageVersion(packageName: string): Promise<{
|
|
|
4
4
|
latest: string | null;
|
|
5
5
|
next: string | null;
|
|
6
6
|
}>;
|
|
7
|
+
export declare function getNpmExecErrorOutput(error: unknown): string | null;
|
|
7
8
|
export declare function executeInstall(packages?: string[], flags?: string | null, options?: {
|
|
8
9
|
cwd?: string;
|
|
9
10
|
}): Promise<void>;
|
package/lib/npm/npmCli.js
CHANGED
|
@@ -23,6 +23,19 @@ export async function getLatestPackageVersion(packageName) {
|
|
|
23
23
|
return { latest: null, next: null };
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
function isNpmExecError(error) {
|
|
27
|
+
return (typeof error === 'object' &&
|
|
28
|
+
error !== null &&
|
|
29
|
+
('stderr' in error || 'stdout' in error));
|
|
30
|
+
}
|
|
31
|
+
export function getNpmExecErrorOutput(error) {
|
|
32
|
+
if (!isNpmExecError(error)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const stderr = error.stderr?.trim();
|
|
36
|
+
const stdout = error.stdout?.trim();
|
|
37
|
+
return stderr || stdout || null;
|
|
38
|
+
}
|
|
26
39
|
export async function executeInstall(packages = [], flags, options) {
|
|
27
40
|
const installCommand = `${DEFAULT_PACKAGE_MANAGER} install${flags ? ` ${flags}` : ''} ${packages.join(' ')}`;
|
|
28
41
|
uiLogger.debug('Running', installCommand);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { fetchProjectBuilds } from '@hubspot/local-dev-lib/api/projects';
|
|
2
|
+
import { BUILD_STATUS } from '@hubspot/local-dev-lib/enums/build';
|
|
3
|
+
export async function getLastSuccessfulBuild(accountId, projectName, latestBuild) {
|
|
4
|
+
if (latestBuild?.status === BUILD_STATUS.SUCCESS) {
|
|
5
|
+
return latestBuild;
|
|
6
|
+
}
|
|
7
|
+
let after;
|
|
8
|
+
let hasMore = true;
|
|
9
|
+
while (hasMore) {
|
|
10
|
+
const { data: { results, paging }, } = await fetchProjectBuilds(accountId, projectName, {
|
|
11
|
+
limit: 100,
|
|
12
|
+
...(after ? { after } : {}),
|
|
13
|
+
});
|
|
14
|
+
const successfulBuild = results.find(build => build.status === BUILD_STATUS.SUCCESS);
|
|
15
|
+
if (successfulBuild) {
|
|
16
|
+
return successfulBuild;
|
|
17
|
+
}
|
|
18
|
+
after = paging?.next?.after;
|
|
19
|
+
hasMore = !!after;
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
@@ -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 = [];
|
|
@@ -43,7 +43,7 @@ export declare function resolveProjectAccountId(derivedAccountId: number, projec
|
|
|
43
43
|
accountId: number;
|
|
44
44
|
profileName?: string;
|
|
45
45
|
} | null>;
|
|
46
|
-
export declare function loadInstallableAppNode(projectConfig: ProjectConfig, projectDir: string, accountId: number): Promise<AppIRNode | null>;
|
|
46
|
+
export declare function loadInstallableAppNode(projectConfig: ProjectConfig, projectDir: string, accountId: number, force?: boolean): Promise<AppIRNode | null>;
|
|
47
47
|
export declare function resolveValidInstallAccount(targetAccountId: number, force: boolean, formatOutputAsJson: boolean): Promise<number | null>;
|
|
48
48
|
export declare function resolveProjectId(options: UploadAndDeployOptions): Promise<number | null>;
|
|
49
49
|
export declare function resolveAppMetadata(options: UploadAndDeployOptions & {
|
|
@@ -6,6 +6,7 @@ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
|
6
6
|
import { getAllConfigAccounts, getConfigAccountIfExists, } from '@hubspot/local-dev-lib/config';
|
|
7
7
|
import { translateForLocalDev } from '@hubspot/project-parsing-lib/translate';
|
|
8
8
|
import { commands } from '../../lang/en.js';
|
|
9
|
+
import { warnAboutSkippedHsMetaFiles } from './ui.js';
|
|
9
10
|
import { isAppDeveloperAccount } from '../accountTypes.js';
|
|
10
11
|
import { ApiErrorContext, debugError, logError, } from '../errorHandlers/index.js';
|
|
11
12
|
import { confirmPrompt, listPrompt } from '../prompts/promptUtils.js';
|
|
@@ -33,15 +34,19 @@ export async function resolveProjectAccountId(derivedAccountId, projectConfig, p
|
|
|
33
34
|
return null;
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
|
-
export async function loadInstallableAppNode(projectConfig, projectDir, accountId) {
|
|
37
|
+
export async function loadInstallableAppNode(projectConfig, projectDir, accountId, force = false) {
|
|
37
38
|
let appNode;
|
|
38
39
|
try {
|
|
39
|
-
const {
|
|
40
|
+
const { intermediateRepresentation, skippedHsMetaFiles } = await translateForLocalDev({
|
|
40
41
|
projectSourceDir: path.join(projectDir, projectConfig.srcDir),
|
|
41
42
|
platformVersion: projectConfig.platformVersion,
|
|
42
43
|
accountId,
|
|
43
44
|
}, { skipValidation: true });
|
|
44
|
-
|
|
45
|
+
const shouldContinue = await warnAboutSkippedHsMetaFiles(skippedHsMetaFiles, force, false);
|
|
46
|
+
if (!shouldContinue) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
appNode = getAppNodeFromProjectNodes(intermediateRepresentation.intermediateNodesIndexedByUid);
|
|
45
50
|
}
|
|
46
51
|
catch (error) {
|
|
47
52
|
debugError(error);
|
|
@@ -2,11 +2,11 @@ import LocalDevLogger from './LocalDevLogger.js';
|
|
|
2
2
|
import { ExitFunction } from '../../../types/Yargs.js';
|
|
3
3
|
type DevSessionManagerConstructorOptions = {
|
|
4
4
|
targetTestingAccountId: number;
|
|
5
|
-
localDevLogger
|
|
5
|
+
localDevLogger: LocalDevLogger;
|
|
6
6
|
exit: ExitFunction;
|
|
7
7
|
};
|
|
8
8
|
declare class DevSessionManager {
|
|
9
|
-
localDevLogger
|
|
9
|
+
localDevLogger: LocalDevLogger;
|
|
10
10
|
targetTestingAccountId: number;
|
|
11
11
|
protected devSessionId: number | undefined;
|
|
12
12
|
private heartbeatInterval;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { getActiveServers } from '@hubspot/local-dev-lib/portManager';
|
|
2
2
|
import { devSessionHeartbeat, registerDevSession, deleteDevSession, } from './helpers/devSessionsApi.js';
|
|
3
3
|
import { EXIT_CODES } from '../../enums/exitCodes.js';
|
|
4
|
-
import { uiLogger } from '../../ui/logger.js';
|
|
5
4
|
import { lib } from '../../../lang/en.js';
|
|
6
|
-
import { getErrorMessage } from '../../errorHandlers/index.js';
|
|
7
5
|
class DevSessionManager {
|
|
8
6
|
localDevLogger;
|
|
9
7
|
targetTestingAccountId;
|
|
@@ -21,13 +19,7 @@ class DevSessionManager {
|
|
|
21
19
|
}
|
|
22
20
|
validateSessionIdExists() {
|
|
23
21
|
if (!this.devSessionId) {
|
|
24
|
-
|
|
25
|
-
this.localDevLogger.devSessionMissingSessionIdError();
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
// Fallback for deprecated local dev manager
|
|
29
|
-
uiLogger.error(lib.LocalDevManager.devSession.missingSessionIdError);
|
|
30
|
-
}
|
|
22
|
+
this.localDevLogger.devSessionMissingSessionIdError();
|
|
31
23
|
throw new Error(lib.LocalDevManager.devSession.missingSessionIdError);
|
|
32
24
|
}
|
|
33
25
|
}
|
|
@@ -39,13 +31,7 @@ class DevSessionManager {
|
|
|
39
31
|
this.devSessionId = registerDevSessionResponse.data.sessionId;
|
|
40
32
|
}
|
|
41
33
|
catch (e) {
|
|
42
|
-
|
|
43
|
-
this.localDevLogger.devSessionRegistrationError(e);
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
// Fallback for deprecated local dev manager
|
|
47
|
-
uiLogger.error(lib.LocalDevManager.devSession.registrationError(getErrorMessage(e)));
|
|
48
|
-
}
|
|
34
|
+
this.localDevLogger.devSessionRegistrationError(e);
|
|
49
35
|
return false;
|
|
50
36
|
}
|
|
51
37
|
try {
|
|
@@ -73,13 +59,7 @@ class DevSessionManager {
|
|
|
73
59
|
this.heartbeatRetries++;
|
|
74
60
|
return;
|
|
75
61
|
}
|
|
76
|
-
|
|
77
|
-
this.localDevLogger.devSessionHeartbeatError(e);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
// Fallback for deprecated local dev manager
|
|
81
|
-
uiLogger.error(lib.LocalDevManager.devSession.heartbeatError(getErrorMessage(e)));
|
|
82
|
-
}
|
|
62
|
+
this.localDevLogger.devSessionHeartbeatError(e);
|
|
83
63
|
return this.exit(EXIT_CODES.ERROR);
|
|
84
64
|
}
|
|
85
65
|
}, 30000);
|
|
@@ -91,13 +71,7 @@ class DevSessionManager {
|
|
|
91
71
|
await deleteDevSession(this.targetTestingAccountId, this.devSessionId);
|
|
92
72
|
}
|
|
93
73
|
catch (e) {
|
|
94
|
-
|
|
95
|
-
this.localDevLogger.devSessionDeletionError(e);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// Fallback for deprecated local dev manager
|
|
99
|
-
uiLogger.error(lib.LocalDevManager.devSession.deletionError(getErrorMessage(e)));
|
|
100
|
-
}
|
|
74
|
+
this.localDevLogger.devSessionDeletionError(e);
|
|
101
75
|
return false;
|
|
102
76
|
}
|
|
103
77
|
}
|
|
@@ -95,8 +95,8 @@ class LocalDevProcess {
|
|
|
95
95
|
});
|
|
96
96
|
return true;
|
|
97
97
|
}
|
|
98
|
-
getIntermediateRepresentation(projectNodesAtLastDeploy) {
|
|
99
|
-
|
|
98
|
+
async getIntermediateRepresentation(projectNodesAtLastDeploy) {
|
|
99
|
+
const { intermediateRepresentation } = await translateForLocalDev({
|
|
100
100
|
projectSourceDir: path.join(this.state.projectDir, this.state.projectConfig.srcDir),
|
|
101
101
|
platformVersion: this.state.projectConfig.platformVersion,
|
|
102
102
|
accountId: this.state.targetProjectAccountId,
|
|
@@ -104,6 +104,7 @@ class LocalDevProcess {
|
|
|
104
104
|
projectNodesAtLastUpload: projectNodesAtLastDeploy,
|
|
105
105
|
profile: this.state.profile,
|
|
106
106
|
});
|
|
107
|
+
return intermediateRepresentation;
|
|
107
108
|
}
|
|
108
109
|
async updateProjectNodes() {
|
|
109
110
|
const intermediateRepresentation = await this.getIntermediateRepresentation(this.state.projectNodesAtLastDeploy);
|
|
@@ -152,14 +153,14 @@ class LocalDevProcess {
|
|
|
152
153
|
return this.state.actions.exit(EXIT_CODES.ERROR);
|
|
153
154
|
}
|
|
154
155
|
this.logger.startupMessage();
|
|
155
|
-
if (isConfigFlagEnabled(CONFIG_FLAGS.AUTO_OPEN_BROWSER, true)) {
|
|
156
|
-
this.openLocalDevUi();
|
|
157
|
-
}
|
|
158
156
|
await this.startDevServers();
|
|
159
157
|
const devSessionRegistered = await this.devSessionManager.registerSession();
|
|
160
158
|
if (!devSessionRegistered) {
|
|
161
159
|
return this.state.actions.exit(EXIT_CODES.ERROR);
|
|
162
160
|
}
|
|
161
|
+
if (isConfigFlagEnabled(CONFIG_FLAGS.AUTO_OPEN_BROWSER, true)) {
|
|
162
|
+
this.openLocalDevUi();
|
|
163
|
+
}
|
|
163
164
|
this.state.devServersStarted = true;
|
|
164
165
|
this.logger.monitorConsoleOutput();
|
|
165
166
|
}
|
|
@@ -197,6 +198,7 @@ class LocalDevProcess {
|
|
|
197
198
|
projectDir: this.state.projectDir,
|
|
198
199
|
callbackFunc: pollProjectBuildAndDeploy,
|
|
199
200
|
sendIR: true,
|
|
201
|
+
force: true,
|
|
200
202
|
});
|
|
201
203
|
const deploy = result?.deployResult;
|
|
202
204
|
if (uploadError) {
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { HubSpotConfigAccount } from '@hubspot/local-dev-lib/types/Accounts';
|
|
2
2
|
import { Environment } from '@hubspot/local-dev-lib/types/Accounts';
|
|
3
3
|
import { DeveloperTestAccount } from '@hubspot/local-dev-lib/types/developerTestAccounts.js';
|
|
4
|
-
import { ProjectDevTargetAccountPromptResponse } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
5
|
-
import { ExitFunction } from '../../../../types/Yargs.js';
|
|
6
|
-
export declare function confirmDefaultAccountIsTarget(accountConfig: HubSpotConfigAccount, exit: ExitFunction): Promise<void>;
|
|
7
|
-
export declare function checkIfDefaultAccountIsSupported(accountConfig: HubSpotConfigAccount, hasPublicApps: boolean, exit: ExitFunction): Promise<void>;
|
|
8
|
-
export declare function checkIfParentAccountIsAuthed(accountConfig: HubSpotConfigAccount): void;
|
|
9
|
-
export declare function checkIfAccountFlagIsSupported(accountConfig: HubSpotConfigAccount, hasPublicApps: boolean): void;
|
|
10
|
-
export declare function suggestRecommendedNestedAccount(accounts: HubSpotConfigAccount[], accountConfig: HubSpotConfigAccount, hasPublicApps: boolean): Promise<ProjectDevTargetAccountPromptResponse>;
|
|
11
4
|
export declare function createSandboxForLocalDev(accountId: number, accountConfig: HubSpotConfigAccount, env: Environment): Promise<number>;
|
|
12
5
|
export declare function createDeveloperTestAccountForLocalDev(accountId: number, accountConfig: HubSpotConfigAccount, env: Environment, useV2?: boolean): Promise<number>;
|
|
13
6
|
export declare function useExistingDevTestAccount(env: Environment, account: DeveloperTestAccount): Promise<boolean>;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { HUBSPOT_ACCOUNT_TYPE_STRINGS } from '@hubspot/local-dev-lib/constants/config';
|
|
2
|
-
import { getConfigAccountIfExists } from '@hubspot/local-dev-lib/config';
|
|
3
1
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
4
2
|
import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
|
|
5
3
|
import { isMissingScopeError } from '@hubspot/local-dev-lib/errors/index';
|
|
@@ -7,15 +5,6 @@ import { PERSONAL_ACCESS_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constant
|
|
|
7
5
|
import { getSandboxUsageLimits } from '@hubspot/local-dev-lib/api/sandboxHubs';
|
|
8
6
|
import { uiLogger } from '../../../ui/logger.js';
|
|
9
7
|
import { lib } from '../../../../lang/en.js';
|
|
10
|
-
import { EXIT_CODES } from '../../../enums/exitCodes.js';
|
|
11
|
-
import { confirmDefaultAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
12
|
-
import { isUnifiedAccount } from '../../../accountTypes.js';
|
|
13
|
-
import { isAppDeveloperAccount } from '../../../accountTypes.js';
|
|
14
|
-
import { isDeveloperTestAccount } from '../../../accountTypes.js';
|
|
15
|
-
import { uiAccountDescription } from '../../../ui/index.js';
|
|
16
|
-
import { uiLine } from '../../../ui/index.js';
|
|
17
|
-
import { selectDeveloperTestTargetAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
18
|
-
import { selectSandboxTargetAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
19
8
|
import { validateSandboxUsageLimits } from '../../../sandboxes.js';
|
|
20
9
|
import { logError } from '../../../errorHandlers/index.js';
|
|
21
10
|
import { hubspotAccountNamePrompt } from '../../../prompts/accountNamePrompt.js';
|
|
@@ -25,73 +14,6 @@ import { buildDeveloperTestAccount, saveAccountToConfig, buildV2Sandbox, } from
|
|
|
25
14
|
import { debugError } from '../../../errorHandlers/index.js';
|
|
26
15
|
import { listPrompt } from '../../../prompts/promptUtils.js';
|
|
27
16
|
import { confirmUseExistingDeveloperTestAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
28
|
-
// If the user passed in the --account flag, confirm they want to use that account as
|
|
29
|
-
// their target account, otherwise exit
|
|
30
|
-
export async function confirmDefaultAccountIsTarget(accountConfig, exit) {
|
|
31
|
-
if (!accountConfig.name || !accountConfig.accountType) {
|
|
32
|
-
uiLogger.error(lib.localDevHelpers.account.confirmDefaultAccountIsTarget.configError);
|
|
33
|
-
return exit(EXIT_CODES.ERROR);
|
|
34
|
-
}
|
|
35
|
-
uiLogger.log('');
|
|
36
|
-
const useDefaultAccount = await confirmDefaultAccountPrompt(accountConfig.name, HUBSPOT_ACCOUNT_TYPE_STRINGS[accountConfig.accountType]);
|
|
37
|
-
if (!useDefaultAccount) {
|
|
38
|
-
uiLogger.log(lib.localDevHelpers.account.confirmDefaultAccountIsTarget
|
|
39
|
-
.declineDefaultAccountExplanation);
|
|
40
|
-
return exit(EXIT_CODES.SUCCESS);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// Confirm the default account is supported for the type of apps being developed
|
|
44
|
-
export async function checkIfDefaultAccountIsSupported(accountConfig, hasPublicApps, exit) {
|
|
45
|
-
const defaultAccountIsUnified = await isUnifiedAccount(accountConfig);
|
|
46
|
-
if (hasPublicApps &&
|
|
47
|
-
!(isAppDeveloperAccount(accountConfig) ||
|
|
48
|
-
isDeveloperTestAccount(accountConfig) ||
|
|
49
|
-
defaultAccountIsUnified)) {
|
|
50
|
-
uiLogger.error(lib.localDevHelpers.account.checkIfDefaultAccountIsSupported.publicApp);
|
|
51
|
-
return exit(EXIT_CODES.SUCCESS);
|
|
52
|
-
}
|
|
53
|
-
else if (!hasPublicApps && isAppDeveloperAccount(accountConfig)) {
|
|
54
|
-
uiLogger.error(lib.localDevHelpers.account.checkIfDefaultAccountIsSupported.privateApp);
|
|
55
|
-
return exit(EXIT_CODES.SUCCESS);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
export function checkIfParentAccountIsAuthed(accountConfig) {
|
|
59
|
-
if (!accountConfig.parentAccountId ||
|
|
60
|
-
!getConfigAccountIfExists(accountConfig.parentAccountId)?.accountId) {
|
|
61
|
-
throw new Error(lib.localDevHelpers.account.checkIfParentAccountIsAuthed.notAuthedError(accountConfig.parentAccountId || '', uiAccountDescription(accountConfig.accountId)));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// Confirm the default account is a developer account if developing public apps
|
|
65
|
-
export function checkIfAccountFlagIsSupported(accountConfig, hasPublicApps) {
|
|
66
|
-
if (hasPublicApps) {
|
|
67
|
-
if (!isDeveloperTestAccount(accountConfig)) {
|
|
68
|
-
throw new Error(lib.localDevHelpers.account.validateAccountOption
|
|
69
|
-
.invalidPublicAppAccount);
|
|
70
|
-
}
|
|
71
|
-
checkIfParentAccountIsAuthed(accountConfig);
|
|
72
|
-
}
|
|
73
|
-
else if (isAppDeveloperAccount(accountConfig)) {
|
|
74
|
-
throw new Error(lib.localDevHelpers.account.validateAccountOption.invalidPrivateAppAccount);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// If the user isn't using the recommended account type, prompt them to use or create one
|
|
78
|
-
export async function suggestRecommendedNestedAccount(accounts, accountConfig, hasPublicApps) {
|
|
79
|
-
uiLogger.log('');
|
|
80
|
-
uiLine();
|
|
81
|
-
if (hasPublicApps) {
|
|
82
|
-
uiLogger.log(lib.localDevHelpers.account.validateAccountOption
|
|
83
|
-
.publicAppNonDeveloperTestAccountWarning);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
uiLogger.log(lib.localDevHelpers.account.validateAccountOption.nonSandboxWarning);
|
|
87
|
-
}
|
|
88
|
-
uiLine();
|
|
89
|
-
uiLogger.log('');
|
|
90
|
-
const targetAccountPrompt = hasPublicApps
|
|
91
|
-
? selectDeveloperTestTargetAccountPrompt
|
|
92
|
-
: selectSandboxTargetAccountPrompt;
|
|
93
|
-
return targetAccountPrompt(accounts, accountConfig);
|
|
94
|
-
}
|
|
95
17
|
// Create a new sandbox and return its accountId
|
|
96
18
|
export async function createSandboxForLocalDev(accountId, accountConfig, env) {
|
|
97
19
|
try {
|
|
@@ -166,8 +88,7 @@ export async function useExistingDevTestAccount(env, account) {
|
|
|
166
88
|
const useExistingDevTestAcct = await confirmUseExistingDeveloperTestAccountPrompt(account);
|
|
167
89
|
if (!useExistingDevTestAcct) {
|
|
168
90
|
uiLogger.log('');
|
|
169
|
-
uiLogger.log(lib.localDevHelpers.account.
|
|
170
|
-
.declineDefaultAccountExplanation);
|
|
91
|
+
uiLogger.log(lib.localDevHelpers.account.declineDefaultAccountExplanation);
|
|
171
92
|
uiLogger.log('');
|
|
172
93
|
return false;
|
|
173
94
|
}
|
|
@@ -85,6 +85,7 @@ export async function createInitialBuildForNewProject(projectConfig, projectDir,
|
|
|
85
85
|
skipValidation: true,
|
|
86
86
|
sendIR,
|
|
87
87
|
profile,
|
|
88
|
+
force: true,
|
|
88
89
|
});
|
|
89
90
|
if (uploadError) {
|
|
90
91
|
if (isSpecifiedError(uploadError, {
|
|
@@ -173,12 +174,12 @@ export async function getDeployedProjectNodes(projectConfig, accountId, deployed
|
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
const deployedProjectSourceDir = path.join(tempDir, deployedSrcDir);
|
|
176
|
-
const {
|
|
177
|
+
const { intermediateRepresentation } = await translate({
|
|
177
178
|
projectSourceDir: deployedProjectSourceDir,
|
|
178
179
|
platformVersion: projectConfig.platformVersion,
|
|
179
180
|
accountId: accountId,
|
|
180
181
|
}, { profile });
|
|
181
|
-
return intermediateNodesIndexedByUid;
|
|
182
|
+
return intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
182
183
|
}
|
|
183
184
|
finally {
|
|
184
185
|
if (tempDir && (await fs.pathExists(tempDir))) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Release } from '../../api/releases.js';
|
|
2
|
+
export declare function resolveBuildId(accountId: number, projectName: string, buildOption?: number, force?: boolean): Promise<number | null | undefined>;
|
|
3
|
+
export declare function validateBuildForRelease(accountId: number, projectName: string, buildId: number): Promise<boolean>;
|
|
4
|
+
export declare function executeRelease(accountId: number, projectName: string, buildId: number): Promise<Release>;
|