@hubspot/cli 7.11.8-experimental.0 → 8.0.0-beta.1

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 (363) hide show
  1. package/api/__tests__/migrate.test.js +19 -1
  2. package/api/migrate.d.ts +1 -1
  3. package/api/migrate.js +2 -1
  4. package/bin/cli.js +12 -27
  5. package/commands/__tests__/customObject.test.js +0 -2
  6. package/commands/__tests__/doctor.test.js +0 -2
  7. package/commands/__tests__/getStarted.test.js +0 -4
  8. package/commands/__tests__/project.test.js +0 -4
  9. package/commands/__tests__/upgrade.test.js +309 -0
  10. package/commands/account/__tests__/auth.test.js +180 -0
  11. package/commands/account/__tests__/list.test.js +128 -3
  12. package/commands/account/__tests__/rename.test.js +0 -2
  13. package/commands/account/__tests__/use.test.js +138 -0
  14. package/commands/account/auth.js +1 -1
  15. package/commands/account/clean.js +4 -3
  16. package/commands/account/createOverride.js +3 -2
  17. package/commands/account/info.js +2 -2
  18. package/commands/account/list.js +4 -4
  19. package/commands/account/remove.js +3 -2
  20. package/commands/account/removeOverride.js +3 -2
  21. package/commands/account/use.js +4 -3
  22. package/commands/app/__tests__/migrate.test.js +8 -25
  23. package/commands/app/migrate.js +10 -16
  24. package/commands/app/secret/__tests__/add.test.js +112 -0
  25. package/commands/app/secret/add.js +13 -13
  26. package/commands/auth.js +8 -2
  27. package/commands/cms/__tests__/fetch.test.js +114 -15
  28. package/commands/cms/__tests__/upload.test.js +308 -0
  29. package/commands/cms/__tests__/watch.test.js +212 -0
  30. package/commands/cms/app/create.js +2 -3
  31. package/commands/cms/convertFields.js +1 -1
  32. package/commands/cms/fetch.js +3 -2
  33. package/commands/cms/function/deploy.js +2 -2
  34. package/commands/cms/function/list.js +2 -3
  35. package/commands/cms/lighthouseScore.js +19 -27
  36. package/commands/cms/module/marketplace-validate.js +0 -1
  37. package/commands/cms/theme/__tests__/preview.test.js +2 -8
  38. package/commands/cms/theme/create.js +1 -1
  39. package/commands/cms/theme/marketplace-validate.js +0 -1
  40. package/commands/cms/theme/preview.d.ts +0 -1
  41. package/commands/cms/theme/preview.js +12 -52
  42. package/commands/cms/upload.js +3 -3
  43. package/commands/cms/watch.js +3 -3
  44. package/commands/customObject.js +0 -2
  45. package/commands/doctor.js +10 -2
  46. package/commands/filemanager/__tests__/upload.test.js +161 -0
  47. package/commands/getStarted.js +13 -3
  48. package/commands/hubdb/__tests__/list.test.js +0 -9
  49. package/commands/hubdb/list.js +6 -8
  50. package/commands/init.js +8 -2
  51. package/commands/mcp/__tests__/start.test.js +113 -3
  52. package/commands/mcp/setup.js +0 -7
  53. package/commands/mcp/start.d.ts +1 -1
  54. package/commands/mcp/start.js +0 -7
  55. package/commands/project/__tests__/add.test.js +0 -2
  56. package/commands/project/__tests__/create.test.js +2 -2
  57. package/commands/project/__tests__/deploy.test.js +0 -4
  58. package/commands/project/__tests__/dev.test.js +273 -0
  59. package/commands/project/__tests__/devUnifiedFlow.test.js +2 -5
  60. package/commands/project/__tests__/installDeps.test.js +0 -2
  61. package/commands/project/__tests__/lint.test.js +0 -5
  62. package/commands/project/__tests__/logs.test.js +24 -31
  63. package/commands/project/__tests__/migrate.test.js +7 -12
  64. package/commands/project/__tests__/updateDeps.test.js +0 -2
  65. package/commands/project/__tests__/upload.test.js +191 -0
  66. package/commands/project/__tests__/validate.test.js +314 -31
  67. package/commands/project/cloneApp.d.ts +1 -7
  68. package/commands/project/cloneApp.js +1 -149
  69. package/commands/project/create.js +3 -4
  70. package/commands/project/deploy.js +18 -7
  71. package/commands/project/dev/deprecatedFlow.js +0 -2
  72. package/commands/project/dev/index.js +23 -11
  73. package/commands/project/dev/unifiedFlow.d.ts +1 -1
  74. package/commands/project/dev/unifiedFlow.js +1 -4
  75. package/commands/project/list.js +4 -4
  76. package/commands/project/listBuilds.js +2 -7
  77. package/commands/project/logs.js +19 -12
  78. package/commands/project/migrate.js +3 -3
  79. package/commands/project/profile/add.js +1 -1
  80. package/commands/project/profile/delete.js +1 -1
  81. package/commands/project/upload.d.ts +1 -1
  82. package/commands/project/upload.js +13 -4
  83. package/commands/project/validate.js +85 -13
  84. package/commands/project/watch.js +7 -7
  85. package/commands/project.js +0 -4
  86. package/commands/sandbox/__tests__/create.test.js +0 -2
  87. package/commands/secret/__tests__/addSecret.test.js +140 -7
  88. package/commands/secret/addSecret.js +3 -1
  89. package/commands/testAccount/__tests__/create.test.js +6 -1
  90. package/commands/testAccount/__tests__/importData.test.js +0 -1
  91. package/commands/testAccount/create.d.ts +1 -0
  92. package/commands/testAccount/create.js +13 -5
  93. package/commands/upgrade.d.ts +8 -0
  94. package/commands/upgrade.js +119 -0
  95. package/lang/en.d.ts +88 -10
  96. package/lang/en.js +105 -26
  97. package/lib/__tests__/buildAccount.test.js +0 -13
  98. package/lib/__tests__/cliUpgradeUtils.test.js +131 -0
  99. package/lib/__tests__/commonOpts.test.js +0 -1
  100. package/lib/__tests__/dependencyManagement.test.js +633 -13
  101. package/lib/__tests__/developerTestAccounts.test.js +0 -1
  102. package/lib/__tests__/hasFeature.test.js +0 -6
  103. package/lib/__tests__/importData.test.js +0 -1
  104. package/lib/__tests__/npmCli.test.js +84 -0
  105. package/lib/__tests__/oauth.test.js +1 -11
  106. package/lib/__tests__/process.test.js +0 -1
  107. package/lib/__tests__/sandboxSync.test.js +0 -1
  108. package/lib/__tests__/sandboxes.test.js +0 -1
  109. package/lib/__tests__/serverlessLogs.test.js +0 -1
  110. package/lib/__tests__/usageTracking.test.js +39 -6
  111. package/lib/__tests__/validation.test.js +0 -1
  112. package/lib/app/__tests__/migrate.test.js +137 -12
  113. package/lib/app/migrate.d.ts +5 -2
  114. package/lib/app/migrate.js +30 -11
  115. package/lib/app/urls.d.ts +1 -1
  116. package/lib/buildAccount.d.ts +1 -1
  117. package/lib/cliUpgradeUtils.d.ts +22 -0
  118. package/lib/cliUpgradeUtils.js +62 -0
  119. package/lib/cmsAssets/api-sample.js +2 -5
  120. package/lib/cmsAssets/function.js +1 -9
  121. package/lib/cmsAssets/module.js +1 -9
  122. package/lib/cmsAssets/template.js +1 -9
  123. package/lib/configOptions.d.ts +0 -1
  124. package/lib/configOptions.js +1 -5
  125. package/lib/constants.d.ts +6 -0
  126. package/lib/constants.js +10 -4
  127. package/lib/dependencyManagement.d.ts +9 -0
  128. package/lib/dependencyManagement.js +127 -26
  129. package/lib/developerTestAccounts.d.ts +1 -1
  130. package/lib/doctor/Diagnosis.d.ts +1 -0
  131. package/lib/doctor/Diagnosis.js +7 -0
  132. package/lib/doctor/DiagnosticInfoBuilder.d.ts +2 -1
  133. package/lib/doctor/DiagnosticInfoBuilder.js +8 -4
  134. package/lib/doctor/Doctor.d.ts +12 -0
  135. package/lib/doctor/Doctor.js +283 -33
  136. package/lib/doctor/__tests__/Diagnosis.test.js +1 -0
  137. package/lib/doctor/__tests__/Doctor.test.js +201 -51
  138. package/lib/errorHandlers/__tests__/index.test.d.ts +1 -0
  139. package/lib/errorHandlers/__tests__/index.test.js +278 -0
  140. package/lib/errorHandlers/index.d.ts +1 -0
  141. package/lib/errorHandlers/index.js +14 -2
  142. package/lib/http.js +3 -1
  143. package/lib/links.js +2 -3
  144. package/lib/mcp/__tests__/setup.test.js +69 -2
  145. package/lib/mcp/setup.d.ts +1 -0
  146. package/lib/mcp/setup.js +37 -4
  147. package/lib/middleware/__tests__/configMiddleware.test.js +1 -43
  148. package/lib/middleware/__tests__/usageTrackingMiddleware.test.d.ts +1 -0
  149. package/lib/middleware/__tests__/usageTrackingMiddleware.test.js +44 -0
  150. package/lib/middleware/__tests__/yargsChecksMiddleware.test.js +0 -5
  151. package/lib/middleware/autoUpdateMiddleware.js +58 -57
  152. package/lib/middleware/configMiddleware.d.ts +0 -3
  153. package/lib/middleware/configMiddleware.js +0 -11
  154. package/lib/middleware/fireAlarmMiddleware.js +1 -1
  155. package/lib/middleware/spinniesMiddleware.d.ts +1 -0
  156. package/lib/middleware/spinniesMiddleware.js +4 -0
  157. package/lib/middleware/usageTrackingMiddleware.d.ts +13 -0
  158. package/lib/middleware/usageTrackingMiddleware.js +16 -0
  159. package/lib/{npm.d.ts → npm/npmCli.d.ts} +8 -3
  160. package/lib/npm/npmCli.js +59 -0
  161. package/lib/npm/packageJson.d.ts +24 -0
  162. package/lib/npm/packageJson.js +102 -0
  163. package/lib/npm/workspaces.d.ts +12 -0
  164. package/lib/npm/workspaces.js +48 -0
  165. package/lib/oauth.js +1 -3
  166. package/lib/projects/__tests__/AppDevModeInterface.test.js +40 -18
  167. package/lib/projects/__tests__/DevServerManager.test.js +1 -0
  168. package/lib/projects/__tests__/DevSessionManager.test.d.ts +1 -0
  169. package/lib/projects/__tests__/DevSessionManager.test.js +250 -0
  170. package/lib/projects/__tests__/LocalDevProcess.test.js +19 -6
  171. package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +0 -2
  172. package/lib/projects/__tests__/UIExtensionsDevModeInterface.test.js +0 -1
  173. package/lib/projects/__tests__/components.test.js +6 -22
  174. package/lib/projects/__tests__/deploy.test.js +0 -1
  175. package/lib/projects/__tests__/localDevProjectHelpers.test.js +3 -5
  176. package/lib/projects/__tests__/pollProjectBuildAndDeploy.test.d.ts +1 -0
  177. package/lib/projects/__tests__/pollProjectBuildAndDeploy.test.js +328 -0
  178. package/lib/projects/__tests__/projectProfiles.test.d.ts +1 -0
  179. package/lib/projects/__tests__/projectProfiles.test.js +441 -0
  180. package/lib/projects/__tests__/projects.test.js +0 -1
  181. package/lib/projects/__tests__/structure.test.js +0 -1
  182. package/lib/projects/__tests__/uieLinting.test.js +2 -11
  183. package/lib/projects/__tests__/upload.test.js +104 -3
  184. package/lib/projects/add/__tests__/legacyAddComponent.test.js +0 -2
  185. package/lib/projects/add/__tests__/v2AddComponent.test.js +2 -4
  186. package/lib/projects/add/v2AddComponent.js +2 -3
  187. package/lib/projects/components.d.ts +1 -1
  188. package/lib/projects/components.js +4 -4
  189. package/lib/projects/create/__tests__/legacy.test.js +0 -1
  190. package/lib/projects/create/__tests__/v2.test.js +0 -1
  191. package/lib/projects/create/v2.d.ts +1 -1
  192. package/lib/projects/create/v2.js +1 -1
  193. package/lib/projects/ensureProjectExists.js +0 -1
  194. package/lib/projects/localDev/AppDevModeInterface.js +9 -2
  195. package/lib/projects/localDev/DevSessionManager.d.ts +18 -0
  196. package/lib/projects/localDev/DevSessionManager.js +95 -0
  197. package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
  198. package/lib/projects/localDev/LocalDevLogger.js +18 -7
  199. package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +4 -3
  200. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +23 -12
  201. package/lib/projects/localDev/LocalDevProcess.d.ts +2 -1
  202. package/lib/projects/localDev/LocalDevProcess.js +18 -7
  203. package/lib/projects/localDev/LocalDevState.d.ts +3 -2
  204. package/lib/projects/localDev/helpers/account.d.ts +1 -1
  205. package/lib/projects/localDev/helpers/devSessionsApi.d.ts +9 -0
  206. package/lib/projects/localDev/helpers/devSessionsApi.js +19 -0
  207. package/lib/projects/localDev/helpers/project.d.ts +1 -1
  208. package/lib/projects/localDev/helpers/project.js +1 -2
  209. package/lib/projects/pollProjectBuildAndDeploy.js +4 -5
  210. package/lib/projects/projectProfiles.d.ts +17 -0
  211. package/lib/projects/projectProfiles.js +140 -0
  212. package/lib/projects/structure.d.ts +1 -1
  213. package/lib/projects/uieLinting.js +6 -8
  214. package/lib/projects/upload.d.ts +9 -1
  215. package/lib/projects/upload.js +11 -5
  216. package/lib/projects/urls.d.ts +1 -0
  217. package/lib/projects/urls.js +3 -3
  218. package/lib/prompts/__tests__/createDeveloperTestAccountConfigPrompt.test.js +8 -4
  219. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +2 -0
  220. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +19 -13
  221. package/lib/sandboxSync.d.ts +1 -1
  222. package/lib/sandboxes.d.ts +1 -1
  223. package/lib/serverlessLogs.js +0 -1
  224. package/lib/theme/__tests__/migrate.test.js +12 -4
  225. package/lib/theme/migrate.js +2 -3
  226. package/lib/ui/__tests__/SpinniesManager.test.js +0 -1
  227. package/lib/usageTracking.js +18 -0
  228. package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +2 -2
  229. package/mcp-server/tools/cms/HsCreateFunctionTool.js +2 -1
  230. package/mcp-server/tools/cms/HsCreateModuleTool.js +2 -1
  231. package/mcp-server/tools/cms/HsCreateTemplateTool.js +2 -1
  232. package/mcp-server/tools/cms/HsFunctionLogsTool.js +2 -2
  233. package/mcp-server/tools/cms/HsListFunctionsTool.js +2 -2
  234. package/mcp-server/tools/cms/HsListTool.js +2 -2
  235. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +4 -4
  236. package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +4 -4
  237. package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +4 -4
  238. package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +4 -4
  239. package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +4 -4
  240. package/mcp-server/tools/cms/__tests__/HsListTool.test.js +4 -4
  241. package/mcp-server/tools/project/AddFeatureToProjectTool.js +4 -3
  242. package/mcp-server/tools/project/CreateProjectTool.js +4 -3
  243. package/mcp-server/tools/project/CreateTestAccountTool.d.ts +7 -2
  244. package/mcp-server/tools/project/CreateTestAccountTool.js +19 -9
  245. package/mcp-server/tools/project/DocFetchTool.js +2 -1
  246. package/mcp-server/tools/project/DocsSearchTool.js +2 -1
  247. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +4 -4
  248. package/mcp-server/tools/project/GetApplicationInfoTool.js +5 -5
  249. package/mcp-server/tools/project/GetConfigValuesTool.js +2 -1
  250. package/mcp-server/tools/project/UploadProjectTools.js +6 -3
  251. package/mcp-server/tools/project/ValidateProjectTool.js +2 -1
  252. package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +4 -2
  253. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +4 -2
  254. package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +23 -4
  255. package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +3 -1
  256. package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +0 -1
  257. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +3 -1
  258. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +4 -2
  259. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +8 -5
  260. package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.js +3 -1
  261. package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.js +3 -1
  262. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +7 -3
  263. package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +3 -1
  264. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +17 -3
  265. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +3 -1
  266. package/mcp-server/utils/__tests__/content.test.js +0 -3
  267. package/mcp-server/utils/__tests__/feedbackTracking.test.js +0 -3
  268. package/mcp-server/utils/__tests__/project.test.js +65 -4
  269. package/mcp-server/utils/project.js +6 -2
  270. package/package.json +15 -17
  271. package/types/Cms.d.ts +1 -1
  272. package/types/Cms.js +2 -0
  273. package/types/LocalDev.d.ts +3 -2
  274. package/types/PackageJson.d.ts +10 -0
  275. package/types/PackageJson.js +1 -0
  276. package/types/ProjectComponents.d.ts +1 -1
  277. package/ui/components/BoxWithTitle.js +1 -1
  278. package/ui/components/Table.d.ts +89 -0
  279. package/ui/components/Table.js +246 -0
  280. package/ui/lib/table.d.ts +2 -0
  281. package/ui/lib/table.js +11 -0
  282. package/ui/playground/Playground.d.ts +5 -0
  283. package/ui/{views/UiSandbox.js → playground/Playground.js} +4 -4
  284. package/ui/{lib/ui-testing-utils.d.ts → playground/fixtures.d.ts} +1 -1
  285. package/ui/{lib/ui-testing-utils.js → playground/fixtures.js} +33 -1
  286. package/ui/render.d.ts +19 -0
  287. package/ui/render.js +44 -0
  288. package/commands/__tests__/create.test.js +0 -53
  289. package/commands/create.d.ts +0 -4
  290. package/commands/create.js +0 -137
  291. package/commands/customObject/__tests__/schema.test.js +0 -53
  292. package/commands/customObject/schema/create.d.ts +0 -4
  293. package/commands/customObject/schema/create.js +0 -34
  294. package/commands/customObject/schema/delete.d.ts +0 -4
  295. package/commands/customObject/schema/delete.js +0 -37
  296. package/commands/customObject/schema/fetch-all.d.ts +0 -4
  297. package/commands/customObject/schema/fetch-all.js +0 -32
  298. package/commands/customObject/schema/fetch.d.ts +0 -4
  299. package/commands/customObject/schema/fetch.js +0 -36
  300. package/commands/customObject/schema/list.d.ts +0 -4
  301. package/commands/customObject/schema/list.js +0 -26
  302. package/commands/customObject/schema/update.d.ts +0 -4
  303. package/commands/customObject/schema/update.js +0 -39
  304. package/commands/customObject/schema.d.ts +0 -3
  305. package/commands/customObject/schema.js +0 -31
  306. package/commands/fetch.d.ts +0 -4
  307. package/commands/fetch.js +0 -52
  308. package/commands/function/deploy.d.ts +0 -4
  309. package/commands/function/deploy.js +0 -31
  310. package/commands/function/list.d.ts +0 -4
  311. package/commands/function/list.js +0 -33
  312. package/commands/function/server.d.ts +0 -4
  313. package/commands/function/server.js +0 -57
  314. package/commands/function.d.ts +0 -3
  315. package/commands/function.js +0 -32
  316. package/commands/lint.d.ts +0 -4
  317. package/commands/lint.js +0 -31
  318. package/commands/list.d.ts +0 -4
  319. package/commands/list.js +0 -31
  320. package/commands/logs.d.ts +0 -4
  321. package/commands/logs.js +0 -58
  322. package/commands/module/marketplace-validate.d.ts +0 -4
  323. package/commands/module/marketplace-validate.js +0 -31
  324. package/commands/module.d.ts +0 -3
  325. package/commands/module.js +0 -23
  326. package/commands/mv.d.ts +0 -4
  327. package/commands/mv.js +0 -35
  328. package/commands/project/__tests__/migrateApp.test.js +0 -78
  329. package/commands/project/migrateApp.d.ts +0 -4
  330. package/commands/project/migrateApp.js +0 -55
  331. package/commands/remove.d.ts +0 -4
  332. package/commands/remove.js +0 -31
  333. package/commands/theme/generate-selectors.d.ts +0 -4
  334. package/commands/theme/generate-selectors.js +0 -30
  335. package/commands/theme/marketplace-validate.d.ts +0 -4
  336. package/commands/theme/marketplace-validate.js +0 -33
  337. package/commands/theme/preview.d.ts +0 -4
  338. package/commands/theme/preview.js +0 -59
  339. package/commands/theme.d.ts +0 -3
  340. package/commands/theme.js +0 -29
  341. package/commands/upload.d.ts +0 -4
  342. package/commands/upload.js +0 -62
  343. package/commands/watch.d.ts +0 -4
  344. package/commands/watch.js +0 -73
  345. package/lib/__tests__/npm.test.js +0 -57
  346. package/lib/__tests__/projectProfiles.test.js +0 -129
  347. package/lib/app/__tests__/migrate_legacy.test.js +0 -143
  348. package/lib/app/migrate_legacy.d.ts +0 -4
  349. package/lib/app/migrate_legacy.js +0 -121
  350. package/lib/npm.js +0 -33
  351. package/lib/projectProfiles.d.ts +0 -7
  352. package/lib/projectProfiles.js +0 -73
  353. package/lib/ui/table.d.ts +0 -3
  354. package/lib/ui/table.js +0 -63
  355. package/ui/index.d.ts +0 -1
  356. package/ui/index.js +0 -6
  357. package/ui/views/UiSandbox.d.ts +0 -5
  358. /package/commands/__tests__/{create.test.d.ts → upgrade.test.d.ts} +0 -0
  359. /package/commands/{customObject/__tests__/schema.test.d.ts → cms/__tests__/upload.test.d.ts} +0 -0
  360. /package/commands/{project/__tests__/migrateApp.test.d.ts → cms/__tests__/watch.test.d.ts} +0 -0
  361. /package/{lib/__tests__/npm.test.d.ts → commands/project/__tests__/dev.test.d.ts} +0 -0
  362. /package/lib/__tests__/{projectProfiles.test.d.ts → cliUpgradeUtils.test.d.ts} +0 -0
  363. /package/lib/{app/__tests__/migrate_legacy.test.d.ts → __tests__/npmCli.test.d.ts} +0 -0
@@ -1,9 +1,79 @@
1
1
  import yargs from 'yargs';
2
+ import * as configLib from '@hubspot/local-dev-lib/config';
3
+ import * as personalAccessKeyLib from '@hubspot/local-dev-lib/personalAccessKey';
4
+ import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
2
5
  import { addGlobalOptions, addTestingOptions, } from '../../../lib/commonOpts.js';
6
+ import * as configMigrate from '../../../lib/configMigrate.js';
7
+ import * as processLib from '../../../lib/process.js';
8
+ import * as usageTrackingLib from '../../../lib/usageTracking.js';
9
+ import * as personalAccessKeyPromptLib from '../../../lib/prompts/personalAccessKeyPrompt.js';
10
+ import * as accountNamePromptLib from '../../../lib/prompts/accountNamePrompt.js';
11
+ import * as setAsDefaultPromptLib from '../../../lib/prompts/setAsDefaultAccountPrompt.js';
12
+ import * as parsingLib from '../../../lib/parsing.js';
13
+ import { uiLogger } from '../../../lib/ui/logger.js';
14
+ import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
3
15
  import accountAuthCommand from '../auth.js';
4
16
  vi.mock('../../../lib/commonOpts');
17
+ vi.mock('@hubspot/local-dev-lib/config');
18
+ vi.mock('@hubspot/local-dev-lib/personalAccessKey');
19
+ vi.mock('../../../lib/configMigrate.js');
20
+ vi.mock('../../../lib/process.js');
21
+ vi.mock('../../../lib/prompts/personalAccessKeyPrompt.js');
22
+ vi.mock('../../../lib/prompts/accountNamePrompt.js');
23
+ vi.mock('../../../lib/prompts/setAsDefaultAccountPrompt.js');
24
+ vi.mock('../../../lib/parsing.js');
25
+ vi.mock('../../../lib/ui/index.js');
26
+ vi.mock('../../../lib/errorHandlers/index.js');
27
+ const localConfigFileExistsSpy = vi.spyOn(configLib, 'localConfigFileExists');
28
+ const globalConfigFileExistsSpy = vi.spyOn(configLib, 'globalConfigFileExists');
29
+ const createEmptyConfigFileSpy = vi.spyOn(configLib, 'createEmptyConfigFile');
30
+ const getAccessTokenSpy = vi.spyOn(personalAccessKeyLib, 'getAccessToken');
31
+ const updateConfigWithAccessTokenSpy = vi.spyOn(personalAccessKeyLib, 'updateConfigWithAccessToken');
32
+ const handleMergeSpy = vi.spyOn(configMigrate, 'handleMerge');
33
+ const handleMigrationSpy = vi.spyOn(configMigrate, 'handleMigration');
34
+ const handleExitSpy = vi.spyOn(processLib, 'handleExit');
35
+ const trackCommandUsageSpy = vi.spyOn(usageTrackingLib, 'trackCommandUsage');
36
+ const trackAuthActionSpy = vi.spyOn(usageTrackingLib, 'trackAuthAction');
37
+ const personalAccessKeyPromptSpy = vi.spyOn(personalAccessKeyPromptLib, 'personalAccessKeyPrompt');
38
+ const cliAccountNamePromptSpy = vi.spyOn(accountNamePromptLib, 'cliAccountNamePrompt');
39
+ const setAsDefaultAccountPromptSpy = vi.spyOn(setAsDefaultPromptLib, 'setAsDefaultAccountPrompt');
40
+ const parseStringToNumberSpy = vi.spyOn(parsingLib, 'parseStringToNumber');
41
+ const processExitSpy = vi.spyOn(process, 'exit');
5
42
  describe('commands/account/auth', () => {
6
43
  const yargsMock = yargs;
44
+ beforeEach(() => {
45
+ // @ts-expect-error Mock implementation
46
+ processExitSpy.mockImplementation(() => { });
47
+ localConfigFileExistsSpy.mockReturnValue(false);
48
+ globalConfigFileExistsSpy.mockReturnValue(true);
49
+ createEmptyConfigFileSpy.mockImplementation(() => { });
50
+ handleExitSpy.mockImplementation(async () => { });
51
+ trackCommandUsageSpy.mockImplementation(async () => { });
52
+ trackAuthActionSpy.mockResolvedValue(undefined);
53
+ personalAccessKeyPromptSpy.mockResolvedValue({
54
+ personalAccessKey: 'test-key',
55
+ env: 'prod',
56
+ });
57
+ getAccessTokenSpy.mockResolvedValue({
58
+ portalId: 456789,
59
+ accessToken: 'test-access-token',
60
+ expiresAt: '2025-01-01T00:00:00.000Z',
61
+ scopeGroups: ['content'],
62
+ encodedOAuthRefreshToken: 'encoded-token',
63
+ hubName: 'Test Hub',
64
+ accountType: 'STANDARD',
65
+ });
66
+ cliAccountNamePromptSpy.mockResolvedValue({ name: 'test-account' });
67
+ updateConfigWithAccessTokenSpy.mockResolvedValue({
68
+ accountId: 456789,
69
+ name: 'test-account',
70
+ authType: 'personalaccesskey',
71
+ env: 'prod',
72
+ auth: { tokenInfo: { accessToken: 'test-token' } },
73
+ personalAccessKey: 'test-key',
74
+ });
75
+ setAsDefaultAccountPromptSpy.mockResolvedValue(true);
76
+ });
7
77
  describe('command', () => {
8
78
  it('should have the correct command structure', () => {
9
79
  expect(accountAuthCommand.command).toEqual('auth');
@@ -23,4 +93,114 @@ describe('commands/account/auth', () => {
23
93
  expect(addGlobalOptions).toHaveBeenCalledWith(yargsMock);
24
94
  });
25
95
  });
96
+ describe('handler', () => {
97
+ let args;
98
+ beforeEach(() => {
99
+ args = {
100
+ derivedAccountId: 0,
101
+ d: false,
102
+ debug: false,
103
+ _: [],
104
+ $0: '',
105
+ };
106
+ });
107
+ it('should track command usage', async () => {
108
+ await accountAuthCommand.handler(args);
109
+ expect(trackCommandUsageSpy).toHaveBeenCalledWith('account-auth', {}, undefined);
110
+ expect(trackAuthActionSpy).toHaveBeenCalledWith('account-auth', 'personalaccesskey', 'started');
111
+ });
112
+ it('should not track when tracking is disabled', async () => {
113
+ args.disableTracking = true;
114
+ await accountAuthCommand.handler(args);
115
+ expect(trackCommandUsageSpy).not.toHaveBeenCalled();
116
+ expect(trackAuthActionSpy).not.toHaveBeenCalled();
117
+ expect(updateConfigWithAccessTokenSpy).toHaveBeenCalled();
118
+ });
119
+ it('should parse user provided account ID', async () => {
120
+ args.userProvidedAccount = '123456';
121
+ parseStringToNumberSpy.mockReturnValue(123456);
122
+ await accountAuthCommand.handler(args);
123
+ expect(parseStringToNumberSpy).toHaveBeenCalledWith('123456');
124
+ expect(trackCommandUsageSpy).toHaveBeenCalledWith('account-auth', {}, 123456);
125
+ });
126
+ it('should error on invalid account ID', async () => {
127
+ args.userProvidedAccount = 'invalid';
128
+ parseStringToNumberSpy.mockImplementation(() => {
129
+ throw new Error('Invalid');
130
+ });
131
+ await accountAuthCommand.handler(args);
132
+ expect(uiLogger.error).toHaveBeenCalledWith('--account must be a number.');
133
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.ERROR);
134
+ });
135
+ it('should handle merge when both configs exist', async () => {
136
+ localConfigFileExistsSpy.mockReturnValue(true);
137
+ globalConfigFileExistsSpy.mockReturnValue(true);
138
+ handleMergeSpy.mockResolvedValue(true);
139
+ await accountAuthCommand.handler(args);
140
+ expect(handleMergeSpy).toHaveBeenCalled();
141
+ });
142
+ it('should exit if merge is not confirmed', async () => {
143
+ localConfigFileExistsSpy.mockReturnValue(true);
144
+ globalConfigFileExistsSpy.mockReturnValue(true);
145
+ handleMergeSpy.mockResolvedValue(false);
146
+ await accountAuthCommand.handler(args);
147
+ expect(uiLogger.log).toHaveBeenCalled();
148
+ expect(trackAuthActionSpy).toHaveBeenCalledWith('account-auth', 'personalaccesskey', 'error');
149
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.ERROR);
150
+ });
151
+ it('should handle migration when only local config exists', async () => {
152
+ localConfigFileExistsSpy.mockReturnValue(true);
153
+ globalConfigFileExistsSpy.mockReturnValue(false);
154
+ handleMigrationSpy.mockResolvedValue(true);
155
+ await accountAuthCommand.handler(args);
156
+ expect(handleMigrationSpy).toHaveBeenCalled();
157
+ });
158
+ it('should create config file if it does not exist', async () => {
159
+ globalConfigFileExistsSpy.mockReturnValue(false);
160
+ await accountAuthCommand.handler(args);
161
+ expect(createEmptyConfigFileSpy).toHaveBeenCalledWith(true);
162
+ });
163
+ it('should prompt for personal access key', async () => {
164
+ await accountAuthCommand.handler(args);
165
+ expect(personalAccessKeyPromptSpy).toHaveBeenCalledWith({
166
+ env: ENVIRONMENTS.PROD,
167
+ account: undefined,
168
+ });
169
+ });
170
+ it('should use provided personal access key', async () => {
171
+ args.personalAccessKey = 'provided-key';
172
+ await accountAuthCommand.handler(args);
173
+ expect(personalAccessKeyPromptSpy).not.toHaveBeenCalled();
174
+ expect(getAccessTokenSpy).toHaveBeenCalledWith('provided-key', ENVIRONMENTS.PROD);
175
+ });
176
+ it('should use QA environment when qa flag is set', async () => {
177
+ args.qa = true;
178
+ await accountAuthCommand.handler(args);
179
+ expect(getAccessTokenSpy).toHaveBeenCalledWith('test-key', ENVIRONMENTS.QA);
180
+ });
181
+ it('should prompt for account name for new config', async () => {
182
+ globalConfigFileExistsSpy.mockReturnValue(false);
183
+ await accountAuthCommand.handler(args);
184
+ expect(cliAccountNamePromptSpy).toHaveBeenCalledWith('test-hub');
185
+ });
186
+ it('should not prompt for account name for existing config', async () => {
187
+ globalConfigFileExistsSpy.mockReturnValue(true);
188
+ await accountAuthCommand.handler(args);
189
+ expect(setAsDefaultAccountPromptSpy).toHaveBeenCalledWith('test-account');
190
+ });
191
+ it('should exit with error if config update fails', async () => {
192
+ getAccessTokenSpy.mockRejectedValue(new Error('Invalid key'));
193
+ await accountAuthCommand.handler(args);
194
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('Failed'));
195
+ expect(trackAuthActionSpy).toHaveBeenCalledWith('account-auth', 'personalaccesskey', 'error');
196
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.ERROR);
197
+ });
198
+ it('should log success for new config', async () => {
199
+ globalConfigFileExistsSpy.mockReturnValue(false);
200
+ await accountAuthCommand.handler(args);
201
+ expect(uiLogger.success).toHaveBeenCalled();
202
+ expect(trackAuthActionSpy).toHaveBeenCalledWith('account-auth', 'personalaccesskey', 'complete', 456789);
203
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.SUCCESS);
204
+ });
205
+ });
26
206
  });
@@ -1,12 +1,34 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import yargs from 'yargs';
2
- import { addConfigOptions } from '../../../lib/commonOpts.js';
3
+ import * as configLib from '@hubspot/local-dev-lib/config';
4
+ import * as defaultAccountOverrideLib from '@hubspot/local-dev-lib/config/defaultAccountOverride';
5
+ import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
6
+ import * as commonOpts from '../../../lib/commonOpts.js';
7
+ import * as usageTrackingLib from '../../../lib/usageTracking.js';
8
+ import { uiLogger } from '../../../lib/ui/logger.js';
3
9
  import accountListCommand from '../list.js';
4
10
  vi.mock('../../../lib/commonOpts');
11
+ vi.mock('@hubspot/local-dev-lib/config');
12
+ vi.mock('@hubspot/local-dev-lib/config/defaultAccountOverride');
13
+ vi.mock('../../../lib/ui/index.js');
14
+ vi.mock('../../../lib/ui/table.js');
15
+ const getConfigFilePathSpy = vi.spyOn(configLib, 'getConfigFilePath');
16
+ const getAllConfigAccountsSpy = vi.spyOn(configLib, 'getAllConfigAccounts');
17
+ const getConfigDefaultAccountIfExistsSpy = vi.spyOn(configLib, 'getConfigDefaultAccountIfExists');
18
+ const getDefaultAccountOverrideFilePathSpy = vi.spyOn(defaultAccountOverrideLib, 'getDefaultAccountOverrideFilePath');
19
+ const trackCommandUsageSpy = vi.spyOn(usageTrackingLib, 'trackCommandUsage');
5
20
  const exampleSpy = vi
6
21
  .spyOn(yargs, 'example')
7
22
  .mockReturnValue(yargs);
8
23
  describe('commands/account/list', () => {
9
24
  const yargsMock = yargs;
25
+ beforeEach(() => {
26
+ getConfigFilePathSpy.mockReturnValue('/test/.hscli.config.yaml');
27
+ getAllConfigAccountsSpy.mockReturnValue([]);
28
+ getConfigDefaultAccountIfExistsSpy.mockReturnValue(undefined);
29
+ getDefaultAccountOverrideFilePathSpy.mockReturnValue(null);
30
+ trackCommandUsageSpy.mockImplementation(async () => { });
31
+ });
10
32
  describe('command', () => {
11
33
  it('should have the correct command structure', () => {
12
34
  expect(accountListCommand.command).toEqual(['list', 'ls']);
@@ -21,8 +43,111 @@ describe('commands/account/list', () => {
21
43
  it('should support the correct options', () => {
22
44
  accountListCommand.builder(yargsMock);
23
45
  expect(exampleSpy).toHaveBeenCalledTimes(1);
24
- expect(addConfigOptions).toHaveBeenCalledTimes(1);
25
- expect(addConfigOptions).toHaveBeenCalledWith(yargsMock);
46
+ expect(commonOpts.addConfigOptions).toHaveBeenCalledTimes(1);
47
+ expect(commonOpts.addConfigOptions).toHaveBeenCalledWith(yargsMock);
48
+ });
49
+ });
50
+ describe('handler', () => {
51
+ let args;
52
+ beforeEach(() => {
53
+ args = {
54
+ derivedAccountId: 123456,
55
+ d: false,
56
+ debug: false,
57
+ _: [],
58
+ $0: '',
59
+ };
60
+ });
61
+ it('should track command usage', async () => {
62
+ await accountListCommand.handler(args);
63
+ expect(trackCommandUsageSpy).toHaveBeenCalledWith('accounts-list', undefined, 123456);
64
+ });
65
+ it('should display accounts list when no default account', async () => {
66
+ const accounts = [
67
+ {
68
+ accountId: 111111,
69
+ name: 'Test Account 1',
70
+ authType: 'personalaccesskey',
71
+ accountType: HUBSPOT_ACCOUNT_TYPES.STANDARD,
72
+ },
73
+ {
74
+ accountId: 222222,
75
+ name: 'Test Account 2',
76
+ authType: 'oauth2',
77
+ accountType: HUBSPOT_ACCOUNT_TYPES.STANDARD,
78
+ },
79
+ ];
80
+ getAllConfigAccountsSpy.mockReturnValue(accounts);
81
+ await accountListCommand.handler(args);
82
+ expect(getAllConfigAccountsSpy).toHaveBeenCalled();
83
+ expect(uiLogger.log).toHaveBeenCalledWith(expect.stringContaining('Accounts'));
84
+ });
85
+ it('should display default account when present', async () => {
86
+ getConfigDefaultAccountIfExistsSpy.mockReturnValue({
87
+ accountId: 123456,
88
+ name: 'Default Account',
89
+ });
90
+ await accountListCommand.handler(args);
91
+ expect(getConfigDefaultAccountIfExistsSpy).toHaveBeenCalled();
92
+ expect(uiLogger.log).toHaveBeenCalled();
93
+ });
94
+ it('should display config file path when default account present', async () => {
95
+ getConfigDefaultAccountIfExistsSpy.mockReturnValue({
96
+ accountId: 123456,
97
+ });
98
+ await accountListCommand.handler(args);
99
+ expect(getConfigFilePathSpy).toHaveBeenCalled();
100
+ expect(uiLogger.log).toHaveBeenCalled();
101
+ });
102
+ it('should display override file path when present', async () => {
103
+ getConfigDefaultAccountIfExistsSpy.mockReturnValue({
104
+ accountId: 123456,
105
+ });
106
+ getDefaultAccountOverrideFilePathSpy.mockReturnValue('/test/override.yaml');
107
+ await accountListCommand.handler(args);
108
+ expect(getDefaultAccountOverrideFilePathSpy).toHaveBeenCalled();
109
+ expect(uiLogger.log).toHaveBeenCalled();
110
+ });
111
+ it('should group sandbox accounts under parent', async () => {
112
+ const accounts = [
113
+ {
114
+ accountId: 111111,
115
+ name: 'Parent Account',
116
+ authType: 'personalaccesskey',
117
+ accountType: HUBSPOT_ACCOUNT_TYPES.STANDARD,
118
+ },
119
+ {
120
+ accountId: 222222,
121
+ name: 'Sandbox Account',
122
+ authType: 'personalaccesskey',
123
+ accountType: HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX,
124
+ parentAccountId: 111111,
125
+ },
126
+ ];
127
+ getAllConfigAccountsSpy.mockReturnValue(accounts);
128
+ await accountListCommand.handler(args);
129
+ expect(getAllConfigAccountsSpy).toHaveBeenCalled();
130
+ expect(uiLogger.log).toHaveBeenCalled();
131
+ });
132
+ it('should display app developer accounts', async () => {
133
+ const accounts = [
134
+ {
135
+ accountId: 333333,
136
+ name: 'App Developer Account',
137
+ authType: 'personalaccesskey',
138
+ accountType: HUBSPOT_ACCOUNT_TYPES.APP_DEVELOPER,
139
+ },
140
+ ];
141
+ getAllConfigAccountsSpy.mockReturnValue(accounts);
142
+ await accountListCommand.handler(args);
143
+ expect(getAllConfigAccountsSpy).toHaveBeenCalled();
144
+ expect(uiLogger.log).toHaveBeenCalled();
145
+ });
146
+ it('should handle empty accounts list', async () => {
147
+ getAllConfigAccountsSpy.mockReturnValue([]);
148
+ await accountListCommand.handler(args);
149
+ expect(getAllConfigAccountsSpy).toHaveBeenCalled();
150
+ expect(uiLogger.log).toHaveBeenCalled();
26
151
  });
27
152
  });
28
153
  });
@@ -8,7 +8,6 @@ import * as usageTracking from '../../../lib/usageTracking.js';
8
8
  vi.mock('../../../lib/commonOpts');
9
9
  vi.mock('@hubspot/local-dev-lib/config');
10
10
  vi.mock('../../../lib/errorHandlers/index.js');
11
- vi.mock('../../../lib/usageTracking.js');
12
11
  const positionalSpy = vi
13
12
  .spyOn(yargs, 'positional')
14
13
  .mockReturnValue(yargs);
@@ -33,7 +32,6 @@ describe('commands/account/rename', () => {
33
32
  describe('handler', () => {
34
33
  let args;
35
34
  beforeEach(() => {
36
- vi.clearAllMocks();
37
35
  renameAccountSpy.mockReturnValue(undefined);
38
36
  processExitSpy.mockImplementation(() => {
39
37
  throw new Error('process.exit called');
@@ -1,5 +1,25 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import yargs from 'yargs';
3
+ import * as configLib from '@hubspot/local-dev-lib/config';
4
+ import * as defaultAccountOverrideLib from '@hubspot/local-dev-lib/config/defaultAccountOverride';
5
+ import * as usageTrackingLib from '../../../lib/usageTracking.js';
6
+ import { uiLogger } from '../../../lib/ui/logger.js';
7
+ vi.mock('@hubspot/local-dev-lib/config');
8
+ vi.mock('@hubspot/local-dev-lib/config/defaultAccountOverride');
9
+ vi.mock('../../../lib/prompts/accountsPrompt.js');
10
+ // Import after mocks
11
+ import * as accountsPromptLib from '../../../lib/prompts/accountsPrompt.js';
2
12
  import accountUseCommand from '../use.js';
13
+ const getConfigFilePathSpy = vi.spyOn(configLib, 'getConfigFilePath');
14
+ const getConfigAccountIfExistsSpy = vi.spyOn(configLib, 'getConfigAccountIfExists');
15
+ const getConfigAccountByNameSpy = vi.spyOn(configLib, 'getConfigAccountByName');
16
+ const getConfigAccountByIdSpy = vi.spyOn(configLib, 'getConfigAccountById');
17
+ const getAllConfigAccountsSpy = vi.spyOn(configLib, 'getAllConfigAccounts');
18
+ const setConfigAccountAsDefaultSpy = vi.spyOn(configLib, 'setConfigAccountAsDefault');
19
+ const getDefaultAccountOverrideAccountIdSpy = vi.spyOn(defaultAccountOverrideLib, 'getDefaultAccountOverrideAccountId');
20
+ const getDefaultAccountOverrideFilePathSpy = vi.spyOn(defaultAccountOverrideLib, 'getDefaultAccountOverrideFilePath');
21
+ const selectAccountFromConfigSpy = vi.spyOn(accountsPromptLib, 'selectAccountFromConfig');
22
+ const trackCommandUsageSpy = vi.spyOn(usageTrackingLib, 'trackCommandUsage');
3
23
  const positionalSpy = vi
4
24
  .spyOn(yargs, 'positional')
5
25
  .mockReturnValue(yargs);
@@ -8,6 +28,14 @@ const exampleSpy = vi
8
28
  .mockReturnValue(yargs);
9
29
  describe('commands/account/use', () => {
10
30
  const yargsMock = yargs;
31
+ beforeEach(() => {
32
+ getConfigFilePathSpy.mockReturnValue('/test/.hscli.config.yaml');
33
+ getAllConfigAccountsSpy.mockReturnValue([]);
34
+ getDefaultAccountOverrideAccountIdSpy.mockReturnValue(null);
35
+ getDefaultAccountOverrideFilePathSpy.mockReturnValue(null);
36
+ trackCommandUsageSpy.mockImplementation(async () => { });
37
+ setConfigAccountAsDefaultSpy.mockImplementation(() => { });
38
+ });
11
39
  describe('command', () => {
12
40
  it('should have the correct command structure', () => {
13
41
  expect(accountUseCommand.command).toEqual('use [account]');
@@ -29,4 +57,114 @@ describe('commands/account/use', () => {
29
57
  });
30
58
  });
31
59
  });
60
+ describe('handler', () => {
61
+ let args;
62
+ beforeEach(() => {
63
+ args = {
64
+ derivedAccountId: 0,
65
+ d: false,
66
+ debug: false,
67
+ _: [],
68
+ $0: '',
69
+ };
70
+ });
71
+ describe('with account ID', () => {
72
+ it('should set account by ID', async () => {
73
+ args.account = '123456';
74
+ const account = {
75
+ accountId: 123456,
76
+ name: 'Test Account',
77
+ };
78
+ getConfigAccountIfExistsSpy.mockReturnValue(account);
79
+ getConfigAccountByIdSpy.mockReturnValue(account);
80
+ await accountUseCommand.handler(args);
81
+ expect(getConfigAccountByIdSpy).toHaveBeenCalledWith(123456);
82
+ expect(setConfigAccountAsDefaultSpy).toHaveBeenCalledWith('123456');
83
+ expect(uiLogger.success).toHaveBeenCalled();
84
+ });
85
+ it('should track command usage', async () => {
86
+ args.account = '123456';
87
+ const account = {
88
+ accountId: 123456,
89
+ name: 'Test Account',
90
+ };
91
+ getConfigAccountIfExistsSpy.mockReturnValue(account);
92
+ getConfigAccountByIdSpy.mockReturnValue(account);
93
+ await accountUseCommand.handler(args);
94
+ expect(trackCommandUsageSpy).toHaveBeenCalledWith('accounts-use', undefined, 123456);
95
+ });
96
+ });
97
+ describe('with account name', () => {
98
+ it('should set account by name', async () => {
99
+ args.account = 'MyAccount';
100
+ const account = {
101
+ accountId: 123456,
102
+ name: 'MyAccount',
103
+ };
104
+ getConfigAccountIfExistsSpy.mockReturnValue(account);
105
+ getConfigAccountByNameSpy.mockReturnValue(account);
106
+ await accountUseCommand.handler(args);
107
+ expect(getConfigAccountByNameSpy).toHaveBeenCalledWith('MyAccount');
108
+ expect(setConfigAccountAsDefaultSpy).toHaveBeenCalledWith('MyAccount');
109
+ expect(uiLogger.success).toHaveBeenCalled();
110
+ });
111
+ });
112
+ describe('account not found', () => {
113
+ it('should prompt when account not found', async () => {
114
+ args.account = 'InvalidAccount';
115
+ const account = {
116
+ accountId: 999999,
117
+ name: 'Selected Account',
118
+ };
119
+ getConfigAccountIfExistsSpy.mockReturnValue(undefined);
120
+ selectAccountFromConfigSpy.mockResolvedValue(999999);
121
+ getConfigAccountByIdSpy.mockReturnValue(account);
122
+ await accountUseCommand.handler(args);
123
+ expect(uiLogger.error).toHaveBeenCalled();
124
+ expect(selectAccountFromConfigSpy).toHaveBeenCalled();
125
+ expect(setConfigAccountAsDefaultSpy).toHaveBeenCalledWith('999999');
126
+ });
127
+ });
128
+ describe('without account argument', () => {
129
+ it('should prompt for account selection', async () => {
130
+ const account = {
131
+ accountId: 888888,
132
+ name: 'Prompted Account',
133
+ };
134
+ selectAccountFromConfigSpy.mockResolvedValue(888888);
135
+ getConfigAccountByIdSpy.mockReturnValue(account);
136
+ await accountUseCommand.handler(args);
137
+ expect(selectAccountFromConfigSpy).toHaveBeenCalled();
138
+ expect(setConfigAccountAsDefaultSpy).toHaveBeenCalledWith('888888');
139
+ });
140
+ });
141
+ describe('account override', () => {
142
+ it('should warn when account override is present', async () => {
143
+ args.account = '123456';
144
+ const account = {
145
+ accountId: 123456,
146
+ name: 'Test Account',
147
+ };
148
+ getConfigAccountIfExistsSpy.mockReturnValue(account);
149
+ getConfigAccountByIdSpy.mockReturnValue(account);
150
+ getDefaultAccountOverrideAccountIdSpy.mockReturnValue(777777);
151
+ getDefaultAccountOverrideFilePathSpy.mockReturnValue('/test/override.yaml');
152
+ getAllConfigAccountsSpy.mockReturnValue([account]);
153
+ await accountUseCommand.handler(args);
154
+ expect(getDefaultAccountOverrideAccountIdSpy).toHaveBeenCalled();
155
+ expect(uiLogger.warn).toHaveBeenCalled();
156
+ });
157
+ it('should not warn when no account override', async () => {
158
+ args.account = '123456';
159
+ const account = {
160
+ accountId: 123456,
161
+ name: 'Test Account',
162
+ };
163
+ getConfigAccountIfExistsSpy.mockReturnValue(account);
164
+ getConfigAccountByIdSpy.mockReturnValue(account);
165
+ await accountUseCommand.handler(args);
166
+ expect(uiLogger.warn).not.toHaveBeenCalled();
167
+ });
168
+ });
169
+ });
32
170
  });
@@ -125,7 +125,7 @@ async function handler(args) {
125
125
  await trackAuthAction('account-auth', authType, TRACKING_STATUS.ERROR);
126
126
  }
127
127
  uiLogger.error(commands.account.subcommands.auth.errors.failedToUpdateConfig);
128
- process.exit(EXIT_CODES.ERROR);
128
+ return process.exit(EXIT_CODES.ERROR);
129
129
  }
130
130
  const { accountId, name } = updatedConfig;
131
131
  if (!configAlreadyExists) {
@@ -7,13 +7,13 @@ import { trackCommandUsage } from '../../lib/usageTracking.js';
7
7
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
8
8
  import { promptUser } from '../../lib/prompts/promptUtils.js';
9
9
  import { selectAccountFromConfig } from '../../lib/prompts/accountsPrompt.js';
10
- import { getTableContents } from '../../lib/ui/table.js';
11
10
  import SpinniesManager from '../../lib/ui/SpinniesManager.js';
12
11
  import { uiAccountDescription } from '../../lib/ui/index.js';
13
12
  import { logError } from '../../lib/errorHandlers/index.js';
14
13
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
15
14
  import { commands } from '../../lang/en.js';
16
15
  import { uiLogger } from '../../lib/ui/logger.js';
16
+ import { renderList } from '../../ui/render.js';
17
17
  const command = 'clean';
18
18
  const describe = commands.account.subcommands.clean.describe;
19
19
  async function handler(args) {
@@ -58,11 +58,12 @@ async function handler(args) {
58
58
  ? commands.account.subcommands.clean.inactiveAccountsFound.one
59
59
  : commands.account.subcommands.clean.inactiveAccountsFound.other(accountsToRemove.length),
60
60
  });
61
- uiLogger.log(getTableContents(accountsToRemove.map(p => [uiAccountDescription(p.accountId)]), { border: { bodyLeft: ' ' } }));
61
+ renderList(accountsToRemove.map(p => [uiAccountDescription(p.accountId)]));
62
+ uiLogger.log('');
62
63
  let promptMessage = oneAccountFound
63
64
  ? commands.account.subcommands.clean.confirm.one
64
65
  : commands.account.subcommands.clean.confirm.other(accountsToRemove.length);
65
- const accountOverride = getDefaultAccountOverrideAccountId();
66
+ const accountOverride = getDefaultAccountOverrideAccountId(accountsList);
66
67
  const overrideFilePath = getDefaultAccountOverrideFilePath();
67
68
  const accountOverrideMatches = accountsToRemove.some(account => account.accountId === accountOverride);
68
69
  if (overrideFilePath && accountOverride && accountOverrideMatches) {
@@ -2,7 +2,7 @@ import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  import { getCwd } from '@hubspot/local-dev-lib/path';
4
4
  import { DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME } from '@hubspot/local-dev-lib/constants/config';
5
- import { getConfigFilePath, getConfigAccountIfExists, globalConfigFileExists, } from '@hubspot/local-dev-lib/config';
5
+ import { getConfigFilePath, getConfigAccountIfExists, globalConfigFileExists, getAllConfigAccounts, } from '@hubspot/local-dev-lib/config';
6
6
  import { getDefaultAccountOverrideAccountId, getDefaultAccountOverrideFilePath, } from '@hubspot/local-dev-lib/config/defaultAccountOverride';
7
7
  import { promptUser } from '../../lib/prompts/promptUtils.js';
8
8
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
@@ -21,7 +21,8 @@ async function handler(args) {
21
21
  uiLogger.error(commands.account.subcommands.createOverride.errors.globalConfigNotFound);
22
22
  process.exit(EXIT_CODES.ERROR);
23
23
  }
24
- const accountOverrideId = getDefaultAccountOverrideAccountId();
24
+ const accounts = getAllConfigAccounts();
25
+ const accountOverrideId = getDefaultAccountOverrideAccountId(accounts);
25
26
  const overrideFilePath = getDefaultAccountOverrideFilePath();
26
27
  if (accountOverrideId && overrideFilePath) {
27
28
  uiLogger.log(commands.account.subcommands.createOverride.accountOverride(overrideFilePath, accountOverrideId.toString()));
@@ -3,9 +3,9 @@ import { getDefaultAccountOverrideFilePath } from '@hubspot/local-dev-lib/config
3
3
  import { getAccessToken } from '@hubspot/local-dev-lib/personalAccessKey';
4
4
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
5
5
  import { indent } from '../../lib/ui/index.js';
6
- import { getTableContents } from '../../lib/ui/table.js';
7
6
  import { commands } from '../../lang/en.js';
8
7
  import { uiLogger } from '../../lib/ui/logger.js';
8
+ import { renderList } from '../../ui/render.js';
9
9
  const describe = commands.account.subcommands.info.describe;
10
10
  const command = 'info [account]';
11
11
  async function handler(args) {
@@ -38,7 +38,7 @@ async function handler(args) {
38
38
  uiLogger.log(commands.account.subcommands.info.name(name));
39
39
  uiLogger.log(commands.account.subcommands.info.accountId(derivedAccountId));
40
40
  uiLogger.log(commands.account.subcommands.info.scopeGroups);
41
- uiLogger.log(getTableContents(scopeGroups, { border: { bodyLeft: ' ' } }));
41
+ renderList(scopeGroups);
42
42
  }
43
43
  else {
44
44
  uiLogger.log(commands.account.subcommands.info.errors.notUsingPersonalAccessKey);
@@ -1,13 +1,13 @@
1
1
  import { getConfigFilePath, getAllConfigAccounts, getConfigDefaultAccountIfExists, } from '@hubspot/local-dev-lib/config';
2
2
  import { getDefaultAccountOverrideFilePath } from '@hubspot/local-dev-lib/config/defaultAccountOverride';
3
3
  import { indent } from '../../lib/ui/index.js';
4
- import { getTableContents, getTableHeader } from '../../lib/ui/table.js';
5
4
  import { trackCommandUsage } from '../../lib/usageTracking.js';
6
5
  import { isSandbox, isDeveloperTestAccount } from '../../lib/accountTypes.js';
7
6
  import { HUBSPOT_ACCOUNT_TYPES, HUBSPOT_ACCOUNT_TYPE_STRINGS, } from '@hubspot/local-dev-lib/constants/config';
8
7
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
8
  import { uiLogger } from '../../lib/ui/logger.js';
10
9
  import { commands } from '../../lang/en.js';
10
+ import { renderTable } from '../../ui/render.js';
11
11
  const command = ['list', 'ls'];
12
12
  const describe = commands.account.subcommands.list.describe;
13
13
  function sortAndMapAccounts(accounts) {
@@ -65,11 +65,11 @@ async function handler(args) {
65
65
  const accountsList = getAllConfigAccounts();
66
66
  const mappedAccountData = sortAndMapAccounts(accountsList);
67
67
  const accountData = getAccountData(mappedAccountData);
68
- accountData.unshift(getTableHeader([
68
+ const tableHeader = [
69
69
  commands.account.subcommands.list.labels.name,
70
70
  commands.account.subcommands.list.labels.accountId,
71
71
  commands.account.subcommands.list.labels.authType,
72
- ]));
72
+ ];
73
73
  const defaultAccount = getConfigDefaultAccountIfExists();
74
74
  const accountId = defaultAccount?.accountId;
75
75
  const overrideFilePath = getDefaultAccountOverrideFilePath();
@@ -88,7 +88,7 @@ async function handler(args) {
88
88
  uiLogger.log('');
89
89
  }
90
90
  uiLogger.log(commands.account.subcommands.list.accounts);
91
- uiLogger.log(getTableContents(accountData, { border: { bodyLeft: ' ' } }));
91
+ renderTable(tableHeader, accountData, true);
92
92
  }
93
93
  function accountListBuilder(yargs) {
94
94
  yargs.example([['$0 accounts list']]);
@@ -1,5 +1,5 @@
1
1
  import fs from 'fs';
2
- import { getConfigFilePath, removeAccountFromConfig, getConfigDefaultAccountIfExists, getConfigAccountIfExists, getConfigAccountById, setConfigAccountAsDefault, } from '@hubspot/local-dev-lib/config';
2
+ import { getConfigFilePath, removeAccountFromConfig, getConfigDefaultAccountIfExists, getConfigAccountIfExists, getConfigAccountById, setConfigAccountAsDefault, getAllConfigAccounts, } from '@hubspot/local-dev-lib/config';
3
3
  import { getDefaultAccountOverrideAccountId, getDefaultAccountOverrideFilePath, } from '@hubspot/local-dev-lib/config/defaultAccountOverride';
4
4
  import { trackCommandUsage } from '../../lib/usageTracking.js';
5
5
  import { promptUser } from '../../lib/prompts/promptUtils.js';
@@ -25,7 +25,8 @@ async function handler(args) {
25
25
  accountToRemoveConfig = getConfigAccountById(accountToRemoveId);
26
26
  trackCommandUsage('accounts-remove', undefined, accountToRemoveId);
27
27
  const currentDefaultAccount = getConfigDefaultAccountIfExists();
28
- const accountOverride = getDefaultAccountOverrideAccountId();
28
+ const accounts = getAllConfigAccounts();
29
+ const accountOverride = getDefaultAccountOverrideAccountId(accounts);
29
30
  const overrideFilePath = getDefaultAccountOverrideFilePath();
30
31
  if (overrideFilePath &&
31
32
  accountOverride &&