@hubspot/cli 7.8.0-experimental.0 → 7.8.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 (357) hide show
  1. package/bin/cli.js +31 -27
  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 +2 -3
  7. package/commands/account/auth.js +1 -0
  8. package/commands/account/clean.js +18 -27
  9. package/commands/account/createOverride.js +13 -31
  10. package/commands/account/info.js +20 -31
  11. package/commands/account/list.js +16 -22
  12. package/commands/account/remove.js +12 -20
  13. package/commands/account/removeOverride.js +11 -21
  14. package/commands/account/rename.js +6 -9
  15. package/commands/account/use.js +12 -26
  16. package/commands/account.js +2 -2
  17. package/commands/app/__tests__/migrate.test.js +5 -6
  18. package/commands/app/migrate.js +13 -19
  19. package/commands/app/secret/add.js +2 -1
  20. package/commands/app/secret/delete.js +2 -1
  21. package/commands/app/secret/list.js +2 -1
  22. package/commands/app/secret/update.js +2 -1
  23. package/commands/app/secret.js +2 -1
  24. package/commands/app.js +2 -2
  25. package/commands/auth.d.ts +1 -0
  26. package/commands/auth.js +17 -7
  27. package/commands/cms/convertFields.js +7 -9
  28. package/commands/cms/getReactModule.js +9 -14
  29. package/commands/cms/lighthouseScore.js +33 -36
  30. package/commands/cms.js +2 -2
  31. package/commands/completion.js +3 -3
  32. package/commands/config/set.d.ts +1 -1
  33. package/commands/config/set.js +64 -37
  34. package/commands/config.js +2 -2
  35. package/commands/create.js +2 -2
  36. package/commands/customObject/create.js +10 -12
  37. package/commands/customObject/schema/create.js +9 -11
  38. package/commands/customObject/schema/delete.js +16 -16
  39. package/commands/customObject/schema/fetch-all.js +12 -11
  40. package/commands/customObject/schema/fetch.js +15 -15
  41. package/commands/customObject/schema/list.js +4 -4
  42. package/commands/customObject/schema/update.js +13 -13
  43. package/commands/customObject/schema.js +2 -2
  44. package/commands/customObject.js +6 -7
  45. package/commands/doctor.js +8 -11
  46. package/commands/feedback.js +8 -13
  47. package/commands/fetch.js +8 -8
  48. package/commands/filemanager/fetch.js +7 -7
  49. package/commands/filemanager/upload.js +15 -34
  50. package/commands/filemanager.js +2 -2
  51. package/commands/function/deploy.js +11 -29
  52. package/commands/function/list.js +8 -8
  53. package/commands/function/server.js +9 -11
  54. package/commands/function.d.ts +1 -1
  55. package/commands/function.js +2 -2
  56. package/commands/getStarted.d.ts +1 -3
  57. package/commands/getStarted.js +68 -20
  58. package/commands/hubdb/clear.js +7 -15
  59. package/commands/hubdb/create.js +9 -15
  60. package/commands/hubdb/delete.js +8 -15
  61. package/commands/hubdb/fetch.js +6 -9
  62. package/commands/hubdb.d.ts +1 -1
  63. package/commands/hubdb.js +2 -2
  64. package/commands/init.js +2 -3
  65. package/commands/lint.js +16 -16
  66. package/commands/list.js +8 -14
  67. package/commands/logs.js +14 -20
  68. package/commands/mcp/__tests__/setup.test.js +2 -2
  69. package/commands/mcp/setup.js +11 -2
  70. package/commands/mcp.js +3 -3
  71. package/commands/mv.js +6 -17
  72. package/commands/open.js +5 -5
  73. package/commands/project/__tests__/add.test.js +15 -13
  74. package/commands/project/__tests__/create.test.js +6 -6
  75. package/commands/project/__tests__/deploy.test.js +3 -7
  76. package/commands/project/__tests__/devUnifiedFlow.test.js +2 -4
  77. package/commands/project/__tests__/installDeps.test.js +8 -8
  78. package/commands/project/__tests__/list.test.js +31 -0
  79. package/commands/project/__tests__/logs.test.js +1 -4
  80. package/commands/project/__tests__/migrate.test.js +7 -7
  81. package/commands/project/__tests__/migrateApp.test.js +3 -7
  82. package/commands/project/__tests__/profile.test.js +1 -1
  83. package/commands/project/__tests__/validate.test.js +98 -0
  84. package/commands/project/add.d.ts +2 -2
  85. package/commands/project/add.js +7 -10
  86. package/commands/project/cloneApp.js +14 -19
  87. package/commands/project/create.js +4 -11
  88. package/commands/project/deploy.js +5 -5
  89. package/commands/project/dev/deprecatedFlow.js +9 -18
  90. package/commands/project/dev/index.js +21 -18
  91. package/commands/project/dev/unifiedFlow.js +15 -8
  92. package/commands/project/download.js +15 -16
  93. package/commands/project/installDeps.d.ts +2 -2
  94. package/commands/project/installDeps.js +9 -9
  95. package/commands/project/list.d.ts +4 -0
  96. package/commands/project/list.js +62 -0
  97. package/commands/project/listBuilds.js +12 -21
  98. package/commands/project/logs.js +21 -24
  99. package/commands/project/migrate.js +33 -12
  100. package/commands/project/migrateApp.js +10 -17
  101. package/commands/project/open.js +6 -14
  102. package/commands/project/profile/add.js +3 -3
  103. package/commands/project/profile/delete.js +1 -2
  104. package/commands/project/profile.js +2 -3
  105. package/commands/project/upload.js +16 -25
  106. package/commands/project/validate.js +7 -7
  107. package/commands/project/watch.js +13 -22
  108. package/commands/project.js +4 -3
  109. package/commands/sandbox/__tests__/create.test.js +5 -5
  110. package/commands/sandbox/create.js +22 -32
  111. package/commands/sandbox/delete.js +39 -64
  112. package/commands/sandbox.js +2 -2
  113. package/commands/secret/addSecret.js +7 -17
  114. package/commands/secret/deleteSecret.js +10 -20
  115. package/commands/secret/listSecret.js +8 -10
  116. package/commands/secret/updateSecret.js +9 -17
  117. package/commands/secret.js +2 -2
  118. package/commands/testAccount/__tests__/delete.test.js +2 -4
  119. package/commands/testAccount/create.js +2 -2
  120. package/commands/testAccount/delete.d.ts +4 -3
  121. package/commands/testAccount/delete.js +155 -14
  122. package/commands/testAccount/importData.d.ts +1 -1
  123. package/commands/testAccount/importData.js +1 -1
  124. package/commands/testAccount.js +1 -1
  125. package/commands/theme/preview.js +1 -4
  126. package/lang/en.d.ts +365 -111
  127. package/lang/en.js +409 -158
  128. package/lang/en.lyaml +4 -4
  129. package/lib/__tests__/buildAccount.test.js +4 -3
  130. package/lib/__tests__/commonOpts.test.js +1 -1
  131. package/lib/__tests__/dependencyManagement.test.js +1 -1
  132. package/lib/__tests__/developerTestAccounts.test.js +3 -3
  133. package/lib/__tests__/hasFeature.test.js +145 -7
  134. package/lib/__tests__/npm.test.js +1 -1
  135. package/lib/__tests__/oauth.test.js +4 -4
  136. package/lib/__tests__/process.test.js +10 -5
  137. package/lib/__tests__/sandboxSync.test.js +8 -8
  138. package/lib/__tests__/sandboxes.test.js +8 -8
  139. package/lib/__tests__/serverlessLogs.test.js +1 -1
  140. package/lib/__tests__/usageTracking.test.js +5 -5
  141. package/lib/__tests__/validation.test.js +2 -1
  142. package/lib/__tests__/yargsUtils.test.js +83 -9
  143. package/lib/app/__tests__/migrate.test.js +19 -56
  144. package/lib/app/__tests__/migrate_legacy.test.js +1 -1
  145. package/lib/app/migrate.d.ts +2 -8
  146. package/lib/app/migrate.js +6 -81
  147. package/lib/app/migrate_legacy.js +20 -24
  148. package/lib/buildAccount.d.ts +2 -2
  149. package/lib/buildAccount.js +32 -64
  150. package/lib/commonOpts.d.ts +1 -1
  151. package/lib/commonOpts.js +25 -22
  152. package/lib/configMigrate.js +88 -9
  153. package/lib/configOptions.js +7 -0
  154. package/lib/constants.d.ts +22 -1
  155. package/lib/constants.js +26 -1
  156. package/lib/dependencyManagement.d.ts +0 -5
  157. package/lib/dependencyManagement.js +9 -36
  158. package/lib/developerTestAccounts.js +9 -23
  159. package/lib/doctor/Diagnosis.js +11 -23
  160. package/lib/doctor/DiagnosticInfoBuilder.js +12 -11
  161. package/lib/doctor/Doctor.js +42 -90
  162. package/lib/doctor/__tests__/Doctor.test.js +4 -4
  163. package/lib/errorHandlers/index.js +12 -20
  164. package/lib/errorHandlers/suppressError.js +11 -18
  165. package/lib/hasFeature.js +6 -0
  166. package/lib/lang.js +6 -5
  167. package/lib/links.d.ts +1 -0
  168. package/lib/links.js +14 -7
  169. package/lib/mcp/setup.js +1 -1
  170. package/lib/middleware/__test__/commandTargetingUtils.test.js +99 -0
  171. package/lib/middleware/__test__/configMiddleware.test.js +11 -11
  172. package/lib/middleware/__test__/yargsChecksMiddleware.test.js +6 -8
  173. package/lib/middleware/commandTargetingUtils.d.ts +8 -0
  174. package/lib/middleware/commandTargetingUtils.js +74 -0
  175. package/lib/middleware/configMiddleware.d.ts +1 -1
  176. package/lib/middleware/configMiddleware.js +21 -81
  177. package/lib/middleware/fireAlarmMiddleware.js +15 -5
  178. package/lib/middleware/gitMiddleware.js +5 -1
  179. package/lib/middleware/notificationsMiddleware.js +5 -11
  180. package/lib/middleware/yargsChecksMiddleware.js +6 -9
  181. package/lib/npm.js +2 -2
  182. package/lib/oauth.js +5 -5
  183. package/lib/process.js +5 -4
  184. package/lib/projects/__tests__/AppDevModeInterface.test.js +87 -90
  185. package/lib/projects/__tests__/LocalDevProcess.test.js +231 -19
  186. package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +89 -63
  187. package/lib/projects/__tests__/deploy.test.js +73 -8
  188. package/lib/projects/__tests__/localDevProjectHelpers.test.js +6 -2
  189. package/lib/projects/__tests__/platformVersion.test.js +8 -8
  190. package/lib/projects/__tests__/projects.test.js +12 -12
  191. package/lib/projects/__tests__/structure.test.js +3 -3
  192. package/lib/projects/__tests__/upload.test.d.ts +1 -0
  193. package/lib/projects/__tests__/upload.test.js +82 -0
  194. package/lib/projects/add/__tests__/legacyAddComponent.test.js +6 -6
  195. package/lib/projects/add/__tests__/v2AddComponent.test.d.ts +1 -0
  196. package/lib/projects/add/__tests__/{v3AddComponent.test.js → v2AddComponent.test.js} +39 -39
  197. package/lib/projects/add/{v3AddComponent.d.ts → v2AddComponent.d.ts} +1 -1
  198. package/lib/projects/add/{v3AddComponent.js → v2AddComponent.js} +5 -5
  199. package/lib/projects/create/__tests__/legacy.test.js +5 -5
  200. package/lib/projects/create/__tests__/v2.test.d.ts +1 -0
  201. package/lib/projects/create/__tests__/{v3.test.js → v2.test.js} +82 -7
  202. package/lib/projects/create/index.js +4 -4
  203. package/lib/projects/create/legacy.js +2 -2
  204. package/lib/projects/create/{v3.d.ts → v2.d.ts} +3 -3
  205. package/lib/projects/create/{v3.js → v2.js} +16 -13
  206. package/lib/projects/deploy.d.ts +1 -1
  207. package/lib/projects/deploy.js +2 -2
  208. package/lib/projects/localDev/AppDevModeInterface.d.ts +10 -1
  209. package/lib/projects/localDev/AppDevModeInterface.js +118 -89
  210. package/lib/projects/localDev/DevServerManager.d.ts +11 -29
  211. package/lib/projects/localDev/DevServerManager.js +19 -61
  212. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +40 -0
  213. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +120 -0
  214. package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
  215. package/lib/projects/localDev/LocalDevLogger.js +27 -6
  216. package/lib/projects/localDev/{LocalDevManager.js → LocalDevManager_DEPRECATED.js} +10 -11
  217. package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
  218. package/lib/projects/localDev/LocalDevProcess.js +93 -21
  219. package/lib/projects/localDev/LocalDevState.d.ts +12 -8
  220. package/lib/projects/localDev/LocalDevState.js +27 -17
  221. package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +6 -1
  222. package/lib/projects/localDev/LocalDevWebsocketServer.js +94 -33
  223. package/lib/projects/localDev/helpers/account.d.ts +1 -1
  224. package/lib/projects/localDev/helpers/account.js +2 -2
  225. package/lib/projects/localDev/helpers/project.d.ts +3 -2
  226. package/lib/projects/localDev/helpers/project.js +49 -10
  227. package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +7 -0
  228. package/lib/projects/localDev/localDevWebsocketServerUtils.js +19 -0
  229. package/lib/projects/platformVersion.d.ts +1 -1
  230. package/lib/projects/platformVersion.js +1 -1
  231. package/lib/projects/pollProjectBuildAndDeploy.js +4 -4
  232. package/lib/projects/structure.js +6 -6
  233. package/lib/projects/upload.d.ts +1 -1
  234. package/lib/projects/upload.js +17 -8
  235. package/lib/projects/urls.d.ts +0 -1
  236. package/lib/projects/urls.js +0 -3
  237. package/lib/prompts/__tests__/downloadProjectPrompt.test.js +1 -0
  238. package/lib/prompts/__tests__/projectAddPrompt.test.js +10 -10
  239. package/lib/prompts/accountNamePrompt.js +14 -19
  240. package/lib/prompts/accountsPrompt.js +2 -2
  241. package/lib/prompts/cmsFieldPrompt.js +2 -2
  242. package/lib/prompts/createApiSamplePrompt.js +5 -5
  243. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +10 -1
  244. package/lib/prompts/createFunctionPrompt.js +14 -14
  245. package/lib/prompts/createModulePrompt.js +9 -9
  246. package/lib/prompts/createTemplatePrompt.js +2 -2
  247. package/lib/prompts/downloadProjectPrompt.js +5 -8
  248. package/lib/prompts/installAppPrompt.d.ts +1 -6
  249. package/lib/prompts/installAppPrompt.js +1 -6
  250. package/lib/prompts/personalAccessKeyPrompt.js +3 -3
  251. package/lib/prompts/previewPrompt.js +6 -6
  252. package/lib/prompts/projectAddPrompt.d.ts +2 -2
  253. package/lib/prompts/projectAddPrompt.js +9 -2
  254. package/lib/prompts/projectDevTargetAccountPrompt.js +20 -32
  255. package/lib/prompts/projectNamePrompt.js +4 -8
  256. package/lib/prompts/projectsLogsPrompt.js +2 -4
  257. package/lib/prompts/promptUtils.js +30 -9
  258. package/lib/prompts/sandboxesPrompt.js +7 -7
  259. package/lib/prompts/secretPrompt.js +3 -3
  260. package/lib/prompts/selectAppPrompt.js +3 -3
  261. package/lib/prompts/selectHubDBTablePrompt.js +9 -13
  262. package/lib/prompts/selectProjectTemplatePrompt.js +2 -0
  263. package/lib/prompts/selectPublicAppForMigrationPrompt.js +15 -19
  264. package/lib/prompts/setAsDefaultAccountPrompt.js +4 -8
  265. package/lib/prompts/uploadPrompt.js +5 -5
  266. package/lib/sandboxSync.js +24 -41
  267. package/lib/sandboxes.js +19 -47
  268. package/lib/schema.js +3 -3
  269. package/lib/serverlessLogs.js +11 -13
  270. package/lib/theme/__tests__/migrate.test.d.ts +1 -0
  271. package/lib/theme/__tests__/migrate.test.js +233 -0
  272. package/lib/theme/migrate.d.ts +13 -0
  273. package/lib/theme/migrate.js +90 -0
  274. package/lib/ui/SpinniesManager.d.ts +2 -0
  275. package/lib/ui/SpinniesManager.js +112 -8
  276. package/lib/ui/boxen.js +1 -2
  277. package/lib/ui/git.js +13 -10
  278. package/lib/ui/index.d.ts +4 -0
  279. package/lib/ui/index.js +47 -38
  280. package/lib/ui/serverlessFunctionLogs.js +9 -7
  281. package/lib/ui/uiMessages.d.ts +72 -0
  282. package/lib/ui/uiMessages.js +75 -0
  283. package/lib/usageTracking.js +8 -8
  284. package/lib/validation.js +20 -23
  285. package/lib/yargsUtils.d.ts +1 -1
  286. package/lib/yargsUtils.js +12 -5
  287. package/mcp-server/tools/cms/HsCreateFunctionTool.js +1 -1
  288. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
  289. package/mcp-server/tools/cms/HsCreateModuleTool.js +1 -1
  290. package/mcp-server/tools/cms/HsCreateTemplateTool.js +1 -1
  291. package/mcp-server/tools/cms/HsFunctionLogsTool.js +2 -2
  292. package/mcp-server/tools/cms/HsListFunctionsTool.js +1 -1
  293. package/mcp-server/tools/cms/HsListTool.js +1 -1
  294. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -1
  295. package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +1 -1
  296. package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +1 -1
  297. package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +2 -2
  298. package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +1 -1
  299. package/mcp-server/tools/cms/__tests__/HsListTool.test.js +1 -1
  300. package/mcp-server/tools/index.js +4 -0
  301. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -3
  302. package/mcp-server/tools/project/AddFeatureToProjectTool.js +3 -3
  303. package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
  304. package/mcp-server/tools/project/CreateProjectTool.js +5 -5
  305. package/mcp-server/tools/project/DeployProjectTool.js +1 -1
  306. package/mcp-server/tools/project/DocFetchTool.js +2 -2
  307. package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
  308. package/mcp-server/tools/project/DocsSearchTool.js +7 -7
  309. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +23 -0
  310. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +68 -0
  311. package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +11 -0
  312. package/mcp-server/tools/project/GetApplicationInfoTool.js +49 -0
  313. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
  314. package/mcp-server/tools/project/GetConfigValuesTool.js +13 -7
  315. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +2 -2
  316. package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
  317. package/mcp-server/tools/project/UploadProjectTools.js +2 -2
  318. package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
  319. package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +1 -1
  320. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +2 -2
  321. package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +1 -1
  322. package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +2 -2
  323. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +14 -12
  324. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.d.ts +1 -0
  325. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +169 -0
  326. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.d.ts +1 -0
  327. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +115 -0
  328. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +9 -8
  329. package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -1
  330. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -1
  331. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -1
  332. package/mcp-server/tools/project/constants.d.ts +1 -1
  333. package/mcp-server/tools/project/constants.js +9 -3
  334. package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
  335. package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
  336. package/mcp-server/utils/cliConfig.d.ts +1 -0
  337. package/mcp-server/utils/cliConfig.js +12 -0
  338. package/mcp-server/utils/toolUsageTracking.js +2 -2
  339. package/package.json +8 -12
  340. package/types/LocalDev.d.ts +19 -3
  341. package/ui/components/HorizontalSelectPrompt.js +1 -1
  342. package/ui/index.js +1 -1
  343. package/commands/getStartedV2.d.ts +0 -9
  344. package/commands/getStartedV2.js +0 -39
  345. package/lib/middleware/__test__/utils.test.js +0 -51
  346. package/lib/middleware/utils.d.ts +0 -8
  347. package/lib/middleware/utils.js +0 -14
  348. package/lib/projects/localDev/DevServerManagerV2.d.ts +0 -22
  349. package/lib/projects/localDev/DevServerManagerV2.js +0 -81
  350. package/ui/components/Ascii.d.ts +0 -10
  351. package/ui/components/Ascii.js +0 -11
  352. package/ui/views/GetStarted.d.ts +0 -7
  353. package/ui/views/GetStarted.js +0 -157
  354. /package/{lib/middleware/__test__/utils.test.d.ts → commands/project/__tests__/list.test.d.ts} +0 -0
  355. /package/{lib/projects/add/__tests__/v3AddComponent.test.d.ts → commands/project/__tests__/validate.test.d.ts} +0 -0
  356. /package/lib/{projects/create/__tests__/v3.test.d.ts → middleware/__test__/commandTargetingUtils.test.d.ts} +0 -0
  357. /package/lib/projects/localDev/{LocalDevManager.d.ts → LocalDevManager_DEPRECATED.d.ts} +0 -0
@@ -99,7 +99,7 @@ describe('lib/projects/deploy', () => {
99
99
  const targetAccountId = 12345;
100
100
  const projectName = 'test-project';
101
101
  const buildId = 5;
102
- const useV3Api = true;
102
+ const useV2Api = true;
103
103
  const force = false;
104
104
  it('successfully deploys and returns deploy result', async () => {
105
105
  const mockDeployResponseData = {
@@ -126,9 +126,9 @@ describe('lib/projects/deploy', () => {
126
126
  data: mockDeployResponseData,
127
127
  });
128
128
  mockPollDeployStatus.mockResolvedValue(mockDeployResult);
129
- const result = await handleProjectDeploy(targetAccountId, projectName, buildId, useV3Api, force);
130
- expect(mockDeployProject).toHaveBeenCalledWith(targetAccountId, projectName, buildId, useV3Api, force);
131
- expect(result).toEqual(mockDeployResult);
129
+ const deploy = await handleProjectDeploy(targetAccountId, projectName, buildId, useV2Api, force);
130
+ expect(mockDeployProject).toHaveBeenCalledWith(targetAccountId, projectName, buildId, useV2Api, force);
131
+ expect(deploy).toEqual(mockDeployResult);
132
132
  });
133
133
  it('handles blocked deploy with warnings', async () => {
134
134
  const mockBlockedResponse = {
@@ -150,15 +150,80 @@ describe('lib/projects/deploy', () => {
150
150
  mockDeployProject.mockResolvedValue({
151
151
  data: mockBlockedResponse,
152
152
  });
153
- const result = await handleProjectDeploy(targetAccountId, projectName, buildId, useV3Api, force);
153
+ await handleProjectDeploy(targetAccountId, projectName, buildId, useV2Api, force);
154
154
  expect(mockUiLogger.warn).toHaveBeenCalledWith(commands.project.deploy.errors.deployWarningsHeader);
155
- expect(result).toBeUndefined();
155
+ });
156
+ it('handles blocked deploy with errors (cannot be forced)', async () => {
157
+ const mockBlockedResponse = {
158
+ buildResultType: 'DEPLOY_BLOCKED',
159
+ issues: [
160
+ {
161
+ uid: 'component-1',
162
+ componentTypeName: 'module',
163
+ errorMessages: [],
164
+ blockingMessages: [
165
+ {
166
+ message: 'This is an error',
167
+ isWarning: false,
168
+ },
169
+ ],
170
+ },
171
+ ],
172
+ };
173
+ mockDeployProject.mockResolvedValue({
174
+ data: mockBlockedResponse,
175
+ });
176
+ await handleProjectDeploy(targetAccountId, projectName, buildId, useV2Api, force);
177
+ expect(mockUiLogger.error).toHaveBeenCalledWith(commands.project.deploy.errors.deployBlockedHeader);
178
+ expect(mockUiLogger.log).toHaveBeenCalledWith(commands.project.deploy.errors.deployIssueComponentWarning('component-1', 'module', 'This is an error'));
179
+ });
180
+ it('handles blocked deploy with no blocking messages', async () => {
181
+ const mockBlockedResponse = {
182
+ buildResultType: 'DEPLOY_BLOCKED',
183
+ issues: [
184
+ {
185
+ uid: 'component-1',
186
+ componentTypeName: 'module',
187
+ errorMessages: [],
188
+ blockingMessages: [],
189
+ },
190
+ ],
191
+ };
192
+ mockDeployProject.mockResolvedValue({
193
+ data: mockBlockedResponse,
194
+ });
195
+ await handleProjectDeploy(targetAccountId, projectName, buildId, useV2Api, force);
196
+ expect(mockUiLogger.warn).toHaveBeenCalledWith(commands.project.deploy.errors.deployWarningsHeader);
197
+ expect(mockUiLogger.log).toHaveBeenCalledWith(commands.project.deploy.errors.deployIssueComponentGeneric('component-1', 'module'));
156
198
  });
157
199
  it('handles general deploy failure', async () => {
158
200
  mockDeployProject.mockResolvedValue({ data: null });
159
- const result = await handleProjectDeploy(targetAccountId, projectName, buildId, useV3Api, force);
201
+ const deploy = await handleProjectDeploy(targetAccountId, projectName, buildId, useV2Api, force);
202
+ expect(mockUiLogger.error).toHaveBeenCalledWith(commands.project.deploy.errors.deploy);
203
+ expect(deploy).toBeUndefined();
204
+ });
205
+ it('handles undefined deploy response', async () => {
206
+ mockDeployProject.mockResolvedValue({ data: undefined });
207
+ const deploy = await handleProjectDeploy(targetAccountId, projectName, buildId, useV2Api, force);
160
208
  expect(mockUiLogger.error).toHaveBeenCalledWith(commands.project.deploy.errors.deploy);
161
- expect(result).toBeUndefined();
209
+ expect(deploy).toBeUndefined();
210
+ });
211
+ it('passes correct parameters to deployProject', async () => {
212
+ const mockDeployResponseData = {
213
+ id: 'deploy-123',
214
+ buildResultType: 'DEPLOY_QUEUED',
215
+ links: {
216
+ status: 'http://status-url',
217
+ },
218
+ };
219
+ mockDeployProject.mockResolvedValue({
220
+ data: mockDeployResponseData,
221
+ });
222
+ mockPollDeployStatus.mockResolvedValue({});
223
+ await handleProjectDeploy(targetAccountId, projectName, buildId, false, true);
224
+ expect(mockDeployProject).toHaveBeenCalledWith(targetAccountId, projectName, buildId, false, // useV2Api
225
+ true // force
226
+ );
162
227
  });
163
228
  });
164
229
  });
@@ -30,6 +30,8 @@ describe('isDeployedProjectUpToDateWithLocal', () => {
30
30
  componentRoot: '/local/path',
31
31
  componentConfigPath: '/local/path/config.json',
32
32
  configUpdatedSinceLastUpload: false,
33
+ removed: false,
34
+ parsingErrors: [],
33
35
  },
34
36
  componentDeps: {},
35
37
  metaFilePath: '/local/path',
@@ -99,7 +101,8 @@ describe('isDeployedProjectUpToDateWithLocal', () => {
99
101
  it('should clean up temp directory even when errors occur', async () => {
100
102
  // Mock downloadProject to throw an error after temp dir is created
101
103
  downloadProject.mockRejectedValue(new Error('Download Error'));
102
- await expect(isDeployedProjectUpToDateWithLocal(mockProjectConfig, mockAccountId, mockBuildId, mockLocalProjectNodes)).rejects.toThrow('Download Error');
104
+ const result = await isDeployedProjectUpToDateWithLocal(mockProjectConfig, mockAccountId, mockBuildId, mockLocalProjectNodes);
105
+ expect(result).toBe(false);
103
106
  expect(fs.remove).toHaveBeenCalledWith(mockTempDir);
104
107
  });
105
108
  it('should handle translateForLocalDev errors', async () => {
@@ -111,7 +114,8 @@ describe('isDeployedProjectUpToDateWithLocal', () => {
111
114
  extractZipArchive.mockResolvedValue(undefined);
112
115
  // Mock translate to throw an error
113
116
  translate.mockRejectedValue(new Error('Translation Error'));
114
- await expect(isDeployedProjectUpToDateWithLocal(mockProjectConfig, mockAccountId, mockBuildId, mockLocalProjectNodes)).rejects.toThrow('Translation Error');
117
+ const result = await isDeployedProjectUpToDateWithLocal(mockProjectConfig, mockAccountId, mockBuildId, mockLocalProjectNodes);
118
+ expect(result).toBe(false);
115
119
  expect(fs.remove).toHaveBeenCalledWith(mockTempDir);
116
120
  });
117
121
  });
@@ -1,23 +1,23 @@
1
- import { useV3Api } from '../platformVersion.js';
1
+ import { isV2Project } from '../platformVersion.js';
2
2
  describe('platformVersion', () => {
3
- describe('useV3Api', () => {
3
+ describe('isV2Project', () => {
4
4
  it('returns true if platform version is UNSTABLE', () => {
5
- expect(useV3Api('UNSTABLE')).toBe(true);
5
+ expect(isV2Project('UNSTABLE')).toBe(true);
6
6
  });
7
7
  it('returns true if platform version is equal to the minimum', () => {
8
- expect(useV3Api('2025.2')).toBe(true);
8
+ expect(isV2Project('2025.2')).toBe(true);
9
9
  });
10
10
  it('returns true if platform version is greater than the minimum', () => {
11
- expect(useV3Api('2026.2')).toBe(true);
11
+ expect(isV2Project('2026.2')).toBe(true);
12
12
  });
13
13
  it('returns false if platform version is less than the minimum', () => {
14
- expect(useV3Api('2025.0')).toBe(false);
14
+ expect(isV2Project('2025.0')).toBe(false);
15
15
  });
16
16
  it('returns false if platform version is invalid', () => {
17
- expect(useV3Api(null)).toBe(false);
17
+ expect(isV2Project(null)).toBe(false);
18
18
  });
19
19
  it('returns false for an invalid platform version', () => {
20
- expect(useV3Api('notplaformversion')).toBe(false);
20
+ expect(isV2Project('notplaformversion')).toBe(false);
21
21
  });
22
22
  });
23
23
  });
@@ -3,8 +3,8 @@ import os from 'os';
3
3
  import path from 'path';
4
4
  import { EXIT_CODES } from '../../enums/exitCodes.js';
5
5
  import { validateProjectConfig } from '../../projects/config.js';
6
- import { logger } from '@hubspot/local-dev-lib/logger';
7
- vi.mock('@hubspot/local-dev-lib/logger');
6
+ import { uiLogger } from '../../ui/logger.js';
7
+ vi.mock('../../ui/logger.js');
8
8
  describe('lib/projects', () => {
9
9
  describe('validateProjectConfig()', () => {
10
10
  let projectDir;
@@ -26,58 +26,58 @@ describe('lib/projects', () => {
26
26
  // @ts-ignore Testing invalid input
27
27
  validateProjectConfig(null, projectDir);
28
28
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
29
- expect(logger.error).toHaveBeenCalledWith(expect.stringMatching(/.*Unable to locate a project configuration file. Try running again from a project directory, or run*/));
29
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/.*Unable to locate a project configuration file. Try running again from a project directory, or run*/));
30
30
  });
31
31
  it('rejects configuration with missing name', () => {
32
32
  // @ts-ignore Testing invalid input
33
33
  validateProjectConfig({ srcDir: '.' }, projectDir);
34
34
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
35
- expect(logger.error).toHaveBeenCalledWith(expect.stringMatching(/.*missing required fields*/));
35
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/.*missing required fields*/));
36
36
  });
37
37
  it('rejects configuration with missing srcDir', () => {
38
38
  // @ts-ignore Testing invalid input
39
39
  validateProjectConfig({ name: 'hello' }, projectDir);
40
40
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
41
- expect(logger.error).toHaveBeenCalledWith(expect.stringMatching(/.*missing required fields.*/));
41
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/.*missing required fields.*/));
42
42
  });
43
43
  describe('rejects configuration with srcDir outside project directory', () => {
44
44
  it('for parent directory', () => {
45
45
  validateProjectConfig({ name: 'hello', srcDir: '..', platformVersion: '' }, projectDir);
46
46
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
47
- expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('srcDir: ".."'));
47
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('srcDir: ".."'));
48
48
  });
49
49
  it('for root directory', () => {
50
50
  validateProjectConfig({ name: 'hello', srcDir: '/', platformVersion: '' }, projectDir);
51
51
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
52
- expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('srcDir: "/"'));
52
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('srcDir: "/"'));
53
53
  });
54
54
  it('for complicated directory', () => {
55
55
  const srcDir = './src/././../src/../../src';
56
56
  validateProjectConfig({ name: 'hello', srcDir, platformVersion: '' }, projectDir);
57
57
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
58
- expect(logger.error).toHaveBeenCalledWith(expect.stringContaining(`srcDir: "${srcDir}"`));
58
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining(`srcDir: "${srcDir}"`));
59
59
  });
60
60
  });
61
61
  it('rejects configuration with srcDir that does not exist', () => {
62
62
  validateProjectConfig({ name: 'hello', srcDir: 'foo', platformVersion: '' }, projectDir);
63
63
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
64
- expect(logger.error).toHaveBeenCalledWith(expect.stringMatching(/.*could not be found in.*/));
64
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/.*could not be found in.*/));
65
65
  });
66
66
  describe('accepts configuration with valid srcDir', () => {
67
67
  it('for current directory', () => {
68
68
  validateProjectConfig({ name: 'hello', srcDir: '.', platformVersion: '' }, projectDir);
69
69
  expect(exitMock).not.toHaveBeenCalled();
70
- expect(logger.error).not.toHaveBeenCalled();
70
+ expect(uiLogger.error).not.toHaveBeenCalled();
71
71
  });
72
72
  it('for relative directory', () => {
73
73
  validateProjectConfig({ name: 'hello', srcDir: './src', platformVersion: '' }, projectDir);
74
74
  expect(exitMock).not.toHaveBeenCalled();
75
- expect(logger.error).not.toHaveBeenCalled();
75
+ expect(uiLogger.error).not.toHaveBeenCalled();
76
76
  });
77
77
  it('for implied relative directory', () => {
78
78
  validateProjectConfig({ name: 'hello', srcDir: 'src', platformVersion: '' }, projectDir);
79
79
  expect(exitMock).not.toHaveBeenCalled();
80
- expect(logger.error).not.toHaveBeenCalled();
80
+ expect(uiLogger.error).not.toHaveBeenCalled();
81
81
  });
82
82
  });
83
83
  });
@@ -1,11 +1,11 @@
1
1
  import fs from 'fs';
2
2
  import * as HSfs from '@hubspot/local-dev-lib/fs';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
3
+ import { uiLogger } from '../../ui/logger.js';
4
4
  import { getComponentTypeFromConfigFile, loadConfigFile, getAppCardConfigs, getIsLegacyApp, componentIsApp, findProjectComponents, getProjectComponentTypes, getComponentUid, componentIsPublicApp, } from '../structure.js';
5
5
  import { ComponentTypes } from '../../../types/Projects.js';
6
6
  vi.mock('fs');
7
7
  vi.mock('@hubspot/local-dev-lib/fs');
8
- vi.mock('@hubspot/local-dev-lib/logger');
8
+ vi.mock('../../ui/logger.js');
9
9
  const mockedReadFileSync = fs.readFileSync;
10
10
  const mockedWalk = HSfs.walk;
11
11
  const getMockPrivateAppConfig = (cards = []) => ({
@@ -46,7 +46,7 @@ describe('lib/projects/structure', () => {
46
46
  throw new Error('File not found');
47
47
  });
48
48
  expect(loadConfigFile('nonexistent/path/app.json')).toBeNull();
49
- expect(logger.debug).toHaveBeenCalled();
49
+ expect(uiLogger.debug).toHaveBeenCalled();
50
50
  });
51
51
  });
52
52
  describe('getAppCardConfigs()', () => {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,82 @@
1
+ import fs from 'fs-extra';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { vi } from 'vitest';
5
+ import { validateSourceDirectory } from '../upload.js';
6
+ import { uiLogger } from '../../ui/logger.js';
7
+ import { lib } from '../../../lang/en.js';
8
+ import { isV2Project } from '../platformVersion.js';
9
+ import ProjectValidationError from '../../errors/ProjectValidationError.js';
10
+ import { walk } from '@hubspot/local-dev-lib/fs';
11
+ // Mock dependencies
12
+ vi.mock('../../ui/logger.js');
13
+ vi.mock('../platformVersion.js');
14
+ vi.mock('@hubspot/local-dev-lib/fs');
15
+ describe('lib/projects/upload', () => {
16
+ describe('validateSourceDirectory', () => {
17
+ let tempDir;
18
+ let srcDir;
19
+ let projectConfig;
20
+ beforeEach(() => {
21
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'upload-test-'));
22
+ srcDir = path.join(tempDir, 'src');
23
+ fs.mkdirSync(srcDir, { recursive: true });
24
+ projectConfig = {
25
+ name: 'test-project',
26
+ srcDir: 'src',
27
+ platformVersion: '2025.2',
28
+ };
29
+ vi.clearAllMocks();
30
+ });
31
+ afterEach(() => {
32
+ fs.removeSync(tempDir);
33
+ });
34
+ it('should throw ProjectValidationError when source directory is empty', async () => {
35
+ vi.mocked(walk).mockResolvedValue([]);
36
+ await expect(validateSourceDirectory(srcDir, projectConfig, tempDir)).rejects.toThrow(ProjectValidationError);
37
+ expect(walk).toHaveBeenCalledWith(srcDir, ['node_modules']);
38
+ });
39
+ it('should warn about legacy files in V2 projects', async () => {
40
+ vi.mocked(isV2Project).mockReturnValue(true);
41
+ const legacyFilePath = path.join(srcDir, 'app', 'serverless.json');
42
+ vi.mocked(walk).mockResolvedValue([legacyFilePath]);
43
+ await validateSourceDirectory(srcDir, projectConfig, tempDir);
44
+ expect(uiLogger.warn).toHaveBeenCalledWith(lib.projectUpload.handleProjectUpload.legacyFileDetected('src/app/serverless.json', '2025.2'));
45
+ });
46
+ it('should warn about multiple legacy files', async () => {
47
+ vi.mocked(isV2Project).mockReturnValue(true);
48
+ const filePaths = [
49
+ path.join(srcDir, 'app1', 'serverless.json'),
50
+ path.join(srcDir, 'app2', 'app.json'),
51
+ path.join(srcDir, 'app3', 'public-app.json'),
52
+ ];
53
+ vi.mocked(walk).mockResolvedValue(filePaths);
54
+ await validateSourceDirectory(srcDir, projectConfig, tempDir);
55
+ expect(uiLogger.warn).toHaveBeenCalledTimes(3);
56
+ expect(uiLogger.warn).toHaveBeenCalledWith(lib.projectUpload.handleProjectUpload.legacyFileDetected('src/app1/serverless.json', '2025.2'));
57
+ expect(uiLogger.warn).toHaveBeenCalledWith(lib.projectUpload.handleProjectUpload.legacyFileDetected('src/app2/app.json', '2025.2'));
58
+ expect(uiLogger.warn).toHaveBeenCalledWith(lib.projectUpload.handleProjectUpload.legacyFileDetected('src/app3/public-app.json', '2025.2'));
59
+ });
60
+ it('should not warn about non-legacy files', async () => {
61
+ vi.mocked(isV2Project).mockReturnValue(true);
62
+ const filePaths = [
63
+ path.join(srcDir, 'component.js'),
64
+ path.join(srcDir, 'config.json'),
65
+ ];
66
+ vi.mocked(walk).mockResolvedValue(filePaths);
67
+ await validateSourceDirectory(srcDir, projectConfig, tempDir);
68
+ expect(uiLogger.warn).not.toHaveBeenCalled();
69
+ });
70
+ it('should not warn about legacy files in non-V2 projects', async () => {
71
+ vi.mocked(isV2Project).mockReturnValue(false);
72
+ projectConfig.platformVersion = '2025.1';
73
+ const filePaths = [
74
+ path.join(srcDir, 'app', 'serverless.json'),
75
+ path.join(srcDir, 'app', 'app.json'),
76
+ ];
77
+ vi.mocked(walk).mockResolvedValue(filePaths);
78
+ await validateSourceDirectory(srcDir, projectConfig, tempDir);
79
+ expect(uiLogger.warn).not.toHaveBeenCalled();
80
+ });
81
+ });
82
+ });
@@ -2,7 +2,7 @@ import { legacyAddComponent } from '../legacyAddComponent.js';
2
2
  import { findProjectComponents } from '../../structure.js';
3
3
  import { getProjectComponentListFromRepo } from '../../create/legacy.js';
4
4
  import { projectAddPrompt } from '../../../prompts/projectAddPrompt.js';
5
- import { logger } from '@hubspot/local-dev-lib/logger';
5
+ import { uiLogger } from '../../../ui/logger.js';
6
6
  import { cloneGithubRepo } from '@hubspot/local-dev-lib/github';
7
7
  import { trackCommandUsage } from '../../../usageTracking.js';
8
8
  import { ComponentTypes, } from '../../../../types/Projects.js';
@@ -10,13 +10,13 @@ import { commands } from '../../../../lang/en.js';
10
10
  vi.mock('../../structure');
11
11
  vi.mock('../../create/legacy');
12
12
  vi.mock('../../../prompts/projectAddPrompt');
13
- vi.mock('@hubspot/local-dev-lib/logger');
13
+ vi.mock('../../../ui/logger.js');
14
14
  vi.mock('@hubspot/local-dev-lib/github');
15
15
  vi.mock('../../../usageTracking.js');
16
16
  const mockedFindProjectComponents = vi.mocked(findProjectComponents);
17
17
  const mockedGetProjectComponentListFromRepo = vi.mocked(getProjectComponentListFromRepo);
18
18
  const mockedProjectAddPrompt = vi.mocked(projectAddPrompt);
19
- const mockedLogger = vi.mocked(logger);
19
+ const mockedUiLogger = vi.mocked(uiLogger);
20
20
  const mockedCloneGithubRepo = vi.mocked(cloneGithubRepo);
21
21
  const mockedTrackCommandUsage = vi.mocked(trackCommandUsage);
22
22
  describe('lib/projects/add/legacyAddComponent', () => {
@@ -75,8 +75,8 @@ describe('lib/projects/add/legacyAddComponent', () => {
75
75
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
76
76
  type: 'module',
77
77
  }, accountId);
78
- expect(mockedLogger.log).toHaveBeenCalledWith(commands.project.add.creatingComponent('test-project'));
79
- expect(mockedLogger.success).toHaveBeenCalledWith(commands.project.add.success('new-component'));
78
+ expect(mockedUiLogger.log).toHaveBeenCalledWith(commands.project.add.creatingComponent('test-project'));
79
+ expect(mockedUiLogger.success).toHaveBeenCalledWith(commands.project.add.success('new-component'));
80
80
  });
81
81
  it('throws an error when project contains a public app', async () => {
82
82
  const mockComponents = [
@@ -206,7 +206,7 @@ describe('lib/projects/add/legacyAddComponent', () => {
206
206
  mockedCloneGithubRepo.mockRejectedValue(new Error('Clone failed'));
207
207
  await expect(legacyAddComponent(mockArgs, projectDir, mockProjectConfig, accountId)).rejects.toThrow(commands.project.add.error.failedToDownloadComponent);
208
208
  expect(mockedCloneGithubRepo).toHaveBeenCalled();
209
- expect(mockedLogger.success).not.toHaveBeenCalled();
209
+ expect(mockedUiLogger.success).not.toHaveBeenCalled();
210
210
  });
211
211
  it('calls trackCommandUsage with correct component type', async () => {
212
212
  const mockComponents = [
@@ -1,37 +1,37 @@
1
1
  import fs from 'fs';
2
- import { v3AddComponent } from '../v3AddComponent.js';
2
+ import { v2AddComponent } from '../v2AddComponent.js';
3
3
  import { getConfigForPlatformVersion } from '../../create/legacy.js';
4
- import { createV3App } from '../../create/v3.js';
4
+ import { createV2App } from '../../create/v2.js';
5
5
  import { confirmPrompt } from '../../../prompts/promptUtils.js';
6
- import { projectAddPromptV3 } from '../../../prompts/projectAddPrompt.js';
6
+ import { projectAddPromptV2 } from '../../../prompts/projectAddPrompt.js';
7
7
  import { cloneGithubRepo } from '@hubspot/local-dev-lib/github';
8
- import { logger } from '@hubspot/local-dev-lib/logger';
8
+ import { uiLogger } from '../../../ui/logger.js';
9
9
  import { getProjectMetadata } from '@hubspot/project-parsing-lib/src/lib/project.js';
10
10
  import { trackCommandUsage } from '../../../usageTracking.js';
11
11
  import { commands } from '../../../../lang/en.js';
12
12
  vi.mock('fs');
13
13
  vi.mock('../../../prompts/promptUtils');
14
14
  vi.mock('../../create/legacy');
15
- vi.mock('../../create/v3');
15
+ vi.mock('../../create/v2');
16
16
  vi.mock('../../../prompts/projectAddPrompt');
17
17
  vi.mock('@hubspot/local-dev-lib/github');
18
- vi.mock('@hubspot/local-dev-lib/logger');
18
+ vi.mock('../../../ui/logger.js');
19
19
  vi.mock('@hubspot/project-parsing-lib/src/lib/project');
20
20
  vi.mock('../../../usageTracking');
21
21
  const mockedFs = vi.mocked(fs);
22
22
  const mockedGetConfigForPlatformVersion = vi.mocked(getConfigForPlatformVersion);
23
23
  const mockedConfirmPrompt = vi.mocked(confirmPrompt);
24
- const mockedCreateV3App = vi.mocked(createV3App);
25
- const mockedProjectAddPromptV3 = vi.mocked(projectAddPromptV3);
24
+ const mockedCreateV2App = vi.mocked(createV2App);
25
+ const mockedProjectAddPromptV2 = vi.mocked(projectAddPromptV2);
26
26
  const mockedCloneGithubRepo = vi.mocked(cloneGithubRepo);
27
- const mockedLogger = vi.mocked(logger);
27
+ const mockedUiLogger = vi.mocked(uiLogger);
28
28
  const mockedGetProjectMetadata = vi.mocked(getProjectMetadata);
29
29
  const mockedTrackCommandUsage = vi.mocked(trackCommandUsage);
30
- describe('lib/projects/add/v3AddComponent', () => {
30
+ describe('lib/projects/add/v2AddComponent', () => {
31
31
  const mockProjectConfig = {
32
32
  name: 'test-project',
33
33
  srcDir: 'src',
34
- platformVersion: 'v3',
34
+ platformVersion: '2025.2',
35
35
  };
36
36
  const mockArgs = {
37
37
  name: 'test-component',
@@ -66,13 +66,13 @@ describe('lib/projects/add/v3AddComponent', () => {
66
66
  },
67
67
  };
68
68
  beforeEach(() => {
69
- mockedCreateV3App.mockResolvedValue({
69
+ mockedCreateV2App.mockResolvedValue({
70
70
  authType: 'oauth',
71
71
  distribution: 'private',
72
72
  });
73
73
  mockedTrackCommandUsage.mockResolvedValue();
74
74
  });
75
- describe('v3AddComponent()', () => {
75
+ describe('v2AddComponent()', () => {
76
76
  it('successfully adds a component when app already exists', async () => {
77
77
  const mockAppMeta = {
78
78
  config: {
@@ -86,21 +86,21 @@ describe('lib/projects/add/v3AddComponent', () => {
86
86
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
87
87
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadata);
88
88
  mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockAppMeta));
89
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
89
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
90
90
  mockedCloneGithubRepo.mockResolvedValue(true);
91
- await v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
92
- expect(mockedGetConfigForPlatformVersion).toHaveBeenCalledWith('v3');
91
+ await v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
92
+ expect(mockedGetConfigForPlatformVersion).toHaveBeenCalledWith('2025.2');
93
93
  expect(mockedGetProjectMetadata).toHaveBeenCalledWith('/path/to/project/src');
94
- expect(mockedProjectAddPromptV3).toHaveBeenCalled();
94
+ expect(mockedProjectAddPromptV2).toHaveBeenCalled();
95
95
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
96
96
  type: 'module',
97
97
  }, mockAccountId);
98
98
  expect(mockedCloneGithubRepo).toHaveBeenCalledWith(expect.any(String), projectDir, expect.objectContaining({
99
- sourceDir: ['v3/test-component'],
99
+ sourceDir: ['2025.2/test-component'],
100
100
  hideLogs: true,
101
101
  branch: 'main',
102
102
  }));
103
- expect(mockedLogger.success).toHaveBeenCalled();
103
+ expect(mockedUiLogger.success).toHaveBeenCalled();
104
104
  });
105
105
  it('creates an app when no app exists and user confirms', async () => {
106
106
  const mockProjectMetadataNoApps = {
@@ -116,15 +116,15 @@ describe('lib/projects/add/v3AddComponent', () => {
116
116
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
117
117
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadataNoApps);
118
118
  mockedConfirmPrompt.mockResolvedValue(true);
119
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
119
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
120
120
  mockedCloneGithubRepo.mockResolvedValue(true);
121
- await v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
122
- expect(mockedCreateV3App).toHaveBeenCalled();
121
+ await v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
122
+ expect(mockedCreateV2App).toHaveBeenCalled();
123
123
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
124
124
  type: 'module',
125
125
  }, mockAccountId);
126
126
  expect(mockedCloneGithubRepo).toHaveBeenCalledWith(expect.any(String), projectDir, expect.objectContaining({
127
- sourceDir: ['v3/test-component', 'v3/app-template'],
127
+ sourceDir: ['2025.2/test-component', '2025.2/app-template'],
128
128
  }));
129
129
  });
130
130
  it('should not call clone', async () => {
@@ -145,10 +145,10 @@ describe('lib/projects/add/v3AddComponent', () => {
145
145
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
146
146
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadataNoApps);
147
147
  mockedConfirmPrompt.mockResolvedValue(true);
148
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
148
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
149
149
  mockedCloneGithubRepo.mockResolvedValue(true);
150
- await v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
151
- expect(mockedCreateV3App).not.toHaveBeenCalled();
150
+ await v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
151
+ expect(mockedCreateV2App).not.toHaveBeenCalled();
152
152
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
153
153
  type: '',
154
154
  }, mockAccountId);
@@ -164,7 +164,7 @@ describe('lib/projects/add/v3AddComponent', () => {
164
164
  };
165
165
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
166
166
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadataMaxApps);
167
- await expect(v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow('This project currently has the maximum number of apps: 1');
167
+ await expect(v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow('This project currently has the maximum number of apps: 1');
168
168
  });
169
169
  it('throws an error when components list is empty', async () => {
170
170
  const mockEmptyConfig = {
@@ -172,7 +172,7 @@ describe('lib/projects/add/v3AddComponent', () => {
172
172
  parentComponents: [],
173
173
  };
174
174
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockEmptyConfig);
175
- await expect(v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow(commands.project.add.error.failedToFetchComponentList);
175
+ await expect(v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow(commands.project.add.error.failedToFetchComponentList);
176
176
  });
177
177
  it('throws an error when app meta file cannot be parsed', async () => {
178
178
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
@@ -180,7 +180,7 @@ describe('lib/projects/add/v3AddComponent', () => {
180
180
  mockedFs.readFileSync.mockImplementation(() => {
181
181
  throw new Error('File read error');
182
182
  });
183
- await expect(v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow('Unable to parse app file');
183
+ await expect(v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow('Unable to parse app file');
184
184
  });
185
185
  it('throws an error when cloning fails', async () => {
186
186
  const mockAppMeta = {
@@ -195,9 +195,9 @@ describe('lib/projects/add/v3AddComponent', () => {
195
195
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
196
196
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadata);
197
197
  mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockAppMeta));
198
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
198
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
199
199
  mockedCloneGithubRepo.mockRejectedValue(new Error('Clone failed'));
200
- await expect(v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow(commands.project.add.error.failedToDownloadComponent);
200
+ await expect(v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId)).rejects.toThrow(commands.project.add.error.failedToDownloadComponent);
201
201
  });
202
202
  it('should track usage with multiple component types', async () => {
203
203
  const mockAppMeta = {
@@ -219,9 +219,9 @@ describe('lib/projects/add/v3AddComponent', () => {
219
219
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
220
220
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadata);
221
221
  mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockAppMeta));
222
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
222
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
223
223
  mockedCloneGithubRepo.mockResolvedValue(true);
224
- await v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
224
+ await v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
225
225
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
226
226
  type: 'module,card',
227
227
  }, mockAccountId);
@@ -243,8 +243,8 @@ describe('lib/projects/add/v3AddComponent', () => {
243
243
  };
244
244
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
245
245
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadataNoApps);
246
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
247
- await v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
246
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
247
+ await v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
248
248
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
249
249
  type: '',
250
250
  }, mockAccountId);
@@ -270,9 +270,9 @@ describe('lib/projects/add/v3AddComponent', () => {
270
270
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
271
271
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadata);
272
272
  mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockAppMeta));
273
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
273
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
274
274
  mockedCloneGithubRepo.mockResolvedValue(true);
275
- await v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
275
+ await v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
276
276
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
277
277
  type: 'workflow-action-tool',
278
278
  }, mockAccountId);
@@ -308,9 +308,9 @@ describe('lib/projects/add/v3AddComponent', () => {
308
308
  mockedGetConfigForPlatformVersion.mockResolvedValue(mockConfig);
309
309
  mockedGetProjectMetadata.mockResolvedValue(mockProjectMetadata);
310
310
  mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockAppMeta));
311
- mockedProjectAddPromptV3.mockResolvedValue(mockPromptResponse);
311
+ mockedProjectAddPromptV2.mockResolvedValue(mockPromptResponse);
312
312
  mockedCloneGithubRepo.mockResolvedValue(true);
313
- await v3AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
313
+ await v2AddComponent(mockArgs, projectDir, mockProjectConfig, mockAccountId);
314
314
  expect(mockedTrackCommandUsage).toHaveBeenCalledWith('project-add', {
315
315
  type: 'workflow-action-tool,module',
316
316
  }, mockAccountId);
@@ -1,5 +1,5 @@
1
1
  import { ProjectConfig } from '../../../types/Projects.js';
2
- export declare function v3AddComponent(args: {
2
+ export declare function v2AddComponent(args: {
3
3
  name?: string;
4
4
  type?: string;
5
5
  features?: string[];