@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
@@ -1,10 +1,9 @@
1
- import { logger } from '@hubspot/local-dev-lib/logger';
2
1
  import { loadConfig, getAccountId, configFileExists, getConfigPath, validateConfig, } from '@hubspot/local-dev-lib/config';
3
2
  import { validateAccount } from '../validation.js';
4
3
  import { EXIT_CODES } from '../enums/exitCodes.js';
5
- import { i18n } from '../lang.js';
4
+ import { commands } from '../../lang/en.js';
6
5
  import { uiDeprecatedTag } from '../ui/index.js';
7
- import { isTargetedCommand } from './utils.js';
6
+ import { isTargetedCommand, shouldLoadConfigForCommand, shouldRunAccountValidationForCommand, shouldRunConfigValidationForCommand, } from './commandTargetingUtils.js';
8
7
  import { parseStringToNumber } from '../parsing.js';
9
8
  import { uiLogger } from '../ui/logger.js';
10
9
  import { lib } from '../../lang/en.js';
@@ -14,9 +13,7 @@ export function handleDeprecatedEnvVariables(argv) {
14
13
  if (argv.useEnv &&
15
14
  process.env.HUBSPOT_PORTAL_ID &&
16
15
  !process.env.HUBSPOT_ACCOUNT_ID) {
17
- uiDeprecatedTag(i18n(`commands.generalErrors.handleDeprecatedEnvVariables.portalEnvVarDeprecated`, {
18
- configPath: getConfigPath(),
19
- }));
16
+ uiDeprecatedTag(commands.generalErrors.handleDeprecatedEnvVariables.portalEnvVarDeprecated);
20
17
  process.env.HUBSPOT_ACCOUNT_ID = process.env.HUBSPOT_PORTAL_ID;
21
18
  }
22
19
  }
@@ -39,99 +36,42 @@ export async function injectAccountIdMiddleware(argv) {
39
36
  argv.derivedAccountId = getAccountId(account);
40
37
  }
41
38
  }
42
- const SKIP_CONFIG_VALIDATION = {
43
- init: { target: true },
44
- auth: { target: true },
45
- mcp: {
46
- target: false,
47
- subCommands: {
48
- setup: { target: true },
49
- start: { target: true },
50
- },
51
- },
52
- };
53
- export async function loadConfigMiddleware(argv) {
39
+ export async function loadAndValidateConfigMiddleware(argv) {
54
40
  // Skip this when no command is provided
55
41
  if (!argv._.length || argv.help) {
56
42
  return;
57
43
  }
58
- const maybeValidateConfig = () => {
59
- if (!isTargetedCommand(argv._, SKIP_CONFIG_VALIDATION) &&
60
- !validateConfig()) {
61
- process.exit(EXIT_CODES.ERROR);
62
- }
63
- };
64
- if (!configFileExists(true) &&
65
- isTargetedCommand(argv._, {
66
- account: { target: false, subCommands: { auth: { target: true } } },
67
- config: { target: false, subCommands: { migrate: { target: true } } },
68
- })) {
44
+ // Do not load or validate the config for the commands that do not require it
45
+ if (!shouldLoadConfigForCommand(argv._)) {
69
46
  return;
70
47
  }
48
+ // If the config file exists and the --config flag is used, exit with an error
71
49
  if (configFileExists(true) &&
72
50
  argv.config &&
73
- !isTargetedCommand(argv._, {
74
- config: { target: false, subCommands: { migrate: { target: true } } },
75
- })) {
76
- logger.error(i18n(`commands.generalErrors.loadConfigMiddleware.configFileExists`, {
77
- configPath: getConfigPath(),
78
- }));
51
+ !isTargetedCommand(argv._, { config: { migrate: true } })) {
52
+ uiLogger.error(commands.generalErrors.loadConfigMiddleware.configFileExists(getConfigPath()));
53
+ process.exit(EXIT_CODES.ERROR);
54
+ }
55
+ const config = loadConfig(argv.config, argv);
56
+ // We don't run validation for auth because users should be able to run it when
57
+ // no accounts are configured, but we still want to exit if the config file is not found
58
+ if (isTargetedCommand(argv._, { auth: true }) && !config) {
79
59
  process.exit(EXIT_CODES.ERROR);
80
60
  }
81
- else if (!isTargetedCommand(argv._, { init: { target: true } })) {
82
- const config = loadConfig(argv.config, argv);
83
- // We don't run validateConfig() for auth because users should be able to run it when
84
- // no accounts are configured, but we still want to exit if the config file is not found
85
- if (isTargetedCommand(argv._, { auth: { target: true } }) && !config) {
61
+ // Only validate the config if the command requires it
62
+ if (shouldRunConfigValidationForCommand(argv._)) {
63
+ const configIsValid = validateConfig();
64
+ if (!configIsValid) {
86
65
  process.exit(EXIT_CODES.ERROR);
87
66
  }
88
67
  }
89
- maybeValidateConfig();
90
68
  }
91
- const accountsSubCommands = {
92
- target: false,
93
- subCommands: {
94
- auth: { target: true },
95
- clean: { target: true },
96
- list: { target: true },
97
- ls: { target: true },
98
- remove: { target: true },
99
- use: { target: true },
100
- },
101
- };
102
- const sandboxesSubCommands = {
103
- target: false,
104
- subCommands: {
105
- delete: { target: true },
106
- },
107
- };
108
- const configSubCommands = {
109
- target: false,
110
- subCommands: {
111
- migrate: { target: true },
112
- },
113
- };
114
- const SKIP_ACCOUNT_VALIDATION = {
115
- init: { target: true },
116
- auth: { target: true },
117
- mcp: {
118
- target: false,
119
- subCommands: {
120
- setup: { target: true },
121
- start: { target: true },
122
- },
123
- },
124
- account: accountsSubCommands,
125
- accounts: accountsSubCommands,
126
- sandbox: sandboxesSubCommands,
127
- sandboxes: sandboxesSubCommands,
128
- config: configSubCommands,
129
- };
130
69
  export async function validateAccountOptions(argv) {
131
70
  // Skip this when no command is provided
132
71
  if (argv._.length && !argv.help) {
133
72
  let validAccount = true;
134
- if (!isTargetedCommand(argv._, SKIP_ACCOUNT_VALIDATION)) {
73
+ // Only validate the account if the command requires it
74
+ if (shouldRunAccountValidationForCommand(argv._)) {
135
75
  validAccount = await validateAccount(argv);
136
76
  }
137
77
  if (!validAccount) {
@@ -3,6 +3,8 @@ import { fetchFireAlarms } from '@hubspot/local-dev-lib/api/fireAlarm';
3
3
  import { debugError } from '../errorHandlers/index.js';
4
4
  import pkg from '../../package.json' with { type: 'json' };
5
5
  import { logInBox } from '../ui/boxen.js';
6
+ import { renderInline } from '../../ui/index.js';
7
+ import { getWarningBox } from '../../ui/components/StatusMessageBoxes.js';
6
8
  /*
7
9
  * Versions can be formatted like this:
8
10
  * =7.2.2 -> targets the exact version 7.2.2
@@ -98,12 +100,20 @@ async function logFireAlarms(accountId, command, version) {
98
100
  }
99
101
  return acc;
100
102
  }, '');
101
- await logInBox({
102
- contents: notifications,
103
- options: {
103
+ if (!process.env.HUBSPOT_ENABLE_INK) {
104
+ await logInBox({
105
+ contents: notifications,
106
+ options: {
107
+ title: 'Notifications',
108
+ },
109
+ });
110
+ }
111
+ else {
112
+ await renderInline(getWarningBox({
104
113
  title: 'Notifications',
105
- },
106
- });
114
+ message: notifications,
115
+ }));
116
+ }
107
117
  }
108
118
  }
109
119
  export async function checkFireAlarms(argv) {
@@ -1,8 +1,12 @@
1
- import { getConfigPath } from '@hubspot/local-dev-lib/config';
1
+ import { getConfigPath, configFileExists } from '@hubspot/local-dev-lib/config';
2
2
  import { checkAndWarnGitInclusion } from '../ui/git.js';
3
3
  export function checkAndWarnGitInclusionMiddleware(argv) {
4
4
  // Skip this when no command is provided
5
5
  if (argv._.length) {
6
+ // Skip if using global config
7
+ if (configFileExists(true)) {
8
+ return;
9
+ }
6
10
  const configPath = getConfigPath();
7
11
  if (configPath) {
8
12
  checkAndWarnGitInclusion(configPath);
@@ -1,8 +1,7 @@
1
1
  import updateNotifier from 'update-notifier';
2
- import chalk from 'chalk';
3
2
  import pkg from '../../package.json' with { type: 'json' };
4
- import { UI_COLORS, uiCommandReference } from '../ui/index.js';
5
- import { i18n } from '../lang.js';
3
+ import { UI_COLORS } from '../ui/index.js';
4
+ import { lib } from '../../lang/en.js';
6
5
  const notifier = updateNotifier({
7
6
  pkg: { ...pkg, name: '@hubspot/cli' },
8
7
  distTag: 'latest',
@@ -12,13 +11,8 @@ const CMS_CLI_PACKAGE_NAME = '@hubspot/cms-cli';
12
11
  export function notifyAboutUpdates() {
13
12
  notifier.notify({
14
13
  message: pkg.name === CMS_CLI_PACKAGE_NAME
15
- ? i18n(`commands.generalErrors.updateNotify.cmsUpdateNotification`, {
16
- packageName: CMS_CLI_PACKAGE_NAME,
17
- updateCommand: uiCommandReference('{updateCommand}'),
18
- })
19
- : i18n(`commands.generalErrors.updateNotify.cliUpdateNotification`, {
20
- updateCommand: uiCommandReference('{updateCommand}'),
21
- }),
14
+ ? lib.middleware.updateNotification.cmsUpdateNotification(CMS_CLI_PACKAGE_NAME)
15
+ : lib.middleware.updateNotification.cliUpdateNotification,
22
16
  defer: false,
23
17
  boxenOptions: {
24
18
  borderColor: UI_COLORS.MARIGOLD_DARK,
@@ -28,7 +22,7 @@ export function notifyAboutUpdates() {
28
22
  borderStyle: 'round',
29
23
  title: pkg.name === CMS_CLI_PACKAGE_NAME
30
24
  ? undefined
31
- : chalk.bold(i18n(`commands.generalErrors.updateNotify.notifyTitle`)),
25
+ : lib.middleware.updateNotification.notifyTitle,
32
26
  },
33
27
  });
34
28
  }
@@ -1,20 +1,17 @@
1
- import { logger } from '@hubspot/local-dev-lib/logger';
1
+ import { uiLogger } from '../ui/logger.js';
2
2
  import { EXIT_CODES } from '../enums/exitCodes.js';
3
- import { i18n } from '../lang.js';
3
+ import { commands } from '../../lang/en.js';
4
4
  import { getIsInProject } from '../projects/config.js';
5
- import { isTargetedCommand } from './utils.js';
5
+ import { isTargetedCommand } from './commandTargetingUtils.js';
6
6
  const UPLOAD_AND_WATCH_COMMANDS = {
7
- upload: { target: true },
8
- watch: { target: true },
7
+ upload: true,
8
+ watch: true,
9
9
  };
10
10
  export function performChecks(argv) {
11
11
  // Require "project" command when running upload/watch inside of a project
12
12
  if (isTargetedCommand(argv._, UPLOAD_AND_WATCH_COMMANDS) &&
13
13
  getIsInProject(argv.src)) {
14
- logger.error(i18n(`commands.generalErrors.srcIsProject`, {
15
- src: argv.src || './',
16
- command: argv._.join(' '),
17
- }));
14
+ uiLogger.error(commands.generalErrors.srcIsProject(argv.src || './', argv._.join(' ')));
18
15
  process.exit(EXIT_CODES.ERROR);
19
16
  }
20
17
  return true;
package/lib/npm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { exec as execAsync } from 'node:child_process';
2
2
  import util from 'util';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
3
+ import { uiLogger } from './ui/logger.js';
4
4
  import pkg from '../package.json' with { type: 'json' };
5
5
  export const DEFAULT_PACKAGE_MANAGER = 'npm';
6
6
  export async function isGloballyInstalled(packageName) {
@@ -21,7 +21,7 @@ export async function getLatestCliVersion() {
21
21
  }
22
22
  export async function executeInstall(packages = [], flags, options) {
23
23
  const installCommand = `${DEFAULT_PACKAGE_MANAGER} install${flags ? ` ${flags}` : ''} ${packages.join(' ')}`;
24
- logger.debug('Running ', installCommand);
24
+ uiLogger.debug('Running', installCommand);
25
25
  const exec = util.promisify(execAsync);
26
26
  await exec(installCommand, options);
27
27
  }
package/lib/oauth.js CHANGED
@@ -5,11 +5,11 @@ import { getAccountConfig } from '@hubspot/local-dev-lib/config';
5
5
  import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountIdentifier';
6
6
  import { addOauthToAccountConfig } from '@hubspot/local-dev-lib/oauth';
7
7
  import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
8
- import { logger } from '@hubspot/local-dev-lib/logger';
8
+ import { uiLogger } from './ui/logger.js';
9
9
  import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
10
10
  import { DEFAULT_OAUTH_SCOPES } from '@hubspot/local-dev-lib/constants/auth';
11
11
  import { handleExit } from './process.js';
12
- import { i18n } from './lang.js';
12
+ import { lib } from '../lang/en.js';
13
13
  import { EXIT_CODES } from './enums/exitCodes.js';
14
14
  const PORT = 3000;
15
15
  const redirectUri = `http://localhost:${PORT}/oauth-callback`;
@@ -18,7 +18,7 @@ function buildAuthUrl(oauthManager) {
18
18
  const env = accountEnv || ENVIRONMENTS.PROD;
19
19
  const scopes = accountScopes || DEFAULT_OAUTH_SCOPES;
20
20
  if (!clientId) {
21
- logger.error(i18n(`lib.oauth.missingClientId`));
21
+ uiLogger.error(lib.oauth.missingClientId);
22
22
  process.exit(EXIT_CODES.ERROR);
23
23
  }
24
24
  return (`${getHubSpotWebsiteOrigin(env)}/oauth/${oauthManager.account.accountId}/authorize` +
@@ -77,7 +77,7 @@ async function authorize(oauthManager) {
77
77
  reject();
78
78
  }
79
79
  });
80
- server = app.listen(PORT, () => logger.log(`Waiting for authorization...`));
80
+ server = app.listen(PORT, () => uiLogger.log(`Waiting for authorization...`));
81
81
  handleServerOnProcessEnd(server);
82
82
  });
83
83
  }
@@ -91,7 +91,7 @@ function setupOauth(accountConfig) {
91
91
  }
92
92
  export async function authenticateWithOauth(accountConfig) {
93
93
  const oauthManager = setupOauth(accountConfig);
94
- logger.log('Authorizing');
94
+ uiLogger.log('Authorizing');
95
95
  await authorize(oauthManager);
96
96
  addOauthToAccountConfig(oauthManager);
97
97
  }
package/lib/process.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import readline from 'readline';
2
- import { logger, setLogLevel, LOG_LEVEL } from '@hubspot/local-dev-lib/logger';
3
- import { i18n } from './lang.js';
2
+ import { setLogLevel, LOG_LEVEL } from '@hubspot/local-dev-lib/logger';
3
+ import { uiLogger } from './ui/logger.js';
4
+ import { lib } from '../lang/en.js';
4
5
  import { logError } from './errorHandlers/index.js';
5
6
  const SIGHUP = 'SIGHUP';
6
7
  const uncaughtException = 'uncaughtException';
@@ -26,13 +27,13 @@ export function handleExit(callback) {
26
27
  if (isSIGHUP) {
27
28
  setLogLevel(LOG_LEVEL.NONE);
28
29
  }
29
- logger.debug(i18n(`lib.process.exitDebug`, { signal }));
30
+ uiLogger.debug(lib.process.exitDebug(signal));
30
31
  if (signal === uncaughtException && args && args.length > 0) {
31
32
  try {
32
33
  logError(args[0]);
33
34
  }
34
35
  catch (e) {
35
- logger.error(args[0]);
36
+ uiLogger.error(String(args[0]));
36
37
  }
37
38
  }
38
39
  await callback({ isSIGHUP });
@@ -11,7 +11,7 @@ vi.mock('@hubspot/ui-extensions-dev-server', () => {
11
11
  };
12
12
  });
13
13
  import { fetchAppInstallationData } from '@hubspot/local-dev-lib/api/localDevAuth';
14
- import { fetchPublicAppsForPortal, fetchPublicAppProductionInstallCounts, installStaticAuthAppOnTestAccount, } from '@hubspot/local-dev-lib/api/appsDev';
14
+ import { fetchAppMetadataByUid, fetchPublicAppProductionInstallCounts, installStaticAuthAppOnTestAccount, } from '@hubspot/local-dev-lib/api/appsDev';
15
15
  import { DevModeUnifiedInterface as UIEDevModeInterface } from '@hubspot/ui-extensions-dev-server';
16
16
  import { requestPorts } from '@hubspot/local-dev-lib/portManager';
17
17
  import { getAccountConfig } from '@hubspot/local-dev-lib/config';
@@ -67,6 +67,8 @@ describe('AppDevModeInterface', () => {
67
67
  componentRoot: '/test/path',
68
68
  componentConfigPath: '/test/path/config.json',
69
69
  configUpdatedSinceLastUpload: false,
70
+ removed: false,
71
+ parsingErrors: [],
70
72
  },
71
73
  componentDeps: {},
72
74
  metaFilePath: '/test/path',
@@ -107,8 +109,8 @@ describe('AppDevModeInterface', () => {
107
109
  LocalDevState.mockImplementation(() => mockLocalDevState);
108
110
  LocalDevLogger.mockImplementation(() => mockLocalDevLogger);
109
111
  // Mock external dependencies
110
- fetchPublicAppsForPortal.mockResolvedValue({
111
- data: { results: [mockPublicApp] },
112
+ fetchAppMetadataByUid.mockResolvedValue({
113
+ data: mockPublicApp,
112
114
  });
113
115
  fetchPublicAppProductionInstallCounts.mockResolvedValue({
114
116
  data: { uniquePortalInstallCount: 5 },
@@ -127,7 +129,16 @@ describe('AppDevModeInterface', () => {
127
129
  getOauthAppInstallUrl.mockReturnValue('http://oauth-install-url');
128
130
  getStaticAuthAppInstallUrl.mockReturnValue('http://static-install-url');
129
131
  installAppAutoPrompt.mockResolvedValue(true);
130
- installAppBrowserPrompt.mockResolvedValue(undefined);
132
+ installAppBrowserPrompt.mockImplementation(async () => {
133
+ setTimeout(() => {
134
+ const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
135
+ if (addListenerCall) {
136
+ const callback = addListenerCall[1];
137
+ callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
138
+ }
139
+ }, 0);
140
+ return undefined;
141
+ });
131
142
  confirmPrompt.mockResolvedValue(true);
132
143
  installStaticAuthAppOnTestAccount.mockResolvedValue(undefined);
133
144
  // Mock process.exit
@@ -189,12 +200,12 @@ describe('AppDevModeInterface', () => {
189
200
  it('should return early if no app node exists', async () => {
190
201
  mockLocalDevState.projectNodes = {};
191
202
  await appDevModeInterface.setup({});
192
- expect(fetchPublicAppsForPortal).not.toHaveBeenCalled();
203
+ expect(fetchAppMetadataByUid).not.toHaveBeenCalled();
193
204
  expect(UIEDevModeInterface.setup).not.toHaveBeenCalled();
194
205
  });
195
206
  it('should setup successfully with private app', async () => {
196
207
  await appDevModeInterface.setup({});
197
- expect(fetchPublicAppsForPortal).toHaveBeenCalledWith(12345);
208
+ expect(fetchAppMetadataByUid).toHaveBeenCalledWith('test-app-uid', 12345);
198
209
  expect(fetchPublicAppProductionInstallCounts).toHaveBeenCalledWith(123, 12345);
199
210
  expect(fetchAppInstallationData).toHaveBeenCalledWith(67890, 999, 'test-app-uid', ['test-scope'], []);
200
211
  expect(UIEDevModeInterface.setup).toHaveBeenCalled();
@@ -240,21 +251,16 @@ describe('AppDevModeInterface', () => {
240
251
  await newAppDevModeInterface.setup({});
241
252
  expect(process.exit).toHaveBeenCalledWith(0);
242
253
  });
243
- // @TODO: Restore test account auto install functionality
244
- // it('should auto-install static auth app on test account', async () => {
245
- // (fetchAppInstallationData as Mock).mockResolvedValue({
246
- // data: {
247
- // isInstalledWithScopeGroups: false,
248
- // previouslyAuthorizedScopeGroups: [],
249
- // },
250
- // });
251
- // await appDevModeInterface.setup({});
252
- // expect(installStaticAuthAppOnTestAccount).toHaveBeenCalledWith(
253
- // 123,
254
- // 67890,
255
- // [1, 2, 3]
256
- // );
257
- // });
254
+ it('should auto-install static auth app on test account', async () => {
255
+ fetchAppInstallationData.mockResolvedValue({
256
+ data: {
257
+ isInstalledWithScopeGroups: false,
258
+ previouslyAuthorizedScopeGroups: [],
259
+ },
260
+ });
261
+ await appDevModeInterface.setup({});
262
+ expect(installStaticAuthAppOnTestAccount).toHaveBeenCalledWith(123, 67890, [1, 2, 3]);
263
+ });
258
264
  it('should open browser for OAuth app installation', async () => {
259
265
  const oauthAppNode = {
260
266
  ...mockAppNode,
@@ -293,81 +299,47 @@ describe('AppDevModeInterface', () => {
293
299
  },
294
300
  });
295
301
  await appDevModeInterface.setup({});
296
- expect(installAppBrowserPrompt).toHaveBeenCalledWith('http://static-install-url', true, {
297
- appUid: 'test-app-uid',
298
- projectAccountId: 12345,
299
- projectName: 'test-project',
300
- testingAccountId: 67890,
301
- });
302
+ expect(installAppBrowserPrompt).toHaveBeenCalledWith('http://static-install-url', true);
302
303
  });
303
304
  it('should handle errors during setup', async () => {
304
305
  const error = new Error('Setup failed');
305
- fetchPublicAppsForPortal.mockRejectedValue(error);
306
+ fetchAppMetadataByUid.mockRejectedValue(error);
306
307
  await appDevModeInterface.setup({});
307
308
  expect(logError).toHaveBeenCalledWith(error);
308
309
  });
309
- it('should exit if app not found in portal', async () => {
310
- // Set up conditions for non-automatic installation to force getAppInstallUrl call
311
- getAccountConfig.mockReturnValue(null);
312
- // First call for fetchAppData succeeds
313
- fetchPublicAppsForPortal
314
- .mockResolvedValueOnce({
315
- data: { results: [mockPublicApp] },
316
- })
317
- // Second call for getAppInstallUrl fails (app not found)
318
- .mockResolvedValueOnce({
319
- data: { results: [] },
310
+ it('should exit if user declines auto-install', async () => {
311
+ // Set up conditions for automatic installation
312
+ getAccountConfig.mockReturnValue({
313
+ parentAccountId: 12345, // matches targetProjectAccountId
320
314
  });
315
+ isDeveloperTestAccount.mockReturnValue(true);
321
316
  fetchAppInstallationData.mockResolvedValue({
322
317
  data: {
323
318
  isInstalledWithScopeGroups: false,
324
319
  previouslyAuthorizedScopeGroups: [],
325
320
  },
326
321
  });
322
+ installAppAutoPrompt.mockResolvedValue(false);
323
+ // Create a new instance to trigger the exit during setup
324
+ const newAppDevModeInterface = new AppDevModeInterface({
325
+ localDevState: mockLocalDevState,
326
+ localDevLogger: mockLocalDevLogger,
327
+ });
327
328
  // The setup method catches the error, so we check that process.exit was called
329
+ await newAppDevModeInterface.setup({});
330
+ expect(process.exit).toHaveBeenCalledWith(0);
331
+ });
332
+ it('should fallback to browser install if auto-install fails', async () => {
333
+ fetchAppInstallationData.mockResolvedValue({
334
+ data: {
335
+ isInstalledWithScopeGroups: false,
336
+ previouslyAuthorizedScopeGroups: [],
337
+ },
338
+ });
339
+ installStaticAuthAppOnTestAccount.mockRejectedValue(new Error('Install failed'));
328
340
  await appDevModeInterface.setup({});
329
- expect(process.exit).toHaveBeenCalledWith(1);
330
- });
331
- // @TODO: Restore test account auto install functionality
332
- // it('should exit if user declines auto-install', async () => {
333
- // // Set up conditions for automatic installation
334
- // (getAccountConfig as Mock).mockReturnValue({
335
- // parentAccountId: 12345, // matches targetProjectAccountId
336
- // });
337
- // (isDeveloperTestAccount as Mock).mockReturnValue(true);
338
- // (fetchAppInstallationData as Mock).mockResolvedValue({
339
- // data: {
340
- // isInstalledWithScopeGroups: false,
341
- // previouslyAuthorizedScopeGroups: [],
342
- // },
343
- // });
344
- // (installAppAutoPrompt as Mock).mockResolvedValue(false);
345
- // // Create a new instance to trigger the exit during setup
346
- // const newAppDevModeInterface = new AppDevModeInterface({
347
- // localDevState: mockLocalDevState,
348
- // localDevLogger: mockLocalDevLogger,
349
- // });
350
- // // The setup method catches the error, so we check that process.exit was called
351
- // await newAppDevModeInterface.setup({});
352
- // expect(process.exit).toHaveBeenCalledWith(0);
353
- // });
354
- // @TODO: Restore test account auto install functionality
355
- // it('should fallback to browser install if auto-install fails', async () => {
356
- // (fetchAppInstallationData as Mock).mockResolvedValue({
357
- // data: {
358
- // isInstalledWithScopeGroups: false,
359
- // previouslyAuthorizedScopeGroups: [],
360
- // },
361
- // });
362
- // (installStaticAuthAppOnTestAccount as Mock).mockRejectedValue(
363
- // new Error('Install failed')
364
- // );
365
- // await appDevModeInterface.setup({});
366
- // expect(installAppBrowserPrompt).toHaveBeenCalledWith(
367
- // 'http://static-install-url',
368
- // false
369
- // );
370
- // });
341
+ expect(installAppBrowserPrompt).toHaveBeenCalledWith('http://static-install-url', false);
342
+ });
371
343
  });
372
344
  describe('start()', () => {
373
345
  it('should return early if no app node exists', async () => {
@@ -424,14 +396,21 @@ describe('AppDevModeInterface', () => {
424
396
  // Reset mocks to ensure clean state
425
397
  vi.clearAllMocks();
426
398
  // Set up basic mocks
427
- fetchPublicAppsForPortal.mockResolvedValue({
428
- data: { results: [mockPublicApp] },
399
+ fetchAppMetadataByUid.mockResolvedValue({
400
+ data: mockPublicApp,
429
401
  });
430
402
  fetchPublicAppProductionInstallCounts.mockResolvedValue({
431
403
  data: { uniquePortalInstallCount: 5 },
432
404
  });
433
405
  getStaticAuthAppInstallUrl.mockReturnValue('http://static-install-url');
434
- installAppBrowserPrompt.mockResolvedValue(undefined);
406
+ installAppBrowserPrompt.mockImplementation(async () => {
407
+ const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
408
+ if (addListenerCall) {
409
+ const callback = addListenerCall[1];
410
+ callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
411
+ }
412
+ return undefined;
413
+ });
435
414
  // Reset the mock LocalDevState
436
415
  mockLocalDevState.getAppDataByUid = vi.fn().mockReturnValue(mockAppData);
437
416
  mockLocalDevState.setAppDataForUid = vi.fn();
@@ -457,14 +436,23 @@ describe('AppDevModeInterface', () => {
457
436
  // Reset mocks to ensure clean state
458
437
  vi.clearAllMocks();
459
438
  // Set up basic mocks
460
- fetchPublicAppsForPortal.mockResolvedValue({
461
- data: { results: [mockPublicApp] },
439
+ fetchAppMetadataByUid.mockResolvedValue({
440
+ data: mockPublicApp,
462
441
  });
463
442
  fetchPublicAppProductionInstallCounts.mockResolvedValue({
464
443
  data: { uniquePortalInstallCount: 5 },
465
444
  });
466
445
  getOauthAppInstallUrl.mockReturnValue('http://oauth-install-url');
467
- installAppBrowserPrompt.mockResolvedValue(undefined);
446
+ installAppBrowserPrompt.mockImplementation(async () => {
447
+ setTimeout(() => {
448
+ const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
449
+ if (addListenerCall) {
450
+ const callback = addListenerCall[1];
451
+ callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
452
+ }
453
+ }, 0);
454
+ return undefined;
455
+ });
468
456
  // Reset the mock LocalDevState
469
457
  mockLocalDevState.getAppDataByUid = vi.fn().mockReturnValue(mockAppData);
470
458
  mockLocalDevState.setAppDataForUid = vi.fn();
@@ -501,14 +489,23 @@ describe('AppDevModeInterface', () => {
501
489
  // Reset mocks to ensure clean state
502
490
  vi.clearAllMocks();
503
491
  // Set up basic mocks
504
- fetchPublicAppsForPortal.mockResolvedValue({
505
- data: { results: [mockPublicApp] },
492
+ fetchAppMetadataByUid.mockResolvedValue({
493
+ data: mockPublicApp,
506
494
  });
507
495
  fetchPublicAppProductionInstallCounts.mockResolvedValue({
508
496
  data: { uniquePortalInstallCount: 5 },
509
497
  });
510
498
  getStaticAuthAppInstallUrl.mockReturnValue('http://static-install-url');
511
- installAppBrowserPrompt.mockResolvedValue(undefined);
499
+ installAppBrowserPrompt.mockImplementation(async () => {
500
+ setTimeout(() => {
501
+ const addListenerCall = mockLocalDevState.addListener.mock.calls.find(call => call[0] === 'devServerMessage');
502
+ if (addListenerCall) {
503
+ const callback = addListenerCall[1];
504
+ callback(LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS);
505
+ }
506
+ }, 0);
507
+ return undefined;
508
+ });
512
509
  // Reset the mock LocalDevState
513
510
  mockLocalDevState.getAppDataByUid = vi.fn().mockReturnValue(mockAppData);
514
511
  mockLocalDevState.setAppDataForUid = vi.fn();