@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,5 +1,4 @@
1
1
  import SpinniesManager from '../../lib/ui/SpinniesManager.js';
2
- import { getTableContents, getTableHeader } from '../../lib/ui/table.js';
3
2
  import { promptUser } from '../../lib/prompts/promptUtils.js';
4
3
  import { commands } from '../../lang/en.js';
5
4
  import { uiLogger } from '../../lib/ui/logger.js';
@@ -9,6 +8,7 @@ import { HUBSPOT_FOLDER, MARKETPLACE_FOLDER } from '../../lib/constants.js';
9
8
  import { uiLink } from '../../lib/ui/index.js';
10
9
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
11
10
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
11
+ import { renderTable } from '../../ui/render.js';
12
12
  const DEFAULT_TABLE_HEADER = [
13
13
  'Accessibility',
14
14
  'Best practices',
@@ -64,12 +64,12 @@ async function handler(args) {
64
64
  const includeMobileScore = target === 'mobile' || !verbose;
65
65
  let themeToCheck = theme;
66
66
  if (themeToCheck) {
67
- let isValidTheme = true;
67
+ let isValidTheme = false;
68
68
  try {
69
- const { data: result } = await fetchThemes(derivedAccountId, {
70
- name: encodeURIComponent(themeToCheck),
71
- });
72
- isValidTheme = result && !!result.total;
69
+ const { data: result } = await fetchThemes(derivedAccountId);
70
+ if (result && result.objects) {
71
+ isValidTheme = result.objects.some(({ theme }) => theme.path === themeToCheck);
72
+ }
73
73
  }
74
74
  catch (err) {
75
75
  isValidTheme = false;
@@ -100,7 +100,6 @@ async function handler(args) {
100
100
  }
101
101
  // Poll till scoring is finished
102
102
  try {
103
- SpinniesManager.init();
104
103
  SpinniesManager.add('lighthouseScore', {
105
104
  text: commands.cms.subcommands.lighthouseScore.info.generatingScore(themeToCheck),
106
105
  });
@@ -175,25 +174,21 @@ async function handler(args) {
175
174
  process.exit(EXIT_CODES.ERROR);
176
175
  }
177
176
  uiLogger.log(commands.cms.subcommands.lighthouseScore.info.themeToCheckTitle(themeToCheck, target));
178
- const tableHeader = getTableHeader(DEFAULT_TABLE_HEADER);
179
177
  const scores = verboseViewAverageScoreResult.scores
180
178
  ? verboseViewAverageScoreResult.scores[0]
181
179
  : EMPTY_SCORE;
182
180
  const averageTableData = [
183
- scores.accessibilityScore,
184
- scores.bestPracticesScore,
185
- scores.performanceScore,
186
- scores.pwaScore,
187
- scores.seoScore,
181
+ [
182
+ scores.accessibilityScore,
183
+ scores.bestPracticesScore,
184
+ scores.performanceScore,
185
+ scores.pwaScore,
186
+ scores.seoScore,
187
+ ],
188
188
  ];
189
- uiLogger.log(getTableContents([tableHeader, averageTableData], {
190
- border: { bodyLeft: ' ' },
191
- }));
189
+ renderTable(DEFAULT_TABLE_HEADER, averageTableData);
190
+ uiLogger.log('');
192
191
  uiLogger.log(commands.cms.subcommands.lighthouseScore.info.pageTemplateScoreTitle);
193
- const table2Header = getTableHeader([
194
- 'Template path',
195
- ...DEFAULT_TABLE_HEADER,
196
- ]);
197
192
  const templateTableData = scoreResult.scores.map(score => {
198
193
  return [
199
194
  score.templatePath,
@@ -204,9 +199,8 @@ async function handler(args) {
204
199
  score.seoScore,
205
200
  ];
206
201
  });
207
- uiLogger.log(getTableContents([table2Header, ...templateTableData], {
208
- border: { bodyLeft: ' ' },
209
- }));
202
+ renderTable(['Template path', ...DEFAULT_TABLE_HEADER], templateTableData);
203
+ uiLogger.log('');
210
204
  uiLogger.log(commands.cms.subcommands.lighthouseScore.info.lighthouseLinksTitle);
211
205
  scoreResult.scores.forEach(score => {
212
206
  if (score.templatePath && score.link) {
@@ -225,7 +219,6 @@ async function handler(args) {
225
219
  }
226
220
  else {
227
221
  uiLogger.log(commands.cms.subcommands.lighthouseScore.info.themeTitle(themeToCheck));
228
- const tableHeader = getTableHeader(['Target', ...DEFAULT_TABLE_HEADER]);
229
222
  const getTableData = (target, scoreResult) => {
230
223
  const scores = scoreResult?.scores ? scoreResult.scores[0] : EMPTY_SCORE;
231
224
  return [
@@ -241,9 +234,8 @@ async function handler(args) {
241
234
  getTableData('desktop', desktopScoreResult),
242
235
  getTableData('mobile', mobileScoreResult),
243
236
  ];
244
- uiLogger.log(getTableContents([tableHeader, ...tableData], {
245
- border: { bodyLeft: ' ' },
246
- }));
237
+ renderTable(['Target', ...DEFAULT_TABLE_HEADER], tableData);
238
+ uiLogger.log('');
247
239
  uiLogger.info(commands.cms.subcommands.lighthouseScore.info.verboseOptionNote);
248
240
  }
249
241
  uiLogger.log('');
@@ -9,7 +9,6 @@ const describe = commands.cms.subcommands.module.subcommands.marketplaceValidate
9
9
  async function handler(args) {
10
10
  const { src, derivedAccountId } = args;
11
11
  trackCommandUsage('validate', undefined, derivedAccountId);
12
- SpinniesManager.init();
13
12
  SpinniesManager.add('marketplaceValidation', {
14
13
  text: commands.cms.subcommands.module.subcommands.marketplaceValidate.logs.validatingModule(src),
15
14
  });
@@ -29,12 +29,6 @@ describe('commands/theme/preview', () => {
29
29
  type: 'string',
30
30
  requiresArg: true,
31
31
  });
32
- expect(optionSpy).toHaveBeenCalledWith('notify', {
33
- describe: expect.any(String),
34
- alias: 'n',
35
- type: 'string',
36
- requiresArg: true,
37
- });
38
32
  expect(optionSpy).toHaveBeenCalledWith('no-ssl', {
39
33
  describe: expect.any(String),
40
34
  type: 'boolean',
@@ -43,11 +37,11 @@ describe('commands/theme/preview', () => {
43
37
  describe: expect.any(String),
44
38
  type: 'number',
45
39
  });
46
- expect(optionSpy).toHaveBeenCalledWith('resetSession', {
40
+ expect(optionSpy).toHaveBeenCalledWith('reset-session', {
47
41
  hidden: true,
48
42
  type: 'boolean',
49
43
  });
50
- expect(optionSpy).toHaveBeenCalledWith('generateFieldsTypes', {
44
+ expect(optionSpy).toHaveBeenCalledWith('generate-fields-types', {
51
45
  hidden: true,
52
46
  type: 'boolean',
53
47
  });
@@ -7,7 +7,7 @@ import { uiLogger } from '../../../lib/ui/logger.js';
7
7
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
8
8
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
9
9
  import assets from '../../../lib/cmsAssets/index.js';
10
- const command = 'create';
10
+ const command = 'create [dest]';
11
11
  const describe = commands.cms.subcommands.theme.subcommands.create.describe;
12
12
  async function handler(args) {
13
13
  const { derivedAccountId, dest } = args;
@@ -8,7 +8,6 @@ const describe = commands.cms.subcommands.theme.subcommands.marketplaceValidate.
8
8
  async function handler(args) {
9
9
  const { path, derivedAccountId } = args;
10
10
  trackCommandUsage('validate', {}, derivedAccountId);
11
- SpinniesManager.init();
12
11
  SpinniesManager.add('marketplaceValidation', {
13
12
  text: commands.cms.subcommands.theme.subcommands.marketplaceValidate.logs.validatingTheme(path),
14
13
  });
@@ -2,7 +2,6 @@ import { CommonArgs, ConfigArgs, AccountArgs, YargsCommandModule } from '../../.
2
2
  export type ThemePreviewArgs = CommonArgs & ConfigArgs & AccountArgs & {
3
3
  src: string;
4
4
  dest: string;
5
- notify: string;
6
5
  'no-ssl'?: boolean;
7
6
  port?: number;
8
7
  resetSession?: boolean;
@@ -5,13 +5,12 @@ import { commands } from '../../../lang/en.js';
5
5
  import { getCwd } from '@hubspot/local-dev-lib/path';
6
6
  import { FILE_UPLOAD_RESULT_TYPES } from '@hubspot/local-dev-lib/constants/files';
7
7
  import { getThemeJSONPath } from '@hubspot/local-dev-lib/cms/themes';
8
- import { preview } from '@hubspot/theme-preview-dev-server';
8
+ import { createDevServer } from '@hubspot/cms-dev-server';
9
9
  import { getUploadableFileList } from '../../../lib/upload.js';
10
10
  import { trackCommandUsage } from '../../../lib/usageTracking.js';
11
11
  import { previewPrompt, previewProjectPrompt, } from '../../../lib/prompts/previewPrompt.js';
12
12
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
13
13
  import { ApiErrorContext, logError } from '../../../lib/errorHandlers/index.js';
14
- import { handleExit, handleKeypress } from '../../../lib/process.js';
15
14
  import { getProjectConfig } from '../../../lib/projects/config.js';
16
15
  import { findProjectComponents } from '../../../lib/projects/structure.js';
17
16
  import { ComponentTypes } from '../../../types/Projects.js';
@@ -36,18 +35,6 @@ function validateSrcPath(src) {
36
35
  }
37
36
  return true;
38
37
  }
39
- function handleUserInput() {
40
- const onTerminate = () => {
41
- uiLogger.log(commands.cms.subcommands.theme.subcommands.preview.logs.processExited);
42
- process.exit(EXIT_CODES.SUCCESS);
43
- };
44
- handleExit(onTerminate);
45
- handleKeypress(key => {
46
- if ((key.ctrl && key.name === 'c') || key.name === 'q') {
47
- onTerminate();
48
- }
49
- });
50
- }
51
38
  async function determineSrcAndDest(args) {
52
39
  let absoluteSrc;
53
40
  let dest;
@@ -84,7 +71,7 @@ async function determineSrcAndDest(args) {
84
71
  return { absoluteSrc, dest };
85
72
  }
86
73
  async function handler(args) {
87
- const { derivedAccountId, notify, noSsl, resetSession, port, generateFieldsTypes, } = args;
74
+ const { derivedAccountId, noSsl, resetSession, port, generateFieldsTypes } = args;
88
75
  const { absoluteSrc, dest } = await determineSrcAndDest(args);
89
76
  const filePaths = await getUploadableFileList(absoluteSrc, false);
90
77
  function startProgressBar(numFiles) {
@@ -140,36 +127,15 @@ async function handler(args) {
140
127
  return uploadOptions;
141
128
  }
142
129
  trackCommandUsage('preview', {}, derivedAccountId);
143
- let createUnifiedDevServer;
144
- try {
145
- const { createDevServer } = await import('@hubspot/cms-dev-server');
146
- createUnifiedDevServer = createDevServer;
147
- }
148
- catch (e) {
149
- uiLogger.warn('Error loading unified dev server. Defaulting to legacy preview.');
150
- }
151
- if (createUnifiedDevServer) {
152
- if (port) {
153
- process.env['PORT'] = port.toString();
154
- }
155
- createUnifiedDevServer(absoluteSrc, false, '', '', !noSsl, generateFieldsTypes, {
156
- filePaths,
157
- resetSession: resetSession || false,
158
- startProgressBar,
159
- dest,
160
- });
161
- }
162
- else {
163
- preview(derivedAccountId, absoluteSrc, dest, {
164
- notify,
165
- filePaths,
166
- noSsl,
167
- port,
168
- resetSession: resetSession || false,
169
- startProgressBar,
170
- handleUserInput,
171
- });
130
+ if (port) {
131
+ process.env['PORT'] = port.toString();
172
132
  }
133
+ createDevServer(absoluteSrc, false, '', '', !noSsl, generateFieldsTypes, {
134
+ filePaths,
135
+ resetSession: resetSession || false,
136
+ startProgressBar,
137
+ dest,
138
+ });
173
139
  }
174
140
  function themePreviewBuilder(yargs) {
175
141
  yargs
@@ -182,12 +148,6 @@ function themePreviewBuilder(yargs) {
182
148
  describe: commands.cms.subcommands.theme.subcommands.preview.positionals.dest,
183
149
  type: 'string',
184
150
  requiresArg: true,
185
- })
186
- .option('notify', {
187
- alias: 'n',
188
- describe: commands.cms.subcommands.theme.subcommands.preview.options.notify,
189
- type: 'string',
190
- requiresArg: true,
191
151
  })
192
152
  .option('no-ssl', {
193
153
  describe: commands.cms.subcommands.theme.subcommands.preview.options.noSsl,
@@ -197,11 +157,11 @@ function themePreviewBuilder(yargs) {
197
157
  describe: commands.cms.subcommands.theme.subcommands.preview.options.port,
198
158
  type: 'number',
199
159
  })
200
- .option('resetSession', {
160
+ .option('reset-session', {
201
161
  hidden: true,
202
162
  type: 'boolean',
203
163
  })
204
- .option('generateFieldsTypes', {
164
+ .option('generate-fields-types', {
205
165
  hidden: true,
206
166
  type: 'boolean',
207
167
  });
@@ -168,18 +168,18 @@ function uploadBuilder(yargs) {
168
168
  describe: commands.cms.subcommands.upload.positionals.dest,
169
169
  type: 'string',
170
170
  });
171
- yargs.option('fieldOptions', {
171
+ yargs.option('field-options', {
172
172
  describe: commands.cms.subcommands.upload.options.options,
173
173
  type: 'array',
174
174
  default: [''],
175
175
  hidden: true,
176
176
  });
177
- yargs.option('saveOutput', {
177
+ yargs.option('save-output', {
178
178
  describe: commands.cms.subcommands.upload.options.saveOutput,
179
179
  type: 'boolean',
180
180
  default: false,
181
181
  });
182
- yargs.option('convertFields', {
182
+ yargs.option('convert-fields', {
183
183
  describe: commands.cms.subcommands.upload.options.convertFields,
184
184
  type: 'boolean',
185
185
  default: false,
@@ -83,7 +83,7 @@ function watchBuilder(yargs) {
83
83
  describe: commands.cms.subcommands.watch.positionals.dest,
84
84
  type: 'string',
85
85
  });
86
- yargs.option('fieldOptions', {
86
+ yargs.option('field-options', {
87
87
  describe: commands.cms.subcommands.watch.options.options,
88
88
  type: 'array',
89
89
  default: [''],
@@ -110,12 +110,12 @@ function watchBuilder(yargs) {
110
110
  type: 'string',
111
111
  requiresArg: true,
112
112
  });
113
- yargs.option('convertFields', {
113
+ yargs.option('convert-fields', {
114
114
  describe: commands.cms.subcommands.watch.options.convertFields,
115
115
  type: 'boolean',
116
116
  default: false,
117
117
  });
118
- yargs.option('saveOutput', {
118
+ yargs.option('save-output', {
119
119
  describe: commands.cms.subcommands.watch.options.saveOutput,
120
120
  type: 'boolean',
121
121
  default: false,
@@ -1,4 +1,3 @@
1
- import schemaCommand from './customObject/schema.js';
2
1
  import createCommand from './customObject/create.js';
3
2
  import createSchemaCommand from './customObject/createSchema.js';
4
3
  import deleteSchemaCommand from './customObject/deleteSchema.js';
@@ -19,7 +18,6 @@ function logBetaMessage() {
19
18
  function customObjectBuilder(yargs) {
20
19
  yargs.middleware([logBetaMessage]);
21
20
  yargs
22
- .command(schemaCommand)
23
21
  .command(createCommand)
24
22
  .command(createSchemaCommand)
25
23
  .command(deleteSchemaCommand)
@@ -6,7 +6,9 @@ import { EXIT_CODES } from '../lib/enums/exitCodes.js';
6
6
  import { getCwd } from '@hubspot/local-dev-lib/path';
7
7
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
8
8
  import { uiLogger } from '../lib/ui/logger.js';
9
+ import { removeAnsiCodes } from '../lib/ui/removeAnsiCodes.js';
9
10
  import { commands } from '../lang/en.js';
11
+ import { getErrorMessage } from '../lib/errorHandlers/index.js';
10
12
  const command = 'doctor';
11
13
  const describe = commands.doctor.describe;
12
14
  const handler = async (args) => {
@@ -34,11 +36,17 @@ const handler = async (args) => {
34
36
  }
35
37
  const outputFile = path.join(outputDirPath, `hubspot-doctor-${new Date().toISOString()}.json`);
36
38
  try {
37
- fs.writeFileSync(outputFile, JSON.stringify(output, null, 4));
39
+ const cleanedOutput = {
40
+ ...output,
41
+ diagnosis: output?.diagnosis
42
+ ? removeAnsiCodes(output.diagnosis)
43
+ : undefined,
44
+ };
45
+ fs.writeFileSync(outputFile, JSON.stringify(cleanedOutput, null, 4));
38
46
  uiLogger.success(commands.doctor.outputWritten(outputFile));
39
47
  }
40
48
  catch (e) {
41
- uiLogger.error(commands.doctor.errors.unableToWriteOutputFile(outputFile, e instanceof Error ? e.message : e));
49
+ uiLogger.error(commands.doctor.errors.unableToWriteOutputFile(outputFile, getErrorMessage(e)));
42
50
  return process.exit(EXIT_CODES.ERROR);
43
51
  }
44
52
  return process.exit(EXIT_CODES.SUCCESS);
@@ -1,9 +1,49 @@
1
1
  import yargs from 'yargs';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import * as fileManagerLib from '@hubspot/local-dev-lib/fileManager';
5
+ import * as fileManagerApiLib from '@hubspot/local-dev-lib/api/fileManager';
6
+ import * as pathLib from '@hubspot/local-dev-lib/path';
7
+ import * as modulesLib from '@hubspot/local-dev-lib/cms/modules';
8
+ import * as ignoreRulesLib from '@hubspot/local-dev-lib/ignoreRules';
9
+ import * as configLib from '@hubspot/local-dev-lib/config';
2
10
  import { addGlobalOptions, addConfigOptions, addAccountOptions, addUseEnvironmentOptions, } from '../../../lib/commonOpts.js';
11
+ import { uiLogger } from '../../../lib/ui/logger.js';
12
+ import * as errorHandlers from '../../../lib/errorHandlers/index.js';
13
+ import * as usageTrackingLib from '../../../lib/usageTracking.js';
14
+ import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
3
15
  import fileManagerUploadCommand from '../upload.js';
4
16
  vi.mock('../../../lib/commonOpts');
17
+ vi.mock('fs');
18
+ vi.mock('@hubspot/local-dev-lib/fileManager');
19
+ vi.mock('@hubspot/local-dev-lib/api/fileManager');
20
+ vi.mock('@hubspot/local-dev-lib/path');
21
+ vi.mock('@hubspot/local-dev-lib/cms/modules');
22
+ vi.mock('@hubspot/local-dev-lib/ignoreRules');
23
+ vi.mock('@hubspot/local-dev-lib/config');
24
+ vi.mock('../../../lib/errorHandlers/index.js');
25
+ const uploadFolderSpy = vi.spyOn(fileManagerLib, 'uploadFolder');
26
+ const uploadFileSpy = vi.spyOn(fileManagerApiLib, 'uploadFile');
27
+ const statSyncSpy = vi.spyOn(fs, 'statSync');
28
+ const validateSrcAndDestPathsSpy = vi.spyOn(modulesLib, 'validateSrcAndDestPaths');
29
+ const shouldIgnoreFileSpy = vi.spyOn(ignoreRulesLib, 'shouldIgnoreFile');
30
+ const getCwdSpy = vi.spyOn(pathLib, 'getCwd');
31
+ const convertToUnixPathSpy = vi.spyOn(pathLib, 'convertToUnixPath');
32
+ const trackCommandUsageSpy = vi.spyOn(usageTrackingLib, 'trackCommandUsage');
33
+ const processExitSpy = vi.spyOn(process, 'exit');
34
+ const logErrorSpy = vi.spyOn(errorHandlers, 'logError');
35
+ const getConfigAccountIfExistsSpy = vi.spyOn(configLib, 'getConfigAccountIfExists');
5
36
  describe('commands/filemanager/upload', () => {
6
37
  const yargsMock = yargs;
38
+ beforeEach(() => {
39
+ // @ts-expect-error Mock implementation
40
+ processExitSpy.mockImplementation(() => { });
41
+ getCwdSpy.mockReturnValue('/test/cwd');
42
+ convertToUnixPathSpy.mockImplementation(p => p.replace(/\\/g, '/'));
43
+ validateSrcAndDestPathsSpy.mockResolvedValue([]);
44
+ // Mock config to prevent reading actual config file in CI
45
+ getConfigAccountIfExistsSpy.mockReturnValue(undefined);
46
+ });
7
47
  describe('command', () => {
8
48
  it('should have the correct command structure', () => {
9
49
  expect(fileManagerUploadCommand.command).toEqual('upload <src> <dest>');
@@ -27,4 +67,125 @@ describe('commands/filemanager/upload', () => {
27
67
  expect(addUseEnvironmentOptions).toHaveBeenCalledWith(yargsMock);
28
68
  });
29
69
  });
70
+ describe('handler', () => {
71
+ let args;
72
+ beforeEach(() => {
73
+ args = {
74
+ src: 'test.js',
75
+ dest: '/dest/test.js',
76
+ derivedAccountId: 123456,
77
+ d: false,
78
+ debug: false,
79
+ };
80
+ });
81
+ describe('validation', () => {
82
+ it('should error if src path is invalid', async () => {
83
+ statSyncSpy.mockImplementation(() => {
84
+ throw new Error('File not found');
85
+ });
86
+ await fileManagerUploadCommand.handler(args);
87
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('path to a file or folder'));
88
+ });
89
+ it('should error if src path is not a file or directory', async () => {
90
+ statSyncSpy.mockReturnValue({
91
+ isFile: () => false,
92
+ isDirectory: () => false,
93
+ });
94
+ await fileManagerUploadCommand.handler(args);
95
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('path to a file or folder'));
96
+ });
97
+ it('should error if dest is not provided', async () => {
98
+ args.dest = '';
99
+ statSyncSpy.mockReturnValue({
100
+ isFile: () => true,
101
+ isDirectory: () => false,
102
+ });
103
+ await fileManagerUploadCommand.handler(args);
104
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('destination'));
105
+ });
106
+ it('should exit if src/dest validation fails', async () => {
107
+ statSyncSpy.mockReturnValue({
108
+ isFile: () => true,
109
+ isDirectory: () => false,
110
+ });
111
+ validateSrcAndDestPathsSpy.mockResolvedValue([
112
+ { id: '1', message: 'Invalid path' },
113
+ ]);
114
+ // @ts-expect-error Mock return value doesn't need full type implementation
115
+ uploadFileSpy.mockResolvedValue({});
116
+ await fileManagerUploadCommand.handler(args);
117
+ expect(uiLogger.error).toHaveBeenCalledWith('Invalid path');
118
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.ERROR);
119
+ });
120
+ });
121
+ describe('file upload', () => {
122
+ beforeEach(() => {
123
+ statSyncSpy.mockReturnValue({
124
+ isFile: () => true,
125
+ isDirectory: () => false,
126
+ });
127
+ shouldIgnoreFileSpy.mockReturnValue(false);
128
+ });
129
+ it('should track command usage for file uploads', async () => {
130
+ // @ts-expect-error Mock return value doesn't need full type implementation
131
+ uploadFileSpy.mockResolvedValue({});
132
+ await fileManagerUploadCommand.handler(args);
133
+ expect(trackCommandUsageSpy).toHaveBeenCalledWith('filemanager-upload', { type: 'file' }, 123456);
134
+ });
135
+ it('should upload a file successfully', async () => {
136
+ // @ts-expect-error Mock return value doesn't need full type implementation
137
+ uploadFileSpy.mockResolvedValue({});
138
+ await fileManagerUploadCommand.handler(args);
139
+ expect(uploadFileSpy).toHaveBeenCalledWith(123456, path.resolve('/test/cwd', 'test.js'), '/dest/test.js');
140
+ expect(uiLogger.success).toHaveBeenCalledWith(expect.stringContaining('test.js'));
141
+ });
142
+ it('should error if file is ignored', async () => {
143
+ shouldIgnoreFileSpy.mockReturnValue(true);
144
+ await fileManagerUploadCommand.handler(args);
145
+ expect(uploadFileSpy).not.toHaveBeenCalled();
146
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringContaining('ignored'));
147
+ });
148
+ it('should handle upload errors', async () => {
149
+ vi.useFakeTimers();
150
+ const error = new Error('Upload failed');
151
+ uploadFileSpy.mockRejectedValue(error);
152
+ await fileManagerUploadCommand.handler(args);
153
+ await vi.runAllTimersAsync();
154
+ expect(uiLogger.error).toHaveBeenCalled();
155
+ expect(logErrorSpy).toHaveBeenCalledWith(error, expect.any(errorHandlers.ApiErrorContext));
156
+ vi.useRealTimers();
157
+ });
158
+ });
159
+ describe('folder upload', () => {
160
+ beforeEach(() => {
161
+ statSyncSpy.mockReturnValue({
162
+ isFile: () => false,
163
+ isDirectory: () => true,
164
+ });
165
+ // @ts-expect-error Mock return value doesn't need full type implementation
166
+ uploadFolderSpy.mockResolvedValue({});
167
+ });
168
+ it('should track command usage for folder uploads', async () => {
169
+ await fileManagerUploadCommand.handler(args);
170
+ expect(trackCommandUsageSpy).toHaveBeenCalledWith('filemanager-upload', { type: 'folder' }, 123456);
171
+ });
172
+ it('should upload a folder successfully', async () => {
173
+ await fileManagerUploadCommand.handler(args);
174
+ expect(uploadFolderSpy).toHaveBeenCalledWith(123456, path.resolve('/test/cwd', 'test.js'), '/dest/test.js');
175
+ expect(uiLogger.success).toHaveBeenCalledWith(expect.stringContaining('complete'));
176
+ });
177
+ it('should handle folder upload errors', async () => {
178
+ vi.useFakeTimers();
179
+ const error = new Error('Folder upload failed');
180
+ uploadFolderSpy.mockRejectedValue(error);
181
+ await fileManagerUploadCommand.handler(args);
182
+ await vi.runAllTimersAsync();
183
+ expect(uiLogger.error).toHaveBeenCalled();
184
+ expect(logErrorSpy).toHaveBeenCalledWith(error, {
185
+ accountId: 123456,
186
+ });
187
+ vi.useRealTimers();
188
+ });
189
+ });
190
+ });
30
191
  });
@@ -11,7 +11,8 @@ import { promptUser } from '../lib/prompts/promptUtils.js';
11
11
  import { projectNameAndDestPrompt } from '../lib/prompts/projectNameAndDestPrompt.js';
12
12
  import { uiAccountDescription, uiFeatureHighlight, uiInfoSection, } from '../lib/ui/index.js';
13
13
  import { uiLogger } from '../lib/ui/logger.js';
14
- import { debugError, logError } from '../lib/errorHandlers/index.js';
14
+ import { debugError } from '../lib/errorHandlers/index.js';
15
+ import ProjectValidationError from '../lib/errors/ProjectValidationError.js';
15
16
  import { handleProjectUpload } from '../lib/projects/upload.js';
16
17
  import { PROJECT_CONFIG_FILE, GET_STARTED_OPTIONS, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, } from '../lib/constants.js';
17
18
  import { writeProjectConfig, getProjectConfig, validateProjectConfig, } from '../lib/projects/config.js';
@@ -165,8 +166,17 @@ async function handler(args) {
165
166
  validateProjectConfig(newProjectConfig, newProjectDir);
166
167
  }
167
168
  catch (error) {
168
- logError(error);
169
- process.exit(EXIT_CODES.ERROR);
169
+ if (error instanceof ProjectValidationError) {
170
+ // Track validation error
171
+ await trackCommandMetadataUsage('get-started', {
172
+ successful: false,
173
+ step: 'project-validation-failed',
174
+ }, derivedAccountId);
175
+ uiLogger.log(' ');
176
+ uiLogger.error(error.message);
177
+ process.exit(EXIT_CODES.ERROR);
178
+ }
179
+ throw error;
170
180
  }
171
181
  uiLogger.log(' ');
172
182
  uiLogger.log(commands.getStarted.logs.uploadingProject);
@@ -8,16 +8,7 @@ import hubdbListCommand from '../list.js';
8
8
  vi.mock('../../../lib/commonOpts');
9
9
  vi.mock('@hubspot/local-dev-lib/api/hubdb');
10
10
  vi.mock('@hubspot/local-dev-lib/config');
11
- vi.mock('../../../lib/ui/logger', () => ({
12
- uiLogger: {
13
- success: vi.fn(),
14
- log: vi.fn(),
15
- error: vi.fn(),
16
- exit: vi.fn(),
17
- },
18
- }));
19
11
  vi.mock('../../../lib/errorHandlers');
20
- vi.mock('../../../lib/usageTracking');
21
12
  const mockExit = vi
22
13
  .spyOn(process, 'exit')
23
14
  .mockImplementation(() => undefined);
@@ -1,13 +1,12 @@
1
1
  import { fetchTables } from '@hubspot/local-dev-lib/api/hubdb';
2
- import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
3
- import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
4
2
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
5
3
  import { uiLogger } from '../../lib/ui/logger.js';
6
4
  import { logError } from '../../lib/errorHandlers/index.js';
7
5
  import { commands } from '../../lang/en.js';
8
6
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
7
  import { trackCommandUsage } from '../../lib/usageTracking.js';
10
- import { getTableContents, getTableHeader } from '../../lib/ui/table.js';
8
+ import { renderTable } from '../../ui/render.js';
9
+ import { getBaseHubSpotUrlForAccount } from '../../lib/projects/urls.js';
11
10
  const command = ['list', 'ls'];
12
11
  const describe = commands.hubdb.subcommands.list.describe;
13
12
  async function getTableData(accountId) {
@@ -35,18 +34,17 @@ async function handler(args) {
35
34
  trackCommandUsage('hubdb-list', {}, derivedAccountId);
36
35
  const { results: tables, total } = await getTableData(derivedAccountId);
37
36
  const tableUIData = mapTablesToUI(tables);
38
- tableUIData.unshift(getTableHeader([
37
+ const tableHeader = [
39
38
  commands.hubdb.subcommands.list.labels.id,
40
39
  commands.hubdb.subcommands.list.labels.label,
41
40
  commands.hubdb.subcommands.list.labels.name,
42
41
  commands.hubdb.subcommands.list.labels.columns,
43
42
  commands.hubdb.subcommands.list.labels.rows,
44
- ]));
43
+ ];
45
44
  uiLogger.success(commands.hubdb.subcommands.list.success(derivedAccountId));
46
45
  uiLogger.log(' ');
47
46
  // link devs to the hubdb page in hubspot for easy access
48
- // TODO: This is hacky, we should make a util like getBaseUrl()
49
- const baseUrl = getHubSpotWebsiteOrigin(getConfigAccountEnvironment(derivedAccountId));
47
+ const baseUrl = getBaseHubSpotUrlForAccount(derivedAccountId);
50
48
  uiLogger.log(commands.hubdb.subcommands.list.viewTablesLink(baseUrl, derivedAccountId));
51
49
  // don't bother showing an empty list of tables
52
50
  if (tables.length > 0) {
@@ -55,7 +53,7 @@ async function handler(args) {
55
53
  uiLogger.log(commands.hubdb.subcommands.list.tablesDisplayed(tables.length, total, truncated));
56
54
  uiLogger.log('--------------------------------');
57
55
  uiLogger.log(commands.hubdb.subcommands.list.tables);
58
- uiLogger.log(getTableContents(tableUIData, { border: { bodyLeft: ' ' } }));
56
+ renderTable(tableHeader, tableUIData);
59
57
  }
60
58
  else {
61
59
  uiLogger.log(commands.hubdb.subcommands.list.noTables(derivedAccountId));