@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
@@ -1,9 +1,9 @@
1
- import { logger } from '@hubspot/local-dev-lib/logger';
1
+ import { uiLogger } from '../../../ui/logger.js';
2
2
  import * as github from '@hubspot/local-dev-lib/api/github';
3
3
  import { EXIT_CODES } from '../../../enums/exitCodes.js';
4
4
  import { getProjectComponentListFromRepo, getProjectTemplateListFromRepo, } from '../legacy.js';
5
5
  import { PROJECT_COMPONENT_TYPES, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, } from '../../../constants.js';
6
- vi.mock('@hubspot/local-dev-lib/logger');
6
+ vi.mock('../../../ui/logger.js');
7
7
  vi.mock('@hubspot/local-dev-lib/api/github');
8
8
  const mockedFetchRepoFile = vi.mocked(github.fetchRepoFile);
9
9
  const repoConfig = {
@@ -60,14 +60,14 @@ describe('lib/projects/create/legacy', () => {
60
60
  it('Logs an error and exits the process if the request for the template list fails', async () => {
61
61
  mockedFetchRepoFile.mockRejectedValue(new Error('Not found'));
62
62
  await getProjectTemplateListFromRepo(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, 'gh-ref');
63
- expect(logger.error).toHaveBeenCalledWith(expect.stringMatching(/Failed to fetch the config.json file from the target repository/));
63
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/Failed to fetch the config.json file from the target repository/));
64
64
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
65
65
  });
66
66
  it('Logs an error and exits the process if there are no projects listed in the repo config', async () => {
67
67
  // @ts-expect-error - Mocking AxiosResponse
68
68
  mockedFetchRepoFile.mockResolvedValue({});
69
69
  await getProjectTemplateListFromRepo(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, 'gh-ref');
70
- expect(logger.error).toHaveBeenCalledWith(expect.stringMatching(/Unable to find any projects in the target repository's config.json file/));
70
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/Unable to find any projects in the target repository's config.json file/));
71
71
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
72
72
  });
73
73
  it('Logs an error and exits the process if any of the projects in the repo config are missing required properties', async () => {
@@ -84,7 +84,7 @@ describe('lib/projects/create/legacy', () => {
84
84
  },
85
85
  });
86
86
  await getProjectTemplateListFromRepo(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, 'gh-ref');
87
- expect(logger.error).toHaveBeenCalledWith(expect.stringMatching(/Found misconfigured projects in the target repository's config.json file/));
87
+ expect(uiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/Found misconfigured projects in the target repository's config.json file/));
88
88
  expect(exitMock).toHaveBeenCalledWith(EXIT_CODES.ERROR);
89
89
  });
90
90
  });
@@ -1,6 +1,6 @@
1
1
  import { calculateComponentTemplateChoices } from '../v3.js';
2
2
  import { hasFeature } from '../../../hasFeature.js';
3
- vi.mock('@hubspot/local-dev-lib/logger');
3
+ vi.mock('../../ui/logger.js');
4
4
  vi.mock('@hubspot/local-dev-lib/api/github');
5
5
  vi.mock('../../../hasFeature.js');
6
6
  const mockHasFeature = vi.mocked(hasFeature);
@@ -1,7 +1,7 @@
1
1
  import { selectProjectTemplatePrompt, } from '../../prompts/selectProjectTemplatePrompt.js';
2
2
  import { projectNameAndDestPrompt } from '../../prompts/projectNameAndDestPrompt.js';
3
3
  import { DEFAULT_PROJECT_TEMPLATE_BRANCH, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, EMPTY_PROJECT, } from '../../constants.js';
4
- import { useV3Api } from '../platformVersion.js';
4
+ import { isV2Project } from '../platformVersion.js';
5
5
  import { v3ComponentFlow } from './v3.js';
6
6
  import { getProjectTemplateListFromRepo } from './legacy.js';
7
7
  import { uiLogger } from '../../ui/logger.js';
@@ -11,7 +11,7 @@ export async function handleProjectCreationFlow(args) {
11
11
  const { platformVersion, templateSource, projectBase, auth: providedAuth, distribution: providedDistribution, } = args;
12
12
  const repo = templateSource || HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
13
13
  const projectNameAndDestPromptResponse = await projectNameAndDestPrompt(args);
14
- if (useV3Api(platformVersion)) {
14
+ if (isV2Project(platformVersion)) {
15
15
  const { componentTemplateChoices, authType, distribution, repoConfig, projectContents, } = await v3ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution, args.derivedAccountId);
16
16
  const selectProjectTemplatePromptResponse = await selectProjectTemplatePrompt(args, undefined, projectContents !== EMPTY_PROJECT ? componentTemplateChoices : undefined);
17
17
  return {
@@ -3,13 +3,13 @@ import { DEFAULT_PROJECT_TEMPLATE_BRANCH, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH
3
3
  import { EXIT_CODES } from '../../enums/exitCodes.js';
4
4
  import { debugError } from '../../errorHandlers/index.js';
5
5
  import { uiLogger } from '../../ui/logger.js';
6
- import { useV3Api } from '../platformVersion.js';
6
+ import { isV2Project } from '../platformVersion.js';
7
7
  import { lib } from '../../../lang/en.js';
8
8
  const PROJECT_TEMPLATE_PROPERTIES = ['name', 'label', 'path'];
9
9
  export const EMPTY_PROJECT_TEMPLATE_NAME = 'no-template';
10
10
  export async function getConfigForPlatformVersion(platformVersion) {
11
11
  let path = '';
12
- if (useV3Api(platformVersion)) {
12
+ if (isV2Project(platformVersion)) {
13
13
  path = `${platformVersion}/`;
14
14
  }
15
15
  const { data } = await fetchRepoFile(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, `${path}config.json`, DEFAULT_PROJECT_TEMPLATE_BRANCH);
@@ -3,7 +3,7 @@ import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, EMPTY_
3
3
  import { commands, lib } from '../../../lang/en.js';
4
4
  import { listPrompt } from '../../prompts/promptUtils.js';
5
5
  import chalk from 'chalk';
6
- import { useV3Api } from '../platformVersion.js';
6
+ import { isV2Project } from '../platformVersion.js';
7
7
  import path from 'path';
8
8
  import { getConfigForPlatformVersion } from './legacy.js';
9
9
  import { logError } from '../../errorHandlers/index.js';
@@ -148,7 +148,7 @@ export async function v3ComponentFlow(platformVersion, projectBase, providedAuth
148
148
  };
149
149
  }
150
150
  export function generateComponentPaths({ selectProjectTemplatePromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }) {
151
- if (!useV3Api(platformVersion)) {
151
+ if (!isV2Project(platformVersion)) {
152
152
  return [];
153
153
  }
154
154
  const components = selectProjectTemplatePromptResponse.componentTemplates?.map((componentTemplate) => {
@@ -15,6 +15,8 @@ declare class AppDevModeInterface {
15
15
  private get appNode();
16
16
  private get appData();
17
17
  private set appData(value);
18
+ private isStaticAuthApp;
19
+ private isOAuthApp;
18
20
  private getAppInstallUrl;
19
21
  private fetchAppData;
20
22
  private checkMarketplaceAppInstalls;
@@ -1,5 +1,5 @@
1
1
  import { fetchAppInstallationData } from '@hubspot/local-dev-lib/api/localDevAuth';
2
- import { fetchPublicAppsForPortal, fetchPublicAppProductionInstallCounts,
2
+ import { fetchAppMetadataByUid, fetchPublicAppProductionInstallCounts,
3
3
  // installStaticAuthAppOnTestAccount,
4
4
  } from '@hubspot/local-dev-lib/api/appsDev';
5
5
  import { DevModeUnifiedInterface as UIEDevModeInterface } from '@hubspot/ui-extensions-dev-server';
@@ -54,6 +54,12 @@ class AppDevModeInterface {
54
54
  }
55
55
  this.localDevState.setAppDataForUid(this.appNode.uid, appData);
56
56
  }
57
+ isStaticAuthApp() {
58
+ return (this.appNode?.config.auth.type.toLowerCase() === APP_AUTH_TYPES.STATIC);
59
+ }
60
+ isOAuthApp() {
61
+ return (this.appNode?.config.auth.type.toLowerCase() === APP_AUTH_TYPES.OAUTH);
62
+ }
57
63
  // @TODO: Restore test account auto install functionality
58
64
  // private isAutomaticallyInstallable(): boolean {
59
65
  // const targetTestingAccount = getAccountConfig(
@@ -71,11 +77,11 @@ class AppDevModeInterface {
71
77
  // return (
72
78
  // isTestAccount &&
73
79
  // hasCorrectParent &&
74
- // this.appNode?.config.auth.type === APP_AUTH_TYPES.STATIC
80
+ // this.isStaticAuthApp()
75
81
  // );
76
82
  // }
77
83
  async getAppInstallUrl() {
78
- if (this.appNode?.config.auth.type.toLowerCase() === APP_AUTH_TYPES.OAUTH) {
84
+ if (this.appNode && this.isOAuthApp()) {
79
85
  return getOauthAppInstallUrl({
80
86
  targetAccountId: this.localDevState.targetTestingAccountId,
81
87
  env: this.localDevState.env,
@@ -84,26 +90,20 @@ class AppDevModeInterface {
84
90
  redirectUrls: this.appNode.config.auth.redirectUrls,
85
91
  });
86
92
  }
87
- const { data: { results }, } = await fetchPublicAppsForPortal(this.localDevState.targetProjectAccountId);
88
- const app = results.find(app => app.sourceId === this.appNode?.uid);
89
- if (!app) {
90
- uiLogger.error(lib.LocalDevManager.appNotFound(this.localDevState.targetProjectAccountId, this.appNode?.uid));
91
- process.exit(EXIT_CODES.ERROR);
92
- }
93
93
  return getStaticAuthAppInstallUrl({
94
94
  targetAccountId: this.localDevState.targetTestingAccountId,
95
95
  env: this.localDevState.env,
96
- appId: app.id,
96
+ appId: this.appData.id,
97
97
  });
98
98
  }
99
99
  async fetchAppData() {
100
100
  SpinniesManager.add('fetchAppData', {
101
101
  text: lib.AppDevModeInterface.fetchAppData.checking(this.appNode?.config.name || ''),
102
102
  });
103
- let portalApps = [];
103
+ let appData;
104
104
  try {
105
- const { data: { results }, } = await fetchPublicAppsForPortal(this.localDevState.targetProjectAccountId);
106
- portalApps = results;
105
+ const { data } = await fetchAppMetadataByUid(this.appNode.uid, this.localDevState.targetProjectAccountId);
106
+ appData = data;
107
107
  }
108
108
  catch (e) {
109
109
  SpinniesManager.fail('fetchAppData', {
@@ -112,7 +112,6 @@ class AppDevModeInterface {
112
112
  logError(e);
113
113
  process.exit(EXIT_CODES.ERROR);
114
114
  }
115
- const appData = portalApps.find(({ sourceId }) => sourceId === this.appNode?.uid);
116
115
  if (!appData) {
117
116
  return;
118
117
  }
@@ -177,13 +176,16 @@ class AppDevModeInterface {
177
176
  // );
178
177
  // }
179
178
  // }
179
+ const staticAuthInstallOptions = this.isStaticAuthApp()
180
+ ? {
181
+ testingAccountId: this.localDevState.targetTestingAccountId,
182
+ projectAccountId: this.localDevState.targetProjectAccountId,
183
+ projectName: this.localDevState.projectConfig.name,
184
+ appUid: this.appNode.uid,
185
+ }
186
+ : undefined;
180
187
  const installUrl = await this.getAppInstallUrl();
181
- await installAppBrowserPrompt(installUrl, isReinstall, {
182
- testingAccountId: this.localDevState.targetTestingAccountId,
183
- projectAccountId: this.localDevState.targetProjectAccountId,
184
- projectName: this.localDevState.projectConfig.name,
185
- appUid: this.appNode.uid,
186
- });
188
+ await installAppBrowserPrompt(installUrl, isReinstall, staticAuthInstallOptions);
187
189
  }
188
190
  async checkTestAccountAppInstallation() {
189
191
  if (!this.appNode || !this.appData) {
@@ -1,6 +1,5 @@
1
1
  import { getAccountId, hasLocalStateFlag } from '@hubspot/local-dev-lib/config';
2
2
  import { getConfigDefaultAccount } from '@hubspot/local-dev-lib/config';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
4
3
  import { uiLogger } from '../../ui/logger.js';
5
4
  import { uiBetaTag, uiLine, uiAccountDescription, uiCommandReference, } from '../../ui/index.js';
6
5
  import { lib } from '../../../lang/en.js';
@@ -26,7 +25,7 @@ class LocalDevLogger {
26
25
  }
27
26
  handleError(e, langFunction) {
28
27
  if (this.state.debug) {
29
- logger.error(e);
28
+ uiLogger.error(e instanceof Error ? e.message : String(e));
30
29
  }
31
30
  uiLogger.error(langFunction(e instanceof Error ? e.message : ''));
32
31
  }
@@ -119,35 +118,35 @@ class LocalDevLogger {
119
118
  uiLogger.log(lib.LocalDevProcess.projectConfigMismatch);
120
119
  }
121
120
  uploadError(error) {
122
- logger.log('');
121
+ uiLogger.log('');
123
122
  logError(error);
124
123
  uiLogger.log(lib.LocalDevProcess.uploadFailed);
125
- logger.log('');
124
+ uiLogger.log('');
126
125
  }
127
126
  uploadSuccess() {
128
- logger.log('');
127
+ uiLogger.log('');
129
128
  uiLogger.log(lib.LocalDevProcess.uploadSuccess);
130
129
  uiLine();
131
- logger.log('');
130
+ uiLogger.log('');
132
131
  }
133
132
  uploadSuccessAutoDeployDisabled() {
134
133
  uiLogger.warn(lib.LocalDevProcess.uploadSuccessAutoDeployDisabled);
135
134
  uiLine();
136
- logger.log('');
135
+ uiLogger.log('');
137
136
  }
138
137
  deployError(error) {
139
- logger.log('');
138
+ uiLogger.log('');
140
139
  if (error) {
141
140
  logError(error);
142
141
  }
143
142
  uiLogger.log(lib.LocalDevProcess.deployFailed);
144
- logger.log('');
143
+ uiLogger.log('');
145
144
  }
146
145
  deploySuccess() {
147
- logger.log('');
146
+ uiLogger.log('');
148
147
  uiLogger.log(lib.LocalDevProcess.deploySuccess);
149
148
  uiLine();
150
- logger.log('');
149
+ uiLogger.log('');
151
150
  }
152
151
  monitorConsoleOutput() {
153
152
  const originalStdoutWrite = process.stdout.write.bind(process.stdout);
@@ -4,7 +4,6 @@ import chalk from 'chalk';
4
4
  import { fetchAppInstallationData } from '@hubspot/local-dev-lib/api/localDevAuth';
5
5
  import { fetchPublicAppsForPortal, fetchPublicAppProductionInstallCounts, } from '@hubspot/local-dev-lib/api/appsDev';
6
6
  import { getAccountId, getConfigDefaultAccount, } from '@hubspot/local-dev-lib/config';
7
- import { logger } from '@hubspot/local-dev-lib/logger';
8
7
  import { PROJECT_CONFIG_FILE } from '../../constants.js';
9
8
  import SpinniesManager from '../../ui/SpinniesManager.js';
10
9
  import DevServerManager from './DevServerManager.js';
@@ -324,7 +323,7 @@ class LocalDevManager {
324
323
  }
325
324
  catch (e) {
326
325
  if (this.debug) {
327
- logger.error(e);
326
+ uiLogger.error(e instanceof Error ? e.message : String(e));
328
327
  }
329
328
  uiLogger.error(lib.LocalDevManager.devServer.setupError(e instanceof Error ? e.message : ''));
330
329
  return false;
@@ -339,7 +338,7 @@ class LocalDevManager {
339
338
  }
340
339
  catch (e) {
341
340
  if (this.debug) {
342
- logger.error(e);
341
+ uiLogger.error(e instanceof Error ? e.message : String(e));
343
342
  }
344
343
  uiLogger.error(lib.LocalDevManager.devServer.startError(e instanceof Error ? e.message : ''));
345
344
  process.exit(EXIT_CODES.ERROR);
@@ -351,7 +350,7 @@ class LocalDevManager {
351
350
  }
352
351
  catch (e) {
353
352
  if (this.debug) {
354
- logger.error(e);
353
+ uiLogger.error(e instanceof Error ? e.message : String(e));
355
354
  }
356
355
  uiLogger.error(lib.LocalDevManager.devServer.fileChangeError(e instanceof Error ? e.message : ''));
357
356
  }
@@ -363,7 +362,7 @@ class LocalDevManager {
363
362
  }
364
363
  catch (e) {
365
364
  if (this.debug) {
366
- logger.error(e);
365
+ uiLogger.error(e instanceof Error ? e.message : String(e));
367
366
  }
368
367
  uiLogger.error(lib.LocalDevManager.devServer.cleanupError(e instanceof Error ? e.message : ''));
369
368
  return false;
@@ -3,7 +3,6 @@ declare class LocalDevWebsocketServer {
3
3
  private server?;
4
4
  private debug?;
5
5
  private localDevProcess;
6
- private ALLOWED_ORIGINS;
7
6
  constructor(localDevProcess: LocalDevProcess, debug?: boolean);
8
7
  private log;
9
8
  private logError;
@@ -1,6 +1,6 @@
1
1
  import { WebSocketServer } from 'ws';
2
2
  import { isPortManagerServerRunning, requestPorts, } from '@hubspot/local-dev-lib/portManager';
3
- import { logger } from '@hubspot/local-dev-lib/logger';
3
+ import { uiLogger } from '../../ui/logger.js';
4
4
  import { addLocalStateFlag } from '@hubspot/local-dev-lib/config';
5
5
  import { LOCAL_DEV_UI_MESSAGE_SEND_TYPES, LOCAL_DEV_SERVER_MESSAGE_TYPES, CONFIG_LOCAL_STATE_FLAGS, } from '../../constants.js';
6
6
  import { lib } from '../../../lang/en.js';
@@ -10,28 +10,25 @@ import pkg from '../../../package.json' with { type: 'json' };
10
10
  const SERVER_INSTANCE_ID = 'local-dev-ui-websocket-server';
11
11
  const LOCAL_DEV_WEBSOCKET_SERVER_VERSION = 1;
12
12
  const LOG_PREFIX = '[LocalDevWebsocketServer]';
13
+ const DOMAINS = ['hubspot.com', 'hubspotqa.com'];
14
+ const SUBDOMAINS = ['local', 'app', 'app-na2', 'app-na3', 'app-ap1', 'app-eu1'];
15
+ const ALLOWED_ORIGIN_REGEX = new RegExp(`^https://(${SUBDOMAINS.join('|')})\\.(${DOMAINS.join('|')})$`);
13
16
  class LocalDevWebsocketServer {
14
17
  server;
15
18
  debug;
16
19
  localDevProcess;
17
- ALLOWED_ORIGINS = [
18
- 'https://app.hubspot.com',
19
- 'https://app.hubspotqa.com',
20
- 'https://local.hubspot.com',
21
- 'https://local.hubspotqa.com',
22
- ];
23
20
  constructor(localDevProcess, debug) {
24
21
  this.localDevProcess = localDevProcess;
25
22
  this.debug = debug;
26
23
  }
27
24
  log(message) {
28
25
  if (this.debug) {
29
- logger.log(LOG_PREFIX, message);
26
+ uiLogger.log(`${LOG_PREFIX} ${message}`);
30
27
  }
31
28
  }
32
29
  logError(message) {
33
30
  if (this.debug) {
34
- logger.error(LOG_PREFIX, message);
31
+ uiLogger.error(`${LOG_PREFIX} ${message}`);
35
32
  }
36
33
  }
37
34
  sendMessage(websocket, message) {
@@ -166,7 +163,7 @@ class LocalDevWebsocketServer {
166
163
  this.log(lib.LocalDevWebsocketServer.logs.startup(port));
167
164
  this.server.on('connection', (ws, req) => {
168
165
  const origin = req.headers.origin;
169
- if (!origin || !this.ALLOWED_ORIGINS.includes(origin)) {
166
+ if (!origin || !ALLOWED_ORIGIN_REGEX.test(origin)) {
170
167
  ws.close(1008, lib.LocalDevWebsocketServer.errors.originNotAllowed(origin));
171
168
  return;
172
169
  }
@@ -10,3 +10,4 @@ export declare function compareLocalProjectToDeployed(projectConfig: ProjectConf
10
10
  export declare function isDeployedProjectUpToDateWithLocal(projectConfig: ProjectConfig, accountId: number, deployedBuildId: number, localProjectNodes: {
11
11
  [key: string]: IntermediateRepresentationNodeLocalDev;
12
12
  }, profile?: string): Promise<boolean>;
13
+ export declare function checkAndInstallDependencies(): Promise<void>;
@@ -20,6 +20,7 @@ import { handleProjectUpload } from '../../upload.js';
20
20
  import { pollProjectBuildAndDeploy } from '../../pollProjectBuildAndDeploy.js';
21
21
  import { debugError, logError } from '../../../errorHandlers/index.js';
22
22
  import { ApiErrorContext } from '../../../errorHandlers/index.js';
23
+ import { getProjectPackageJsonLocations, hasMissingPackages, installPackages, } from '../../../dependencyManagement.js';
23
24
  // Prompt the user to create a new project if one doesn't exist on their target account
24
25
  export async function createNewProjectForLocalDev(projectConfig, targetAccountId, shouldCreateWithoutConfirmation, hasPublicApps) {
25
26
  // Create the project without prompting if this is a newly created sandbox
@@ -174,3 +175,39 @@ export async function isDeployedProjectUpToDateWithLocal(projectConfig, accountI
174
175
  }
175
176
  }
176
177
  }
178
+ export async function checkAndInstallDependencies() {
179
+ SpinniesManager.init();
180
+ uiLogger.log('');
181
+ SpinniesManager.add('checkingDependencies', {
182
+ text: lib.localDevHelpers.project.checkAndInstallDependencies
183
+ .checkingDependencies,
184
+ });
185
+ try {
186
+ const installLocations = await getProjectPackageJsonLocations();
187
+ const locationsToInstall = [];
188
+ for (const location of installLocations) {
189
+ if (await hasMissingPackages(location)) {
190
+ locationsToInstall.push(location);
191
+ }
192
+ }
193
+ if (locationsToInstall.length > 0) {
194
+ SpinniesManager.remove('checkingDependencies');
195
+ await installPackages({ installLocations: locationsToInstall });
196
+ }
197
+ else {
198
+ SpinniesManager.succeed('checkingDependencies', {
199
+ text: lib.localDevHelpers.project.checkAndInstallDependencies
200
+ .dependenciesUpToDate,
201
+ });
202
+ }
203
+ uiLogger.log('');
204
+ }
205
+ catch (e) {
206
+ logError(e);
207
+ SpinniesManager.fail('checkingDependencies', {
208
+ text: lib.localDevHelpers.project.checkAndInstallDependencies
209
+ .dependenciesFailure,
210
+ });
211
+ process.exit(EXIT_CODES.ERROR);
212
+ }
213
+ }
@@ -1 +1 @@
1
- export declare function useV3Api(platformVersion?: string | null): boolean;
1
+ export declare function isV2Project(platformVersion?: string | null): boolean;
@@ -1,4 +1,4 @@
1
- export function useV3Api(platformVersion) {
1
+ export function isV2Project(platformVersion) {
2
2
  if (!platformVersion || typeof platformVersion !== 'string') {
3
3
  return false;
4
4
  }
@@ -1,5 +1,5 @@
1
1
  import { ComponentTypes, Component, GenericComponentConfig, PublicAppComponentConfig, PrivateAppComponentConfig, AppCardComponentConfig } from '../../types/Projects.js';
2
- import { IntermediateRepresentationNode, IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types.js';
2
+ import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types.js';
3
3
  import { AppIRNode } from '../../types/ProjectComponents.js';
4
4
  export declare const CONFIG_FILES: {
5
5
  [k in ComponentTypes]: string;
@@ -15,4 +15,4 @@ export declare function getProjectComponentTypes(components: Array<Component>):
15
15
  export declare function getComponentUid(component?: Component | null): string | null;
16
16
  export declare function componentIsApp(component?: Component | null): component is Component<PublicAppComponentConfig | PrivateAppComponentConfig>;
17
17
  export declare function componentIsPublicApp(component?: Component | null): component is Component<PublicAppComponentConfig>;
18
- export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev | IntermediateRepresentationNode): component is AppIRNode;
18
+ export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev): component is AppIRNode;
@@ -1,14 +1,14 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { walk } from '@hubspot/local-dev-lib/fs';
4
- import { logger } from '@hubspot/local-dev-lib/logger';
4
+ import { uiLogger } from '../ui/logger.js';
5
5
  import { logError } from '../errorHandlers/index.js';
6
6
  import { ComponentTypes, } from '../../types/Projects.js';
7
- import { IR_COMPONENT_TYPES } from '../constants.js';
7
+ import { IR_COMPONENT_TYPES, LEGACY_PRIVATE_APP_FILE, LEGACY_PUBLIC_APP_FILE, THEME_FILE, } from '../constants.js';
8
8
  export const CONFIG_FILES = {
9
- [ComponentTypes.PrivateApp]: 'app.json',
10
- [ComponentTypes.PublicApp]: 'public-app.json',
11
- [ComponentTypes.HublTheme]: 'theme.json',
9
+ [ComponentTypes.PrivateApp]: LEGACY_PRIVATE_APP_FILE,
10
+ [ComponentTypes.PublicApp]: LEGACY_PUBLIC_APP_FILE,
11
+ [ComponentTypes.HublTheme]: THEME_FILE,
12
12
  };
13
13
  export function getComponentTypeFromConfigFile(configFile) {
14
14
  let key;
@@ -27,7 +27,7 @@ export function loadConfigFile(configPath) {
27
27
  return parsedConfig;
28
28
  }
29
29
  catch (e) {
30
- logger.debug(e);
30
+ uiLogger.debug(e);
31
31
  }
32
32
  }
33
33
  return null;
@@ -1,5 +1,4 @@
1
1
  import { FileResult } from 'tmp';
2
- import { IntermediateRepresentation } from '@hubspot/project-parsing-lib';
3
2
  import { ProjectConfig } from '../../types/Projects.js';
4
3
  type ProjectUploadCallbackFunction<T> = (accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number) => Promise<T>;
5
4
  type ProjectUploadResult<T> = {
@@ -19,7 +18,7 @@ type HandleProjectUploadArg<T> = {
19
18
  profile?: string;
20
19
  };
21
20
  export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
22
- export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig): void;
21
+ export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig, projectDir: string): Promise<void>;
23
22
  export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
24
- export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<IntermediateRepresentation | undefined>;
23
+ export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<unknown>;
25
24
  export {};
@@ -12,9 +12,11 @@ import util from 'node:util';
12
12
  import { lib } from '../../lang/en.js';
13
13
  import { ensureProjectExists } from './ensureProjectExists.js';
14
14
  import { uiLogger } from '../ui/logger.js';
15
- import { useV3Api } from './platformVersion.js';
15
+ import { isV2Project } from './platformVersion.js';
16
16
  import { EXIT_CODES } from '../enums/exitCodes.js';
17
17
  import ProjectValidationError from '../errors/ProjectValidationError.js';
18
+ import { walk } from '@hubspot/local-dev-lib/fs';
19
+ import { LEGACY_CONFIG_FILES } from '../constants.js';
18
20
  async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
19
21
  SpinniesManager.init({});
20
22
  const accountIdentifier = uiAccountDescription(accountId) || `${accountId}`;
@@ -45,7 +47,7 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
45
47
  export async function handleProjectUpload({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage = '', forceCreate = false, isUploadCommand = false, sendIR = false, skipValidation = false, }) {
46
48
  const srcDir = path.resolve(projectDir, projectConfig.srcDir);
47
49
  try {
48
- validateSourceDirectory(srcDir, projectConfig);
50
+ await validateSourceDirectory(srcDir, projectConfig, projectDir);
49
51
  }
50
52
  catch (e) {
51
53
  logError(e);
@@ -70,8 +72,7 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
70
72
  intermediateRepresentation = await handleTranslate(projectDir, projectConfig, accountId, skipValidation, profile);
71
73
  }
72
74
  catch (e) {
73
- logError(e);
74
- process.exit(EXIT_CODES.ERROR);
75
+ resolve({ uploadError: e });
75
76
  }
76
77
  }
77
78
  await ensureProjectExists(accountId, projectConfig.name, {
@@ -105,15 +106,23 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
105
106
  archive.finalize();
106
107
  return result;
107
108
  }
108
- export function validateSourceDirectory(srcDir, projectConfig) {
109
- const filenames = fs.readdirSync(srcDir);
110
- if (!filenames || filenames.length === 0) {
109
+ export async function validateSourceDirectory(srcDir, projectConfig, projectDir) {
110
+ const projectFilePaths = await walk(srcDir, ['node_modules']);
111
+ if (!projectFilePaths || projectFilePaths.length === 0) {
111
112
  throw new ProjectValidationError(lib.projectUpload.handleProjectUpload.emptySource(projectConfig.srcDir));
112
113
  }
114
+ if (isV2Project(projectConfig.platformVersion)) {
115
+ projectFilePaths.forEach(filePath => {
116
+ const filename = path.basename(filePath);
117
+ if (LEGACY_CONFIG_FILES.includes(filename)) {
118
+ uiLogger.warn(lib.projectUpload.handleProjectUpload.legacyFileDetected(path.relative(projectDir, filePath), projectConfig.platformVersion));
119
+ }
120
+ });
121
+ }
113
122
  }
114
123
  export async function validateNoHSMetaMismatch(srcDir, projectConfig) {
115
124
  const hasHsMetaFiles = await projectContainsHsMetaFiles(srcDir);
116
- if (!useV3Api(projectConfig.platformVersion) && hasHsMetaFiles) {
125
+ if (!isV2Project(projectConfig.platformVersion) && hasHsMetaFiles) {
117
126
  throw new ProjectValidationError(lib.projectUpload.wrongPlatformVersionMetaFiles);
118
127
  }
119
128
  }
@@ -133,5 +142,4 @@ export async function handleTranslate(projectDir, projectConfig, accountId, skip
133
142
  }
134
143
  throw e;
135
144
  }
136
- return undefined;
137
145
  }
@@ -11,6 +11,7 @@ vi.mock('@hubspot/local-dev-lib/api/projects', () => ({
11
11
  }));
12
12
  vi.mock('@hubspot/local-dev-lib/config', () => ({
13
13
  getAccountId: vi.fn().mockImplementation(() => 123456789),
14
+ configFileExists: vi.fn().mockImplementation(() => true),
14
15
  }));
15
16
  describe('lib/prompts/downloadProjectPrompt', () => {
16
17
  it('should honor the account passed as an option', async () => {