@hubspot/cli 7.10.0 → 7.10.1-experimental.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/bin/cli.js +5 -4
  2. package/commands/__tests__/getStarted.test.js +10 -0
  3. package/commands/__tests__/project.test.js +3 -0
  4. package/commands/account/__tests__/rename.test.js +10 -3
  5. package/commands/account/auth.js +10 -14
  6. package/commands/account/clean.js +11 -19
  7. package/commands/account/createOverride.js +15 -11
  8. package/commands/account/info.js +8 -5
  9. package/commands/account/list.js +15 -19
  10. package/commands/account/remove.js +23 -22
  11. package/commands/account/removeOverride.js +6 -6
  12. package/commands/account/rename.js +2 -2
  13. package/commands/account/use.js +19 -8
  14. package/commands/app/__tests__/migrate.test.js +8 -4
  15. package/commands/app/migrate.js +2 -2
  16. package/commands/auth.js +18 -14
  17. package/commands/config/migrate.js +5 -5
  18. package/commands/customObject/createSchema.js +2 -3
  19. package/commands/customObject/updateSchema.js +2 -3
  20. package/commands/getStarted.js +2 -3
  21. package/commands/hubdb/__tests__/list.test.js +1 -0
  22. package/commands/hubdb/list.js +2 -2
  23. package/commands/init.js +36 -32
  24. package/commands/project/__tests__/deploy.test.js +10 -5
  25. package/commands/project/__tests__/devUnifiedFlow.test.js +6 -4
  26. package/commands/project/__tests__/lint.test.js +709 -0
  27. package/commands/project/__tests__/logs.test.js +4 -0
  28. package/commands/project/__tests__/validate.test.js +286 -28
  29. package/commands/project/cloneApp.js +2 -2
  30. package/commands/project/deploy.js +16 -8
  31. package/commands/project/dev/deprecatedFlow.js +4 -5
  32. package/commands/project/dev/index.js +19 -7
  33. package/commands/project/dev/unifiedFlow.js +4 -5
  34. package/commands/project/lint.d.ts +6 -0
  35. package/commands/project/lint.js +178 -0
  36. package/commands/project/logs.js +2 -3
  37. package/commands/project/migrate.js +4 -13
  38. package/commands/project/profile/add.js +6 -7
  39. package/commands/project/profile/delete.js +2 -2
  40. package/commands/project/upload.js +10 -4
  41. package/commands/project/validate.js +73 -13
  42. package/commands/project.js +2 -0
  43. package/commands/sandbox/__tests__/create.test.js +14 -5
  44. package/commands/sandbox/create.js +4 -5
  45. package/commands/sandbox/delete.js +23 -20
  46. package/commands/testAccount/create.js +2 -2
  47. package/commands/testAccount/delete.js +9 -8
  48. package/lang/en.d.ts +48 -11
  49. package/lang/en.js +58 -15
  50. package/lib/__tests__/buildAccount.test.js +22 -30
  51. package/lib/__tests__/commonOpts.test.js +9 -13
  52. package/lib/__tests__/developerTestAccounts.test.js +29 -17
  53. package/lib/__tests__/importData.test.js +20 -10
  54. package/lib/__tests__/oauth.test.js +19 -8
  55. package/lib/__tests__/projectProfiles.test.js +273 -32
  56. package/lib/__tests__/sandboxSync.test.js +33 -11
  57. package/lib/__tests__/sandboxes.test.js +30 -19
  58. package/lib/__tests__/usageTracking.test.js +10 -10
  59. package/lib/__tests__/validation.test.js +32 -32
  60. package/lib/accountTypes.d.ts +9 -9
  61. package/lib/accountTypes.js +2 -4
  62. package/lib/app/__tests__/migrate.test.js +15 -0
  63. package/lib/app/__tests__/migrate_legacy.test.js +9 -0
  64. package/lib/app/migrate_legacy.d.ts +2 -2
  65. package/lib/buildAccount.d.ts +4 -4
  66. package/lib/buildAccount.js +7 -14
  67. package/lib/commonOpts.js +3 -3
  68. package/lib/configMigrate.d.ts +2 -2
  69. package/lib/configMigrate.js +42 -18
  70. package/lib/configOptions.js +3 -2
  71. package/lib/developerTestAccounts.d.ts +3 -3
  72. package/lib/developerTestAccounts.js +4 -7
  73. package/lib/doctor/DiagnosticInfoBuilder.d.ts +1 -1
  74. package/lib/doctor/DiagnosticInfoBuilder.js +9 -6
  75. package/lib/doctor/Doctor.js +4 -3
  76. package/lib/doctor/__tests__/Diagnosis.test.js +4 -3
  77. package/lib/doctor/__tests__/DiagnosticInfoBuilder.test.js +17 -9
  78. package/lib/doctor/__tests__/Doctor.test.js +14 -0
  79. package/lib/importData.js +8 -7
  80. package/lib/links.js +5 -5
  81. package/lib/middleware/{__test__ → __tests__}/commandTargetingUtils.test.js +3 -3
  82. package/lib/middleware/{__test__ → __tests__}/configMiddleware.test.js +23 -22
  83. package/lib/middleware/{__test__ → __tests__}/gitMiddleware.test.js +9 -7
  84. package/lib/middleware/autoUpdateMiddleware.js +34 -23
  85. package/lib/middleware/commandTargetingUtils.js +3 -2
  86. package/lib/middleware/configMiddleware.d.ts +6 -1
  87. package/lib/middleware/configMiddleware.js +36 -15
  88. package/lib/middleware/fireAlarmMiddleware.js +4 -15
  89. package/lib/middleware/gitMiddleware.js +8 -4
  90. package/lib/oauth.d.ts +2 -2
  91. package/lib/oauth.js +8 -10
  92. package/lib/projectProfiles.d.ts +4 -3
  93. package/lib/projectProfiles.js +78 -32
  94. package/lib/projects/__tests__/AppDevModeInterface.test.js +17 -6
  95. package/lib/projects/__tests__/DevServerManager.test.js +1 -0
  96. package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
  97. package/lib/projects/__tests__/deploy.test.js +1 -0
  98. package/lib/projects/__tests__/uieLinting.test.js +640 -0
  99. package/lib/projects/create/__tests__/v2.test.js +11 -0
  100. package/lib/projects/localDev/AppDevModeInterface.js +2 -2
  101. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +2 -2
  102. package/lib/projects/localDev/LocalDevLogger.js +4 -4
  103. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +3 -3
  104. package/lib/projects/localDev/helpers/account.d.ts +10 -10
  105. package/lib/projects/localDev/helpers/account.js +6 -11
  106. package/lib/projects/uieLinting.d.ts +33 -0
  107. package/lib/projects/uieLinting.js +222 -0
  108. package/lib/projects/urls.js +5 -6
  109. package/lib/prompts/__tests__/downloadProjectPrompt.test.js +7 -5
  110. package/lib/prompts/accountNamePrompt.js +3 -3
  111. package/lib/prompts/accountsPrompt.d.ts +1 -1
  112. package/lib/prompts/accountsPrompt.js +6 -7
  113. package/lib/prompts/confirmImportDataPrompt.js +2 -2
  114. package/lib/prompts/downloadProjectPrompt.d.ts +1 -0
  115. package/lib/prompts/downloadProjectPrompt.js +5 -2
  116. package/lib/prompts/importDataTestAccountSelectPrompt.js +4 -5
  117. package/lib/prompts/personalAccessKeyPrompt.js +2 -2
  118. package/lib/prompts/projectDevTargetAccountPrompt.d.ts +3 -3
  119. package/lib/prompts/projectDevTargetAccountPrompt.js +5 -7
  120. package/lib/prompts/sandboxesPrompt.js +7 -8
  121. package/lib/prompts/setAsDefaultAccountPrompt.js +7 -6
  122. package/lib/sandboxSync.d.ts +2 -2
  123. package/lib/sandboxSync.js +3 -9
  124. package/lib/sandboxes.d.ts +4 -4
  125. package/lib/sandboxes.js +6 -11
  126. package/lib/serverlessLogs.js +2 -2
  127. package/lib/theme/__tests__/migrate.test.js +15 -0
  128. package/lib/ui/index.js +6 -3
  129. package/lib/usageTracking.js +15 -8
  130. package/lib/validation.js +13 -11
  131. package/mcp-server/tools/cms/HsCreateFunctionTool.js +4 -2
  132. package/mcp-server/tools/cms/HsCreateModuleTool.js +4 -2
  133. package/mcp-server/tools/cms/HsCreateTemplateTool.js +4 -2
  134. package/mcp-server/tools/cms/HsFunctionLogsTool.js +4 -2
  135. package/mcp-server/tools/cms/HsListFunctionsTool.js +3 -1
  136. package/mcp-server/tools/cms/HsListTool.js +3 -1
  137. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -0
  138. package/mcp-server/tools/index.js +4 -0
  139. package/mcp-server/tools/project/AddFeatureToProjectTool.js +4 -2
  140. package/mcp-server/tools/project/CreateProjectTool.js +4 -2
  141. package/mcp-server/tools/project/CreateTestAccountTool.js +17 -7
  142. package/mcp-server/tools/project/DeployProjectTool.js +3 -1
  143. package/mcp-server/tools/project/DocFetchTool.js +6 -4
  144. package/mcp-server/tools/project/DocsSearchTool.d.ts +1 -1
  145. package/mcp-server/tools/project/DocsSearchTool.js +10 -8
  146. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +1 -1
  147. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -7
  148. package/mcp-server/tools/project/GetApplicationInfoTool.js +8 -6
  149. package/mcp-server/tools/project/GetBuildLogsTool.d.ts +26 -0
  150. package/mcp-server/tools/project/GetBuildLogsTool.js +125 -0
  151. package/mcp-server/tools/project/GetBuildStatusTool.d.ts +26 -0
  152. package/mcp-server/tools/project/GetBuildStatusTool.js +166 -0
  153. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +1 -1
  154. package/mcp-server/tools/project/GetConfigValuesTool.js +9 -7
  155. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +1 -1
  156. package/mcp-server/tools/project/GuidedWalkthroughTool.js +5 -3
  157. package/mcp-server/tools/project/UploadProjectTools.js +3 -1
  158. package/mcp-server/tools/project/ValidateProjectTool.js +4 -2
  159. package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +12 -2
  160. package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +5 -1
  161. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +23 -11
  162. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +7 -5
  163. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +7 -5
  164. package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.d.ts +1 -0
  165. package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.js +305 -0
  166. package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.d.ts +1 -0
  167. package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.js +240 -0
  168. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -6
  169. package/mcp-server/utils/__tests__/content.test.js +21 -20
  170. package/mcp-server/utils/__tests__/feedbackTracking.test.js +34 -28
  171. package/mcp-server/utils/config.d.ts +1 -0
  172. package/mcp-server/utils/config.js +10 -0
  173. package/mcp-server/utils/content.d.ts +1 -1
  174. package/mcp-server/utils/content.js +2 -2
  175. package/mcp-server/utils/feedbackTracking.d.ts +1 -1
  176. package/mcp-server/utils/feedbackTracking.js +3 -3
  177. package/mcp-server/utils/toolUsageTracking.js +4 -3
  178. package/package.json +9 -9
  179. package/ui/components/BoxWithTitle.d.ts +2 -1
  180. package/ui/components/BoxWithTitle.js +2 -2
  181. package/ui/components/StatusMessageBoxes.d.ts +5 -4
  182. package/ui/components/StatusMessageBoxes.js +8 -8
  183. package/lib/middleware/__test__/notificationsMiddleware.test.js +0 -8
  184. package/lib/middleware/notificationsMiddleware.d.ts +0 -1
  185. package/lib/middleware/notificationsMiddleware.js +0 -28
  186. package/lib/ui/boxen.d.ts +0 -5
  187. package/lib/ui/boxen.js +0 -26
  188. package/mcp-server/utils/__tests__/cliConfig.test.js +0 -110
  189. package/mcp-server/utils/cliConfig.d.ts +0 -1
  190. package/mcp-server/utils/cliConfig.js +0 -12
  191. /package/{lib/middleware/__test__/commandTargetingUtils.test.d.ts → commands/project/__tests__/lint.test.d.ts} +0 -0
  192. /package/lib/middleware/{__test__/configMiddleware.test.d.ts → __tests__/commandTargetingUtils.test.d.ts} +0 -0
  193. /package/lib/middleware/{__test__/gitMiddleware.test.d.ts → __tests__/configMiddleware.test.d.ts} +0 -0
  194. /package/lib/middleware/{__test__/notificationsMiddleware.test.d.ts → __tests__/gitMiddleware.test.d.ts} +0 -0
  195. /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.d.ts +0 -0
  196. /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.js +0 -0
  197. /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.d.ts +0 -0
  198. /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.js +0 -0
  199. /package/{mcp-server/utils/__tests__/cliConfig.test.d.ts → lib/projects/__tests__/uieLinting.test.d.ts} +0 -0
@@ -1,7 +1,7 @@
1
1
  import yargs from 'yargs';
2
2
  import { PLATFORM_VERSIONS } from '@hubspot/local-dev-lib/constants/projects';
3
3
  import { uiLogger } from '../../../lib/ui/logger.js';
4
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
4
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
5
5
  import { migrateApp2025_2 } from '../../../lib/app/migrate.js';
6
6
  import { migrateApp2023_2 } from '../../../lib/app/migrate_legacy.js';
7
7
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
@@ -11,8 +11,9 @@ vi.mock('../../../lib/ui/logger.js');
11
11
  vi.mock('../../../lib/app/migrate');
12
12
  vi.mock('../../../lib/app/migrate_legacy');
13
13
  vi.mock('../../../lib/projects/config.js');
14
+ vi.mock('../../../lib/usageTracking.js');
14
15
  const mockYargs = yargs;
15
- const mockedGetAccountConfig = getAccountConfig;
16
+ const mockedGetConfigAccountById = getConfigAccountById;
16
17
  const mockedMigrateApp2023_2 = migrateApp2023_2;
17
18
  const mockedMigrateApp2025_2 = migrateApp2025_2;
18
19
  const mockedUiLogger = uiLogger;
@@ -24,11 +25,14 @@ const exitSpy = vi
24
25
  describe('commands/app/migrate', () => {
25
26
  const mockAccountId = 123;
26
27
  const mockAccountConfig = {
28
+ accountId: mockAccountId,
27
29
  name: 'Test Account',
28
30
  env: 'prod',
31
+ authType: 'personalaccesskey',
32
+ personalAccessKey: 'test-key',
29
33
  };
30
34
  beforeEach(() => {
31
- mockedGetAccountConfig.mockReturnValue(mockAccountConfig);
35
+ mockedGetConfigAccountById.mockReturnValue(mockAccountConfig);
32
36
  exitSpy.mockClear();
33
37
  });
34
38
  afterEach(() => {
@@ -36,7 +40,7 @@ describe('commands/app/migrate', () => {
36
40
  });
37
41
  describe('handler', () => {
38
42
  it('should exit with error when no account config is found', async () => {
39
- mockedGetAccountConfig.mockReturnValue(null);
43
+ mockedGetConfigAccountById.mockReturnValue(null);
40
44
  await migrateCommand.handler({
41
45
  derivedAccountId: mockAccountId,
42
46
  });
@@ -1,4 +1,4 @@
1
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
1
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
2
2
  import { PLATFORM_VERSIONS } from '@hubspot/local-dev-lib/constants/projects';
3
3
  import { trackCommandMetadataUsage, trackCommandUsage, } from '../../lib/usageTracking.js';
4
4
  import { commands } from '../../lang/en.js';
@@ -16,7 +16,7 @@ export function handlerGenerator(commandTrackingName) {
16
16
  return async function handler(args) {
17
17
  const { derivedAccountId, platformVersion, unstable } = args;
18
18
  await trackCommandUsage(commandTrackingName, {}, derivedAccountId);
19
- const accountConfig = getAccountConfig(derivedAccountId);
19
+ const accountConfig = getConfigAccountById(derivedAccountId);
20
20
  if (!accountConfig) {
21
21
  uiLogger.error(commands.project.migrateApp.errors.noAccountConfig);
22
22
  return process.exit(EXIT_CODES.ERROR);
package/commands/auth.js CHANGED
@@ -3,7 +3,7 @@ import { OAUTH_AUTH_METHOD, PERSONAL_ACCESS_KEY_AUTH_METHOD, } from '@hubspot/lo
3
3
  import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
4
4
  import { DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME } from '@hubspot/local-dev-lib/constants/config';
5
5
  import { getAccessToken, updateConfigWithAccessToken, } from '@hubspot/local-dev-lib/personalAccessKey';
6
- import { updateAccountConfig, writeConfig, getConfigPath, loadConfig, getAccountId, configFileExists, } from '@hubspot/local-dev-lib/config';
6
+ import { updateConfigAccount, getConfigFilePath, globalConfigFileExists, } from '@hubspot/local-dev-lib/config';
7
7
  import { commaSeparatedValues, toKebabCase } from '@hubspot/local-dev-lib/text';
8
8
  import { promptUser } from '../lib/prompts/promptUtils.js';
9
9
  import { personalAccessKeyPrompt, OAUTH_FLOW, } from '../lib/prompts/personalAccessKeyPrompt.js';
@@ -47,13 +47,11 @@ async function handler(args) {
47
47
  PERSONAL_ACCESS_KEY_AUTH_METHOD.value;
48
48
  setCLILogLevel(args);
49
49
  const env = qa ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD;
50
- // Needed to load deprecated config
51
- loadConfig(configFlagValue);
52
- const configPath = getConfigPath();
50
+ const configPath = getConfigFilePath();
53
51
  if (configPath) {
54
52
  checkAndWarnGitInclusion(configPath);
55
53
  }
56
- if (configFileExists(true)) {
54
+ if (!configFlagValue && globalConfigFileExists()) {
57
55
  uiLogger.error(commands.auth.errors.globalConfigFileExists('hs account auth'));
58
56
  process.exit(EXIT_CODES.ERROR);
59
57
  }
@@ -62,7 +60,7 @@ async function handler(args) {
62
60
  trackAuthAction('auth', authType, TRACKING_STATUS.STARTED, parsedUserProvidedAccountId);
63
61
  }
64
62
  let configData;
65
- let updatedConfig;
63
+ let updatedConfig = undefined;
66
64
  let validName;
67
65
  let successAuthMethod;
68
66
  let token;
@@ -70,10 +68,19 @@ async function handler(args) {
70
68
  switch (authType) {
71
69
  case OAUTH_AUTH_METHOD.value:
72
70
  configData = await promptUser(OAUTH_FLOW);
73
- await authenticateWithOauth({
74
- ...configData,
71
+ const oauthAccount = {
72
+ name: configData.name,
73
+ accountId: configData.accountId,
74
+ authType: OAUTH_AUTH_METHOD.value,
75
75
  env,
76
- });
76
+ auth: {
77
+ clientId: configData.clientId,
78
+ clientSecret: configData.clientSecret,
79
+ scopes: configData.scopes,
80
+ tokenInfo: {},
81
+ },
82
+ };
83
+ await authenticateWithOauth(oauthAccount);
77
84
  successAuthMethod = OAUTH_AUTH_METHOD.name;
78
85
  break;
79
86
  case PERSONAL_ACCESS_KEY_AUTH_METHOD.value:
@@ -99,13 +106,10 @@ async function handler(args) {
99
106
  const { name: namePrompt } = await cliAccountNamePrompt(defaultName);
100
107
  validName = namePrompt;
101
108
  }
102
- updateAccountConfig({
109
+ updateConfigAccount({
103
110
  ...updatedConfig,
104
- env: updatedConfig.env,
105
- tokenInfo: updatedConfig.auth.tokenInfo,
106
111
  name: validName,
107
112
  });
108
- writeConfig();
109
113
  successAuthMethod = PERSONAL_ACCESS_KEY_AUTH_METHOD.name;
110
114
  break;
111
115
  default:
@@ -126,7 +130,7 @@ async function handler(args) {
126
130
  'accountOption',
127
131
  'accountsListCommand',
128
132
  ]);
129
- const accountId = getAccountId(accountName) || undefined;
133
+ const accountId = updatedConfig?.accountId;
130
134
  if (!disableTracking) {
131
135
  await trackAuthAction('auth', authType, TRACKING_STATUS.COMPLETE, accountId);
132
136
  }
@@ -1,5 +1,5 @@
1
1
  import fs from 'fs';
2
- import { configFileExists } from '@hubspot/local-dev-lib/config/migrate';
2
+ import { localConfigFileExists, globalConfigFileExists, } from '@hubspot/local-dev-lib/config';
3
3
  import { handleMigration, handleMerge } from '../../lib/configMigrate.js';
4
4
  import { logError } from '../../lib/errorHandlers/index.js';
5
5
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
@@ -16,8 +16,8 @@ async function handler(args) {
16
16
  uiLogger.error(commands.config.subcommands.migrate.errors.configNotFound(configPath));
17
17
  process.exit(EXIT_CODES.ERROR);
18
18
  }
19
- const deprecatedConfigExists = configFileExists(false, configPath);
20
- const globalConfigExists = configFileExists(true);
19
+ const deprecatedConfigExists = localConfigFileExists();
20
+ const globalConfigExists = globalConfigFileExists();
21
21
  if (!deprecatedConfigExists) {
22
22
  uiLogger.error(commands.config.subcommands.migrate.errors.noConfigToMigrate);
23
23
  process.exit(EXIT_CODES.ERROR);
@@ -25,10 +25,10 @@ async function handler(args) {
25
25
  let success = false;
26
26
  try {
27
27
  if (!globalConfigExists) {
28
- success = await handleMigration(configPath, true);
28
+ success = await handleMigration(true);
29
29
  }
30
30
  else {
31
- success = await handleMerge(configPath, force, true);
31
+ success = await handleMerge(force, true);
32
32
  }
33
33
  }
34
34
  catch (error) {
@@ -1,6 +1,5 @@
1
1
  import { uiLogger } from '../../lib/ui/logger.js';
2
- import { getEnv } from '@hubspot/local-dev-lib/config';
3
- import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
2
+ import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
4
3
  import { getAbsoluteFilePath } from '@hubspot/local-dev-lib/path';
5
4
  import { createObjectSchema } from '@hubspot/local-dev-lib/api/customObjects';
6
5
  import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
@@ -24,7 +23,7 @@ async function handler(args) {
24
23
  }
25
24
  try {
26
25
  const { data } = await createObjectSchema(derivedAccountId, schemaJson);
27
- uiLogger.success(commands.customObject.subcommands.createSchema.success.schemaViewable(`${getHubSpotWebsiteOrigin(getEnv() === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD)}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
26
+ uiLogger.success(commands.customObject.subcommands.createSchema.success.schemaViewable(`${getHubSpotWebsiteOrigin(getConfigAccountEnvironment(derivedAccountId))}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
28
27
  }
29
28
  catch (e) {
30
29
  logError(e, { accountId: derivedAccountId });
@@ -1,8 +1,7 @@
1
1
  import { fetchObjectSchemas, updateObjectSchema, } from '@hubspot/local-dev-lib/api/customObjects';
2
2
  import { uiLogger } from '../../lib/ui/logger.js';
3
3
  import { getAbsoluteFilePath } from '@hubspot/local-dev-lib/path';
4
- import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
5
- import { getEnv } from '@hubspot/local-dev-lib/config';
4
+ import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
6
5
  import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
7
6
  import { listPrompt } from '../../lib/prompts/promptUtils.js';
8
7
  import { logError } from '../../lib/errorHandlers/index.js';
@@ -34,7 +33,7 @@ async function handler(args) {
34
33
  choices: schemaNames,
35
34
  });
36
35
  const { data } = await updateObjectSchema(derivedAccountId, name, schemaJson);
37
- uiLogger.success(commands.customObject.subcommands.updateSchema.success.viewAtUrl(`${getHubSpotWebsiteOrigin(getEnv() === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD)}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
36
+ uiLogger.success(commands.customObject.subcommands.updateSchema.success.viewAtUrl(`${getHubSpotWebsiteOrigin(getConfigAccountEnvironment(derivedAccountId))}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
38
37
  }
39
38
  catch (e) {
40
39
  logError(e, { accountId: derivedAccountId });
@@ -19,14 +19,13 @@ import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDe
19
19
  import { isV2Project } from '../lib/projects/platformVersion.js';
20
20
  import { openLink } from '../lib/links.js';
21
21
  import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
22
- import { getEnv } from '@hubspot/local-dev-lib/config';
23
- import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
22
+ import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
24
23
  import { fetchPublicAppsForPortal } from '@hubspot/local-dev-lib/api/appsDev';
25
24
  const command = 'get-started';
26
25
  const describe = commands.getStarted.describe;
27
26
  async function handler(args) {
28
27
  const { derivedAccountId } = args;
29
- const env = getEnv(derivedAccountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD;
28
+ const env = getConfigAccountEnvironment(derivedAccountId);
30
29
  await trackCommandUsage('get-started', {}, derivedAccountId);
31
30
  const accountName = uiAccountDescription(derivedAccountId);
32
31
  uiInfoSection(commands.getStarted.startTitle, () => {
@@ -7,6 +7,7 @@ import { trackCommandUsage } from '../../../lib/usageTracking.js';
7
7
  import hubdbListCommand from '../list.js';
8
8
  vi.mock('../../../lib/commonOpts');
9
9
  vi.mock('@hubspot/local-dev-lib/api/hubdb');
10
+ vi.mock('@hubspot/local-dev-lib/config');
10
11
  vi.mock('../../../lib/ui/logger', () => ({
11
12
  uiLogger: {
12
13
  success: vi.fn(),
@@ -1,5 +1,5 @@
1
1
  import { fetchTables } from '@hubspot/local-dev-lib/api/hubdb';
2
- import { getEnv } from '@hubspot/local-dev-lib/config';
2
+ import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
3
3
  import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
4
4
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
5
5
  import { uiLogger } from '../../lib/ui/logger.js';
@@ -46,7 +46,7 @@ async function handler(args) {
46
46
  uiLogger.log(' ');
47
47
  // link devs to the hubdb page in hubspot for easy access
48
48
  // TODO: This is hacky, we should make a util like getBaseUrl()
49
- const baseUrl = getHubSpotWebsiteOrigin(getEnv());
49
+ const baseUrl = getHubSpotWebsiteOrigin(getConfigAccountEnvironment(derivedAccountId));
50
50
  uiLogger.log(commands.hubdb.subcommands.list.viewTablesLink(baseUrl, derivedAccountId));
51
51
  // don't bother showing an empty list of tables
52
52
  if (tables.length > 0) {
package/commands/init.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import path from 'path';
2
- import fs from 'fs-extra';
3
- import { loadConfig, getConfigPath, createEmptyConfigFile, deleteEmptyConfigFile, updateDefaultAccount, configFileExists, } from '@hubspot/local-dev-lib/config';
2
+ import { existsSync } from 'fs';
3
+ import { getConfigFilePath, createEmptyConfigFile, deleteConfigFileIfEmpty, setConfigAccountAsDefault, globalConfigFileExists, } from '@hubspot/local-dev-lib/config';
4
4
  import { OAUTH_AUTH_METHOD, PERSONAL_ACCESS_KEY_AUTH_METHOD, } from '@hubspot/local-dev-lib/constants/auth';
5
5
  import { checkAndAddConfigToGitignore } from '@hubspot/local-dev-lib/gitignore';
6
6
  import { DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME } from '@hubspot/local-dev-lib/constants/config';
@@ -8,7 +8,6 @@ import { getAccessToken, updateConfigWithAccessToken, } from '@hubspot/local-dev
8
8
  import { getCwd } from '@hubspot/local-dev-lib/path';
9
9
  import { toKebabCase } from '@hubspot/local-dev-lib/text';
10
10
  import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
11
- import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountIdentifier';
12
11
  import { setCLILogLevel } from '../lib/commonOpts.js';
13
12
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
14
13
  import { handleExit } from '../lib/process.js';
@@ -44,13 +43,21 @@ async function personalAccessKeyConfigCreationFlow(env, account) {
44
43
  }
45
44
  async function oauthConfigCreationFlow(env) {
46
45
  const configData = await promptUser(OAUTH_FLOW);
47
- const accountConfig = {
48
- ...configData,
46
+ const oauthAccount = {
47
+ name: configData.name,
48
+ accountId: configData.accountId,
49
+ authType: OAUTH_AUTH_METHOD.value,
49
50
  env,
51
+ auth: {
52
+ clientId: configData.clientId,
53
+ clientSecret: configData.clientSecret,
54
+ scopes: configData.scopes,
55
+ tokenInfo: {},
56
+ },
50
57
  };
51
- await authenticateWithOauth(accountConfig);
52
- updateDefaultAccount(accountConfig.name);
53
- return accountConfig;
58
+ await authenticateWithOauth(oauthAccount);
59
+ setConfigAccountAsDefault(configData.accountId);
60
+ return oauthAccount;
54
61
  }
55
62
  const AUTH_TYPE_NAMES = {
56
63
  [PERSONAL_ACCESS_KEY_AUTH_METHOD.value]: PERSONAL_ACCESS_KEY_AUTH_METHOD.name,
@@ -59,7 +66,7 @@ const AUTH_TYPE_NAMES = {
59
66
  const command = 'init';
60
67
  const describe = commands.init.describe;
61
68
  async function handler(args) {
62
- const { authType: authTypeFlagValue, c: configFlagValue, disableTracking, useHiddenConfig, userProvidedAccount, } = args;
69
+ const { authType: authTypeFlagValue, c: configFlagValue, disableTracking, userProvidedAccount, } = args;
63
70
  let parsedUserProvidedAccountId;
64
71
  try {
65
72
  if (userProvidedAccount) {
@@ -72,8 +79,13 @@ async function handler(args) {
72
79
  }
73
80
  const authType = (authTypeFlagValue && authTypeFlagValue.toLowerCase()) ||
74
81
  PERSONAL_ACCESS_KEY_AUTH_METHOD.value;
75
- const configPath = (configFlagValue && path.join(getCwd(), configFlagValue)) ||
76
- getConfigPath('', useHiddenConfig);
82
+ let existingConfigPath;
83
+ try {
84
+ existingConfigPath =
85
+ (configFlagValue && path.join(getCwd(), configFlagValue)) ||
86
+ getConfigFilePath();
87
+ }
88
+ catch (err) { }
77
89
  setCLILogLevel(args);
78
90
  if (!disableTracking) {
79
91
  trackCommandUsage('init', {
@@ -81,44 +93,36 @@ async function handler(args) {
81
93
  });
82
94
  }
83
95
  const env = args.qa ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD;
84
- if (configFileExists(true)) {
96
+ // Only check for global config if user is not providing a custom config path
97
+ if (!configFlagValue && globalConfigFileExists()) {
85
98
  uiLogger.error(commands.init.errors.globalConfigFileExists);
86
99
  process.exit(EXIT_CODES.ERROR);
87
100
  }
88
- if (fs.existsSync(configPath)) {
89
- uiLogger.error(commands.init.errors.configFileExists(configPath));
101
+ // Check if the specific config file path already exists
102
+ if (existingConfigPath && existsSync(existingConfigPath)) {
103
+ uiLogger.error(commands.init.errors.configFileExists(existingConfigPath));
90
104
  uiLogger.info(commands.init.logs.updateConfig);
91
105
  process.exit(EXIT_CODES.ERROR);
92
106
  }
93
107
  if (!disableTracking) {
94
108
  await trackAuthAction('init', authType, TRACKING_STATUS.STARTED, parsedUserProvidedAccountId);
95
109
  }
96
- const doesOtherConfigFileExist = configFileExists(!useHiddenConfig);
97
- if (doesOtherConfigFileExist) {
98
- const path = getConfigPath('', !useHiddenConfig);
99
- uiLogger.error(commands.init.errors.bothConfigFilesNotAllowed(path));
100
- process.exit(EXIT_CODES.ERROR);
101
- }
102
- createEmptyConfigFile({ path: configPath }, useHiddenConfig);
103
- //Needed to load deprecated config
104
- loadConfig(configPath, args);
105
- handleExit(deleteEmptyConfigFile);
110
+ createEmptyConfigFile(false);
111
+ handleExit(deleteConfigFileIfEmpty);
106
112
  try {
107
113
  let accountId;
108
114
  let name;
109
115
  if (authType === PERSONAL_ACCESS_KEY_AUTH_METHOD.value) {
110
116
  const personalAccessKeyResult = await personalAccessKeyConfigCreationFlow(env, parsedUserProvidedAccountId);
111
- if (personalAccessKeyResult) {
112
- accountId = getAccountIdentifier(personalAccessKeyResult);
113
- name = personalAccessKeyResult.name;
114
- }
117
+ accountId = personalAccessKeyResult.accountId;
118
+ name = personalAccessKeyResult.name;
115
119
  }
116
120
  else {
117
- const oauthResult = await oauthConfigCreationFlow(env);
118
- accountId = oauthResult.accountId;
119
- name = oauthResult.name;
121
+ const oauthAccount = await oauthConfigCreationFlow(env);
122
+ accountId = oauthAccount.accountId;
123
+ name = oauthAccount.name;
120
124
  }
121
- const configPath = getConfigPath();
125
+ const configPath = getConfigFilePath();
122
126
  try {
123
127
  checkAndAddConfigToGitignore(configPath);
124
128
  }
@@ -1,6 +1,5 @@
1
1
  import { HttpStatusCode } from 'axios';
2
2
  import yargs from 'yargs';
3
- import chalk from 'chalk';
4
3
  import * as configUtils from '@hubspot/local-dev-lib/config';
5
4
  import * as projectApiUtils from '@hubspot/local-dev-lib/api/projects';
6
5
  import * as ui from '../../../lib/ui/index.js';
@@ -17,6 +16,7 @@ import { mockHubSpotHttpResponse, mockHubSpotHttpError, } from '../../../lib/tes
17
16
  const exampleProject = loadJson(import.meta.url, './fixtures/exampleProject.json');
18
17
  import projectDeployCommand from '../deploy.js';
19
18
  import { uiLogger } from '../../../lib/ui/logger.js';
19
+ import chalk from 'chalk';
20
20
  vi.mock('@hubspot/local-dev-lib/api/projects');
21
21
  vi.mock('@hubspot/local-dev-lib/config');
22
22
  vi.mock('../../../lib/commonOpts');
@@ -38,7 +38,7 @@ const projectNamePromptSpy = vi.spyOn(projectNamePrompt, 'projectNamePrompt');
38
38
  const getProjectDetailUrlSpy = vi.spyOn(projectUrlUtils, 'getProjectDetailUrl');
39
39
  const fetchProjectSpy = vi.spyOn(projectApiUtils, 'fetchProject');
40
40
  const deployProjectSpy = vi.spyOn(projectApiUtils, 'deployProject');
41
- const getAccountConfigSpy = vi.spyOn(configUtils, 'getAccountConfig');
41
+ const getConfigAccountByIdSpy = vi.spyOn(configUtils, 'getConfigAccountById');
42
42
  const promptUserSpy = vi.spyOn(promptUtils, 'promptUser');
43
43
  const processExitSpy = vi.spyOn(process, 'exit');
44
44
  const optionsSpy = vi
@@ -137,7 +137,12 @@ describe('commands/project/deploy', () => {
137
137
  projectName: projectNameFromPrompt,
138
138
  });
139
139
  getProjectDetailUrlSpy.mockReturnValue(projectDetailUrl);
140
- getAccountConfigSpy.mockReturnValue({ accountType, env: 'qa' });
140
+ getConfigAccountByIdSpy.mockReturnValue({
141
+ accountId: 123,
142
+ name: 'SuperCoolTestAccount',
143
+ accountType,
144
+ env: 'qa',
145
+ });
141
146
  fetchProjectSpy.mockReturnValue(mockHubSpotHttpResponse(exampleProject));
142
147
  deployProjectSpy.mockReturnValue(mockHubSpotHttpResponse(deployDetails));
143
148
  // Spy on process.exit so our tests don't close when it's called
@@ -146,8 +151,8 @@ describe('commands/project/deploy', () => {
146
151
  });
147
152
  it('should load the account config for the correct account id', async () => {
148
153
  await projectDeployCommand.handler(args);
149
- expect(getAccountConfigSpy).toHaveBeenCalledTimes(1);
150
- expect(getAccountConfigSpy).toHaveBeenCalledWith(args.derivedAccountId);
154
+ expect(getConfigAccountByIdSpy).toHaveBeenCalledTimes(1);
155
+ expect(getConfigAccountByIdSpy).toHaveBeenCalledWith(args.derivedAccountId);
151
156
  });
152
157
  it('should track the command usage', async () => {
153
158
  await projectDeployCommand.handler(args);
@@ -1,7 +1,7 @@
1
1
  import path from 'path';
2
2
  import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
3
3
  import { translateForLocalDev } from '@hubspot/project-parsing-lib';
4
- import { getConfigAccounts, getAccountConfig, } from '@hubspot/local-dev-lib/config';
4
+ import { getAllConfigAccounts, getConfigAccountById, getConfigAccountEnvironment, } from '@hubspot/local-dev-lib/config';
5
5
  import { getValidEnv } from '@hubspot/local-dev-lib/environment';
6
6
  import { getServerPortByInstanceId } from '@hubspot/local-dev-lib/portManager';
7
7
  import { logError } from '../../../lib/errorHandlers/index.js';
@@ -75,6 +75,7 @@ describe('unifiedProjectDevFlow', () => {
75
75
  accountId: 123,
76
76
  name: 'test-account',
77
77
  accountType: HUBSPOT_ACCOUNT_TYPES.STANDARD,
78
+ env: ENVIRONMENTS.PROD,
78
79
  };
79
80
  const mockProject = {
80
81
  id: 1,
@@ -119,8 +120,9 @@ describe('unifiedProjectDevFlow', () => {
119
120
  translateForLocalDev.mockResolvedValue({
120
121
  intermediateNodesIndexedByUid: mockProjectNodes,
121
122
  });
122
- getAccountConfig.mockReturnValue(mockAccountConfig);
123
- getConfigAccounts.mockReturnValue([mockAccountConfig]);
123
+ getConfigAccountById.mockReturnValue(mockAccountConfig);
124
+ getConfigAccountEnvironment.mockReturnValue(ENVIRONMENTS.PROD);
125
+ getAllConfigAccounts.mockReturnValue([mockAccountConfig]);
124
126
  isUnifiedAccount.mockResolvedValue(true);
125
127
  isTestAccountOrSandbox.mockReturnValue(false);
126
128
  ensureProjectExists.mockResolvedValue({
@@ -210,7 +212,7 @@ describe('unifiedProjectDevFlow', () => {
210
212
  expect(uiLogger.error).toHaveBeenCalledWith(commands.project.dev.errors.noRunnableComponents);
211
213
  });
212
214
  it('should exit with error when account config not found', async () => {
213
- getAccountConfig.mockReturnValue(null);
215
+ getConfigAccountById.mockReturnValue(null);
214
216
  await expect(unifiedProjectDevFlow({
215
217
  args: mockArgs,
216
218
  targetProjectAccountId: mockTargetProjectAccountId,