@hubspot/cli 7.8.0-experimental.0 → 7.8.2-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.
Files changed (143) hide show
  1. package/bin/cli.js +0 -2
  2. package/commands/__tests__/getStarted.test.js +2 -2
  3. package/commands/__tests__/mcp.test.js +1 -1
  4. package/commands/__tests__/project.test.js +0 -3
  5. package/commands/app/__tests__/migrate.test.js +0 -1
  6. package/commands/app/migrate.js +4 -5
  7. package/commands/app/secret/add.js +2 -1
  8. package/commands/app/secret/delete.js +2 -1
  9. package/commands/app/secret/list.js +2 -1
  10. package/commands/app/secret/update.js +2 -1
  11. package/commands/app/secret.js +2 -1
  12. package/commands/app.js +2 -2
  13. package/commands/config/set.js +0 -1
  14. package/commands/feedback.js +1 -1
  15. package/commands/getStarted.d.ts +1 -3
  16. package/commands/getStarted.js +66 -18
  17. package/commands/mcp/__tests__/setup.test.js +2 -2
  18. package/commands/mcp/setup.js +11 -2
  19. package/commands/mcp.js +3 -3
  20. package/commands/project/__tests__/create.test.js +6 -6
  21. package/commands/project/__tests__/deploy.test.js +0 -3
  22. package/commands/project/__tests__/devUnifiedFlow.test.js +2 -4
  23. package/commands/project/__tests__/logs.test.js +0 -3
  24. package/commands/project/__tests__/migrate.test.js +1 -2
  25. package/commands/project/__tests__/migrateApp.test.js +1 -2
  26. package/commands/project/__tests__/profile.test.js +1 -1
  27. package/commands/project/add.js +1 -5
  28. package/commands/project/create.js +3 -9
  29. package/commands/project/deploy.js +2 -2
  30. package/commands/project/dev/index.js +4 -3
  31. package/commands/project/dev/unifiedFlow.js +6 -4
  32. package/commands/project/download.js +1 -2
  33. package/commands/project/installDeps.js +1 -2
  34. package/commands/project/listBuilds.js +2 -2
  35. package/commands/project/logs.js +2 -2
  36. package/commands/project/migrate.js +28 -10
  37. package/commands/project/migrateApp.js +1 -2
  38. package/commands/project/open.js +1 -2
  39. package/commands/project/profile/add.js +3 -3
  40. package/commands/project/profile/delete.js +1 -2
  41. package/commands/project/profile.js +2 -3
  42. package/commands/project/upload.js +2 -2
  43. package/commands/project/validate.js +1 -1
  44. package/commands/project/watch.js +2 -2
  45. package/commands/project.js +1 -2
  46. package/commands/sandbox/delete.js +1 -1
  47. package/commands/testAccount/importData.d.ts +1 -1
  48. package/commands/testAccount/importData.js +1 -1
  49. package/commands/testAccount.js +1 -1
  50. package/lang/en.d.ts +15 -4
  51. package/lang/en.js +18 -6
  52. package/lib/__tests__/hasFeature.test.js +145 -7
  53. package/lib/app/__tests__/migrate.test.js +14 -51
  54. package/lib/app/migrate.d.ts +2 -8
  55. package/lib/app/migrate.js +5 -80
  56. package/lib/constants.d.ts +8 -0
  57. package/lib/constants.js +8 -0
  58. package/lib/dependencyManagement.d.ts +0 -5
  59. package/lib/dependencyManagement.js +0 -9
  60. package/lib/hasFeature.js +6 -0
  61. package/lib/links.d.ts +1 -0
  62. package/lib/links.js +10 -3
  63. package/lib/mcp/setup.js +1 -1
  64. package/lib/middleware/fireAlarmMiddleware.js +15 -5
  65. package/lib/projects/__tests__/LocalDevProcess.test.js +227 -16
  66. package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +16 -21
  67. package/lib/projects/__tests__/deploy.test.js +71 -6
  68. package/lib/projects/__tests__/localDevProjectHelpers.test.js +4 -2
  69. package/lib/projects/create/__tests__/v3.test.js +79 -4
  70. package/lib/projects/create/v3.js +11 -8
  71. package/lib/projects/localDev/AppDevModeInterface.js +5 -5
  72. package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
  73. package/lib/projects/localDev/LocalDevLogger.js +22 -0
  74. package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
  75. package/lib/projects/localDev/LocalDevProcess.js +90 -19
  76. package/lib/projects/localDev/LocalDevState.d.ts +9 -8
  77. package/lib/projects/localDev/LocalDevState.js +18 -17
  78. package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +2 -0
  79. package/lib/projects/localDev/LocalDevWebsocketServer.js +55 -23
  80. package/lib/projects/localDev/helpers/project.d.ts +2 -2
  81. package/lib/projects/localDev/helpers/project.js +10 -7
  82. package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +4 -0
  83. package/lib/projects/localDev/localDevWebsocketServerUtils.js +10 -0
  84. package/lib/projects/pollProjectBuildAndDeploy.js +4 -4
  85. package/lib/prompts/projectAddPrompt.js +2 -1
  86. package/lib/prompts/promptUtils.js +3 -0
  87. package/lib/prompts/selectProjectTemplatePrompt.js +2 -0
  88. package/lib/theme/__tests__/migrate.test.d.ts +1 -0
  89. package/lib/theme/__tests__/migrate.test.js +233 -0
  90. package/lib/theme/migrate.d.ts +13 -0
  91. package/lib/theme/migrate.js +90 -0
  92. package/lib/ui/SpinniesManager.js +105 -8
  93. package/lib/usageTracking.js +2 -2
  94. package/mcp-server/tools/cms/HsCreateFunctionTool.js +1 -1
  95. package/mcp-server/tools/cms/HsCreateModuleTool.js +1 -1
  96. package/mcp-server/tools/cms/HsCreateTemplateTool.js +1 -1
  97. package/mcp-server/tools/cms/HsFunctionLogsTool.js +2 -2
  98. package/mcp-server/tools/cms/HsListFunctionsTool.js +1 -1
  99. package/mcp-server/tools/cms/HsListTool.js +1 -1
  100. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -1
  101. package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +1 -1
  102. package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +1 -1
  103. package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +2 -2
  104. package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +1 -1
  105. package/mcp-server/tools/cms/__tests__/HsListTool.test.js +1 -1
  106. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -3
  107. package/mcp-server/tools/project/AddFeatureToProjectTool.js +3 -3
  108. package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
  109. package/mcp-server/tools/project/CreateProjectTool.js +5 -5
  110. package/mcp-server/tools/project/DeployProjectTool.js +1 -1
  111. package/mcp-server/tools/project/DocFetchTool.js +2 -2
  112. package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
  113. package/mcp-server/tools/project/DocsSearchTool.js +7 -7
  114. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
  115. package/mcp-server/tools/project/GetConfigValuesTool.js +11 -5
  116. package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
  117. package/mcp-server/tools/project/UploadProjectTools.js +2 -2
  118. package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
  119. package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +1 -1
  120. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
  121. package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +1 -1
  122. package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +2 -2
  123. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +14 -12
  124. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +9 -8
  125. package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -1
  126. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -1
  127. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -1
  128. package/mcp-server/tools/project/constants.d.ts +1 -1
  129. package/mcp-server/tools/project/constants.js +9 -3
  130. package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
  131. package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
  132. package/mcp-server/utils/cliConfig.d.ts +1 -0
  133. package/mcp-server/utils/cliConfig.js +12 -0
  134. package/package.json +4 -9
  135. package/types/LocalDev.d.ts +19 -3
  136. package/ui/components/HorizontalSelectPrompt.js +1 -1
  137. package/ui/index.js +1 -1
  138. package/commands/getStartedV2.d.ts +0 -9
  139. package/commands/getStartedV2.js +0 -39
  140. package/ui/components/Ascii.d.ts +0 -10
  141. package/ui/components/Ascii.js +0 -11
  142. package/ui/views/GetStarted.d.ts +0 -7
  143. package/ui/views/GetStarted.js +0 -157
@@ -7,7 +7,7 @@ import { writeProjectConfig, getProjectConfig, } from '../../lib/projects/config
7
7
  import { EMPTY_PROJECT_TEMPLATE_NAME } from '../../lib/projects/create/legacy.js';
8
8
  import { generateComponentPaths } from '../../lib/projects/create/v3.js';
9
9
  import { PROJECT_WITH_APP, EMPTY_PROJECT } from '../../lib/constants.js';
10
- import { uiBetaTag, uiFeatureHighlight } from '../../lib/ui/index.js';
10
+ import { uiFeatureHighlight } from '../../lib/ui/index.js';
11
11
  import { debugError, logError } from '../../lib/errorHandlers/index.js';
12
12
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
13
13
  import { PROJECT_CONFIG_FILE, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, marketplaceDistribution, privateDistribution, oAuth, staticAuth, DEFAULT_PROJECT_TEMPLATE_BRANCH, } from '../../lib/constants.js';
@@ -19,7 +19,7 @@ import { handleProjectCreationFlow, } from '../../lib/projects/create/index.js';
19
19
  import { getProjectMetadata, } from '@hubspot/project-parsing-lib/src/lib/project.js';
20
20
  import { updateHsMetaFilesWithAutoGeneratedFields } from '../../lib/projects/components.js';
21
21
  const command = ['create', 'init'];
22
- const describe = uiBetaTag(commands.project.create.describe, false);
22
+ const describe = commands.project.create.describe;
23
23
  const { v2023_2, v2025_1, v2025_2 } = PLATFORM_VERSIONS;
24
24
  async function handler(args) {
25
25
  const { derivedAccountId, platformVersion, templateSource } = args;
@@ -112,7 +112,6 @@ function projectCreateBuilder(yargs) {
112
112
  type: 'string',
113
113
  },
114
114
  template: {
115
- // TODO: When we release 2025.2 scaffolding, we need to point out this is only valid for 2025.1 prior
116
115
  describe: commands.project.create.options.template.describe,
117
116
  type: 'string',
118
117
  },
@@ -122,32 +121,27 @@ function projectCreateBuilder(yargs) {
122
121
  },
123
122
  'platform-version': {
124
123
  describe: commands.project.create.options.platformVersion.describe,
125
- hidden: true,
126
124
  type: 'string',
127
125
  choices: [v2023_2, v2025_1, v2025_2],
128
- default: v2023_2,
126
+ default: v2025_2,
129
127
  },
130
128
  'project-base': {
131
129
  describe: commands.project.create.options.projectBase.describe,
132
- hidden: true,
133
130
  type: 'string',
134
131
  choices: [EMPTY_PROJECT, PROJECT_WITH_APP],
135
132
  },
136
133
  distribution: {
137
134
  describe: commands.project.create.options.distribution.describe,
138
- hidden: true,
139
135
  type: 'string',
140
136
  choices: [privateDistribution, marketplaceDistribution],
141
137
  },
142
138
  auth: {
143
139
  describe: commands.project.create.options.auth.describe,
144
- hidden: true,
145
140
  type: 'string',
146
141
  choices: [oAuth, staticAuth],
147
142
  },
148
143
  features: {
149
144
  describe: commands.project.create.options.features.describe,
150
- hidden: true,
151
145
  type: 'array',
152
146
  },
153
147
  });
@@ -7,7 +7,7 @@ import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
7
7
  import { getProjectConfig } from '../../lib/projects/config.js';
8
8
  import { projectNamePrompt } from '../../lib/prompts/projectNamePrompt.js';
9
9
  import { promptUser } from '../../lib/prompts/promptUtils.js';
10
- import { uiBetaTag, uiLine } from '../../lib/ui/index.js';
10
+ import { uiLine } from '../../lib/ui/index.js';
11
11
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
12
12
  import { uiLogger } from '../../lib/ui/logger.js';
13
13
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
@@ -16,7 +16,7 @@ import { PROJECT_DEPLOY_TEXT } from '../../lib/constants.js';
16
16
  import { commands } from '../../lang/en.js';
17
17
  import { handleProjectDeploy, validateBuildIdForDeploy, logDeployErrors, } from '../../lib/projects/deploy.js';
18
18
  const command = 'deploy';
19
- const describe = uiBetaTag(commands.project.deploy.describe, false);
19
+ const describe = commands.project.deploy.describe;
20
20
  async function handler(args) {
21
21
  const { derivedAccountId, project: projectOption, buildId: buildIdOption, force: forceOption, deployLatestBuild: deployLatestBuildOption, json: formatOutputAsJson, } = args;
22
22
  const accountConfig = getAccountConfig(derivedAccountId);
@@ -2,7 +2,7 @@ import { trackCommandUsage } from '../../../lib/usageTracking.js';
2
2
  import { getAccountId } from '@hubspot/local-dev-lib/config';
3
3
  import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
4
4
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
5
- import { uiBetaTag, uiLine } from '../../../lib/ui/index.js';
5
+ import { uiLine } from '../../../lib/ui/index.js';
6
6
  import { deprecatedProjectDevFlow } from './deprecatedFlow.js';
7
7
  import { unifiedProjectDevFlow } from './unifiedFlow.js';
8
8
  import { useV3Api } from '../../../lib/projects/platformVersion.js';
@@ -10,8 +10,9 @@ import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
10
10
  import { loadProfile, exitIfUsingProfiles, } from '../../../lib/projectProfiles.js';
11
11
  import { commands } from '../../../lang/en.js';
12
12
  import { uiLogger } from '../../../lib/ui/logger.js';
13
+ import { logger } from '@hubspot/local-dev-lib/logger';
13
14
  const command = 'dev';
14
- const describe = uiBetaTag(commands.project.dev.describe, false);
15
+ const describe = commands.project.dev.describe;
15
16
  function validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV3) {
16
17
  // Legacy projects do not support targetTestingAccount and targetProjectAccount
17
18
  if (testingAccount && projectAccount && !useV3) {
@@ -33,7 +34,7 @@ async function handler(args) {
33
34
  process.exit(EXIT_CODES.ERROR);
34
35
  }
35
36
  validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV3);
36
- uiBetaTag(commands.project.dev.logs.betaMessage);
37
+ logger.log(commands.project.dev.logs.header);
37
38
  if (useV3) {
38
39
  uiLogger.log(commands.project.dev.logs.learnMoreMessageV3);
39
40
  }
@@ -9,7 +9,7 @@ import { logError } from '../../../lib/errorHandlers/index.js';
9
9
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
10
10
  import { ensureProjectExists } from '../../../lib/projects/ensureProjectExists.js';
11
11
  import { createInitialBuildForNewProject, createNewProjectForLocalDev, compareLocalProjectToDeployed, } from '../../../lib/projects/localDev/helpers/project.js';
12
- import { useExistingDevTestAccount, createDeveloperTestAccountForLocalDev, selectAccountTypePrompt, } from '../../../lib/projects/localDev/helpers/account.js';
12
+ import { useExistingDevTestAccount, createDeveloperTestAccountForLocalDev, selectAccountTypePrompt, createSandboxForLocalDev, } from '../../../lib/projects/localDev/helpers/account.js';
13
13
  import { selectDeveloperTestTargetAccountPrompt, selectSandboxTargetAccountPrompt, } from '../../../lib/prompts/projectDevTargetAccountPrompt.js';
14
14
  import SpinniesManager from '../../../lib/ui/SpinniesManager.js';
15
15
  import LocalDevProcess from '../../../lib/projects/localDev/LocalDevProcess.js';
@@ -93,6 +93,9 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
93
93
  const sandboxAccountPromptResponse = await selectSandboxTargetAccountPrompt(accounts, targetProjectAccountConfig);
94
94
  targetTestingAccountId =
95
95
  sandboxAccountPromptResponse.targetAccountId || undefined;
96
+ if (sandboxAccountPromptResponse.createNestedAccount) {
97
+ targetTestingAccountId = await createSandboxForLocalDev(targetProjectAccountId, targetProjectAccountConfig, env);
98
+ }
96
99
  }
97
100
  else {
98
101
  targetTestingAccountId = targetProjectAccountId;
@@ -109,7 +112,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
109
112
  let project = uploadedProject;
110
113
  SpinniesManager.init();
111
114
  if (projectExists && project) {
112
- await compareLocalProjectToDeployed(projectConfig, targetProjectAccountId, project.deployedBuild?.buildId, projectNodes);
115
+ await compareLocalProjectToDeployed(projectConfig, targetProjectAccountId, project.deployedBuild?.buildId, projectNodes, args.profile);
113
116
  }
114
117
  else {
115
118
  project = await createNewProjectForLocalDev(projectConfig, targetProjectAccountId, false, false);
@@ -125,8 +128,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
125
128
  targetTestingAccountId: targetTestingAccountId,
126
129
  projectConfig,
127
130
  projectDir,
128
- projectName: project.name,
129
- projectId: project.id,
131
+ projectData: project,
130
132
  env,
131
133
  });
132
134
  await localDevProcess.start();
@@ -7,12 +7,11 @@ import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
7
7
  import { getProjectConfig } from '../../lib/projects/config.js';
8
8
  import { downloadProjectPrompt } from '../../lib/prompts/downloadProjectPrompt.js';
9
9
  import { i18n } from '../../lib/lang.js';
10
- import { uiBetaTag } from '../../lib/ui/index.js';
11
10
  import { trackCommandUsage } from '../../lib/usageTracking.js';
12
11
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
13
12
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
14
13
  const command = 'download';
15
- const describe = uiBetaTag(i18n(`commands.project.subcommands.download.describe`), false);
14
+ const describe = i18n(`commands.project.subcommands.download.describe`);
16
15
  async function handler(args) {
17
16
  const { projectConfig } = await getProjectConfig();
18
17
  if (projectConfig) {
@@ -6,11 +6,10 @@ import { promptUser } from '../../lib/prompts/promptUtils.js';
6
6
  import path from 'path';
7
7
  import { i18n } from '../../lib/lang.js';
8
8
  import { trackCommandUsage } from '../../lib/usageTracking.js';
9
- import { uiBetaTag } from '../../lib/ui/index.js';
10
9
  import { logError } from '../../lib/errorHandlers/index.js';
11
10
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
12
11
  const command = 'install-deps [packages..]';
13
- const describe = uiBetaTag(i18n(`commands.project.subcommands.installDeps.help.describe`), false);
12
+ const describe = i18n(`commands.project.subcommands.installDeps.help.describe`);
14
13
  async function handler(args) {
15
14
  const { derivedAccountId, packages } = args;
16
15
  try {
@@ -2,7 +2,7 @@ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
2
2
  import { logger } from '@hubspot/local-dev-lib/logger';
3
3
  import { fetchProject, fetchProjectBuilds, } from '@hubspot/local-dev-lib/api/projects';
4
4
  import { getTableContents, getTableHeader } from '../../lib/ui/table.js';
5
- import { uiBetaTag, uiLink } from '../../lib/ui/index.js';
5
+ import { uiLink } from '../../lib/ui/index.js';
6
6
  import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/config.js';
7
7
  import { getProjectDetailUrl } from '../../lib/projects/urls.js';
8
8
  import moment from 'moment';
@@ -14,7 +14,7 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
14
14
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
15
15
  import { commands } from '../../lang/en.js';
16
16
  const command = 'list-builds';
17
- const describe = uiBetaTag(i18n(`commands.project.subcommands.listBuilds.describe`), false);
17
+ const describe = i18n(`commands.project.subcommands.listBuilds.describe`);
18
18
  async function fetchAndDisplayBuilds(accountId, project, options) {
19
19
  const { data: { results, paging }, } = await fetchProjectBuilds(accountId, project.name, options);
20
20
  const currentDeploy = project.deployedBuildId;
@@ -5,7 +5,7 @@ import { logger } from '@hubspot/local-dev-lib/logger';
5
5
  import { trackCommandUsage } from '../../lib/usageTracking.js';
6
6
  import { getTableContents, getTableHeader } from '../../lib/ui/table.js';
7
7
  import { logError } from '../../lib/errorHandlers/index.js';
8
- import { uiBetaTag, uiLine, uiLink } from '../../lib/ui/index.js';
8
+ import { uiLine, uiLink } from '../../lib/ui/index.js';
9
9
  import { projectLogsPrompt } from '../../lib/prompts/projectsLogsPrompt.js';
10
10
  import { i18n } from '../../lib/lang.js';
11
11
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
@@ -43,7 +43,7 @@ function logPreamble() {
43
43
  uiLine();
44
44
  }
45
45
  const command = 'logs';
46
- const describe = uiBetaTag(i18n(`commands.project.subcommands.logs.describe`), false);
46
+ const describe = i18n(`commands.project.subcommands.logs.describe`);
47
47
  async function handler(args) {
48
48
  const { derivedAccountId } = args;
49
49
  trackCommandUsage('project-logs', undefined, derivedAccountId);
@@ -10,9 +10,12 @@ import { uiLogger } from '../../lib/ui/logger.js';
10
10
  import { logInBox } from '../../lib/ui/boxen.js';
11
11
  import { renderInline } from '../../ui/index.js';
12
12
  import { getWarningBox } from '../../ui/components/StatusMessageBoxes.js';
13
+ import { getHasMigratableThemes, migrateThemes2025_2, } from '../../lib/theme/migrate.js';
14
+ import { hasFeature } from '../../lib/hasFeature.js';
15
+ import { FEATURES } from '../../lib/constants.js';
13
16
  const { v2025_2 } = PLATFORM_VERSIONS;
14
17
  const command = 'migrate';
15
- const describe = undefined; // commands.project.migrate.describe
18
+ const describe = commands.project.migrate.describe;
16
19
  async function handler(args) {
17
20
  const { platformVersion, unstable } = args;
18
21
  const projectConfig = await getProjectConfig();
@@ -21,7 +24,7 @@ async function handler(args) {
21
24
  return process.exit(EXIT_CODES.ERROR);
22
25
  }
23
26
  if (projectConfig?.projectConfig) {
24
- if (!process.env.ENABLE_INK) {
27
+ if (!process.env.HUBSPOT_ENABLE_INK) {
25
28
  await logInBox({
26
29
  contents: lib.migrate.projectMigrationWarning,
27
30
  options: { title: lib.migrate.projectMigrationWarningTitle },
@@ -36,13 +39,29 @@ async function handler(args) {
36
39
  }
37
40
  const { derivedAccountId } = args;
38
41
  try {
39
- await migrateApp2025_2(derivedAccountId, {
40
- ...args,
41
- name: projectConfig?.projectConfig?.name,
42
- platformVersion: unstable
43
- ? PLATFORM_VERSIONS.unstable
44
- : platformVersion,
45
- }, projectConfig);
42
+ const { hasMigratableThemes, migratableThemesCount } = await getHasMigratableThemes(projectConfig);
43
+ if (hasMigratableThemes) {
44
+ const hasThemeMigrationAccess = await hasFeature(derivedAccountId, FEATURES.THEME_MIGRATION_2025_2);
45
+ if (!hasThemeMigrationAccess) {
46
+ uiLogger.error(commands.project.migrate.errors.noThemeMigrationAccess(derivedAccountId));
47
+ return process.exit(EXIT_CODES.ERROR);
48
+ }
49
+ await migrateThemes2025_2(derivedAccountId, {
50
+ ...args,
51
+ platformVersion: unstable
52
+ ? PLATFORM_VERSIONS.unstable
53
+ : platformVersion,
54
+ }, migratableThemesCount, projectConfig);
55
+ }
56
+ else {
57
+ await migrateApp2025_2(derivedAccountId, {
58
+ ...args,
59
+ name: projectConfig?.projectConfig?.name,
60
+ platformVersion: unstable
61
+ ? PLATFORM_VERSIONS.unstable
62
+ : platformVersion,
63
+ }, projectConfig);
64
+ }
46
65
  }
47
66
  catch (error) {
48
67
  logError(error);
@@ -56,7 +75,6 @@ function projectMigrateBuilder(yargs) {
56
75
  type: 'string',
57
76
  choices: [v2025_2],
58
77
  default: v2025_2,
59
- hidden: true,
60
78
  })
61
79
  .option('unstable', {
62
80
  type: 'boolean',
@@ -34,8 +34,7 @@ function projectMigrateAppBuilder(yargs) {
34
34
  'platform-version': {
35
35
  type: 'string',
36
36
  choices: [v2023_2, v2025_2],
37
- hidden: true,
38
- default: v2023_2,
37
+ default: v2025_2,
39
38
  },
40
39
  });
41
40
  yargs.example([
@@ -6,11 +6,10 @@ import { getProjectConfig } from '../../lib/projects/config.js';
6
6
  import { ensureProjectExists } from '../../lib/projects/ensureProjectExists.js';
7
7
  import { getProjectDetailUrl } from '../../lib/projects/urls.js';
8
8
  import { projectNamePrompt } from '../../lib/prompts/projectNamePrompt.js';
9
- import { uiBetaTag } from '../../lib/ui/index.js';
10
9
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
11
10
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
12
11
  const command = 'open';
13
- const describe = uiBetaTag(i18n(`commands.project.subcommands.open.describe`), false);
12
+ const describe = i18n(`commands.project.subcommands.open.describe`);
14
13
  async function handler(args) {
15
14
  const { project, derivedAccountId } = args;
16
15
  trackCommandUsage('project-open', undefined, derivedAccountId);
@@ -5,7 +5,7 @@ import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountId
5
5
  import { getAllHsProfiles, getHsProfileFilename, loadHsProfileFile, } from '@hubspot/project-parsing-lib';
6
6
  import { trackCommandUsage } from '../../../lib/usageTracking.js';
7
7
  import { getProjectConfig } from '../../../lib/projects/config.js';
8
- import { uiBetaTag, uiAccountDescription } from '../../../lib/ui/index.js';
8
+ import { uiAccountDescription } from '../../../lib/ui/index.js';
9
9
  import { uiLogger } from '../../../lib/ui/logger.js';
10
10
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
11
11
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
@@ -14,8 +14,8 @@ import { promptUser, listPrompt, confirmPrompt, } from '../../../lib/prompts/pro
14
14
  import { fileExists } from '../../../lib/validation.js';
15
15
  import { debugError } from '../../../lib/errorHandlers/index.js';
16
16
  const command = 'add [name]';
17
- const describe = uiBetaTag(commands.project.profile.add.describe, false);
18
- const verboseDescribe = uiBetaTag(commands.project.profile.add.verboseDescribe, false);
17
+ const describe = commands.project.profile.add.describe;
18
+ const verboseDescribe = commands.project.profile.add.verboseDescribe;
19
19
  async function selectProfileToCopyVariablesFrom(existingProfiles) {
20
20
  let profileToCopyVariablesFrom;
21
21
  if (existingProfiles.length == 1) {
@@ -5,7 +5,6 @@ import { fetchProject, deleteProject, } from '@hubspot/local-dev-lib/api/project
5
5
  import { getAccountConfig } from '@hubspot/local-dev-lib/config';
6
6
  import { trackCommandUsage } from '../../../lib/usageTracking.js';
7
7
  import { getProjectConfig } from '../../../lib/projects/config.js';
8
- import { uiBetaTag } from '../../../lib/ui/index.js';
9
8
  import { uiLogger } from '../../../lib/ui/logger.js';
10
9
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
11
10
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
@@ -15,7 +14,7 @@ import { fileExists } from '../../../lib/validation.js';
15
14
  import { debugError } from '../../../lib/errorHandlers/index.js';
16
15
  import { isDeveloperTestAccount, isSandbox, } from '../../../lib/accountTypes.js';
17
16
  const command = 'delete [name]';
18
- const describe = uiBetaTag(commands.project.profile.delete.describe, false);
17
+ const describe = commands.project.profile.delete.describe;
19
18
  async function handler(args) {
20
19
  const { derivedAccountId } = args;
21
20
  trackCommandUsage('project-profile-delete', undefined, derivedAccountId);
@@ -1,11 +1,10 @@
1
- import { uiBetaTag } from '../../lib/ui/index.js';
2
1
  import add from './profile/add.js';
3
2
  import deleteProfile from './profile/delete.js';
4
3
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
5
4
  import { commands } from '../../lang/en.js';
6
5
  const command = ['profile', 'profiles'];
7
- const describe = undefined; // uiBetaTag(commands.project.profile.describe, false);
8
- const verboseDescribe = uiBetaTag(commands.project.profile.verboseDescribe, false);
6
+ const describe = commands.project.profile.describe;
7
+ const verboseDescribe = commands.project.profile.verboseDescribe;
9
8
  function projectProfileBuilder(yargs) {
10
9
  yargs.command(add).command(deleteProfile).demandCommand(1, '');
11
10
  return yargs;
@@ -3,7 +3,7 @@ import { logger } from '@hubspot/local-dev-lib/logger';
3
3
  import { getAccountConfig } from '@hubspot/local-dev-lib/config';
4
4
  import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
5
5
  import { useV3Api } from '../../lib/projects/platformVersion.js';
6
- import { uiBetaTag, uiCommandReference } from '../../lib/ui/index.js';
6
+ import { uiCommandReference } from '../../lib/ui/index.js';
7
7
  import { trackCommandUsage } from '../../lib/usageTracking.js';
8
8
  import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/config.js';
9
9
  import { logFeedbackMessage } from '../../lib/projects/ui.js';
@@ -17,7 +17,7 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
17
17
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
18
18
  import { uiLogger } from '../../lib/ui/logger.js';
19
19
  const command = 'upload';
20
- const describe = uiBetaTag(i18n(`commands.project.subcommands.upload.describe`), false);
20
+ const describe = i18n(`commands.project.subcommands.upload.describe`);
21
21
  async function handler(args) {
22
22
  const { forceCreate, message, derivedAccountId, skipValidation, formatOutputAsJson, profile, } = args;
23
23
  const jsonOutput = {};
@@ -11,7 +11,7 @@ import { commands } from '../../lang/en.js';
11
11
  import { loadAndValidateProfile } from '../../lib/projectProfiles.js';
12
12
  import { logError } from '../../lib/errorHandlers/index.js';
13
13
  const command = 'validate';
14
- const describe = undefined;
14
+ const describe = commands.project.validate.describe;
15
15
  async function handler(args) {
16
16
  const { derivedAccountId, profile } = args;
17
17
  const { projectConfig, projectDir } = await getProjectConfig();
@@ -1,7 +1,7 @@
1
1
  import { cancelStagedBuild, fetchProjectBuilds, } from '@hubspot/local-dev-lib/api/projects';
2
2
  import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
3
3
  import { useV3Api } from '../../lib/projects/platformVersion.js';
4
- import { uiCommandReference, uiLink, uiBetaTag } from '../../lib/ui/index.js';
4
+ import { uiCommandReference, uiLink } from '../../lib/ui/index.js';
5
5
  import { i18n } from '../../lib/lang.js';
6
6
  import { createWatcher } from '../../lib/projects/watch.js';
7
7
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
@@ -16,7 +16,7 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
16
16
  import { handleKeypress, handleExit } from '../../lib/process.js';
17
17
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
18
18
  const command = 'watch';
19
- const describe = uiBetaTag(i18n(`commands.project.subcommands.watch.describe`), false);
19
+ const describe = i18n(`commands.project.subcommands.watch.describe`);
20
20
  async function handleBuildStatus(accountId, projectName, buildId) {
21
21
  const { isAutoDeployEnabled, deployStatusTaskLocator } = await pollBuildStatus(accountId, projectName, buildId, null);
22
22
  if (isAutoDeployEnabled && deployStatusTaskLocator) {
@@ -1,5 +1,4 @@
1
1
  import { i18n } from '../lib/lang.js';
2
- import { uiBetaTag } from '../lib/ui/index.js';
3
2
  import deploy from './project/deploy.js';
4
3
  import create from './project/create.js';
5
4
  import upload from './project/upload.js';
@@ -18,7 +17,7 @@ import profile from './project/profile.js';
18
17
  import projectValidate from './project/validate.js';
19
18
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
20
19
  const command = ['project', 'projects'];
21
- const describe = uiBetaTag(i18n(`commands.project.describe`), false);
20
+ const describe = i18n(`commands.project.describe`);
22
21
  function projectBuilder(yargs) {
23
22
  yargs
24
23
  .command(create)
@@ -121,7 +121,7 @@ async function handler(args) {
121
121
  const newDefaultAccount = await selectAccountFromConfig();
122
122
  updateDefaultAccount(newDefaultAccount);
123
123
  }
124
- else {
124
+ else if (isDefaultAccount && force) {
125
125
  // If force is specified, skip prompt and set the parent account id as the default account
126
126
  updateDefaultAccount(parentAccountId);
127
127
  }
@@ -1,6 +1,6 @@
1
1
  import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, YargsCommandModule } from '../../types/Yargs.js';
2
2
  export declare const command = "import-data";
3
- export declare const describe: undefined;
3
+ export declare const describe: "Import data into the CRM";
4
4
  type CrmImportDataArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
5
5
  filePath: string | undefined;
6
6
  skipConfirm: boolean | undefined;
@@ -8,7 +8,7 @@ import { handleImportData, handleTargetTestAccountSelectionFlow, } from '../../l
8
8
  import { confirmImportDataPrompt } from '../../lib/prompts/confirmImportDataPrompt.js';
9
9
  import { commands } from '../../lang/en.js';
10
10
  export const command = 'import-data';
11
- export const describe = undefined; // commands.testAccount.subcommands.importData.describe;
11
+ export const describe = commands.testAccount.subcommands.importData.describe;
12
12
  async function handler(args) {
13
13
  const { derivedAccountId, userProvidedAccount, filePath: providedFilePath, skipConfirm, } = args;
14
14
  trackCommandUsage('crm-import-data', {}, derivedAccountId);
@@ -5,7 +5,7 @@ import deleteTestAccountCommand from './testAccount/delete.js';
5
5
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
6
6
  import { commands } from '../lang/en.js';
7
7
  const command = ['test-account', 'test-accounts'];
8
- const describe = undefined; //commands.testAccount.describe;
8
+ const describe = commands.testAccount.describe;
9
9
  function testAccountBuilder(yargs) {
10
10
  yargs
11
11
  .command(createTestAccountCommand)
package/lang/en.d.ts CHANGED
@@ -10,6 +10,7 @@ export declare const commands: {
10
10
  };
11
11
  };
12
12
  readonly getStarted: {
13
+ readonly describe: "A step-by-step command to get you started with a HubSpot project.";
13
14
  readonly options: {
14
15
  readonly dest: {
15
16
  readonly describe: "Directory where the project should be created";
@@ -859,8 +860,9 @@ Global configuration replaces hubspot.config.yml, and you will be prompted to mi
859
860
  readonly tailLogs: (functionPath: string, accountId: string) => string;
860
861
  };
861
862
  readonly mcp: {
862
- readonly describe: "Commands for managing HubSpot MCP servers";
863
+ readonly describe: "Commands for managing HubSpot MCP servers.";
863
864
  readonly setup: {
865
+ readonly describe: "Setup the HubSpot development MCP servers.";
864
866
  readonly installingDocSearch: "Adding the docs-search mcp server";
865
867
  readonly claudeCode: "Claude Code";
866
868
  readonly cursor: "Cursor";
@@ -872,6 +874,7 @@ Global configuration replaces hubspot.config.yml, and you will be prompted to mi
872
874
  };
873
875
  readonly success: (derivedTargets: string[]) => string;
874
876
  readonly errors: {
877
+ readonly needsMcpAccess: (accountId?: number) => string;
875
878
  readonly needsNode20: "This feature requires node >=20";
876
879
  readonly errorParsingJsonFIle: (filename: string, errorMessage: string) => string;
877
880
  };
@@ -1008,7 +1011,7 @@ Profiles enable you to reference variables in your component configuration files
1008
1011
  readonly dev: {
1009
1012
  readonly describe: "Start local dev for the current project.";
1010
1013
  readonly logs: {
1011
- readonly betaMessage: "HubSpot projects local development";
1014
+ readonly header: "HubSpot projects local development";
1012
1015
  readonly placeholderAccountSelection: "Using default account as target account (for now)";
1013
1016
  readonly accountTypeInformation: "Testing in a developer test account is strongly recommended, but you can use a sandbox account if your plan allows you to create one.";
1014
1017
  readonly learnMoreMessageV3: `Learn more about ${string} | ${string}`;
@@ -1070,7 +1073,7 @@ ${string}`;
1070
1073
  readonly describe: "Project name (cannot be changed)";
1071
1074
  };
1072
1075
  readonly template: {
1073
- readonly describe: "The starting template";
1076
+ readonly describe: "The starting template. Only applies when platform version is less than 2025.2.";
1074
1077
  };
1075
1078
  readonly templateSource: {
1076
1079
  readonly describe: "Path to custom GitHub repository from which to create project template";
@@ -1136,6 +1139,7 @@ ${string}`;
1136
1139
  readonly describe: "Migrate an existing project to the new version of the projects framework.";
1137
1140
  readonly errors: {
1138
1141
  readonly noProjectConfig: (command: string) => string;
1142
+ readonly noThemeMigrationAccess: (accountId?: number) => string;
1139
1143
  };
1140
1144
  readonly examples: {
1141
1145
  readonly default: "Migrate an existing project to the new version of the projects framework.";
@@ -2591,8 +2595,13 @@ export declare const lib: {
2591
2595
  readonly LocalDevProcess: {
2592
2596
  readonly projectConfigMismatch: `Unable to upload project. The project config has been modified since starting ${string}.`;
2593
2597
  readonly uploadInitiated: "Project upload initiated from Local Dev UI.";
2598
+ readonly deployInitiated: "Project deploy initiated from Local Dev UI.";
2594
2599
  readonly uploadFailed: "Project upload failed. To proceed with local development, fix any necessary errors, then re-upload your project.";
2600
+ readonly deployFailed: "Project deploy failed. To proceed with local development, fix any necessary errors, then re-deploy your project.";
2595
2601
  readonly uploadSuccess: "Project upload completed successfully. Resuming local dev...";
2602
+ readonly uploadSuccessAutoDeployDisabled: "Project upload completed successfully, but auto-deploy is disabled for this project. Deploy your latest build to proceed with local development.";
2603
+ readonly deploySuccess: "Project deploy completed successfully. Resuming local dev...";
2604
+ readonly noBuildToDeploy: "Error deploying project. No build was found to deploy.";
2596
2605
  };
2597
2606
  readonly localDevHelpers: {
2598
2607
  readonly project: {
@@ -2601,7 +2610,7 @@ export declare const lib: {
2601
2610
  readonly checking: "Checking if your deployed build is up to date...";
2602
2611
  readonly upToDate: "Deployed build is up to date.";
2603
2612
  readonly notUpToDate: "Your project contains undeployed local changes.";
2604
- readonly notUpToDateExplanation: `Run ${string} to upload these changes to HubSpot, then re-run ${string} to continue local development.`;
2613
+ readonly notUpToDateExplanation: (profile?: string) => string;
2605
2614
  };
2606
2615
  readonly createNewProjectForLocalDev: {
2607
2616
  readonly projectMustExistExplanation: (projectName: string, accountId: number) => string;
@@ -3111,6 +3120,7 @@ Run ${string} to upgrade to version ${string}`;
3111
3120
  };
3112
3121
  readonly projectAddPrompt: {
3113
3122
  readonly selectType: "[--type] Select an app feature to add: ";
3123
+ readonly selectFeatures: "[--features] Select an app feature to add: ";
3114
3124
  readonly enterName: "[--name] Give your component a name: ";
3115
3125
  readonly errors: {
3116
3126
  readonly nameRequired: "A component name is required";
@@ -3388,6 +3398,7 @@ Run ${string} to upgrade to version ${string}`;
3388
3398
  readonly sourceContentsMoved: (newLocation: string) => string;
3389
3399
  readonly projectMigrationWarningTitle: "Important: Migrating to platformVersion 2025.2 is irreversible";
3390
3400
  readonly projectMigrationWarning: string;
3401
+ readonly exitWithoutMigrating: "Exiting without migrating";
3391
3402
  readonly success: {
3392
3403
  readonly downloadedProject: (projectName: string, projectDest: string) => string;
3393
3404
  readonly themesMigrationSuccess: (platformVersion: string) => string;