@hubspot/cli 8.10.0 → 8.12.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/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/hubdb/list.d.ts +1 -1
- 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 +19 -17
- 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/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 +25 -26
- package/commands/project/list.js +1 -1
- 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 +14 -6
- package/commands/project/upload.d.ts +2 -1
- package/commands/project/upload.js +23 -17
- package/commands/project/validate.d.ts +1 -1
- package/commands/project.js +2 -2
- 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 +32 -28
- package/lang/en.js +41 -37
- package/lib/commonOpts.js +6 -1
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +1 -0
- package/lib/jsonOutput.d.ts +109 -0
- package/lib/jsonOutput.js +94 -0
- package/lib/mcp/setup.d.ts +6 -1
- package/lib/mcp/setup.js +29 -18
- package/lib/projects/builds.d.ts +2 -0
- package/lib/projects/builds.js +22 -0
- package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
- package/lib/projects/localDev/DevSessionManager.js +4 -30
- package/lib/projects/localDev/helpers/account.d.ts +0 -7
- package/lib/projects/localDev/helpers/account.js +1 -80
- package/lib/projects/release.d.ts +4 -0
- package/lib/projects/release.js +90 -0
- package/lib/projects/upload.d.ts +1 -1
- package/lib/projects/upload.js +4 -8
- 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 +2 -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 +2 -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 +9 -3
- package/mcp-server/tools/project/FindProjectsTool.js +1 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -4
- package/mcp-server/tools/project/GetApplicationInfoTool.js +9 -4
- package/mcp-server/tools/project/GetBuildLogsTool.js +9 -3
- package/mcp-server/tools/project/GetBuildStatusTool.js +9 -3
- package/mcp-server/tools/project/GetConfigValuesTool.js +9 -3
- 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/utils/command.d.ts +25 -2
- package/mcp-server/utils/command.js +67 -17
- package/mcp-server/utils/logger.d.ts +3 -0
- package/mcp-server/utils/logger.js +30 -0
- package/mcp-server/utils/toolUsageTracking.js +8 -1
- package/package.json +10 -8
- 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
|
@@ -32,8 +32,9 @@ const defaultMcpCommand = {
|
|
|
32
32
|
command: 'hs',
|
|
33
33
|
args: ['mcp', 'start'],
|
|
34
34
|
};
|
|
35
|
-
export async function configureMcpServer(
|
|
35
|
+
export async function configureMcpServer(options) {
|
|
36
36
|
try {
|
|
37
|
+
const { targets, standalone, cliVersion: cliVersionFlag } = options;
|
|
37
38
|
let derivedTargets = [];
|
|
38
39
|
if (!targets || targets.length === 0) {
|
|
39
40
|
const { selectedTargets } = await promptUser({
|
|
@@ -52,23 +53,33 @@ export async function configureMcpServer(targets) {
|
|
|
52
53
|
else {
|
|
53
54
|
derivedTargets = targets;
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
56
|
+
let useStandaloneMode = standalone;
|
|
57
|
+
if (useStandaloneMode === undefined) {
|
|
58
|
+
const response = await promptUser({
|
|
59
|
+
name: 'useStandaloneMode',
|
|
60
|
+
type: 'confirm',
|
|
61
|
+
message: commands.mcp.setup.prompts.standaloneMode,
|
|
62
|
+
default: false,
|
|
63
|
+
});
|
|
64
|
+
useStandaloneMode = response.useStandaloneMode;
|
|
65
|
+
}
|
|
66
|
+
let cliVersion = '';
|
|
67
|
+
if (useStandaloneMode) {
|
|
68
|
+
if (cliVersionFlag !== undefined) {
|
|
69
|
+
cliVersion = cliVersionFlag;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const response = await promptUser({
|
|
73
|
+
name: 'cliVersion',
|
|
74
|
+
type: 'input',
|
|
75
|
+
message: commands.mcp.setup.prompts.cliVersion,
|
|
76
|
+
validate: (v) => !v || /^[\d]+\.[\d]+\.[\d]+([-+][\w.]+)?$/.test(v.trim())
|
|
77
|
+
? true
|
|
78
|
+
: 'Please enter a valid semver version (e.g. 8.0.1) or leave blank for latest.',
|
|
79
|
+
});
|
|
80
|
+
cliVersion = response.cliVersion;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
72
83
|
const cliPackage = cliVersion
|
|
73
84
|
? `@hubspot/cli@${cliVersion}`
|
|
74
85
|
: '@hubspot/cli';
|
|
@@ -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
|
+
}
|
|
@@ -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
|
}
|
|
@@ -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
|
}
|
|
@@ -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>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { fetchProjectBuilds, getBuildStatus, } from '@hubspot/local-dev-lib/api/projects';
|
|
3
|
+
import { BUILD_STATUS } from '@hubspot/local-dev-lib/enums/build';
|
|
4
|
+
import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
|
|
5
|
+
import { meetsMinimumPlatformVersion } from '@hubspot/project-parsing-lib/projects';
|
|
6
|
+
import { PLATFORM_VERSIONS } from '@hubspot/project-parsing-lib/constants';
|
|
7
|
+
import { getLastSuccessfulBuild } from './builds.js';
|
|
8
|
+
import { logError, ApiErrorContext } from '../errorHandlers/index.js';
|
|
9
|
+
import { uiLogger } from '../ui/logger.js';
|
|
10
|
+
import { listPrompt } from '../prompts/promptUtils.js';
|
|
11
|
+
import { commands } from '../../lang/en.js';
|
|
12
|
+
import { createRelease } from '../../api/releases.js';
|
|
13
|
+
function buildChoiceName(build) {
|
|
14
|
+
const base = build.uploadMessage
|
|
15
|
+
? `${build.buildId} — ${build.uploadMessage}`
|
|
16
|
+
: `${build.buildId} — ${commands.project.release.create.noUploadMessage}`;
|
|
17
|
+
return build.status !== BUILD_STATUS.SUCCESS
|
|
18
|
+
? `[${chalk.yellow('DISABLED')}] ${base}`
|
|
19
|
+
: base;
|
|
20
|
+
}
|
|
21
|
+
export async function resolveBuildId(accountId, projectName, buildOption, force) {
|
|
22
|
+
if (buildOption) {
|
|
23
|
+
return buildOption;
|
|
24
|
+
}
|
|
25
|
+
if (force) {
|
|
26
|
+
const lastSuccessful = await getLastSuccessfulBuild(accountId, projectName);
|
|
27
|
+
return lastSuccessful ? lastSuccessful.buildId : null;
|
|
28
|
+
}
|
|
29
|
+
let results;
|
|
30
|
+
try {
|
|
31
|
+
({
|
|
32
|
+
data: { results },
|
|
33
|
+
} = await fetchProjectBuilds(accountId, projectName));
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
if (isSpecifiedError(e, { statusCode: 404 }) ||
|
|
37
|
+
isSpecifiedError(e, { statusCode: 400 })) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
if (results.length === 0) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const lastSuccessful = await getLastSuccessfulBuild(accountId, projectName);
|
|
46
|
+
if (!lastSuccessful) {
|
|
47
|
+
uiLogger.error(commands.project.release.create.errors.noSuccessfulBuilds(projectName));
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return listPrompt(commands.project.release.create.buildIdPrompt, {
|
|
51
|
+
choices: results.map(b => ({
|
|
52
|
+
name: buildChoiceName(b),
|
|
53
|
+
value: b.buildId,
|
|
54
|
+
disabled: b.status !== BUILD_STATUS.SUCCESS
|
|
55
|
+
? `– ${commands.project.release.create.buildStatus[b.status] ?? b.status}`
|
|
56
|
+
: undefined,
|
|
57
|
+
})),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
export async function validateBuildForRelease(accountId, projectName, buildId) {
|
|
61
|
+
try {
|
|
62
|
+
const { data: build } = await getBuildStatus(accountId, projectName, buildId);
|
|
63
|
+
return meetsMinimumPlatformVersion(build.platformVersion, PLATFORM_VERSIONS.v2026_09_BETA);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
if (isSpecifiedError(e, { statusCode: 404 })) {
|
|
67
|
+
uiLogger.error(commands.project.release.create.errors.buildNotFound(buildId, projectName));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
logError(e, new ApiErrorContext({
|
|
71
|
+
accountId,
|
|
72
|
+
request: 'project release create',
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
throw e;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export async function executeRelease(accountId, projectName, buildId) {
|
|
79
|
+
try {
|
|
80
|
+
const { data: release } = await createRelease(accountId, projectName, buildId);
|
|
81
|
+
return release;
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
logError(e, new ApiErrorContext({
|
|
85
|
+
accountId,
|
|
86
|
+
request: 'project release create',
|
|
87
|
+
}));
|
|
88
|
+
throw e;
|
|
89
|
+
}
|
|
90
|
+
}
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ type HandleProjectUploadArg<T> = {
|
|
|
24
24
|
profile?: string;
|
|
25
25
|
force?: boolean;
|
|
26
26
|
};
|
|
27
|
-
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, skipNpmAudit, skipAutoDeploy
|
|
27
|
+
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, skipNpmAudit, skipAutoDeploy, force, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
|
|
28
28
|
export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig, projectDir: string): Promise<void>;
|
|
29
29
|
export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
30
30
|
type HandleTranslateArg = {
|
package/lib/projects/upload.js
CHANGED
|
@@ -21,7 +21,7 @@ import { archiveWorkspacesAndDependencies, getPackageJsonPathsToUpdate, getLockf
|
|
|
21
21
|
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
22
22
|
import { validateLintConfigOnUpload } from './validateLintConfigOnUpload.js';
|
|
23
23
|
import { runNpmAuditsBeforeProjectUpload } from './npmAuditOnUpload.js';
|
|
24
|
-
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
|
|
24
|
+
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation, skipAutoDeploy) {
|
|
25
25
|
const accountIdentifier = uiAccountDescription(accountId) || `${accountId}`;
|
|
26
26
|
SpinniesManager.add('upload', {
|
|
27
27
|
text: lib.projectUpload.uploadProjectFiles.add(projectName, accountIdentifier),
|
|
@@ -30,8 +30,7 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
|
|
|
30
30
|
let buildId;
|
|
31
31
|
let error;
|
|
32
32
|
try {
|
|
33
|
-
|
|
34
|
-
const { data: upload } = await uploadProject(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation);
|
|
33
|
+
const { data: upload } = await uploadProject(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation, skipAutoDeploy);
|
|
35
34
|
buildId = upload.buildId;
|
|
36
35
|
SpinniesManager.succeed('upload', {
|
|
37
36
|
text: lib.projectUpload.uploadProjectFiles.succeed(projectName, accountIdentifier),
|
|
@@ -48,10 +47,7 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
|
|
|
48
47
|
}
|
|
49
48
|
return { buildId, error };
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
export async function handleProjectUpload({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage = '', forceCreate = false, isUploadCommand = false, sendIR = false, skipValidation = false, skipNpmAudit = false,
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
54
|
-
skipAutoDeploy: _skipAutoDeploy = false, force = false, }) {
|
|
50
|
+
export async function handleProjectUpload({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage = '', forceCreate = false, isUploadCommand = false, sendIR = false, skipValidation = false, skipNpmAudit = false, skipAutoDeploy = false, force = false, }) {
|
|
55
51
|
const srcDir = path.resolve(projectDir, projectConfig.srcDir);
|
|
56
52
|
await validateSourceDirectory(srcDir, projectConfig, projectDir);
|
|
57
53
|
await validateNoHSMetaMismatch(srcDir, projectConfig);
|
|
@@ -119,7 +115,7 @@ skipAutoDeploy: _skipAutoDeploy = false, force = false, }) {
|
|
|
119
115
|
return resolve({ projectNotFound: true });
|
|
120
116
|
}
|
|
121
117
|
const projectId = project?.id;
|
|
122
|
-
const { buildId, error } = await uploadProjectFiles(accountId, projectConfig.name, tempFile.name, uploadMessage, projectConfig.platformVersion, intermediateRepresentation);
|
|
118
|
+
const { buildId, error } = await uploadProjectFiles(accountId, projectConfig.name, tempFile.name, uploadMessage, projectConfig.platformVersion, intermediateRepresentation, skipAutoDeploy);
|
|
123
119
|
if (error) {
|
|
124
120
|
resolve({ uploadError: error, projectId });
|
|
125
121
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { ArgumentsCamelCase } from 'yargs';
|
|
2
|
+
import { z } from 'zod';
|
|
2
3
|
import { CommonArgs } from '../../types/Yargs.js';
|
|
3
|
-
export
|
|
4
|
+
export type WrappedHandlerOptions = {
|
|
5
|
+
jsonOutputSchema?: z.ZodType;
|
|
6
|
+
};
|
|
7
|
+
export declare function makeWrappedYargsHandler<T extends CommonArgs>(trackingName: string, handler: (args: ArgumentsCamelCase<T>) => Promise<void>, options?: WrappedHandlerOptions): (args: ArgumentsCamelCase<T>) => Promise<void>;
|