@hubspot/cli 7.7.35-experimental.0 → 7.8.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 (284) hide show
  1. package/bin/cli.js +31 -25
  2. package/commands/__tests__/auth.test.js +5 -0
  3. package/commands/__tests__/doctor.test.js +16 -16
  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/account/clean.js +18 -27
  8. package/commands/account/createOverride.js +13 -31
  9. package/commands/account/info.js +20 -31
  10. package/commands/account/list.js +16 -22
  11. package/commands/account/remove.js +12 -20
  12. package/commands/account/removeOverride.js +11 -21
  13. package/commands/account/rename.js +6 -9
  14. package/commands/account/use.js +12 -26
  15. package/commands/account.js +2 -2
  16. package/commands/app/__tests__/migrate.test.js +5 -6
  17. package/commands/app/migrate.js +13 -19
  18. package/commands/app/secret/add.js +2 -1
  19. package/commands/app/secret/delete.js +2 -1
  20. package/commands/app/secret/list.js +2 -1
  21. package/commands/app/secret/update.js +2 -1
  22. package/commands/app/secret.js +2 -1
  23. package/commands/app.js +2 -2
  24. package/commands/auth.d.ts +1 -0
  25. package/commands/auth.js +16 -7
  26. package/commands/cms/convertFields.js +7 -9
  27. package/commands/cms/getReactModule.js +9 -14
  28. package/commands/cms/lighthouseScore.js +33 -36
  29. package/commands/cms.js +2 -2
  30. package/commands/completion.js +3 -3
  31. package/commands/config/set.d.ts +1 -1
  32. package/commands/config/set.js +64 -37
  33. package/commands/config.js +2 -2
  34. package/commands/create.js +2 -2
  35. package/commands/customObject/create.js +10 -12
  36. package/commands/customObject/schema/create.js +9 -11
  37. package/commands/customObject/schema/delete.js +16 -16
  38. package/commands/customObject/schema/fetch-all.js +12 -11
  39. package/commands/customObject/schema/fetch.js +15 -15
  40. package/commands/customObject/schema/list.js +4 -4
  41. package/commands/customObject/schema/update.js +13 -13
  42. package/commands/customObject/schema.js +2 -2
  43. package/commands/customObject.js +6 -7
  44. package/commands/doctor.js +8 -11
  45. package/commands/feedback.js +7 -12
  46. package/commands/fetch.js +8 -8
  47. package/commands/filemanager/fetch.js +7 -7
  48. package/commands/filemanager/upload.js +15 -34
  49. package/commands/filemanager.js +2 -2
  50. package/commands/function/deploy.js +11 -29
  51. package/commands/function/list.js +8 -8
  52. package/commands/function/server.js +9 -11
  53. package/commands/function.d.ts +1 -1
  54. package/commands/function.js +2 -2
  55. package/commands/getStarted.d.ts +0 -2
  56. package/commands/getStarted.js +4 -4
  57. package/commands/hubdb/clear.js +7 -15
  58. package/commands/hubdb/create.js +9 -15
  59. package/commands/hubdb/delete.js +8 -15
  60. package/commands/hubdb/fetch.js +6 -9
  61. package/commands/hubdb.d.ts +1 -1
  62. package/commands/hubdb.js +2 -2
  63. package/commands/init.js +2 -3
  64. package/commands/lint.js +16 -16
  65. package/commands/list.js +8 -14
  66. package/commands/logs.js +14 -20
  67. package/commands/mcp/__tests__/setup.test.js +2 -2
  68. package/commands/mcp/setup.js +11 -2
  69. package/commands/mcp.js +3 -3
  70. package/commands/mv.js +6 -17
  71. package/commands/open.js +5 -5
  72. package/commands/project/__tests__/add.test.js +4 -2
  73. package/commands/project/__tests__/create.test.js +6 -6
  74. package/commands/project/__tests__/deploy.test.js +3 -7
  75. package/commands/project/__tests__/devUnifiedFlow.test.js +2 -4
  76. package/commands/project/__tests__/installDeps.test.js +8 -8
  77. package/commands/project/__tests__/logs.test.js +1 -4
  78. package/commands/project/__tests__/migrate.test.js +6 -7
  79. package/commands/project/__tests__/migrateApp.test.js +3 -7
  80. package/commands/project/__tests__/profile.test.js +1 -1
  81. package/commands/project/__tests__/validate.test.js +98 -0
  82. package/commands/project/add.js +4 -8
  83. package/commands/project/cloneApp.js +14 -19
  84. package/commands/project/create.js +2 -9
  85. package/commands/project/deploy.js +5 -5
  86. package/commands/project/dev/deprecatedFlow.js +7 -16
  87. package/commands/project/dev/index.js +16 -13
  88. package/commands/project/dev/unifiedFlow.js +8 -4
  89. package/commands/project/download.js +10 -14
  90. package/commands/project/installDeps.js +8 -9
  91. package/commands/project/listBuilds.js +12 -21
  92. package/commands/project/logs.js +21 -24
  93. package/commands/project/migrate.js +41 -13
  94. package/commands/project/migrateApp.js +10 -17
  95. package/commands/project/open.js +6 -14
  96. package/commands/project/profile/add.js +3 -3
  97. package/commands/project/profile/delete.js +1 -2
  98. package/commands/project/profile.js +2 -3
  99. package/commands/project/upload.js +16 -25
  100. package/commands/project/validate.js +7 -7
  101. package/commands/project/watch.js +13 -22
  102. package/commands/project.js +2 -3
  103. package/commands/sandbox/__tests__/create.test.js +5 -5
  104. package/commands/sandbox/create.js +22 -32
  105. package/commands/sandbox/delete.js +35 -63
  106. package/commands/sandbox.js +2 -2
  107. package/commands/secret/addSecret.js +7 -17
  108. package/commands/secret/deleteSecret.js +10 -20
  109. package/commands/secret/listSecret.js +8 -10
  110. package/commands/secret/updateSecret.js +9 -17
  111. package/commands/secret.js +2 -2
  112. package/commands/testAccount/__tests__/delete.test.js +2 -4
  113. package/commands/testAccount/delete.d.ts +4 -3
  114. package/commands/testAccount/delete.js +155 -14
  115. package/commands/testAccount/importData.d.ts +1 -1
  116. package/commands/testAccount/importData.js +1 -1
  117. package/commands/testAccount.js +1 -1
  118. package/lang/en.d.ts +317 -98
  119. package/lang/en.js +312 -96
  120. package/lang/en.lyaml +2 -2
  121. package/lib/__tests__/buildAccount.test.js +2 -1
  122. package/lib/__tests__/commonOpts.test.js +1 -1
  123. package/lib/__tests__/dependencyManagement.test.js +1 -1
  124. package/lib/__tests__/developerTestAccounts.test.js +3 -3
  125. package/lib/__tests__/npm.test.js +1 -1
  126. package/lib/__tests__/oauth.test.js +4 -4
  127. package/lib/__tests__/process.test.js +10 -5
  128. package/lib/__tests__/sandboxSync.test.js +8 -8
  129. package/lib/__tests__/sandboxes.test.js +8 -8
  130. package/lib/__tests__/serverlessLogs.test.js +1 -1
  131. package/lib/__tests__/usageTracking.test.js +5 -5
  132. package/lib/__tests__/validation.test.js +2 -1
  133. package/lib/__tests__/yargsUtils.test.js +83 -9
  134. package/lib/app/__tests__/migrate.test.js +19 -56
  135. package/lib/app/__tests__/migrate_legacy.test.js +1 -1
  136. package/lib/app/migrate.d.ts +2 -8
  137. package/lib/app/migrate.js +5 -80
  138. package/lib/app/migrate_legacy.js +20 -24
  139. package/lib/buildAccount.js +25 -57
  140. package/lib/commonOpts.d.ts +1 -1
  141. package/lib/commonOpts.js +25 -22
  142. package/lib/configOptions.js +7 -0
  143. package/lib/constants.d.ts +13 -0
  144. package/lib/constants.js +17 -0
  145. package/lib/dependencyManagement.js +9 -27
  146. package/lib/developerTestAccounts.js +9 -23
  147. package/lib/doctor/Diagnosis.js +11 -23
  148. package/lib/doctor/DiagnosticInfoBuilder.js +12 -11
  149. package/lib/doctor/Doctor.js +42 -90
  150. package/lib/doctor/__tests__/Doctor.test.js +4 -4
  151. package/lib/errorHandlers/index.js +12 -20
  152. package/lib/errorHandlers/suppressError.js +10 -17
  153. package/lib/lang.js +6 -5
  154. package/lib/links.d.ts +1 -0
  155. package/lib/links.js +14 -7
  156. package/lib/mcp/setup.js +1 -1
  157. package/lib/middleware/__test__/commandTargetingUtils.test.d.ts +1 -0
  158. package/lib/middleware/__test__/commandTargetingUtils.test.js +99 -0
  159. package/lib/middleware/__test__/configMiddleware.test.js +11 -11
  160. package/lib/middleware/__test__/yargsChecksMiddleware.test.js +6 -8
  161. package/lib/middleware/commandTargetingUtils.d.ts +8 -0
  162. package/lib/middleware/commandTargetingUtils.js +78 -0
  163. package/lib/middleware/configMiddleware.d.ts +1 -1
  164. package/lib/middleware/configMiddleware.js +21 -81
  165. package/lib/middleware/fireAlarmMiddleware.js +15 -5
  166. package/lib/middleware/gitMiddleware.js +5 -1
  167. package/lib/middleware/notificationsMiddleware.js +5 -11
  168. package/lib/middleware/yargsChecksMiddleware.js +6 -9
  169. package/lib/npm.js +2 -2
  170. package/lib/oauth.js +5 -5
  171. package/lib/process.js +5 -4
  172. package/lib/projects/__tests__/AppDevModeInterface.test.js +2 -0
  173. package/lib/projects/__tests__/LocalDevProcess.test.js +227 -16
  174. package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +86 -60
  175. package/lib/projects/__tests__/deploy.test.js +71 -6
  176. package/lib/projects/__tests__/localDevProjectHelpers.test.js +6 -2
  177. package/lib/projects/__tests__/platformVersion.test.js +8 -8
  178. package/lib/projects/__tests__/projects.test.js +12 -12
  179. package/lib/projects/__tests__/structure.test.js +3 -3
  180. package/lib/projects/__tests__/upload.test.d.ts +1 -0
  181. package/lib/projects/__tests__/upload.test.js +82 -0
  182. package/lib/projects/add/__tests__/legacyAddComponent.test.js +6 -6
  183. package/lib/projects/add/__tests__/v3AddComponent.test.js +4 -4
  184. package/lib/projects/create/__tests__/legacy.test.js +5 -5
  185. package/lib/projects/create/__tests__/v3.test.js +80 -5
  186. package/lib/projects/create/index.js +2 -2
  187. package/lib/projects/create/legacy.js +2 -2
  188. package/lib/projects/create/v3.js +10 -8
  189. package/lib/projects/localDev/AppDevModeInterface.d.ts +2 -0
  190. package/lib/projects/localDev/AppDevModeInterface.js +21 -12
  191. package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
  192. package/lib/projects/localDev/LocalDevLogger.js +27 -6
  193. package/lib/projects/localDev/LocalDevManager.js +4 -5
  194. package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
  195. package/lib/projects/localDev/LocalDevProcess.js +90 -19
  196. package/lib/projects/localDev/LocalDevState.d.ts +9 -8
  197. package/lib/projects/localDev/LocalDevState.js +18 -17
  198. package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +2 -1
  199. package/lib/projects/localDev/LocalDevWebsocketServer.js +62 -33
  200. package/lib/projects/localDev/helpers/project.d.ts +1 -0
  201. package/lib/projects/localDev/helpers/project.js +42 -1
  202. package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +4 -0
  203. package/lib/projects/localDev/localDevWebsocketServerUtils.js +10 -0
  204. package/lib/projects/platformVersion.d.ts +1 -1
  205. package/lib/projects/platformVersion.js +1 -1
  206. package/lib/projects/pollProjectBuildAndDeploy.js +4 -4
  207. package/lib/projects/structure.js +6 -6
  208. package/lib/projects/upload.d.ts +1 -1
  209. package/lib/projects/upload.js +17 -8
  210. package/lib/prompts/accountNamePrompt.js +14 -19
  211. package/lib/prompts/accountsPrompt.js +2 -2
  212. package/lib/prompts/cmsFieldPrompt.js +2 -2
  213. package/lib/prompts/createApiSamplePrompt.js +5 -5
  214. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +10 -1
  215. package/lib/prompts/createFunctionPrompt.js +14 -14
  216. package/lib/prompts/createModulePrompt.js +9 -9
  217. package/lib/prompts/createTemplatePrompt.js +2 -2
  218. package/lib/prompts/downloadProjectPrompt.js +5 -8
  219. package/lib/prompts/personalAccessKeyPrompt.js +3 -3
  220. package/lib/prompts/previewPrompt.js +6 -6
  221. package/lib/prompts/projectAddPrompt.js +8 -1
  222. package/lib/prompts/projectDevTargetAccountPrompt.js +20 -32
  223. package/lib/prompts/projectNamePrompt.js +4 -8
  224. package/lib/prompts/projectsLogsPrompt.js +2 -4
  225. package/lib/prompts/promptUtils.js +30 -9
  226. package/lib/prompts/sandboxesPrompt.js +7 -7
  227. package/lib/prompts/secretPrompt.js +3 -3
  228. package/lib/prompts/selectAppPrompt.js +3 -3
  229. package/lib/prompts/selectHubDBTablePrompt.js +9 -13
  230. package/lib/prompts/selectProjectTemplatePrompt.js +2 -0
  231. package/lib/prompts/selectPublicAppForMigrationPrompt.js +15 -19
  232. package/lib/prompts/setAsDefaultAccountPrompt.js +4 -8
  233. package/lib/prompts/uploadPrompt.js +5 -5
  234. package/lib/sandboxSync.js +24 -41
  235. package/lib/sandboxes.js +19 -47
  236. package/lib/schema.js +3 -3
  237. package/lib/serverlessLogs.js +11 -13
  238. package/lib/theme/__tests__/migrate.test.d.ts +1 -0
  239. package/lib/theme/__tests__/migrate.test.js +233 -0
  240. package/lib/theme/migrate.d.ts +13 -0
  241. package/lib/theme/migrate.js +90 -0
  242. package/lib/ui/SpinniesManager.d.ts +2 -0
  243. package/lib/ui/SpinniesManager.js +7 -0
  244. package/lib/ui/boxen.js +1 -2
  245. package/lib/ui/git.js +13 -10
  246. package/lib/ui/index.js +38 -37
  247. package/lib/ui/serverlessFunctionLogs.js +9 -7
  248. package/lib/ui/uiMessages.d.ts +68 -0
  249. package/lib/ui/uiMessages.js +71 -0
  250. package/lib/usageTracking.js +8 -8
  251. package/lib/validation.js +20 -23
  252. package/lib/yargsUtils.d.ts +1 -1
  253. package/lib/yargsUtils.js +12 -5
  254. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
  255. package/mcp-server/tools/index.js +4 -0
  256. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +2 -2
  257. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  258. package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
  259. package/mcp-server/tools/project/DocsSearchTool.js +5 -5
  260. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +23 -0
  261. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +68 -0
  262. package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +11 -0
  263. package/mcp-server/tools/project/GetApplicationInfoTool.js +49 -0
  264. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
  265. package/mcp-server/tools/project/GetConfigValuesTool.js +12 -6
  266. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +2 -2
  267. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +12 -10
  268. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.d.ts +1 -0
  269. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +169 -0
  270. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.d.ts +1 -0
  271. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +115 -0
  272. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -7
  273. package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
  274. package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
  275. package/mcp-server/utils/cliConfig.d.ts +1 -0
  276. package/mcp-server/utils/cliConfig.js +12 -0
  277. package/mcp-server/utils/toolUsageTracking.js +2 -2
  278. package/package.json +4 -4
  279. package/types/LocalDev.d.ts +19 -3
  280. package/ui/index.js +1 -1
  281. package/lib/middleware/__test__/utils.test.js +0 -51
  282. package/lib/middleware/utils.d.ts +0 -8
  283. package/lib/middleware/utils.js +0 -14
  284. /package/{lib/middleware/__test__/utils.test.d.ts → commands/project/__tests__/validate.test.d.ts} +0 -0
@@ -0,0 +1,98 @@
1
+ import path from 'path';
2
+ import { vi } from 'vitest';
3
+ import { validateSourceDirectory } from '../../../lib/projects/upload.js';
4
+ import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
5
+ import { uiLogger } from '../../../lib/ui/logger.js';
6
+ import { commands } from '../../../lang/en.js';
7
+ import { isV2Project } from '../../../lib/projects/platformVersion.js';
8
+ import { loadAndValidateProfile } from '../../../lib/projectProfiles.js';
9
+ import { trackCommandUsage } from '../../../lib/usageTracking.js';
10
+ import { getAccountConfig } from '@hubspot/local-dev-lib/config';
11
+ import { handleTranslate } from '../../../lib/projects/upload.js';
12
+ import projectValidateCommand from '../validate.js';
13
+ // Mock dependencies
14
+ vi.mock('../../../lib/projects/upload.js');
15
+ vi.mock('../../../lib/projects/config.js');
16
+ vi.mock('../../../lib/ui/logger.js');
17
+ vi.mock('../../../lib/usageTracking.js');
18
+ vi.mock('../../../lib/projectProfiles.js');
19
+ vi.mock('../../../lib/errorHandlers/index.js');
20
+ vi.mock('@hubspot/local-dev-lib/config');
21
+ vi.mock('../../../lib/projects/platformVersion.js');
22
+ describe('commands/project/validate', () => {
23
+ const projectDir = '/test/project';
24
+ let exitSpy;
25
+ beforeEach(() => {
26
+ // Mock process.exit to throw to stop execution
27
+ exitSpy = vi.spyOn(process, 'exit').mockImplementation(code => {
28
+ throw new Error(`Process exited with code ${code}`);
29
+ });
30
+ vi.clearAllMocks();
31
+ });
32
+ afterEach(() => {
33
+ exitSpy.mockRestore();
34
+ });
35
+ describe('project configuration validation', () => {
36
+ it('should exit with error when project config is null', async () => {
37
+ vi.mocked(getProjectConfig).mockResolvedValue({
38
+ projectConfig: null,
39
+ projectDir: null,
40
+ });
41
+ await expect(
42
+ // @ts-expect-error partial mock
43
+ projectValidateCommand.handler({
44
+ derivedAccountId: 123,
45
+ d: false,
46
+ debug: false,
47
+ })).rejects.toThrow('Process exited with code 1');
48
+ expect(uiLogger.error).toHaveBeenCalledWith(commands.project.validate.mustBeRanWithinAProject);
49
+ });
50
+ it('should exit with error when project directory is null', async () => {
51
+ vi.mocked(getProjectConfig).mockResolvedValue({
52
+ projectConfig: {
53
+ name: 'test',
54
+ srcDir: 'src',
55
+ platformVersion: '2025.2',
56
+ },
57
+ projectDir: null,
58
+ });
59
+ await expect(
60
+ // @ts-expect-error partial mock
61
+ projectValidateCommand.handler({
62
+ derivedAccountId: 123,
63
+ d: false,
64
+ debug: false,
65
+ })).rejects.toThrow('Process exited with code 1');
66
+ expect(uiLogger.error).toHaveBeenCalledWith(commands.project.validate.mustBeRanWithinAProject);
67
+ });
68
+ });
69
+ it('should call validateSourceDirectory with correct parameters', async () => {
70
+ const mockProjectConfig = {
71
+ name: 'test-project',
72
+ srcDir: 'src',
73
+ platformVersion: '2025.2',
74
+ };
75
+ vi.mocked(getProjectConfig).mockResolvedValue({
76
+ projectConfig: mockProjectConfig,
77
+ projectDir,
78
+ });
79
+ vi.mocked(isV2Project).mockReturnValue(true);
80
+ vi.mocked(validateProjectConfig).mockReturnValue(undefined);
81
+ vi.mocked(loadAndValidateProfile).mockResolvedValue(123);
82
+ vi.mocked(getAccountConfig).mockReturnValue({
83
+ accountType: 'STANDARD',
84
+ accountId: 123,
85
+ env: 'prod',
86
+ });
87
+ vi.mocked(trackCommandUsage);
88
+ vi.mocked(validateSourceDirectory).mockResolvedValue(undefined);
89
+ vi.mocked(handleTranslate).mockResolvedValue(undefined);
90
+ await expect(projectValidateCommand.handler({
91
+ derivedAccountId: 123,
92
+ d: false,
93
+ debug: false,
94
+ })).rejects.toThrow('Process exited with code 0');
95
+ const expectedSrcDir = path.resolve(projectDir, mockProjectConfig.srcDir);
96
+ expect(validateSourceDirectory).toHaveBeenCalledWith(expectedSrcDir, mockProjectConfig, projectDir);
97
+ });
98
+ });
@@ -1,16 +1,15 @@
1
1
  import { logError } from '../../lib/errorHandlers/index.js';
2
2
  import { getProjectConfig } from '../../lib/projects/config.js';
3
- import { uiBetaTag } from '../../lib/ui/index.js';
4
3
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
5
4
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
6
5
  import { commands } from '../../lang/en.js';
7
- import { useV3Api } from '../../lib/projects/platformVersion.js';
6
+ import { isV2Project } from '../../lib/projects/platformVersion.js';
8
7
  import { legacyAddComponent } from '../../lib/projects/add/legacyAddComponent.js';
9
8
  import { v3AddComponent } from '../../lib/projects/add/v3AddComponent.js';
10
9
  import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, } from '../../lib/constants.js';
11
10
  import { uiLogger } from '../../lib/ui/logger.js';
12
11
  const command = 'add';
13
- const describe = uiBetaTag(commands.project.add.describe, false);
12
+ const describe = commands.project.add.describe;
14
13
  async function handler(args) {
15
14
  try {
16
15
  const { derivedAccountId } = args;
@@ -19,8 +18,8 @@ async function handler(args) {
19
18
  uiLogger.error(commands.project.add.error.locationInProject);
20
19
  process.exit(EXIT_CODES.ERROR);
21
20
  }
22
- const isV3ProjectCreate = useV3Api(projectConfig.platformVersion);
23
- if (isV3ProjectCreate) {
21
+ const isV2ProjectCreate = isV2Project(projectConfig.platformVersion);
22
+ if (isV2ProjectCreate) {
24
23
  await v3AddComponent(args, projectDir, projectConfig, derivedAccountId);
25
24
  }
26
25
  else {
@@ -45,19 +44,16 @@ function projectAddBuilder(yargs) {
45
44
  },
46
45
  distribution: {
47
46
  describe: commands.project.add.options.distribution.describe,
48
- hidden: true,
49
47
  type: 'string',
50
48
  choices: [privateDistribution, marketplaceDistribution],
51
49
  },
52
50
  auth: {
53
51
  describe: commands.project.add.options.auth.describe,
54
- hidden: true,
55
52
  type: 'string',
56
53
  choices: [oAuth, staticAuth],
57
54
  },
58
55
  features: {
59
56
  describe: commands.project.add.options.features.describe,
60
- hidden: true,
61
57
  type: 'array',
62
58
  },
63
59
  });
@@ -1,7 +1,7 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs';
3
3
  import { trackCommandUsage, trackCommandMetadataUsage, } from '../../lib/usageTracking.js';
4
- import { i18n } from '../../lib/lang.js';
4
+ import { commands } from '../../lang/en.js';
5
5
  import { selectPublicAppForMigrationPrompt } from '../../lib/prompts/selectPublicAppForMigrationPrompt.js';
6
6
  import { projectNameAndDestPrompt } from '../../lib/prompts/projectNameAndDestPrompt.js';
7
7
  import { poll } from '../../lib/polling.js';
@@ -12,7 +12,7 @@ import { writeProjectConfig } from '../../lib/projects/config.js';
12
12
  import { PROJECT_CONFIG_FILE } from '../../lib/constants.js';
13
13
  import { cloneApp, checkCloneStatus, downloadClonedProject, } from '@hubspot/local-dev-lib/api/projects';
14
14
  import { getCwd, sanitizeFileName } from '@hubspot/local-dev-lib/path';
15
- import { logger } from '@hubspot/local-dev-lib/logger';
15
+ import { uiLogger } from '../../lib/ui/logger.js';
16
16
  import { extractZipArchive } from '@hubspot/local-dev-lib/archive';
17
17
  import { getAccountConfig } from '@hubspot/local-dev-lib/config';
18
18
  import SpinniesManager from '../../lib/ui/SpinniesManager.js';
@@ -20,7 +20,7 @@ import { logInvalidAccountError } from '../../lib/app/migrate.js';
20
20
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
21
21
  import { uiDeprecatedTag, uiLine, uiAccountDescription, } from '../../lib/ui/index.js';
22
22
  const command = 'clone-app';
23
- const describe = uiDeprecatedTag(i18n(`commands.project.subcommands.cloneApp.describe`), false);
23
+ const describe = uiDeprecatedTag(commands.project.cloneApp.describe, false);
24
24
  const deprecated = true;
25
25
  async function handler(args) {
26
26
  const { derivedAccountId } = args;
@@ -28,7 +28,7 @@ async function handler(args) {
28
28
  const accountConfig = getAccountConfig(derivedAccountId);
29
29
  const accountName = uiAccountDescription(derivedAccountId);
30
30
  if (!accountConfig) {
31
- throw new Error(i18n(`commands.projects.subcommands.cloneApp.errors.noAccountConfig`));
31
+ throw new Error(commands.project.cloneApp.errors.noAccountConfig(derivedAccountId));
32
32
  }
33
33
  const defaultAccountIsUnified = await isUnifiedAccount(accountConfig);
34
34
  if (!isAppDeveloperAccount(accountConfig) && !defaultAccountIsUnified) {
@@ -60,7 +60,7 @@ async function handler(args) {
60
60
  try {
61
61
  SpinniesManager.init();
62
62
  SpinniesManager.add('cloneApp', {
63
- text: i18n(`commands.project.subcommands.cloneApp.cloneStatus.inProgress`),
63
+ text: commands.project.cloneApp.cloneStatus.inProgress,
64
64
  });
65
65
  const { data: { exportId }, } = await cloneApp(derivedAccountId, appId);
66
66
  const { status } = await poll(() => checkCloneStatus(derivedAccountId, exportId));
@@ -84,25 +84,23 @@ async function handler(args) {
84
84
  };
85
85
  const success = writeProjectConfig(configPath, configContent);
86
86
  SpinniesManager.succeed('cloneApp', {
87
- text: i18n(`commands.project.subcommands.cloneApp.cloneStatus.done`),
87
+ text: commands.project.cloneApp.cloneStatus.done,
88
88
  succeedColor: 'white',
89
89
  });
90
90
  if (!success) {
91
- logger.error(i18n(`commands.project.subcommands.cloneApp.errors.couldNotWriteConfigPath`), configPath);
91
+ uiLogger.error(commands.project.cloneApp.errors.couldNotWriteConfigPath(configPath));
92
92
  }
93
- logger.log('');
93
+ uiLogger.log('');
94
94
  uiLine();
95
- logger.success(i18n(`commands.project.subcommands.cloneApp.cloneStatus.success`, {
96
- dest: projectDest,
97
- }));
98
- logger.log('');
95
+ uiLogger.success(commands.project.cloneApp.cloneStatus.success(projectDest));
96
+ uiLogger.log('');
99
97
  process.exit(EXIT_CODES.SUCCESS);
100
98
  }
101
99
  }
102
100
  catch (error) {
103
101
  await trackCommandMetadataUsage('clone-app', { successful: false }, derivedAccountId);
104
102
  SpinniesManager.fail('cloneApp', {
105
- text: i18n(`commands.project.subcommands.cloneApp.cloneStatus.failure`),
103
+ text: commands.project.cloneApp.cloneStatus.failure,
106
104
  failColor: 'white',
107
105
  });
108
106
  // Migrations endpoints return a response object with an errors property. The errors property contains an array of errors.
@@ -122,19 +120,16 @@ async function handler(args) {
122
120
  function cloneAppBuilder(yargs) {
123
121
  yargs.options({
124
122
  dest: {
125
- describe: i18n(`commands.project.subcommands.cloneApp.options.dest.describe`),
123
+ describe: commands.project.cloneApp.options.dest.describe,
126
124
  type: 'string',
127
125
  },
128
126
  'app-id': {
129
- describe: i18n(`commands.project.subcommands.cloneApp.options.appId.describe`),
127
+ describe: commands.project.cloneApp.options.appId.describe,
130
128
  type: 'number',
131
129
  },
132
130
  });
133
131
  yargs.example([
134
- [
135
- '$0 project clone-app',
136
- i18n(`commands.project.subcommands.cloneApp.examples.default`),
137
- ],
132
+ ['$0 project clone-app', commands.project.cloneApp.examples.default],
138
133
  ]);
139
134
  return yargs;
140
135
  }
@@ -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;
@@ -97,7 +97,6 @@ async function handler(args) {
97
97
  'projectInstallDepsCommand',
98
98
  'projectHelpCommand',
99
99
  'feedbackCommand',
100
- 'sampleProjects',
101
100
  ]);
102
101
  process.exit(EXIT_CODES.SUCCESS);
103
102
  }
@@ -112,7 +111,6 @@ function projectCreateBuilder(yargs) {
112
111
  type: 'string',
113
112
  },
114
113
  template: {
115
- // TODO: When we release 2025.2 scaffolding, we need to point out this is only valid for 2025.1 prior
116
114
  describe: commands.project.create.options.template.describe,
117
115
  type: 'string',
118
116
  },
@@ -122,32 +120,27 @@ function projectCreateBuilder(yargs) {
122
120
  },
123
121
  'platform-version': {
124
122
  describe: commands.project.create.options.platformVersion.describe,
125
- hidden: true,
126
123
  type: 'string',
127
124
  choices: [v2023_2, v2025_1, v2025_2],
128
125
  default: v2025_2,
129
126
  },
130
127
  'project-base': {
131
128
  describe: commands.project.create.options.projectBase.describe,
132
- hidden: true,
133
129
  type: 'string',
134
130
  choices: [EMPTY_PROJECT, PROJECT_WITH_APP],
135
131
  },
136
132
  distribution: {
137
133
  describe: commands.project.create.options.distribution.describe,
138
- hidden: true,
139
134
  type: 'string',
140
135
  choices: [privateDistribution, marketplaceDistribution],
141
136
  },
142
137
  auth: {
143
138
  describe: commands.project.create.options.auth.describe,
144
- hidden: true,
145
139
  type: 'string',
146
140
  choices: [oAuth, staticAuth],
147
141
  },
148
142
  features: {
149
143
  describe: commands.project.create.options.features.describe,
150
- hidden: true,
151
144
  type: 'array',
152
145
  },
153
146
  });
@@ -1,13 +1,13 @@
1
1
  import { fetchProject } from '@hubspot/local-dev-lib/api/projects';
2
2
  import { getAccountConfig } from '@hubspot/local-dev-lib/config';
3
3
  import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
4
- import { useV3Api } from '../../lib/projects/platformVersion.js';
4
+ import { isV2Project } from '../../lib/projects/platformVersion.js';
5
5
  import { trackCommandUsage } from '../../lib/usageTracking.js';
6
6
  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);
@@ -24,7 +24,7 @@ async function handler(args) {
24
24
  let targetAccountId;
25
25
  const jsonOutput = {};
26
26
  const { projectConfig, projectDir } = await getProjectConfig();
27
- if (useV3Api(projectConfig?.platformVersion)) {
27
+ if (isV2Project(projectConfig?.platformVersion)) {
28
28
  if (args.profile) {
29
29
  logProfileHeader(args.profile);
30
30
  const profile = loadProfile(projectConfig, projectDir, args.profile);
@@ -87,7 +87,7 @@ async function handler(args) {
87
87
  uiLogger.error(commands.project.deploy.errors.noBuildId);
88
88
  return process.exit(EXIT_CODES.ERROR);
89
89
  }
90
- const deployResult = await handleProjectDeploy(targetAccountId, projectName, buildIdToDeploy, useV3Api(projectConfig?.platformVersion), forceOption);
90
+ const deployResult = await handleProjectDeploy(targetAccountId, projectName, buildIdToDeploy, isV2Project(projectConfig?.platformVersion), forceOption);
91
91
  if (!deployResult) {
92
92
  return process.exit(EXIT_CODES.ERROR);
93
93
  }
@@ -1,11 +1,10 @@
1
- import { logger } from '@hubspot/local-dev-lib/logger';
2
1
  import { getAccountConfig, getConfigAccounts, getEnv, } from '@hubspot/local-dev-lib/config';
3
2
  import { getValidEnv } from '@hubspot/local-dev-lib/environment';
4
3
  import { findProjectComponents, getProjectComponentTypes, } from '../../../lib/projects/structure.js';
5
4
  import { ComponentTypes } from '../../../types/Projects.js';
6
- import { i18n } from '../../../lib/lang.js';
5
+ import { commands } from '../../../lang/en.js';
6
+ import { uiLogger } from '../../../lib/ui/logger.js';
7
7
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
8
- import { uiCommandReference } from '../../../lib/ui/index.js';
9
8
  import SpinniesManager from '../../../lib/ui/SpinniesManager.js';
10
9
  import LocalDevManager from '../../../lib/projects/localDev/LocalDevManager.js';
11
10
  import { confirmDefaultAccountIsTarget, suggestRecommendedNestedAccount, checkIfAccountFlagIsSupported, checkIfDefaultAccountIsSupported, createSandboxForLocalDev, createDeveloperTestAccountForLocalDev, useExistingDevTestAccount, checkIfParentAccountIsAuthed, hasSandboxes, } from '../../../lib/projects/localDev/helpers/account.js';
@@ -23,28 +22,20 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
23
22
  const hasPublicApps = !!componentTypes[ComponentTypes.PublicApp];
24
23
  const accountConfig = getAccountConfig(accountId);
25
24
  if (!accountConfig) {
26
- logger.error(i18n('commands.project.subcommands.dev.errors.noAccount', {
27
- accountId: accountId,
28
- authCommand: uiCommandReference('hs auth'),
29
- }));
25
+ uiLogger.error(commands.project.dev.errors.noAccount(accountId));
30
26
  process.exit(EXIT_CODES.ERROR);
31
27
  }
32
28
  if (runnableComponents.length === 0) {
33
- logger.error(i18n(`commands.project.subcommands.dev.errors.noRunnableComponents`, {
34
- projectDir,
35
- command: uiCommandReference('hs project add'),
36
- }));
29
+ uiLogger.error(commands.project.dev.errors.noRunnableComponents);
37
30
  process.exit(EXIT_CODES.SUCCESS);
38
31
  }
39
32
  else if (hasPrivateApps && hasPublicApps) {
40
- logger.error(i18n(`commands.project.subcommands.dev.errors.invalidProjectComponents`));
33
+ uiLogger.error(commands.project.dev.errors.invalidProjectComponents);
41
34
  process.exit(EXIT_CODES.SUCCESS);
42
35
  }
43
36
  const accounts = getConfigAccounts();
44
37
  if (!accounts) {
45
- logger.error(i18n(`commands.project.subcommands.dev.errors.noAccountsInConfig`, {
46
- authCommand: uiCommandReference('hs auth'),
47
- }));
38
+ uiLogger.error(commands.project.dev.errors.noAccountsInConfig);
48
39
  process.exit(EXIT_CODES.ERROR);
49
40
  }
50
41
  let bypassRecommendedAccountPrompt = false;
@@ -110,7 +101,7 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
110
101
  targetProjectAccountId = derivedAccountId;
111
102
  }
112
103
  if (!targetProjectAccountId || !targetTestingAccountId) {
113
- logger.error(i18n(`commands.project.subcommands.dev.errors.noAccount`));
104
+ uiLogger.error(commands.project.dev.errors.noAccount(accountId));
114
105
  process.exit(EXIT_CODES.ERROR);
115
106
  }
116
107
  // eslint-disable-next-line prefer-const
@@ -2,16 +2,16 @@ 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
- import { useV3Api } from '../../../lib/projects/platformVersion.js';
8
+ import { isV2Project } from '../../../lib/projects/platformVersion.js';
9
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
13
  const command = 'dev';
14
- const describe = uiBetaTag(commands.project.dev.describe, false);
14
+ const describe = commands.project.dev.describe;
15
15
  function validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV3) {
16
16
  // Legacy projects do not support targetTestingAccount and targetProjectAccount
17
17
  if (testingAccount && projectAccount && !useV3) {
@@ -27,14 +27,14 @@ async function handler(args) {
27
27
  const { derivedAccountId, userProvidedAccount, testingAccount, projectAccount, } = args;
28
28
  const { projectConfig, projectDir } = await getProjectConfig();
29
29
  validateProjectConfig(projectConfig, projectDir);
30
- const useV3 = useV3Api(projectConfig.platformVersion);
30
+ const useV2Projects = isV2Project(projectConfig.platformVersion);
31
31
  if (!projectDir) {
32
32
  uiLogger.error(commands.project.dev.errors.noProjectConfig);
33
33
  process.exit(EXIT_CODES.ERROR);
34
34
  }
35
- validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV3);
36
- uiBetaTag(commands.project.dev.logs.betaMessage);
37
- if (useV3) {
35
+ validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV2Projects);
36
+ uiLogger.log(commands.project.dev.logs.header);
37
+ if (useV2Projects) {
38
38
  uiLogger.log(commands.project.dev.logs.learnMoreMessageV3);
39
39
  }
40
40
  else {
@@ -54,7 +54,7 @@ async function handler(args) {
54
54
  else if (userProvidedAccount && derivedAccountId) {
55
55
  targetProjectAccountId = derivedAccountId;
56
56
  }
57
- if (!targetProjectAccountId && useV3Api(projectConfig.platformVersion)) {
57
+ if (!targetProjectAccountId && isV2Project(projectConfig.platformVersion)) {
58
58
  if (args.profile) {
59
59
  profile = loadProfile(projectConfig, projectDir, args.profile);
60
60
  if (!profile) {
@@ -73,13 +73,13 @@ async function handler(args) {
73
73
  if (!targetProjectAccountId) {
74
74
  // The user is not using profile or account flags, so we can use the derived accountId
75
75
  targetProjectAccountId = derivedAccountId;
76
- if (useV3) {
76
+ if (useV2Projects) {
77
77
  uiLogger.log('');
78
78
  uiLogger.log(commands.project.dev.logs.defaultProjectAccountExplanation(targetProjectAccountId));
79
79
  }
80
80
  }
81
81
  trackCommandUsage('project-dev', {}, targetProjectAccountId);
82
- if (useV3Api(projectConfig.platformVersion)) {
82
+ if (isV2Project(projectConfig.platformVersion)) {
83
83
  const targetTestingAccountId = (testingAccount && getAccountId(testingAccount)) || undefined;
84
84
  await unifiedProjectDevFlow({
85
85
  args,
@@ -109,15 +109,19 @@ function projectDevBuilder(yargs) {
109
109
  yargs.options('testing-account', {
110
110
  type: 'string',
111
111
  description: commands.project.dev.options.testingAccount,
112
- hidden: true,
113
112
  implies: ['project-account'],
114
113
  });
115
114
  yargs.options('project-account', {
116
115
  type: 'string',
117
116
  description: commands.project.dev.options.projectAccount,
118
- hidden: true,
119
117
  implies: ['testingAccount'],
120
118
  });
119
+ yargs.option('account', {
120
+ alias: 'a',
121
+ describe: '',
122
+ type: 'string',
123
+ description: commands.project.dev.options.account,
124
+ });
121
125
  yargs.example([['$0 project dev', commands.project.dev.examples.default]]);
122
126
  yargs.conflicts('profile', 'account');
123
127
  yargs.conflicts('profile', 'testing-account');
@@ -126,7 +130,6 @@ function projectDevBuilder(yargs) {
126
130
  }
127
131
  export const builder = makeYargsBuilder(projectDevBuilder, command, describe, {
128
132
  useGlobalOptions: true,
129
- useAccountOptions: true,
130
133
  useConfigOptions: true,
131
134
  useEnvironmentOptions: true,
132
135
  });
@@ -8,8 +8,8 @@ import { getValidEnv } from '@hubspot/local-dev-lib/environment';
8
8
  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
- import { createInitialBuildForNewProject, createNewProjectForLocalDev, compareLocalProjectToDeployed, } from '../../../lib/projects/localDev/helpers/project.js';
12
- import { useExistingDevTestAccount, createDeveloperTestAccountForLocalDev, selectAccountTypePrompt, } from '../../../lib/projects/localDev/helpers/account.js';
11
+ import { createInitialBuildForNewProject, createNewProjectForLocalDev, compareLocalProjectToDeployed, checkAndInstallDependencies, } from '../../../lib/projects/localDev/helpers/project.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;
@@ -115,6 +118,8 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
115
118
  project = await createNewProjectForLocalDev(projectConfig, targetProjectAccountId, false, false);
116
119
  await createInitialBuildForNewProject(projectConfig, projectDir, targetProjectAccountId, true, args.profile);
117
120
  }
121
+ // Check for missing/outdated dependencies
122
+ await checkAndInstallDependencies();
118
123
  // End setup, start local dev process
119
124
  const localDevProcess = new LocalDevProcess({
120
125
  initialProjectNodes: projectNodes,
@@ -125,8 +130,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
125
130
  targetTestingAccountId: targetTestingAccountId,
126
131
  projectConfig,
127
132
  projectDir,
128
- projectName: project.name,
129
- projectId: project.id,
133
+ projectData: project,
130
134
  env,
131
135
  });
132
136
  await localDevProcess.start();
@@ -1,22 +1,21 @@
1
1
  import path from 'path';
2
2
  import { getCwd, sanitizeFileName } from '@hubspot/local-dev-lib/path';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
4
3
  import { extractZipArchive } from '@hubspot/local-dev-lib/archive';
5
4
  import { downloadProject, fetchProjectBuilds, } from '@hubspot/local-dev-lib/api/projects';
6
5
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
7
6
  import { getProjectConfig } from '../../lib/projects/config.js';
8
7
  import { downloadProjectPrompt } from '../../lib/prompts/downloadProjectPrompt.js';
9
- import { i18n } from '../../lib/lang.js';
10
- import { uiBetaTag } from '../../lib/ui/index.js';
8
+ import { commands } from '../../lang/en.js';
9
+ import { uiLogger } from '../../lib/ui/logger.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 = commands.project.download.describe;
16
15
  async function handler(args) {
17
16
  const { projectConfig } = await getProjectConfig();
18
17
  if (projectConfig) {
19
- logger.error(i18n(`commands.project.subcommands.download.warnings.cannotDownloadWithinProject`));
18
+ uiLogger.error(commands.project.download.warnings.cannotDownloadWithinProject);
20
19
  process.exit(EXIT_CODES.ERROR);
21
20
  }
22
21
  const { dest, build, derivedAccountId } = args;
@@ -33,16 +32,13 @@ async function handler(args) {
33
32
  }
34
33
  }
35
34
  if (!buildNumberToDownload) {
36
- logger.error(i18n(`commands.project.subcommands.download.errors.noBuildIdToDownload`));
35
+ uiLogger.error(commands.project.download.errors.noBuildIdToDownload);
37
36
  process.exit(EXIT_CODES.ERROR);
38
37
  }
39
38
  const absoluteDestPath = dest ? path.resolve(getCwd(), dest) : getCwd();
40
39
  const { data: zippedProject } = await downloadProject(derivedAccountId, projectName, buildNumberToDownload);
41
40
  await extractZipArchive(zippedProject, sanitizeFileName(projectName), path.resolve(absoluteDestPath), { includesRootDir: false });
42
- logger.log(i18n(`commands.project.subcommands.download.logs.downloadSucceeded`, {
43
- buildId: buildNumberToDownload,
44
- projectName,
45
- }));
41
+ uiLogger.log(commands.project.download.logs.downloadSucceeded(buildNumberToDownload, projectName));
46
42
  process.exit(EXIT_CODES.SUCCESS);
47
43
  }
48
44
  catch (e) {
@@ -56,15 +52,15 @@ async function handler(args) {
56
52
  function projectDownloadBuilder(yargs) {
57
53
  yargs.options({
58
54
  project: {
59
- describe: i18n(`commands.project.subcommands.download.options.project.describe`),
55
+ describe: commands.project.download.options.project.describe,
60
56
  type: 'string',
61
57
  },
62
58
  dest: {
63
- describe: i18n(`commands.project.subcommands.download.options.dest.describe`),
59
+ describe: commands.project.download.options.dest.describe,
64
60
  type: 'string',
65
61
  },
66
62
  build: {
67
- describe: i18n(`commands.project.subcommands.download.options.build.describe`),
63
+ describe: commands.project.download.options.build.describe,
68
64
  alias: ['build-id'],
69
65
  type: 'number',
70
66
  },
@@ -72,7 +68,7 @@ function projectDownloadBuilder(yargs) {
72
68
  yargs.example([
73
69
  [
74
70
  '$0 project download --project=myProject --dest=myProjectFolder',
75
- i18n(`commands.project.subcommands.download.examples.default`),
71
+ commands.project.download.examples.default,
76
72
  ],
77
73
  ]);
78
74
  return yargs;