@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.
Files changed (110) hide show
  1. package/commands/account/clean.js +1 -1
  2. package/commands/account/list.js +1 -1
  3. package/commands/account/remove.js +1 -1
  4. package/commands/account/rename.js +1 -1
  5. package/commands/account/use.js +1 -1
  6. package/commands/api.d.ts +4 -1
  7. package/commands/api.js +11 -14
  8. package/commands/hubdb/list.d.ts +1 -1
  9. package/commands/mcp/setup.d.ts +2 -0
  10. package/commands/mcp/setup.js +29 -1
  11. package/commands/project/appInstallStatus.d.ts +2 -1
  12. package/commands/project/appInstallStatus.js +19 -17
  13. package/commands/project/create.js +0 -1
  14. package/commands/project/deploy.d.ts +2 -1
  15. package/commands/project/deploy.js +31 -14
  16. package/commands/project/dev/index.js +18 -64
  17. package/commands/project/info.d.ts +2 -1
  18. package/commands/project/info.js +8 -6
  19. package/commands/project/installApp.d.ts +2 -1
  20. package/commands/project/installApp.js +25 -26
  21. package/commands/project/list.js +1 -1
  22. package/commands/project/profile/add.d.ts +2 -1
  23. package/commands/project/profile/add.js +22 -1
  24. package/commands/project/profile/delete.d.ts +1 -1
  25. package/commands/project/release/create.d.ts +2 -1
  26. package/commands/project/release/create.js +68 -69
  27. package/commands/project/release/info.d.ts +2 -1
  28. package/commands/project/release/info.js +7 -6
  29. package/commands/project/release/list.d.ts +2 -1
  30. package/commands/project/release/list.js +14 -6
  31. package/commands/project/upload.d.ts +2 -1
  32. package/commands/project/upload.js +23 -17
  33. package/commands/project/validate.d.ts +1 -1
  34. package/commands/project.js +2 -2
  35. package/commands/testAccount/create.d.ts +2 -1
  36. package/commands/testAccount/create.js +7 -7
  37. package/commands/testAccount/importData.d.ts +1 -1
  38. package/lang/en.d.ts +32 -28
  39. package/lang/en.js +41 -37
  40. package/lib/commonOpts.js +6 -1
  41. package/lib/constants.d.ts +1 -0
  42. package/lib/constants.js +1 -0
  43. package/lib/jsonOutput.d.ts +109 -0
  44. package/lib/jsonOutput.js +94 -0
  45. package/lib/mcp/setup.d.ts +6 -1
  46. package/lib/mcp/setup.js +29 -18
  47. package/lib/projects/builds.d.ts +2 -0
  48. package/lib/projects/builds.js +22 -0
  49. package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
  50. package/lib/projects/localDev/DevSessionManager.js +4 -30
  51. package/lib/projects/localDev/helpers/account.d.ts +0 -7
  52. package/lib/projects/localDev/helpers/account.js +1 -80
  53. package/lib/projects/release.d.ts +4 -0
  54. package/lib/projects/release.js +90 -0
  55. package/lib/projects/upload.d.ts +1 -1
  56. package/lib/projects/upload.js +4 -8
  57. package/lib/yargs/makeWrappedYargsHandler.d.ts +5 -1
  58. package/lib/yargs/makeWrappedYargsHandler.js +123 -65
  59. package/mcp-server/Tool.d.ts +8 -3
  60. package/mcp-server/Tool.js +58 -32
  61. package/mcp-server/server.js +10 -6
  62. package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +2 -2
  63. package/mcp-server/tools/cms/HsCreateFunctionTool.js +10 -17
  64. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
  65. package/mcp-server/tools/cms/HsCreateModuleTool.js +12 -18
  66. package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +2 -2
  67. package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -10
  68. package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +2 -2
  69. package/mcp-server/tools/cms/HsFunctionLogsTool.js +9 -9
  70. package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +2 -2
  71. package/mcp-server/tools/cms/HsListFunctionsTool.js +7 -7
  72. package/mcp-server/tools/cms/HsListTool.d.ts +2 -2
  73. package/mcp-server/tools/cms/HsListTool.js +6 -10
  74. package/mcp-server/tools/index.js +2 -0
  75. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +2 -2
  76. package/mcp-server/tools/project/AddFeatureToProjectTool.js +8 -9
  77. package/mcp-server/tools/project/AuthAccountTool.d.ts +18 -0
  78. package/mcp-server/tools/project/AuthAccountTool.js +78 -0
  79. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  80. package/mcp-server/tools/project/CreateProjectTool.js +13 -12
  81. package/mcp-server/tools/project/CreateTestAccountTool.d.ts +2 -2
  82. package/mcp-server/tools/project/CreateTestAccountTool.js +14 -15
  83. package/mcp-server/tools/project/DeployProjectTool.d.ts +2 -2
  84. package/mcp-server/tools/project/DeployProjectTool.js +10 -10
  85. package/mcp-server/tools/project/DocFetchTool.js +1 -1
  86. package/mcp-server/tools/project/DocsSearchTool.js +9 -3
  87. package/mcp-server/tools/project/FindProjectsTool.js +1 -1
  88. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -4
  89. package/mcp-server/tools/project/GetApplicationInfoTool.js +9 -4
  90. package/mcp-server/tools/project/GetBuildLogsTool.js +9 -3
  91. package/mcp-server/tools/project/GetBuildStatusTool.js +9 -3
  92. package/mcp-server/tools/project/GetConfigValuesTool.js +9 -3
  93. package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
  94. package/mcp-server/tools/project/UploadProjectTools.d.ts +2 -2
  95. package/mcp-server/tools/project/UploadProjectTools.js +9 -8
  96. package/mcp-server/tools/project/ValidateProjectTool.d.ts +2 -2
  97. package/mcp-server/tools/project/ValidateProjectTool.js +5 -4
  98. package/mcp-server/utils/command.d.ts +25 -2
  99. package/mcp-server/utils/command.js +67 -17
  100. package/mcp-server/utils/logger.d.ts +3 -0
  101. package/mcp-server/utils/logger.js +30 -0
  102. package/mcp-server/utils/toolUsageTracking.js +8 -1
  103. package/package.json +10 -8
  104. package/types/Yargs.d.ts +3 -1
  105. package/commands/project/dev/deprecatedFlow.d.ts +0 -11
  106. package/commands/project/dev/deprecatedFlow.js +0 -180
  107. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +0 -43
  108. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +0 -128
  109. package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +0 -64
  110. 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(targets) {
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
- // Prompt for standalone mode
56
- const { useStandaloneMode } = await promptUser({
57
- name: 'useStandaloneMode',
58
- type: 'confirm',
59
- message: commands.mcp.setup.prompts.standaloneMode,
60
- default: false,
61
- });
62
- const { cliVersion } = useStandaloneMode
63
- ? await promptUser({
64
- name: 'cliVersion',
65
- type: 'input',
66
- message: commands.mcp.setup.prompts.cliVersion,
67
- validate: (v) => !v || /^[\d]+\.[\d]+\.[\d]+([-+][\w.]+)?$/.test(v.trim())
68
- ? true
69
- : 'Please enter a valid semver version (e.g. 8.0.1) or leave blank for latest.',
70
- })
71
- : { cliVersion: '' };
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,2 @@
1
+ import { type Build } from '@hubspot/local-dev-lib/types/Build';
2
+ export declare function getLastSuccessfulBuild(accountId: number, projectName: string, latestBuild?: Build): Promise<Build | undefined>;
@@ -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?: LocalDevLogger;
5
+ localDevLogger: LocalDevLogger;
6
6
  exit: ExitFunction;
7
7
  };
8
8
  declare class DevSessionManager {
9
- localDevLogger?: 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
- if (this.localDevLogger) {
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
- if (this.localDevLogger) {
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
- if (this.localDevLogger) {
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
- if (this.localDevLogger) {
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.confirmDefaultAccountIsTarget
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
+ }
@@ -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: _skipAutoDeploy, force, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
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 = {
@@ -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
- // TODO(skip-auto-deploy): Pass skipAutoDeploy once local-dev-lib is bumped
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
- // TODO(skip-auto-deploy): Use skipAutoDeploy once local-dev-lib is bumped to support it
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 declare function makeWrappedYargsHandler<T extends CommonArgs>(trackingName: string, handler: (args: ArgumentsCamelCase<T>) => Promise<void>): (args: ArgumentsCamelCase<T>) => Promise<void>;
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>;