@hubspot/cli 7.8.12-experimental.0 → 7.8.12-experimental.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 (244) hide show
  1. package/bin/cli.js +31 -25
  2. package/commands/__tests__/auth.test.js +5 -0
  3. package/commands/__tests__/doctor.test.js +16 -16
  4. package/commands/account/clean.js +18 -27
  5. package/commands/account/createOverride.js +13 -31
  6. package/commands/account/info.js +20 -31
  7. package/commands/account/list.js +16 -22
  8. package/commands/account/remove.js +12 -20
  9. package/commands/account/removeOverride.js +11 -21
  10. package/commands/account/rename.js +6 -9
  11. package/commands/account/use.js +12 -26
  12. package/commands/account.js +2 -2
  13. package/commands/app/__tests__/migrate.test.js +5 -5
  14. package/commands/app/migrate.js +13 -18
  15. package/commands/app.js +1 -6
  16. package/commands/auth.d.ts +1 -0
  17. package/commands/auth.js +16 -7
  18. package/commands/cms/convertFields.js +7 -9
  19. package/commands/cms/getReactModule.js +9 -14
  20. package/commands/cms/lighthouseScore.js +33 -36
  21. package/commands/cms.js +2 -2
  22. package/commands/completion.js +3 -3
  23. package/commands/config/set.d.ts +1 -1
  24. package/commands/config/set.js +64 -36
  25. package/commands/config.js +2 -2
  26. package/commands/create.js +2 -2
  27. package/commands/customObject/create.js +10 -12
  28. package/commands/customObject/schema/create.js +9 -11
  29. package/commands/customObject/schema/delete.js +16 -16
  30. package/commands/customObject/schema/fetch-all.js +12 -11
  31. package/commands/customObject/schema/fetch.js +15 -15
  32. package/commands/customObject/schema/list.js +4 -4
  33. package/commands/customObject/schema/update.js +13 -13
  34. package/commands/customObject/schema.js +2 -2
  35. package/commands/customObject.js +6 -7
  36. package/commands/doctor.js +8 -11
  37. package/commands/feedback.js +6 -11
  38. package/commands/fetch.js +8 -8
  39. package/commands/filemanager/fetch.js +7 -7
  40. package/commands/filemanager/upload.js +15 -34
  41. package/commands/filemanager.js +2 -2
  42. package/commands/function/deploy.js +11 -29
  43. package/commands/function/list.js +8 -8
  44. package/commands/function/server.js +9 -11
  45. package/commands/function.d.ts +1 -1
  46. package/commands/function.js +2 -2
  47. package/commands/getStarted.js +2 -2
  48. package/commands/hubdb/clear.js +7 -15
  49. package/commands/hubdb/create.js +9 -15
  50. package/commands/hubdb/delete.js +8 -15
  51. package/commands/hubdb/fetch.js +6 -9
  52. package/commands/hubdb.d.ts +1 -1
  53. package/commands/hubdb.js +2 -2
  54. package/commands/init.js +2 -3
  55. package/commands/lint.js +16 -16
  56. package/commands/list.js +8 -14
  57. package/commands/logs.js +14 -20
  58. package/commands/mv.js +6 -17
  59. package/commands/open.js +5 -5
  60. package/commands/project/__tests__/add.test.js +4 -2
  61. package/commands/project/__tests__/deploy.test.js +3 -4
  62. package/commands/project/__tests__/installDeps.test.js +8 -8
  63. package/commands/project/__tests__/logs.test.js +1 -1
  64. package/commands/project/__tests__/migrate.test.js +5 -5
  65. package/commands/project/__tests__/migrateApp.test.js +2 -5
  66. package/commands/project/__tests__/validate.test.js +98 -0
  67. package/commands/project/add.js +3 -3
  68. package/commands/project/cloneApp.js +14 -19
  69. package/commands/project/create.js +0 -1
  70. package/commands/project/deploy.js +3 -3
  71. package/commands/project/dev/deprecatedFlow.js +7 -16
  72. package/commands/project/dev/index.js +14 -12
  73. package/commands/project/dev/unifiedFlow.js +3 -1
  74. package/commands/project/download.js +10 -13
  75. package/commands/project/installDeps.js +8 -8
  76. package/commands/project/listBuilds.js +11 -20
  77. package/commands/project/logs.js +21 -24
  78. package/commands/project/migrateApp.js +9 -15
  79. package/commands/project/open.js +6 -13
  80. package/commands/project/upload.d.ts +2 -2
  81. package/commands/project/upload.js +17 -26
  82. package/commands/project/validate.js +6 -6
  83. package/commands/project/watch.js +13 -22
  84. package/commands/project.js +2 -2
  85. package/commands/sandbox/__tests__/create.test.js +5 -5
  86. package/commands/sandbox/create.js +22 -32
  87. package/commands/sandbox/delete.js +38 -63
  88. package/commands/sandbox.js +2 -2
  89. package/commands/secret/addSecret.js +7 -17
  90. package/commands/secret/deleteSecret.js +10 -20
  91. package/commands/secret/listSecret.js +8 -10
  92. package/commands/secret/updateSecret.js +9 -17
  93. package/commands/secret.js +2 -2
  94. package/commands/testAccount/__tests__/delete.test.js +2 -4
  95. package/commands/testAccount/create.js +0 -3
  96. package/commands/testAccount/delete.d.ts +4 -3
  97. package/commands/testAccount/delete.js +155 -14
  98. package/commands/theme/preview.js +1 -4
  99. package/lang/en.d.ts +310 -124
  100. package/lang/en.js +351 -169
  101. package/lang/en.lyaml +2 -2
  102. package/lib/__tests__/buildAccount.test.js +2 -1
  103. package/lib/__tests__/commonOpts.test.js +1 -1
  104. package/lib/__tests__/dependencyManagement.test.js +1 -1
  105. package/lib/__tests__/developerTestAccounts.test.js +3 -3
  106. package/lib/__tests__/npm.test.js +1 -1
  107. package/lib/__tests__/oauth.test.js +4 -4
  108. package/lib/__tests__/process.test.js +10 -5
  109. package/lib/__tests__/sandboxSync.test.js +8 -8
  110. package/lib/__tests__/sandboxes.test.js +8 -8
  111. package/lib/__tests__/serverlessLogs.test.js +1 -1
  112. package/lib/__tests__/usageTracking.test.js +5 -5
  113. package/lib/__tests__/validation.test.js +2 -1
  114. package/lib/__tests__/yargsUtils.test.js +83 -9
  115. package/lib/app/__tests__/migrate.test.js +5 -5
  116. package/lib/app/__tests__/migrate_legacy.test.js +1 -1
  117. package/lib/app/migrate.js +1 -1
  118. package/lib/app/migrate_legacy.js +20 -24
  119. package/lib/buildAccount.js +25 -57
  120. package/lib/commonOpts.d.ts +1 -1
  121. package/lib/commonOpts.js +25 -22
  122. package/lib/configOptions.js +7 -0
  123. package/lib/constants.d.ts +6 -1
  124. package/lib/constants.js +10 -1
  125. package/lib/dependencyManagement.js +9 -27
  126. package/lib/developerTestAccounts.js +9 -23
  127. package/lib/doctor/Diagnosis.js +11 -23
  128. package/lib/doctor/DiagnosticInfoBuilder.js +12 -11
  129. package/lib/doctor/Doctor.js +42 -90
  130. package/lib/doctor/__tests__/Doctor.test.js +4 -4
  131. package/lib/errorHandlers/index.js +12 -20
  132. package/lib/errorHandlers/suppressError.js +11 -18
  133. package/lib/lang.js +6 -5
  134. package/lib/links.js +4 -4
  135. package/lib/middleware/__test__/commandTargetingUtils.test.js +99 -0
  136. package/lib/middleware/__test__/configMiddleware.test.js +11 -11
  137. package/lib/middleware/__test__/yargsChecksMiddleware.test.js +6 -8
  138. package/lib/middleware/commandTargetingUtils.d.ts +8 -0
  139. package/lib/middleware/commandTargetingUtils.js +78 -0
  140. package/lib/middleware/configMiddleware.d.ts +1 -1
  141. package/lib/middleware/configMiddleware.js +21 -81
  142. package/lib/middleware/gitMiddleware.js +5 -1
  143. package/lib/middleware/notificationsMiddleware.js +5 -11
  144. package/lib/middleware/yargsChecksMiddleware.js +6 -9
  145. package/lib/npm.js +2 -2
  146. package/lib/oauth.js +5 -5
  147. package/lib/process.js +5 -4
  148. package/lib/projectProfiles.d.ts +1 -1
  149. package/lib/projectProfiles.js +2 -10
  150. package/lib/projects/__tests__/AppDevModeInterface.test.js +14 -34
  151. package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +70 -39
  152. package/lib/projects/__tests__/localDevProjectHelpers.test.js +2 -0
  153. package/lib/projects/__tests__/platformVersion.test.js +8 -8
  154. package/lib/projects/__tests__/projects.test.js +12 -12
  155. package/lib/projects/__tests__/structure.test.js +3 -3
  156. package/lib/projects/__tests__/upload.test.d.ts +1 -0
  157. package/lib/projects/__tests__/upload.test.js +82 -0
  158. package/lib/projects/add/__tests__/legacyAddComponent.test.js +6 -6
  159. package/lib/projects/add/__tests__/v3AddComponent.test.js +4 -4
  160. package/lib/projects/create/__tests__/legacy.test.js +5 -5
  161. package/lib/projects/create/__tests__/v3.test.js +1 -1
  162. package/lib/projects/create/index.js +2 -2
  163. package/lib/projects/create/legacy.js +2 -2
  164. package/lib/projects/create/v3.js +2 -2
  165. package/lib/projects/localDev/AppDevModeInterface.d.ts +2 -0
  166. package/lib/projects/localDev/AppDevModeInterface.js +22 -20
  167. package/lib/projects/localDev/LocalDevLogger.js +10 -11
  168. package/lib/projects/localDev/LocalDevManager.js +4 -5
  169. package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +0 -1
  170. package/lib/projects/localDev/LocalDevWebsocketServer.js +7 -10
  171. package/lib/projects/localDev/helpers/project.d.ts +1 -0
  172. package/lib/projects/localDev/helpers/project.js +37 -0
  173. package/lib/projects/platformVersion.d.ts +1 -1
  174. package/lib/projects/platformVersion.js +1 -1
  175. package/lib/projects/structure.d.ts +2 -2
  176. package/lib/projects/structure.js +6 -6
  177. package/lib/projects/upload.d.ts +2 -3
  178. package/lib/projects/upload.js +17 -9
  179. package/lib/prompts/__tests__/downloadProjectPrompt.test.js +1 -0
  180. package/lib/prompts/accountNamePrompt.js +14 -19
  181. package/lib/prompts/accountsPrompt.js +2 -2
  182. package/lib/prompts/cmsFieldPrompt.js +2 -2
  183. package/lib/prompts/createApiSamplePrompt.js +5 -5
  184. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +10 -1
  185. package/lib/prompts/createFunctionPrompt.js +14 -14
  186. package/lib/prompts/createModulePrompt.js +9 -9
  187. package/lib/prompts/createTemplatePrompt.js +2 -2
  188. package/lib/prompts/downloadProjectPrompt.js +5 -8
  189. package/lib/prompts/personalAccessKeyPrompt.js +3 -3
  190. package/lib/prompts/previewPrompt.js +6 -6
  191. package/lib/prompts/projectAddPrompt.js +6 -0
  192. package/lib/prompts/projectDevTargetAccountPrompt.js +20 -32
  193. package/lib/prompts/projectNamePrompt.js +4 -8
  194. package/lib/prompts/projectsLogsPrompt.js +2 -4
  195. package/lib/prompts/promptUtils.js +27 -9
  196. package/lib/prompts/sandboxesPrompt.js +7 -7
  197. package/lib/prompts/secretPrompt.js +3 -3
  198. package/lib/prompts/selectAppPrompt.js +3 -3
  199. package/lib/prompts/selectHubDBTablePrompt.js +9 -13
  200. package/lib/prompts/selectPublicAppForMigrationPrompt.js +15 -19
  201. package/lib/prompts/setAsDefaultAccountPrompt.js +4 -8
  202. package/lib/prompts/uploadPrompt.js +5 -5
  203. package/lib/sandboxSync.js +24 -41
  204. package/lib/sandboxes.js +19 -47
  205. package/lib/schema.js +3 -3
  206. package/lib/serverlessLogs.js +11 -13
  207. package/lib/theme/__tests__/migrate.test.js +3 -3
  208. package/lib/theme/migrate.js +2 -2
  209. package/lib/ui/SpinniesManager.d.ts +2 -0
  210. package/lib/ui/SpinniesManager.js +7 -0
  211. package/lib/ui/boxen.js +1 -2
  212. package/lib/ui/git.js +13 -10
  213. package/lib/ui/index.d.ts +4 -0
  214. package/lib/ui/index.js +47 -38
  215. package/lib/ui/serverlessFunctionLogs.js +9 -7
  216. package/lib/ui/uiMessages.d.ts +68 -0
  217. package/lib/ui/uiMessages.js +71 -0
  218. package/lib/usageTracking.js +7 -7
  219. package/lib/validation.js +20 -23
  220. package/lib/yargsUtils.d.ts +1 -1
  221. package/lib/yargsUtils.js +12 -5
  222. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
  223. package/mcp-server/tools/index.js +4 -0
  224. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +23 -0
  225. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +68 -0
  226. package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +11 -0
  227. package/mcp-server/tools/project/GetApplicationInfoTool.js +49 -0
  228. package/mcp-server/tools/project/GetConfigValuesTool.js +2 -2
  229. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +2 -2
  230. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.d.ts +1 -0
  231. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +169 -0
  232. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.d.ts +1 -0
  233. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +115 -0
  234. package/mcp-server/utils/toolUsageTracking.js +2 -2
  235. package/package.json +6 -6
  236. package/types/Yargs.d.ts +1 -1
  237. package/commands/app/__tests__/install.test.js +0 -47
  238. package/commands/app/install.d.ts +0 -8
  239. package/commands/app/install.js +0 -122
  240. package/lib/middleware/__test__/utils.test.js +0 -51
  241. package/lib/middleware/utils.d.ts +0 -8
  242. package/lib/middleware/utils.js +0 -14
  243. /package/commands/{app/__tests__/install.test.d.ts → project/__tests__/validate.test.d.ts} +0 -0
  244. /package/lib/middleware/__test__/{utils.test.d.ts → commandTargetingUtils.test.d.ts} +0 -0
package/lib/schema.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import chalk from 'chalk';
2
2
  import { table, getBorderCharacters } from 'table';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
4
3
  import { fetchObjectSchemas } from '@hubspot/local-dev-lib/api/customObjects';
4
+ import { uiLogger } from './ui/logger.js';
5
5
  export function logSchemas(schemas) {
6
6
  const data = schemas
7
7
  .map(r => [r.labels.singular, r.name, r.objectTypeId || ''])
8
8
  .sort((a, b) => (a[1] > b[1] ? 1 : -1));
9
9
  if (data.length === 0) {
10
- logger.log('No Schemas were found');
10
+ uiLogger.log('No Schemas were found');
11
11
  return;
12
12
  }
13
13
  data.unshift([
@@ -19,7 +19,7 @@ export function logSchemas(schemas) {
19
19
  singleLine: true,
20
20
  border: getBorderCharacters('honeywell'),
21
21
  };
22
- logger.log(table(data, tableConfig));
22
+ uiLogger.log(table(data, tableConfig));
23
23
  }
24
24
  export async function listSchemas(accountId) {
25
25
  const { data } = await fetchObjectSchemas(accountId);
@@ -1,6 +1,6 @@
1
1
  import https from 'https';
2
2
  import chalk from 'chalk';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
3
+ import { uiLogger } from './ui/logger.js';
4
4
  import { isHubSpotHttpError, isMissingScopeError, } from '@hubspot/local-dev-lib/errors/index';
5
5
  import { SCOPE_GROUPS, PERSONAL_ACCESS_KEY_AUTH_METHOD, } from '@hubspot/local-dev-lib/constants/auth';
6
6
  import { getAccountConfig } from '@hubspot/local-dev-lib/config';
@@ -10,7 +10,7 @@ import { logError, ApiErrorContext } from './errorHandlers/index.js';
10
10
  import SpinniesManager from './ui/SpinniesManager.js';
11
11
  import { handleExit, handleKeypress } from './process.js';
12
12
  import { EXIT_CODES } from './enums/exitCodes.js';
13
- import { i18n } from './lang.js';
13
+ import { lib } from '../lang/en.js';
14
14
  const TAIL_DELAY = 5000;
15
15
  function base64EncodeString(valueToEncode) {
16
16
  if (typeof valueToEncode !== 'string') {
@@ -47,22 +47,20 @@ async function verifyAccessKeyAndUserAccess(accountId, scopeGroup) {
47
47
  scopesData = resp.data;
48
48
  }
49
49
  catch (e) {
50
- logger.debug(i18n(`lib.serverless.verifyAccessKeyAndUserAccess.fetchScopeDataError`, {
51
- scopeGroup,
52
- }));
53
- logger.debug(e);
50
+ uiLogger.debug(lib.serverless.verifyAccessKeyAndUserAccess.fetchScopeDataError(scopeGroup));
51
+ uiLogger.debug(e);
54
52
  return;
55
53
  }
56
54
  const { portalScopesInGroup, userScopesInGroup } = scopesData;
57
55
  if (!portalScopesInGroup.length) {
58
- logger.error(i18n(`lib.serverless.verifyAccessKeyAndUserAccess.portalMissingScope`));
56
+ uiLogger.error(lib.serverless.verifyAccessKeyAndUserAccess.portalMissingScope);
59
57
  return;
60
58
  }
61
59
  if (!portalScopesInGroup.every(s => userScopesInGroup.includes(s))) {
62
- logger.error(i18n(`lib.serverless.verifyAccessKeyAndUserAccess.userMissingScope`));
60
+ uiLogger.error(lib.serverless.verifyAccessKeyAndUserAccess.userMissingScope);
63
61
  }
64
62
  else {
65
- logger.error(i18n(`lib.serverless.verifyAccessKeyAndUserAccess.genericMissingScope`));
63
+ uiLogger.error(lib.serverless.verifyAccessKeyAndUserAccess.genericMissingScope);
66
64
  }
67
65
  }
68
66
  export async function tailLogs(accountId, name, fetchLatest, tailCall, compact = false) {
@@ -120,7 +118,7 @@ export async function tailLogs(accountId, name, fetchLatest, tailCall, compact =
120
118
  }
121
119
  export async function outputBuildLog(buildLogUrl) {
122
120
  if (!buildLogUrl) {
123
- logger.debug('Unable to display build output. No build log URL was provided.');
121
+ uiLogger.debug('Unable to display build output. No build log URL was provided.');
124
122
  return '';
125
123
  }
126
124
  return new Promise(resolve => {
@@ -135,16 +133,16 @@ export async function outputBuildLog(buildLogUrl) {
135
133
  data += chunk;
136
134
  });
137
135
  response.on('end', () => {
138
- logger.log(data);
136
+ uiLogger.log(data);
139
137
  resolve(data);
140
138
  });
141
139
  })
142
140
  .on('error', () => {
143
- logger.error('The build log could not be retrieved.');
141
+ uiLogger.error('The build log could not be retrieved.');
144
142
  });
145
143
  }
146
144
  catch (e) {
147
- logger.error('The build log could not be retrieved.');
145
+ uiLogger.error('The build log could not be retrieved.');
148
146
  resolve('');
149
147
  }
150
148
  });
@@ -2,11 +2,11 @@ import { getProjectThemeDetails, migrateThemes, } from '@hubspot/project-parsing
2
2
  import { confirmPrompt } from '../../prompts/promptUtils.js';
3
3
  import { writeProjectConfig, } from '../../projects/config.js';
4
4
  import { ensureProjectExists } from '../../projects/ensureProjectExists.js';
5
- import { useV3Api } from '../../projects/platformVersion.js';
5
+ import { isV2Project } from '../../projects/platformVersion.js';
6
6
  import { fetchMigrationApps } from '../../app/migrate.js';
7
7
  import { getHasMigratableThemes, validateMigrationAppsAndThemes, handleThemesMigration, migrateThemes2025_2, } from '../migrate.js';
8
8
  import { lib } from '../../../lang/en.js';
9
- vi.mock('@hubspot/local-dev-lib/logger');
9
+ vi.mock('../../ui/logger.js');
10
10
  vi.mock('@hubspot/project-parsing-lib');
11
11
  vi.mock('../../prompts/promptUtils');
12
12
  vi.mock('../../projects/config');
@@ -18,7 +18,7 @@ const mockedMigrateThemes = migrateThemes;
18
18
  const mockedConfirmPrompt = confirmPrompt;
19
19
  const mockedWriteProjectConfig = writeProjectConfig;
20
20
  const mockedEnsureProjectExists = ensureProjectExists;
21
- const mockedUseV3Api = useV3Api;
21
+ const mockedUseV3Api = isV2Project;
22
22
  const mockedFetchMigrationApps = fetchMigrationApps;
23
23
  const ACCOUNT_ID = 123;
24
24
  const PROJECT_NAME = 'Test Project';
@@ -7,7 +7,7 @@ import { lib } from '../../lang/en.js';
7
7
  import { PROJECT_CONFIG_FILE } from '../constants.js';
8
8
  import { uiLogger } from '../ui/logger.js';
9
9
  import { debugError } from '../errorHandlers/index.js';
10
- import { useV3Api } from '../projects/platformVersion.js';
10
+ import { isV2Project } from '../projects/platformVersion.js';
11
11
  import { confirmPrompt } from '../prompts/promptUtils.js';
12
12
  import { fetchMigrationApps } from '../app/migrate.js';
13
13
  export async function getHasMigratableThemes(projectConfig) {
@@ -22,7 +22,7 @@ export async function getHasMigratableThemes(projectConfig) {
22
22
  };
23
23
  }
24
24
  export async function validateMigrationAppsAndThemes(hasApps, projectConfig) {
25
- if (useV3Api(projectConfig?.projectConfig?.platformVersion)) {
25
+ if (isV2Project(projectConfig?.projectConfig?.platformVersion)) {
26
26
  throw new Error(lib.migrate.errors.project.themesAlreadyMigrated);
27
27
  }
28
28
  if (hasApps > 0 && projectConfig) {
@@ -3,6 +3,7 @@ interface SpinnerState extends BaseSpinnerOptions {
3
3
  name?: string;
4
4
  }
5
5
  declare class SpinniesManager {
6
+ private disableOutput;
6
7
  private options;
7
8
  private spinners;
8
9
  private isCursorHidden;
@@ -14,6 +15,7 @@ declare class SpinniesManager {
14
15
  constructor();
15
16
  init(options?: Partial<SpinnerState>): void;
16
17
  private resetState;
18
+ setDisableOutput(disableOutput: boolean): void;
17
19
  pick(name: string): SpinnerState | undefined;
18
20
  add(name: string, options?: Partial<SpinnerState>): SpinnerState & {
19
21
  name: string;
@@ -19,6 +19,7 @@ function safeColor(text, color) {
19
19
  return text;
20
20
  }
21
21
  class SpinniesManager {
22
+ disableOutput = false;
22
23
  options;
23
24
  spinners = {};
24
25
  isCursorHidden = false;
@@ -61,6 +62,9 @@ class SpinniesManager {
61
62
  this.lineCount = 0;
62
63
  this.currentFrameIndex = 0;
63
64
  }
65
+ setDisableOutput(disableOutput) {
66
+ this.disableOutput = disableOutput;
67
+ }
64
68
  pick(name) {
65
69
  return this.spinners?.[name];
66
70
  }
@@ -142,6 +146,9 @@ class SpinniesManager {
142
146
  this.spinners[name] = { ...this.spinners[name], ...options, status };
143
147
  }
144
148
  updateSpinnerState() {
149
+ if (this.disableOutput) {
150
+ return;
151
+ }
145
152
  if (this.spin) {
146
153
  if (this.currentInterval) {
147
154
  clearInterval(this.currentInterval);
package/lib/ui/boxen.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { uiLogger } from './logger.js';
2
2
  import { UI_COLORS } from './index.js';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
4
3
  import { lib } from '../../lang/en.js';
5
4
  const defaultOptions = {
6
5
  titleAlignment: 'left',
@@ -17,7 +16,7 @@ export async function logInBox({ contents, options, }) {
17
16
  return;
18
17
  }
19
18
  catch (error) {
20
- logger.debug(lib.boxen.failedToLoad);
19
+ uiLogger.debug(lib.boxen.failedToLoad);
21
20
  if (options?.title) {
22
21
  uiLogger.log(options.title);
23
22
  uiLogger.log('');
package/lib/ui/git.js CHANGED
@@ -1,22 +1,25 @@
1
1
  import os from 'os';
2
2
  import { checkGitInclusion } from '@hubspot/local-dev-lib/gitignore';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
4
- import { i18n } from '../lang.js';
3
+ import { uiLogger } from './logger.js';
4
+ import { lib } from '../../lang/en.js';
5
+ import { uiLine } from './index.js';
5
6
  export function checkAndWarnGitInclusion(configPath) {
6
7
  try {
7
8
  const { inGit, configIgnored } = checkGitInclusion(configPath);
8
9
  if (!inGit || configIgnored)
9
10
  return;
10
- logger.warn(i18n(`lib.ui.git.securityIssue`));
11
- logger.warn(i18n(`lib.ui.git.configFileTracked`));
12
- logger.warn(i18n(`lib.ui.git.fileName`, { configPath }));
13
- logger.warn(i18n(`lib.ui.git.remediate`));
14
- logger.warn(i18n(`lib.ui.git.moveConfig`, { homeDir: os.homedir() }));
15
- logger.warn(i18n(`lib.ui.git.addGitignore`, { configPath }));
16
- logger.warn(i18n(`lib.ui.git.noRemote`));
11
+ uiLine();
12
+ uiLogger.warn(lib.ui.git.securityIssue);
13
+ uiLogger.log(lib.ui.git.configFileTracked);
14
+ uiLogger.log(lib.ui.git.fileName(configPath));
15
+ uiLogger.log('');
16
+ uiLogger.log(lib.ui.git.moveConfig(os.homedir()));
17
+ uiLogger.log(lib.ui.git.addGitignore(configPath));
18
+ uiLogger.log(lib.ui.git.noRemote);
19
+ uiLine();
17
20
  }
18
21
  catch (e) {
19
22
  // fail silently
20
- logger.debug(i18n(`lib.ui.git.checkFailed`));
23
+ uiLogger.debug(lib.ui.git.checkFailed);
21
24
  }
22
25
  }
package/lib/ui/index.d.ts CHANGED
@@ -13,6 +13,10 @@ export declare function uiLink(linkText: string, url: string): string;
13
13
  export declare function uiAccountDescription(accountId?: number | null, bold?: boolean): string;
14
14
  export declare function uiInfoSection(title: string, logContent: () => void): void;
15
15
  export declare function uiCommandReference(command: string, withQuotes?: boolean): string;
16
+ export declare function uiAuthCommandReference({ accountId, qa, }?: {
17
+ accountId?: number | string;
18
+ qa?: boolean;
19
+ }): string;
16
20
  export declare function uiFeatureHighlight(features: string[], title?: string): void;
17
21
  export declare function uiBetaTag(message: string, log?: true): undefined;
18
22
  export declare function uiBetaTag(message: string, log: false): string;
package/lib/ui/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import chalk from 'chalk';
2
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
2
+ import { getAccountConfig, configFileExists, } from '@hubspot/local-dev-lib/config';
3
+ import { uiLogger } from './logger.js';
4
4
  import { supportsHyperlinkModule } from './supportHyperlinks.js';
5
5
  import { supportsColor } from './supportsColor.js';
6
- import { i18n } from '../lang.js';
6
+ import { uiMessages } from './uiMessages.js';
7
7
  import { HUBSPOT_ACCOUNT_TYPE_STRINGS } from '@hubspot/local-dev-lib/constants/config';
8
8
  export const UI_COLORS = {
9
9
  SORBET: '#FF8F59',
@@ -11,7 +11,7 @@ export const UI_COLORS = {
11
11
  MARIGOLD_DARK: '#dbae60',
12
12
  };
13
13
  export function uiLine() {
14
- logger.log('-'.repeat(50));
14
+ uiLogger.log('-'.repeat(50));
15
15
  }
16
16
  export function getTerminalUISupport() {
17
17
  return {
@@ -50,10 +50,10 @@ export function uiAccountDescription(accountId, bold = true) {
50
50
  }
51
51
  export function uiInfoSection(title, logContent) {
52
52
  uiLine();
53
- logger.log(chalk.bold(title));
54
- logger.log('');
53
+ uiLogger.log(chalk.bold(title));
54
+ uiLogger.log('');
55
55
  logContent();
56
- logger.log('');
56
+ uiLogger.log('');
57
57
  uiLine();
58
58
  }
59
59
  export function uiCommandReference(command, withQuotes = true) {
@@ -63,66 +63,75 @@ export function uiCommandReference(command, withQuotes = true) {
63
63
  ? chalk.hex(UI_COLORS.MARIGOLD_DARK)(commandReference)
64
64
  : commandReference);
65
65
  }
66
+ export function uiAuthCommandReference({ accountId, qa, } = {}) {
67
+ const userIsUsingGlobalConfig = configFileExists(true);
68
+ let command = 'hs auth';
69
+ if (userIsUsingGlobalConfig) {
70
+ command = 'hs account auth';
71
+ }
72
+ return uiCommandReference(`${command}${accountId ? ` --account=${accountId}` : ''}${qa ? ' --qa' : ''}`);
73
+ }
66
74
  export function uiFeatureHighlight(features, title) {
67
- uiInfoSection(title ? title : i18n(`lib.ui.featureHighlight.defaultTitle`), () => {
75
+ uiInfoSection(title ? title : uiMessages.featureHighlight.defaultTitle, () => {
68
76
  features.forEach(feature => {
69
- const featureKey = `lib.ui.featureHighlight.featureKeys.${feature}`;
70
- const message = i18n(`${featureKey}.message`, {
71
- command: uiCommandReference(i18n(`${featureKey}.command`)),
72
- link: uiLink(i18n(`${featureKey}.linkText`), i18n(`${featureKey}.url`)),
73
- });
74
- logger.log(` - ${message}`);
77
+ const featureConfig = uiMessages.featureHighlight.featureKeys[feature];
78
+ if (!featureConfig) {
79
+ uiLogger.debug(`Feature config not found for: ${feature}`);
80
+ return;
81
+ }
82
+ let message;
83
+ if ('linkText' in featureConfig && 'url' in featureConfig) {
84
+ // linkText + url (for sampleProjects)
85
+ message = featureConfig.message(uiLink(featureConfig.linkText, featureConfig.url));
86
+ }
87
+ else if ('command' in featureConfig && 'message' in featureConfig) {
88
+ // Command + Message function (most cases)
89
+ message = featureConfig.message(uiCommandReference(featureConfig.command));
90
+ }
91
+ else {
92
+ // Message only (for projectCommandTip)
93
+ message = featureConfig.message;
94
+ }
95
+ uiLogger.log(` - ${message}`);
75
96
  });
76
97
  });
77
98
  }
78
99
  export function uiBetaTag(message, log = true) {
79
- const tag = i18n(`lib.ui.betaTag`);
100
+ const tag = uiMessages.betaTag;
80
101
  const result = `${tag} ${message}`;
81
102
  if (log) {
82
- logger.log(result);
103
+ uiLogger.log(result);
83
104
  return;
84
105
  }
85
106
  return result;
86
107
  }
87
108
  export function uiDeprecatedTag(message, log = true) {
88
- const tag = i18n(`lib.ui.deprecatedTag`);
109
+ const tag = uiMessages.deprecatedTag;
89
110
  const result = `${tag} ${message}`;
90
111
  if (log) {
91
- logger.log(result);
112
+ uiLogger.log(result);
92
113
  return;
93
114
  }
94
115
  return result;
95
116
  }
96
117
  export function uiCommandDisabledBanner(command, url, message) {
97
118
  const tag = message ||
98
- i18n(`lib.ui.disabledMessage`, {
99
- command: uiCommandReference(command),
100
- url: url ? uiLink(i18n(`lib.ui.disabledUrlText`), url) : '',
101
- npmCommand: uiCommandReference('npm i -g @hubspot/cli@latest'),
102
- });
103
- logger.log();
119
+ `The ${uiCommandReference(command)} command is disabled. Run ${uiCommandReference('npm i -g @hubspot/cli@latest')} to update to the latest HubSpot CLI version. ${url ? uiLink('See all HubSpot CLI commands here.', url) : ''}`;
120
+ uiLogger.log('');
104
121
  uiLine();
105
- logger.error(tag);
122
+ uiLogger.error(tag);
106
123
  uiLine();
107
- logger.log();
124
+ uiLogger.log('');
108
125
  }
109
126
  export function uiDeprecatedDescription(message, command, url) {
110
- const tag = i18n(`lib.ui.deprecatedDescription`, {
111
- message,
112
- command: uiCommandReference(command),
113
- url: url ? uiLink(i18n(`lib.ui.deprecatedUrlText`), url) : '',
114
- });
127
+ const tag = message || uiMessages.disabledMessage(command, url);
115
128
  return uiDeprecatedTag(tag);
116
129
  }
117
130
  export function uiDeprecatedMessage(command, url, message) {
118
- const tag = message ||
119
- i18n(`lib.ui.deprecatedMessage`, {
120
- command: uiCommandReference(command),
121
- url: url ? uiLink(i18n(`lib.ui.deprecatedUrlText`), url) : '',
122
- });
123
- logger.log();
131
+ const tag = uiMessages.deprecatedDescription(message || '', command, url);
132
+ uiLogger.log('');
124
133
  uiDeprecatedTag(tag);
125
- logger.log();
134
+ uiLogger.log('');
126
135
  }
127
136
  export function indent(level) {
128
137
  const indentation = ' ';
@@ -1,7 +1,8 @@
1
1
  import moment from 'moment';
2
2
  import chalk from 'chalk';
3
- import { logger, Styles } from '@hubspot/local-dev-lib/logger';
4
- import { i18n } from '../lang.js';
3
+ import { Styles } from '@hubspot/local-dev-lib/logger';
4
+ import { uiLogger } from './logger.js';
5
+ import { lib } from '../../lang/en.js';
5
6
  const SEPARATOR = ' - ';
6
7
  const LOG_STATUS_COLORS = {
7
8
  SUCCESS: Styles.success,
@@ -56,9 +57,7 @@ function processLog(log, options) {
56
57
  return logHandler[log.status](log, options);
57
58
  }
58
59
  catch (e) {
59
- logger.error(i18n(`lib.ui.serverlessFunctionLogs.unableToProcessLog`, {
60
- log: JSON.stringify(log),
61
- }));
60
+ uiLogger.error(lib.ui.serverlessFunctionLogs.unableToProcessLog(JSON.stringify(log)));
62
61
  }
63
62
  }
64
63
  function isLogsResponse(logsResp) {
@@ -70,7 +69,7 @@ function isLogsResponse(logsResp) {
70
69
  function processLogs(logsResp, options) {
71
70
  const isLogsResp = isLogsResponse(logsResp);
72
71
  if (!logsResp || (isLogsResp && logsResp.results.length === 0)) {
73
- return i18n(`lib.ui.serverlessFunctionLogs.noLogsFound`);
72
+ return lib.ui.serverlessFunctionLogs.noLogsFound;
74
73
  }
75
74
  else if (isLogsResp) {
76
75
  return logsResp
@@ -82,5 +81,8 @@ function processLogs(logsResp, options) {
82
81
  return processLog(logsResp, options);
83
82
  }
84
83
  export function outputLogs(logsResp, options) {
85
- logger.log(processLogs(logsResp, options));
84
+ const result = processLogs(logsResp, options);
85
+ if (result) {
86
+ uiLogger.log(result);
87
+ }
86
88
  }
@@ -0,0 +1,68 @@
1
+ export declare const uiMessages: {
2
+ betaTag: string;
3
+ deprecatedTag: string;
4
+ deprecatedDescription: (message: string, command: string, url?: string) => string;
5
+ disabledMessage: (command: string, url?: string) => string;
6
+ disabledUrlText: string;
7
+ featureHighlight: {
8
+ defaultTitle: string;
9
+ featureKeys: {
10
+ accountOption: {
11
+ command: string;
12
+ message: (command: string) => string;
13
+ };
14
+ accountsListCommand: {
15
+ command: string;
16
+ message: (command: string) => string;
17
+ };
18
+ accountsUseCommand: {
19
+ command: string;
20
+ message: (command: string) => string;
21
+ };
22
+ authCommand: {
23
+ command: string;
24
+ message: (command: string) => string;
25
+ };
26
+ feedbackCommand: {
27
+ command: string;
28
+ message: (command: string) => string;
29
+ };
30
+ helpCommand: {
31
+ command: string;
32
+ message: (command: string) => string;
33
+ };
34
+ projectCreateCommand: {
35
+ command: string;
36
+ message: (command: string) => string;
37
+ };
38
+ projectDeployCommand: {
39
+ command: string;
40
+ message: (command: string) => string;
41
+ };
42
+ projectHelpCommand: {
43
+ command: string;
44
+ message: (command: string) => string;
45
+ };
46
+ projectUploadCommand: {
47
+ command: string;
48
+ message: (command: string) => string;
49
+ };
50
+ projectDevCommand: {
51
+ command: string;
52
+ message: (command: string) => string;
53
+ };
54
+ projectInstallDepsCommand: {
55
+ command: string;
56
+ message: (command: string) => string;
57
+ };
58
+ projectCommandTip: {
59
+ message: string;
60
+ };
61
+ sampleProjects: {
62
+ linkText: string;
63
+ url: string;
64
+ message: (link: string) => string;
65
+ };
66
+ };
67
+ };
68
+ };
@@ -0,0 +1,71 @@
1
+ // UI messages for the UI module - separate file to avoid circular imports with lang/en.ts
2
+ // This contains the same strings that would be in lib.ui.* from lang/en.ts
3
+ import { uiCommandReference, uiLink } from './index.js';
4
+ export const uiMessages = {
5
+ betaTag: '[BETA]',
6
+ deprecatedTag: '[DEPRECATED]',
7
+ deprecatedDescription: (message, command, url) => `${message}. The ${uiCommandReference(command)} command is deprecated and will be disabled soon. ${url ? uiLink('Learn more', url) : ''}`,
8
+ disabledMessage: (command, url) => `The ${uiCommandReference(command)} command is disabled. Run ${uiCommandReference('npm i -g @hubspot/cli@latest')} to update to the latest HubSpot CLI version. ${url ? uiLink('Learn more', url) : ''}`,
9
+ disabledUrlText: 'See all HubSpot CLI commands here.',
10
+ featureHighlight: {
11
+ defaultTitle: "What's next?",
12
+ featureKeys: {
13
+ accountOption: {
14
+ command: '--account',
15
+ message: (command) => `Use the ${command} option with any command to override the default account`,
16
+ },
17
+ accountsListCommand: {
18
+ command: 'hs accounts list',
19
+ message: (command) => `${command} - See a list of configured HubSpot accounts`,
20
+ },
21
+ accountsUseCommand: {
22
+ command: 'hs accounts use',
23
+ message: (command) => `${command} - Set the Hubspot account that the CLI will target by default`,
24
+ },
25
+ authCommand: {
26
+ command: 'hs auth',
27
+ message: (command) => `${command} - Connect the CLI to additional HubSpot accounts`,
28
+ },
29
+ feedbackCommand: {
30
+ command: 'hs feedback',
31
+ message: (command) => `${command} - Report a bug or leave feedback`,
32
+ },
33
+ helpCommand: {
34
+ command: 'hs help',
35
+ message: (command) => `${command} - See a list of available commands`,
36
+ },
37
+ projectCreateCommand: {
38
+ command: 'hs project create',
39
+ message: (command) => `${command} - Create a new project`,
40
+ },
41
+ projectDeployCommand: {
42
+ command: 'hs project deploy',
43
+ message: (command) => `Ready to take your project live? Run ${command}`,
44
+ },
45
+ projectHelpCommand: {
46
+ command: 'hs project --help',
47
+ message: (command) => `${command} - Learn more about available project commands`,
48
+ },
49
+ projectUploadCommand: {
50
+ command: 'hs project upload',
51
+ message: (command) => `${command} - Upload your project to HubSpot and trigger builds`,
52
+ },
53
+ projectDevCommand: {
54
+ command: 'hs project dev',
55
+ message: (command) => `${command} - Set up a test environment and start local development`,
56
+ },
57
+ projectInstallDepsCommand: {
58
+ command: 'hs project install-deps',
59
+ message: (command) => `${command} - Install all project dependencies`,
60
+ },
61
+ projectCommandTip: {
62
+ message: 'Tip: All project commands must be run from within a project directory',
63
+ },
64
+ sampleProjects: {
65
+ linkText: "HubSpot's sample projects",
66
+ url: 'https://developers.hubspot.com/docs/platform/sample-projects?utm_source=cli&utm_content=project_create_whats_next',
67
+ message: (link) => `See ${link}`,
68
+ },
69
+ },
70
+ },
71
+ };
@@ -1,7 +1,7 @@
1
1
  import { trackUsage } from '@hubspot/local-dev-lib/trackUsage';
2
2
  import { isTrackingAllowed, getAccountConfig, } from '@hubspot/local-dev-lib/config';
3
3
  import { API_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
4
- import { logger } from '@hubspot/local-dev-lib/logger';
4
+ import { uiLogger } from './ui/logger.js';
5
5
  import packageJson from '../package.json' with { type: 'json' };
6
6
  const version = packageJson.version;
7
7
  import { debugError } from './errorHandlers/index.js';
@@ -31,7 +31,7 @@ export async function trackCommandUsage(command, meta = {}, accountId) {
31
31
  if (!isTrackingAllowed()) {
32
32
  return;
33
33
  }
34
- logger.debug('Attempting to track usage of "%s" command', command);
34
+ uiLogger.debug(`Attempting to track usage of "${command}" command`);
35
35
  let authType = 'unknown';
36
36
  if (accountId) {
37
37
  const accountConfig = getAccountConfig(accountId);
@@ -53,10 +53,10 @@ export async function trackHelpUsage(command) {
53
53
  return;
54
54
  }
55
55
  if (command) {
56
- logger.debug('Tracking help usage of "%s" sub-command', command);
56
+ uiLogger.debug(`Tracking help usage of "${command}" sub-command`);
57
57
  }
58
58
  else {
59
- logger.debug('Tracking help usage of main command');
59
+ uiLogger.debug('Tracking help usage of main command');
60
60
  }
61
61
  return trackCliInteraction({
62
62
  action: 'cli-help',
@@ -84,7 +84,7 @@ export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
84
84
  if (!isTrackingAllowed()) {
85
85
  return;
86
86
  }
87
- logger.debug('Attempting to track metadata usage of "%s" command', command);
87
+ uiLogger.debug(`Attempting to track metadata usage of "${command}" command`);
88
88
  let authType = 'unknown';
89
89
  if (accountId) {
90
90
  const accountConfig = getAccountConfig(accountId);
@@ -122,7 +122,7 @@ async function trackCliInteraction({ action, accountId, command, authType, meta
122
122
  action: 'cli-mcp-server',
123
123
  type: process.env.HUBSPOT_MCP_AI_AGENT,
124
124
  }, accountId);
125
- logger.debug('Sent AI usage tracking command event: %o', {
125
+ uiLogger.debug('Sent AI usage tracking command event:', {
126
126
  ...usageTrackingEvent,
127
127
  action: 'cli-mcp-server',
128
128
  type: process.env.HUBSPOT_MCP_AI_AGENT,
@@ -133,7 +133,7 @@ async function trackCliInteraction({ action, accountId, command, authType, meta
133
133
  }
134
134
  }
135
135
  try {
136
- logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
136
+ uiLogger.debug('Sent usage tracking command event:', usageTrackingEvent);
137
137
  return trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
138
138
  }
139
139
  catch (error) {