@hubspot/cli 7.6.0-beta.9 → 7.6.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 (217) hide show
  1. package/api/__tests__/migrate.test.js +5 -5
  2. package/api/migrate.d.ts +4 -5
  3. package/api/migrate.js +2 -10
  4. package/commands/__tests__/getStarted.test.js +2 -2
  5. package/commands/__tests__/mcp.test.js +1 -1
  6. package/commands/__tests__/project.test.js +0 -3
  7. package/commands/app/__tests__/migrate.test.js +1 -1
  8. package/commands/app/migrate.js +4 -5
  9. package/commands/app/secret/add.js +2 -1
  10. package/commands/app/secret/delete.js +2 -1
  11. package/commands/app/secret/list.js +2 -1
  12. package/commands/app/secret/update.js +2 -1
  13. package/commands/app/secret.js +2 -1
  14. package/commands/app.js +2 -2
  15. package/commands/config/set.js +0 -1
  16. package/commands/getStarted.d.ts +0 -2
  17. package/commands/getStarted.js +72 -24
  18. package/commands/mcp/__tests__/setup.test.js +2 -2
  19. package/commands/mcp/setup.d.ts +0 -1
  20. package/commands/mcp/setup.js +14 -13
  21. package/commands/mcp.js +3 -3
  22. package/commands/project/__tests__/add.test.js +64 -0
  23. package/commands/project/__tests__/create.test.js +57 -0
  24. package/commands/project/__tests__/deploy.test.js +3 -5
  25. package/commands/project/__tests__/devUnifiedFlow.test.js +20 -11
  26. package/commands/project/__tests__/logs.test.js +0 -3
  27. package/commands/project/__tests__/migrate.test.js +1 -2
  28. package/commands/project/__tests__/migrateApp.test.js +1 -2
  29. package/commands/project/__tests__/profile.test.js +1 -1
  30. package/commands/project/add.d.ts +1 -1
  31. package/commands/project/add.js +4 -10
  32. package/commands/project/create.js +10 -11
  33. package/commands/project/deploy.js +11 -63
  34. package/commands/project/dev/deprecatedFlow.js +2 -1
  35. package/commands/project/dev/index.js +36 -15
  36. package/commands/project/dev/unifiedFlow.js +14 -10
  37. package/commands/project/download.js +1 -2
  38. package/commands/project/installDeps.js +1 -2
  39. package/commands/project/listBuilds.js +2 -2
  40. package/commands/project/logs.js +2 -2
  41. package/commands/project/migrate.js +41 -13
  42. package/commands/project/migrateApp.js +1 -2
  43. package/commands/project/open.js +1 -2
  44. package/commands/project/profile/add.js +3 -3
  45. package/commands/project/profile/delete.js +1 -2
  46. package/commands/project/profile.js +2 -3
  47. package/commands/project/upload.js +4 -4
  48. package/commands/project/validate.js +2 -2
  49. package/commands/project/watch.js +4 -4
  50. package/commands/project.js +1 -2
  51. package/commands/sandbox/delete.js +1 -1
  52. package/commands/testAccount/importData.d.ts +1 -1
  53. package/commands/testAccount/importData.js +1 -1
  54. package/commands/testAccount.js +1 -1
  55. package/lang/en.d.ts +104 -56
  56. package/lang/en.js +118 -68
  57. package/lang/en.lyaml +12 -12
  58. package/lib/__tests__/hasFeature.test.js +145 -7
  59. package/lib/__tests__/importData.test.js +1 -1
  60. package/lib/app/__tests__/migrate.test.js +26 -31
  61. package/lib/app/migrate.d.ts +3 -10
  62. package/lib/app/migrate.js +14 -25
  63. package/lib/constants.d.ts +9 -0
  64. package/lib/constants.js +9 -0
  65. package/lib/errorHandlers/index.d.ts +4 -0
  66. package/lib/errorHandlers/index.js +1 -1
  67. package/lib/hasFeature.js +6 -0
  68. package/lib/importData.js +1 -1
  69. package/lib/links.d.ts +1 -0
  70. package/lib/links.js +10 -3
  71. package/lib/mcp/setup.d.ts +0 -2
  72. package/lib/mcp/setup.js +4 -29
  73. package/lib/middleware/fireAlarmMiddleware.js +15 -5
  74. package/lib/projects/__tests__/AppDevModeInterface.test.js +72 -44
  75. package/lib/projects/__tests__/LocalDevProcess.test.js +228 -16
  76. package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +16 -21
  77. package/lib/projects/__tests__/components.test.js +164 -7
  78. package/lib/projects/__tests__/deploy.test.js +229 -0
  79. package/lib/projects/__tests__/{localDevHelpers.test.js → localDevProjectHelpers.test.js} +5 -3
  80. package/lib/projects/__tests__/platformVersion.test.d.ts +1 -0
  81. package/lib/projects/__tests__/{buildAndDeploy.test.js → platformVersion.test.js} +2 -2
  82. package/lib/projects/add/__tests__/legacyAddComponent.test.js +49 -6
  83. package/lib/projects/add/__tests__/v3AddComponent.test.js +142 -8
  84. package/lib/projects/add/legacyAddComponent.d.ts +1 -1
  85. package/lib/projects/add/legacyAddComponent.js +5 -1
  86. package/lib/projects/add/v3AddComponent.d.ts +2 -1
  87. package/lib/projects/add/v3AddComponent.js +22 -5
  88. package/lib/projects/components.d.ts +1 -0
  89. package/lib/projects/components.js +27 -1
  90. package/lib/projects/create/__tests__/v3.test.js +174 -11
  91. package/lib/projects/create/index.js +2 -2
  92. package/lib/projects/create/legacy.js +1 -1
  93. package/lib/projects/create/v3.d.ts +2 -2
  94. package/lib/projects/create/v3.js +38 -13
  95. package/lib/projects/deploy.d.ts +13 -0
  96. package/lib/projects/deploy.js +63 -0
  97. package/lib/projects/localDev/AppDevModeInterface.d.ts +5 -3
  98. package/lib/projects/localDev/AppDevModeInterface.js +132 -48
  99. package/lib/projects/localDev/DevServerManagerV2.js +1 -0
  100. package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
  101. package/lib/projects/localDev/LocalDevLogger.js +22 -0
  102. package/lib/projects/localDev/LocalDevManager.js +1 -1
  103. package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
  104. package/lib/projects/localDev/LocalDevProcess.js +93 -20
  105. package/lib/projects/localDev/LocalDevState.d.ts +13 -9
  106. package/lib/projects/localDev/LocalDevState.js +26 -17
  107. package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +2 -0
  108. package/lib/projects/localDev/LocalDevWebsocketServer.js +55 -23
  109. package/lib/projects/localDev/{helpers.d.ts → helpers/account.d.ts} +1 -14
  110. package/lib/projects/localDev/helpers/account.js +233 -0
  111. package/lib/projects/localDev/helpers/project.d.ts +12 -0
  112. package/lib/projects/localDev/helpers/project.js +176 -0
  113. package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +4 -0
  114. package/lib/projects/localDev/localDevWebsocketServerUtils.js +10 -0
  115. package/lib/projects/platformVersion.d.ts +1 -0
  116. package/lib/projects/platformVersion.js +10 -0
  117. package/lib/projects/{buildAndDeploy.d.ts → pollProjectBuildAndDeploy.d.ts} +0 -1
  118. package/lib/projects/{buildAndDeploy.js → pollProjectBuildAndDeploy.js} +4 -14
  119. package/lib/projects/upload.js +1 -1
  120. package/lib/projects/urls.d.ts +2 -0
  121. package/lib/projects/urls.js +7 -0
  122. package/lib/prompts/__tests__/projectAddPrompt.test.d.ts +1 -0
  123. package/lib/prompts/__tests__/projectAddPrompt.test.js +143 -0
  124. package/lib/prompts/__tests__/selectProjectTemplatePrompt.test.d.ts +1 -0
  125. package/lib/prompts/__tests__/selectProjectTemplatePrompt.test.js +160 -0
  126. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +1 -0
  127. package/lib/prompts/importDataFilePathPrompt.js +4 -2
  128. package/lib/prompts/installAppPrompt.d.ts +6 -1
  129. package/lib/prompts/installAppPrompt.js +6 -1
  130. package/lib/prompts/projectAddPrompt.js +3 -2
  131. package/lib/prompts/projectDevTargetAccountPrompt.js +1 -0
  132. package/lib/prompts/promptUtils.d.ts +7 -1
  133. package/lib/prompts/promptUtils.js +17 -1
  134. package/lib/prompts/selectProjectTemplatePrompt.js +3 -1
  135. package/lib/theme/__tests__/migrate.test.d.ts +1 -0
  136. package/lib/theme/__tests__/migrate.test.js +233 -0
  137. package/lib/theme/migrate.d.ts +13 -0
  138. package/lib/theme/migrate.js +90 -0
  139. package/lib/ui/index.js +3 -6
  140. package/lib/usageTracking.js +2 -2
  141. package/mcp-server/server.js +2 -1
  142. package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +32 -0
  143. package/mcp-server/tools/cms/HsCreateFunctionTool.js +96 -0
  144. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +38 -0
  145. package/mcp-server/tools/cms/HsCreateModuleTool.js +118 -0
  146. package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +26 -0
  147. package/mcp-server/tools/cms/HsCreateTemplateTool.js +75 -0
  148. package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +32 -0
  149. package/mcp-server/tools/cms/HsFunctionLogsTool.js +76 -0
  150. package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +23 -0
  151. package/mcp-server/tools/cms/HsListFunctionsTool.js +58 -0
  152. package/mcp-server/tools/cms/HsListTool.d.ts +23 -0
  153. package/mcp-server/tools/cms/HsListTool.js +58 -0
  154. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.d.ts +1 -0
  155. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +251 -0
  156. package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.d.ts +1 -0
  157. package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +224 -0
  158. package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.d.ts +1 -0
  159. package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +206 -0
  160. package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.d.ts +1 -0
  161. package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +183 -0
  162. package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.d.ts +1 -0
  163. package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +120 -0
  164. package/mcp-server/tools/cms/__tests__/HsListTool.test.d.ts +1 -0
  165. package/mcp-server/tools/cms/__tests__/HsListTool.test.js +120 -0
  166. package/mcp-server/tools/index.d.ts +1 -0
  167. package/mcp-server/tools/index.js +16 -0
  168. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -3
  169. package/mcp-server/tools/project/AddFeatureToProjectTool.js +3 -3
  170. package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
  171. package/mcp-server/tools/project/CreateProjectTool.js +5 -5
  172. package/mcp-server/tools/project/DeployProjectTool.js +1 -1
  173. package/mcp-server/tools/project/DocFetchTool.js +3 -3
  174. package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
  175. package/mcp-server/tools/project/DocsSearchTool.js +8 -8
  176. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
  177. package/mcp-server/tools/project/GetConfigValuesTool.js +14 -8
  178. package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
  179. package/mcp-server/tools/project/UploadProjectTools.js +2 -2
  180. package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
  181. package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +1 -1
  182. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
  183. package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +1 -1
  184. package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +3 -3
  185. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +15 -13
  186. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +9 -8
  187. package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -1
  188. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -1
  189. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -1
  190. package/mcp-server/tools/project/constants.d.ts +1 -1
  191. package/mcp-server/tools/project/constants.js +14 -6
  192. package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
  193. package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
  194. package/mcp-server/utils/cliConfig.d.ts +1 -0
  195. package/mcp-server/utils/cliConfig.js +12 -0
  196. package/package.json +5 -4
  197. package/types/LocalDev.d.ts +21 -4
  198. package/types/Projects.d.ts +1 -0
  199. package/types/Prompts.d.ts +1 -0
  200. package/ui/components/BoxWithTitle.d.ts +8 -0
  201. package/ui/components/BoxWithTitle.js +9 -0
  202. package/ui/components/HorizontalSelectPrompt.d.ts +8 -0
  203. package/ui/components/HorizontalSelectPrompt.js +30 -0
  204. package/ui/components/StatusMessageBoxes.d.ts +12 -0
  205. package/ui/components/StatusMessageBoxes.js +31 -0
  206. package/ui/index.js +1 -1
  207. package/ui/lib/ui-testing-utils.d.ts +9 -0
  208. package/ui/lib/ui-testing-utils.js +47 -0
  209. package/ui/lib/useTerminalSize.d.ts +13 -0
  210. package/ui/lib/useTerminalSize.js +31 -0
  211. package/ui/styles.d.ts +18 -0
  212. package/ui/styles.js +18 -0
  213. package/ui/views/UiSandbox.d.ts +5 -0
  214. package/ui/views/UiSandbox.js +25 -0
  215. package/lib/projects/localDev/helpers.js +0 -388
  216. /package/lib/projects/__tests__/{buildAndDeploy.test.d.ts → deploy.test.d.ts} +0 -0
  217. /package/lib/projects/__tests__/{localDevHelpers.test.d.ts → localDevProjectHelpers.test.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { http } from '@hubspot/local-dev-lib/http';
2
2
  import { MIGRATION_STATUS } from '@hubspot/local-dev-lib/types/Migration';
3
- import { listAppsForMigration, initializeMigration, continueMigration, checkMigrationStatusV2, isMigrationStatus, } from '../migrate.js';
3
+ import { listAppsForMigration, initializeAppMigration, continueAppMigration, checkMigrationStatusV2, isMigrationStatus, } from '../migrate.js';
4
4
  vi.mock('@hubspot/local-dev-lib/http');
5
5
  const httpMock = http;
6
6
  describe('api/migrate', () => {
@@ -49,12 +49,12 @@ describe('api/migrate', () => {
49
49
  expect(result).toEqual(mockResponse);
50
50
  });
51
51
  });
52
- describe('initializeMigration', () => {
52
+ describe('initializeAppMigration', () => {
53
53
  it('should call http.post with correct parameters', async () => {
54
54
  const mockResponse = { migrationId: mockMigrationId };
55
55
  // @ts-expect-error Mock
56
56
  httpMock.post.mockResolvedValue(mockResponse);
57
- const result = await initializeMigration(mockAccountId, mockAppId, mockPlatformVersion);
57
+ const result = await initializeAppMigration(mockAccountId, mockAppId, mockPlatformVersion);
58
58
  expect(http.post).toHaveBeenCalledWith(mockAccountId, {
59
59
  url: 'dfs/migrations/v2/migrations',
60
60
  data: {
@@ -65,12 +65,12 @@ describe('api/migrate', () => {
65
65
  expect(result).toEqual(mockResponse);
66
66
  });
67
67
  });
68
- describe('continueMigration', () => {
68
+ describe('continueAppMigration', () => {
69
69
  it('should call http.post with correct parameters', async () => {
70
70
  const mockResponse = { migrationId: mockMigrationId };
71
71
  // @ts-expect-error Mock
72
72
  httpMock.post.mockResolvedValue(mockResponse);
73
- const result = await continueMigration(mockPortalId, mockMigrationId, mockComponentUids, mockProjectName);
73
+ const result = await continueAppMigration(mockPortalId, mockMigrationId, mockComponentUids, mockProjectName);
74
74
  expect(http.post).toHaveBeenCalledWith(mockPortalId, {
75
75
  url: 'dfs/migrations/v2/migrations/continue',
76
76
  data: {
package/api/migrate.d.ts CHANGED
@@ -30,7 +30,7 @@ export interface ListThemesResponse {
30
30
  REACT_THEME: string[];
31
31
  };
32
32
  }
33
- export interface InitializeMigrationResponse {
33
+ export interface InitializeAppMigrationResponse {
34
34
  migrationId: number;
35
35
  }
36
36
  export interface ListAppsMigrationComponent {
@@ -38,7 +38,7 @@ export interface ListAppsMigrationComponent {
38
38
  componentType: string;
39
39
  isSupported: boolean;
40
40
  }
41
- export type ContinueMigrationResponse = {
41
+ export type ContinueAppMigrationResponse = {
42
42
  migrationId: number;
43
43
  };
44
44
  export interface MigrationBaseStatus {
@@ -71,8 +71,7 @@ export interface MigrationFailed extends MigrationBaseStatus {
71
71
  export type MigrationStatus = MigrationInProgress | MigrationInputRequired | MigrationSuccess | MigrationFailed;
72
72
  export declare function isMigrationStatus(error: unknown): error is MigrationStatus;
73
73
  export declare function listAppsForMigration(accountId: number, platformVersion: string): HubSpotPromise<ListAppsResponse>;
74
- export declare function listThemesForMigration(accountId: number, projectName: string): HubSpotPromise<ListThemesResponse>;
75
- export declare function initializeMigration(accountId: number, applicationId: number, platformVersion: string): HubSpotPromise<InitializeMigrationResponse>;
76
- export declare function continueMigration(portalId: number, migrationId: number, componentUids: Record<string, string>, projectName: string): HubSpotPromise<ContinueMigrationResponse>;
74
+ export declare function initializeAppMigration(accountId: number, applicationId: number, platformVersion: string): HubSpotPromise<InitializeAppMigrationResponse>;
75
+ export declare function continueAppMigration(portalId: number, migrationId: number, componentUids: Record<string, string>, projectName: string): HubSpotPromise<ContinueAppMigrationResponse>;
77
76
  export declare function checkMigrationStatusV2(accountId: number, id: number): HubSpotPromise<MigrationStatus>;
78
77
  export {};
package/api/migrate.js CHANGED
@@ -18,21 +18,13 @@ export async function listAppsForMigration(accountId, platformVersion) {
18
18
  },
19
19
  });
20
20
  }
21
- export async function listThemesForMigration(accountId, projectName) {
22
- return http.get(accountId, {
23
- url: `${MIGRATIONS_API_PATH_V2}/list-themes`,
24
- params: {
25
- projectName,
26
- },
27
- });
28
- }
29
21
  function mapPlatformVersionToEnum(platformVersion) {
30
22
  if (platformVersion === PLATFORM_VERSIONS.unstable) {
31
23
  return PLATFORM_VERSIONS.unstable.toUpperCase();
32
24
  }
33
25
  return `V${platformVersion.replace('.', '_')}`;
34
26
  }
35
- export async function initializeMigration(accountId, applicationId, platformVersion) {
27
+ export async function initializeAppMigration(accountId, applicationId, platformVersion) {
36
28
  return http.post(accountId, {
37
29
  url: `${MIGRATIONS_API_PATH_V2}/migrations`,
38
30
  data: {
@@ -41,7 +33,7 @@ export async function initializeMigration(accountId, applicationId, platformVers
41
33
  },
42
34
  });
43
35
  }
44
- export async function continueMigration(portalId, migrationId, componentUids, projectName) {
36
+ export async function continueAppMigration(portalId, migrationId, componentUids, projectName) {
45
37
  return http.post(portalId, {
46
38
  url: `${MIGRATIONS_API_PATH_V2}/migrations/continue`,
47
39
  data: {
@@ -34,8 +34,8 @@ describe('commands/get-started', () => {
34
34
  });
35
35
  });
36
36
  describe('describe', () => {
37
- it('should have undefined describe property', () => {
38
- expect(getStartedCommand.describe).toBeUndefined();
37
+ it('should have a defined describe property', () => {
38
+ expect(getStartedCommand.describe).toBeDefined();
39
39
  });
40
40
  });
41
41
  describe('command structure', () => {
@@ -19,7 +19,7 @@ describe('commands/mcp', () => {
19
19
  });
20
20
  describe('describe', () => {
21
21
  it('should provide a description', () => {
22
- expect(mcpCommand.describe).toBeUndefined();
22
+ expect(mcpCommand.describe).toBeDefined();
23
23
  });
24
24
  });
25
25
  describe('builder', () => {
@@ -51,9 +51,6 @@ describe('commands/project', () => {
51
51
  });
52
52
  });
53
53
  describe('describe', () => {
54
- it('should contain the beta tag', () => {
55
- expect(projectCommand.describe).toContain('[BETA]');
56
- });
57
54
  it('should provide a description', () => {
58
55
  expect(projectCommand.describe).toBeDefined();
59
56
  });
@@ -10,6 +10,7 @@ vi.mock('@hubspot/local-dev-lib/config');
10
10
  vi.mock('@hubspot/local-dev-lib/logger');
11
11
  vi.mock('../../../lib/app/migrate');
12
12
  vi.mock('../../../lib/app/migrate_legacy');
13
+ vi.mock('../../../lib/projects/config.js');
13
14
  const mockYargs = yargs;
14
15
  const mockedGetAccountConfig = getAccountConfig;
15
16
  const mockedMigrateApp2023_2 = migrateApp2023_2;
@@ -102,7 +103,6 @@ describe('commands/app/migrate', () => {
102
103
  'platform-version': expect.objectContaining({
103
104
  type: 'string',
104
105
  default: '2025.2',
105
- hidden: true,
106
106
  }),
107
107
  }));
108
108
  });
@@ -6,13 +6,13 @@ import { i18n } from '../../lib/lang.js';
6
6
  import { ApiErrorContext, logError } from '../../lib/errorHandlers/index.js';
7
7
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
8
8
  import { migrateApp2025_2 } from '../../lib/app/migrate.js';
9
- import { uiBetaTag, uiCommandReference, uiLink } from '../../lib/ui/index.js';
9
+ import { uiCommandReference, uiLink } from '../../lib/ui/index.js';
10
10
  import { migrateApp2023_2 } from '../../lib/app/migrate_legacy.js';
11
11
  import { getIsInProject } from '../../lib/projects/config.js';
12
12
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
13
13
  const { v2023_2, v2025_2 } = PLATFORM_VERSIONS;
14
14
  const command = 'migrate';
15
- const describe = undefined; // uiBetaTag(i18n(`commands.project.subcommands.migrateApp.header.text.describe`), false);
15
+ const describe = i18n(`commands.project.subcommands.migrateApp.describe`);
16
16
  export function handlerGenerator(commandTrackingName) {
17
17
  return async function handler(args) {
18
18
  const { derivedAccountId, platformVersion, unstable } = args;
@@ -23,7 +23,7 @@ export function handlerGenerator(commandTrackingName) {
23
23
  return process.exit(EXIT_CODES.ERROR);
24
24
  }
25
25
  logger.log('');
26
- logger.log(uiBetaTag(i18n(`commands.project.subcommands.migrateApp.header.text`), false));
26
+ logger.log(i18n(`commands.project.subcommands.migrateApp.header.text`));
27
27
  logger.log(uiLink(i18n(`commands.project.subcommands.migrateApp.header.link`), 'https://developers.hubspot.com/docs/platform/migrate-a-public-app-to-projects'));
28
28
  logger.log('');
29
29
  try {
@@ -76,7 +76,6 @@ function appMigrateBuilder(yargs) {
76
76
  'platform-version': {
77
77
  type: 'string',
78
78
  choices: [v2023_2, v2025_2],
79
- hidden: true,
80
79
  default: v2025_2,
81
80
  },
82
81
  unstable: {
@@ -93,7 +92,7 @@ function appMigrateBuilder(yargs) {
93
92
  ]);
94
93
  return yargs;
95
94
  }
96
- const builder = makeYargsBuilder(appMigrateBuilder, command, uiBetaTag(i18n(`commands.project.subcommands.migrateApp.describe`), false), {
95
+ const builder = makeYargsBuilder(appMigrateBuilder, command, i18n(`commands.project.subcommands.migrateApp.describe`), {
97
96
  useGlobalOptions: true,
98
97
  useConfigOptions: true,
99
98
  useAccountOptions: true,
@@ -7,8 +7,9 @@ import { commands } from '../../../lang/en.js';
7
7
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
8
8
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
9
9
  import { uiLogger } from '../../../lib/ui/logger.js';
10
+ import { uiBetaTag } from '../../../lib/ui/index.js';
10
11
  const command = 'add [name]';
11
- const describe = commands.app.subcommands.secret.subcommands.add.describe;
12
+ const describe = uiBetaTag(commands.app.subcommands.secret.subcommands.add.describe, false);
12
13
  async function handler(args) {
13
14
  const { derivedAccountId } = args;
14
15
  trackCommandUsage('app-secret-add', {}, derivedAccountId);
@@ -7,8 +7,9 @@ import { commands } from '../../../lang/en.js';
7
7
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
8
8
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
9
9
  import { uiLogger } from '../../../lib/ui/logger.js';
10
+ import { uiBetaTag } from '../../../lib/ui/index.js';
10
11
  const command = 'delete [name]';
11
- const describe = commands.app.subcommands.secret.subcommands.delete.describe;
12
+ const describe = uiBetaTag(commands.app.subcommands.secret.subcommands.delete.describe, false);
12
13
  async function handler(args) {
13
14
  const { derivedAccountId, force } = args;
14
15
  trackCommandUsage('app-secret-delete', {}, derivedAccountId);
@@ -6,8 +6,9 @@ import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
6
6
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
7
7
  import { selectAppPrompt } from '../../../lib/prompts/selectAppPrompt.js';
8
8
  import { uiLogger } from '../../../lib/ui/logger.js';
9
+ import { uiBetaTag } from '../../../lib/ui/index.js';
9
10
  const command = 'list';
10
- const describe = commands.app.subcommands.secret.subcommands.list.describe;
11
+ const describe = uiBetaTag(commands.app.subcommands.secret.subcommands.list.describe, false);
11
12
  async function handler(args) {
12
13
  const { derivedAccountId } = args;
13
14
  trackCommandUsage('app-secret-list', {}, derivedAccountId);
@@ -8,8 +8,9 @@ import { commands } from '../../../lang/en.js';
8
8
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
9
9
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
10
10
  import { uiLogger } from '../../../lib/ui/logger.js';
11
+ import { uiBetaTag } from '../../../lib/ui/index.js';
11
12
  const command = 'update [name]';
12
- const describe = commands.app.subcommands.secret.subcommands.update.describe;
13
+ const describe = uiBetaTag(commands.app.subcommands.secret.subcommands.update.describe, false);
13
14
  async function handler(args) {
14
15
  const { derivedAccountId } = args;
15
16
  trackCommandUsage('app-secret-update', {}, derivedAccountId);
@@ -4,8 +4,9 @@ import addAppSecretCommand from './secret/add.js';
4
4
  import deleteAppSecretCommand from './secret/delete.js';
5
5
  import listAppSecretsCommand from './secret/list.js';
6
6
  import updateAppSecretCommand from './secret/update.js';
7
+ import { uiBetaTag } from '../../lib/ui/index.js';
7
8
  const command = ['secret', 'secrets'];
8
- const describe = undefined; // commands.app.subcommands.secret.describe;
9
+ const describe = uiBetaTag(commands.app.subcommands.secret.describe, false);
9
10
  function appSecretBuilder(yargs) {
10
11
  yargs
11
12
  .command(addAppSecretCommand)
package/commands/app.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import migrateCommand from './app/migrate.js';
2
2
  import appSecretCommand from './app/secret.js';
3
3
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
4
+ import { commands } from '../lang/en.js';
4
5
  const command = ['app', 'apps'];
5
- // Keep the command hidden for now
6
- const describe = undefined;
6
+ const describe = commands.app.describe;
7
7
  function appBuilder(yargs) {
8
8
  yargs.command(migrateCommand).command(appSecretCommand).demandCommand(1, '');
9
9
  return yargs;
@@ -84,7 +84,6 @@ function configSetBuilder(yargs) {
84
84
  'auto-open-browser': {
85
85
  describe: commands.config.subcommands.set.options.autoOpenBrowser.describe,
86
86
  type: 'boolean',
87
- hidden: true,
88
87
  },
89
88
  })
90
89
  .conflicts(getExclusiveConflicts([
@@ -1,6 +1,4 @@
1
1
  import { AccountArgs, YargsCommandModule, CommonArgs, ConfigArgs, EnvironmentArgs } from '../types/Yargs.js';
2
- export declare const command = "get-started";
3
- export declare const describe: undefined;
4
2
  type GetStartedArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
5
3
  name?: string;
6
4
  dest?: string;
@@ -4,7 +4,7 @@ import open from 'open';
4
4
  import { getCwd } from '@hubspot/local-dev-lib/path';
5
5
  import { cloneGithubRepo } from '@hubspot/local-dev-lib/github';
6
6
  import { commands } from '../lang/en.js';
7
- import { trackCommandUsage } from '../lib/usageTracking.js';
7
+ import { trackCommandMetadataUsage, trackCommandUsage, } from '../lib/usageTracking.js';
8
8
  import { EXIT_CODES } from '../lib/enums/exitCodes.js';
9
9
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
10
10
  import { promptUser } from '../lib/prompts/promptUtils.js';
@@ -16,22 +16,23 @@ import { handleProjectUpload } from '../lib/projects/upload.js';
16
16
  import { PROJECT_CONFIG_FILE, GET_STARTED_OPTIONS, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, } from '../lib/constants.js';
17
17
  import { writeProjectConfig, getProjectConfig, validateProjectConfig, } from '../lib/projects/config.js';
18
18
  import { getProjectPackageJsonLocations, installPackages, } from '../lib/dependencyManagement.js';
19
- import { pollProjectBuildAndDeploy, useV3Api, } from '../lib/projects/buildAndDeploy.js';
19
+ import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
20
+ import { useV3Api } from '../lib/projects/platformVersion.js';
20
21
  import { openLink } from '../lib/links.js';
21
22
  import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
22
23
  import { getEnv } from '@hubspot/local-dev-lib/config';
23
24
  import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
24
25
  import { fetchPublicAppsForPortal } from '@hubspot/local-dev-lib/api/appsDev';
25
- export const command = 'get-started';
26
- export const describe = undefined;
26
+ const command = 'get-started';
27
+ const describe = commands.getStarted.describe;
27
28
  async function handler(args) {
28
29
  const { derivedAccountId } = args;
29
30
  const env = getEnv(derivedAccountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD;
30
- // TODO: Put this in constants.ts once we have a defined place for the template before INBOUND
31
- const templateSource = 'robrown-hubspot/hubspot-project-components-ua-app-objects-beta';
32
- trackCommandUsage('get-started', {}, derivedAccountId);
31
+ await trackCommandUsage('get-started', {}, derivedAccountId);
32
+ const accountName = uiAccountDescription(derivedAccountId);
33
33
  uiInfoSection(commands.getStarted.startTitle, () => {
34
34
  uiLogger.log(commands.getStarted.startDescription);
35
+ uiLogger.log(commands.getStarted.guideOverview(accountName));
35
36
  });
36
37
  const { default: selectedOption } = await promptUser([
37
38
  {
@@ -51,6 +52,8 @@ async function handler(args) {
51
52
  default: GET_STARTED_OPTIONS.APP,
52
53
  },
53
54
  ]);
55
+ // Track user's initial choice
56
+ await trackCommandMetadataUsage('get-started', { step: 'select-option', type: selectedOption }, derivedAccountId);
54
57
  if (selectedOption === GET_STARTED_OPTIONS.CMS) {
55
58
  uiLogger.log(' ');
56
59
  uiLogger.log(commands.getStarted.designManager);
@@ -63,6 +66,11 @@ async function handler(args) {
63
66
  message: commands.getStarted.openDesignManagerPrompt,
64
67
  },
65
68
  ]);
69
+ // Track Design Manager browser action
70
+ await trackCommandMetadataUsage('get-started', {
71
+ step: 'open-design-manager',
72
+ type: shouldOpen ? 'opened' : 'declined',
73
+ }, derivedAccountId);
66
74
  if (shouldOpen) {
67
75
  uiLogger.log('');
68
76
  openLink(derivedAccountId, 'design-manager');
@@ -73,36 +81,37 @@ async function handler(args) {
73
81
  else {
74
82
  uiLogger.log(' ');
75
83
  uiLogger.log(commands.getStarted.logs.appSelected);
76
- // 1. Fetch project templates
77
- let latestRepoReleaseTag;
78
84
  const { dest, name } = await projectNameAndDestPrompt(args);
79
- // Specific template for get-started command
80
- const projectTemplate = {
81
- name: 'private-app-get-started-template',
82
- label: 'CRM getting started project with private apps',
83
- path: 'projects/private-app-get-started-template',
84
- };
85
- // 3. Create the project files
86
85
  const projectDest = path.resolve(getCwd(), dest);
87
86
  const { projectConfig: existingProjectConfig, projectDir: existingProjectDir, } = await getProjectConfig(projectDest);
88
87
  if (existingProjectConfig &&
89
88
  existingProjectDir &&
90
89
  projectDest.startsWith(existingProjectDir)) {
90
+ // Track nested project error
91
+ await trackCommandMetadataUsage('get-started', {
92
+ successful: false,
93
+ step: 'project-creation',
94
+ }, derivedAccountId);
91
95
  uiLogger.log(' ');
92
96
  uiLogger.error(commands.project.create.errors.cannotNestProjects(existingProjectDir));
93
97
  process.exit(EXIT_CODES.ERROR);
94
98
  }
95
- const repo = templateSource || HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
96
99
  // 4. Clone the project template from GitHub
97
- // This is temporary until we have the UA template in the main repo
98
100
  try {
99
- await cloneGithubRepo(repo, projectDest, {
100
- sourceDir: projectTemplate.path,
101
- tag: latestRepoReleaseTag,
101
+ await cloneGithubRepo(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, projectDest, {
102
+ sourceDir: '2025.2/private-app-get-started-template',
102
103
  hideLogs: true,
103
104
  });
105
+ await trackCommandMetadataUsage('get-started', {
106
+ successful: true,
107
+ step: 'github-clone',
108
+ }, derivedAccountId);
104
109
  }
105
110
  catch (err) {
111
+ await trackCommandMetadataUsage('get-started', {
112
+ successful: false,
113
+ step: 'github-clone',
114
+ }, derivedAccountId);
106
115
  debugError(err);
107
116
  uiLogger.log(' ');
108
117
  uiLogger.error(commands.project.create.errors.failedToDownloadProject);
@@ -121,6 +130,11 @@ async function handler(args) {
121
130
  uiLogger.log(' ');
122
131
  uiLogger.log(commands.getStarted.prompts.projectCreated.description);
123
132
  uiLogger.log(' ');
133
+ // Track successful project creation
134
+ await trackCommandMetadataUsage('get-started', {
135
+ successful: true,
136
+ step: 'project-creation',
137
+ }, derivedAccountId);
124
138
  // 5. Install dependencies
125
139
  const installLocations = await getProjectPackageJsonLocations(projectDest);
126
140
  try {
@@ -138,7 +152,6 @@ async function handler(args) {
138
152
  uiLogger.log(' ');
139
153
  }
140
154
  // 6. Ask user if they want to upload the project
141
- const accountName = uiAccountDescription(derivedAccountId);
142
155
  const { shouldUpload } = await promptUser([
143
156
  {
144
157
  type: 'confirm',
@@ -147,22 +160,31 @@ async function handler(args) {
147
160
  default: true,
148
161
  },
149
162
  ]);
163
+ // Track upload decision
164
+ await trackCommandMetadataUsage('get-started', {
165
+ step: 'upload-decision',
166
+ type: shouldUpload ? 'upload' : 'skip',
167
+ }, derivedAccountId);
150
168
  if (shouldUpload) {
151
169
  try {
152
170
  // Get the project config for the newly created project
153
171
  const { projectConfig: newProjectConfig, projectDir: newProjectDir } = await getProjectConfig(projectDest);
154
172
  if (!newProjectConfig || !newProjectDir) {
173
+ // Track config file not found error
174
+ await trackCommandMetadataUsage('get-started', {
175
+ successful: false,
176
+ step: 'config-file-not-found',
177
+ }, derivedAccountId);
155
178
  uiLogger.log(' ');
156
179
  uiLogger.error(commands.getStarted.errors.configFileNotFound);
157
180
  process.exit(EXIT_CODES.ERROR);
158
181
  }
159
182
  validateProjectConfig(newProjectConfig, newProjectDir);
160
- const targetAccountId = derivedAccountId;
161
183
  uiLogger.log(' ');
162
184
  uiLogger.log(commands.getStarted.logs.uploadingProject);
163
185
  uiLogger.log(' ');
164
186
  const { result, uploadError } = await handleProjectUpload({
165
- accountId: targetAccountId,
187
+ accountId: derivedAccountId,
166
188
  projectConfig: newProjectConfig,
167
189
  projectDir: newProjectDir,
168
190
  callbackFunc: pollProjectBuildAndDeploy,
@@ -173,11 +195,22 @@ async function handler(args) {
173
195
  skipValidation: false,
174
196
  });
175
197
  if (uploadError) {
198
+ // Track upload failure
199
+ await trackCommandMetadataUsage('get-started', {
200
+ successful: false,
201
+ step: 'upload',
202
+ }, derivedAccountId);
176
203
  uiLogger.log(' ');
177
204
  uiLogger.error(commands.getStarted.errors.uploadFailed);
178
205
  debugError(uploadError);
179
206
  }
180
207
  else if (result) {
208
+ // Track successful upload completion
209
+ await trackCommandMetadataUsage('get-started', {
210
+ successful: true,
211
+ step: 'upload',
212
+ }, derivedAccountId);
213
+ uiLogger.log(' ');
181
214
  uiLogger.success(commands.getStarted.logs.uploadSuccess);
182
215
  const { data: { results }, } = await fetchPublicAppsForPortal(derivedAccountId);
183
216
  const lastCreatedApp = results.sort((a, b) => b.createdAt - a.createdAt)[0];
@@ -192,6 +225,11 @@ async function handler(args) {
192
225
  message: commands.getStarted.openInstallUrl,
193
226
  },
194
227
  ]);
228
+ // Track Developer Overview browser action
229
+ await trackCommandMetadataUsage('get-started', {
230
+ step: 'open-distribution-page',
231
+ type: shouldOpenOverview ? 'opened' : 'declined',
232
+ }, derivedAccountId);
195
233
  if (shouldOpenOverview) {
196
234
  open(getStaticAuthAppInstallUrl({
197
235
  targetAccountId: derivedAccountId,
@@ -207,6 +245,11 @@ async function handler(args) {
207
245
  }
208
246
  }
209
247
  catch (err) {
248
+ // Track upload exception
249
+ await trackCommandMetadataUsage('get-started', {
250
+ successful: false,
251
+ step: 'upload',
252
+ }, derivedAccountId);
210
253
  uiLogger.log(' ');
211
254
  uiLogger.error(commands.getStarted.errors.uploadFailed);
212
255
  debugError(err);
@@ -214,6 +257,11 @@ async function handler(args) {
214
257
  }
215
258
  }
216
259
  }
260
+ // Track successful completion of get-started command
261
+ await trackCommandMetadataUsage('get-started', {
262
+ successful: true,
263
+ step: 'command-completed',
264
+ }, derivedAccountId);
217
265
  process.exit(EXIT_CODES.SUCCESS);
218
266
  }
219
267
  function getStartedBuilder(yargs) {
@@ -3,12 +3,12 @@ vi.mock('../../../lib/commonOpts');
3
3
  describe('commands/mcp/setup', () => {
4
4
  describe('command', () => {
5
5
  it('should have the correct command structure', () => {
6
- expect(setupCommand.command).toEqual(['setup', 'update']);
6
+ expect(setupCommand.command).toEqual(['setup']);
7
7
  });
8
8
  });
9
9
  describe('describe', () => {
10
10
  it('should be undefined to keep the command hidden', () => {
11
- expect(setupCommand.describe).toBeUndefined();
11
+ expect(setupCommand.describe).toBeDefined();
12
12
  });
13
13
  });
14
14
  describe('builder', () => {
@@ -1,7 +1,6 @@
1
1
  import { CommonArgs, YargsCommandModule } from '../../types/Yargs.js';
2
2
  interface MCPSetupArgs extends CommonArgs {
3
3
  client?: string[];
4
- addDocsSearch?: boolean;
5
4
  }
6
5
  declare const mcpSetupCommand: YargsCommandModule<unknown, MCPSetupArgs>;
7
6
  export default mcpSetupCommand;
@@ -2,11 +2,20 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
2
2
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
3
3
  import { commands } from '../../lang/en.js';
4
4
  import { uiLogger } from '../../lib/ui/logger.js';
5
- import { addMcpServerToConfig, addMintlifyMcpServer, supportedTools, } from '../../lib/mcp/setup.js';
5
+ import { addMcpServerToConfig, supportedTools } from '../../lib/mcp/setup.js';
6
6
  import { trackCommandUsage } from '../../lib/usageTracking.js';
7
- const command = ['setup', 'update'];
8
- const describe = undefined; // Leave hidden for now
7
+ import { hasFeature } from '../../lib/hasFeature.js';
8
+ import { FEATURES } from '../../lib/constants.js';
9
+ import { uiBetaTag } from '../../lib/ui/index.js';
10
+ const command = ['setup'];
11
+ const describe = uiBetaTag(commands.mcp.setup.describe, false);
9
12
  async function handler(args) {
13
+ const { derivedAccountId } = args;
14
+ const hasMcpAccess = await hasFeature(derivedAccountId, FEATURES.MCP_ACCESS);
15
+ if (!hasMcpAccess) {
16
+ uiLogger.error(commands.mcp.setup.errors.needsMcpAccess(derivedAccountId));
17
+ process.exit(EXIT_CODES.ERROR);
18
+ }
10
19
  try {
11
20
  await import('@modelcontextprotocol/sdk/server/mcp.js');
12
21
  }
@@ -16,10 +25,7 @@ async function handler(args) {
16
25
  }
17
26
  trackCommandUsage('mcp-setup', {}, args.derivedAccountId);
18
27
  try {
19
- const derivedTargets = await addMcpServerToConfig(args.client);
20
- if (args.addDocsSearch) {
21
- await addMintlifyMcpServer(derivedTargets);
22
- }
28
+ await addMcpServerToConfig(args.client);
23
29
  }
24
30
  catch (e) {
25
31
  process.exit(EXIT_CODES.ERROR);
@@ -27,15 +33,10 @@ async function handler(args) {
27
33
  process.exit(EXIT_CODES.SUCCESS);
28
34
  }
29
35
  function setupBuilder(yargs) {
30
- yargs
31
- .option('client', {
36
+ yargs.option('client', {
32
37
  describe: commands.mcp.setup.args.client,
33
38
  type: 'array',
34
39
  choices: [...supportedTools.map(tool => tool.value)],
35
- })
36
- .option('add-docs-search', {
37
- type: 'boolean',
38
- hidden: true,
39
40
  });
40
41
  return yargs;
41
42
  }
package/commands/mcp.js CHANGED
@@ -2,14 +2,14 @@ import startCommand from './mcp/start.js';
2
2
  import setupCommand from './mcp/setup.js';
3
3
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
4
4
  import { commands } from '../lang/en.js';
5
+ import { uiBetaTag } from '../lib/ui/index.js';
5
6
  const command = 'mcp';
6
- // Leave this as undefined to hide the command
7
- const describe = undefined;
7
+ const describe = uiBetaTag(commands.mcp.describe, false);
8
8
  function mcpBuilder(yargs) {
9
9
  yargs.command(startCommand).command(setupCommand).demandCommand(1, '');
10
10
  return yargs;
11
11
  }
12
- const builder = makeYargsBuilder(mcpBuilder, command, commands.mcp.describe, {
12
+ const builder = makeYargsBuilder(mcpBuilder, command, describe, {
13
13
  useGlobalOptions: true,
14
14
  });
15
15
  const mcpCommand = {