@hubspot/cli 7.8.0-beta.0 → 7.8.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/commands/__tests__/project.test.js +2 -0
  2. package/commands/account/auth.js +1 -0
  3. package/commands/auth.js +1 -0
  4. package/commands/feedback.js +1 -1
  5. package/commands/project/__tests__/add.test.js +12 -12
  6. package/commands/project/__tests__/list.test.js +31 -0
  7. package/commands/project/__tests__/migrate.test.js +1 -0
  8. package/commands/project/add.d.ts +2 -2
  9. package/commands/project/add.js +3 -2
  10. package/commands/project/create.js +1 -1
  11. package/commands/project/dev/deprecatedFlow.js +2 -2
  12. package/commands/project/dev/index.js +5 -5
  13. package/commands/project/dev/unifiedFlow.js +6 -3
  14. package/commands/project/download.js +5 -2
  15. package/commands/project/installDeps.d.ts +2 -2
  16. package/commands/project/installDeps.js +1 -0
  17. package/commands/project/list.d.ts +4 -0
  18. package/commands/project/list.js +62 -0
  19. package/commands/project/migrate.js +5 -2
  20. package/commands/project.js +2 -0
  21. package/commands/sandbox/delete.js +5 -2
  22. package/commands/testAccount/create.js +2 -2
  23. package/commands/theme/preview.js +1 -4
  24. package/lang/en.d.ts +49 -14
  25. package/lang/en.js +121 -86
  26. package/lang/en.lyaml +2 -2
  27. package/lib/__tests__/buildAccount.test.js +2 -2
  28. package/lib/app/migrate.js +1 -1
  29. package/lib/buildAccount.d.ts +2 -2
  30. package/lib/buildAccount.js +7 -7
  31. package/lib/configMigrate.js +88 -9
  32. package/lib/constants.d.ts +8 -1
  33. package/lib/constants.js +8 -1
  34. package/lib/doctor/Doctor.js +2 -2
  35. package/lib/errorHandlers/suppressError.js +2 -2
  36. package/lib/middleware/commandTargetingUtils.d.ts +1 -1
  37. package/lib/middleware/commandTargetingUtils.js +16 -20
  38. package/lib/projects/__tests__/AppDevModeInterface.test.js +85 -90
  39. package/lib/projects/__tests__/LocalDevProcess.test.js +6 -5
  40. package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +6 -6
  41. package/lib/projects/__tests__/deploy.test.js +9 -9
  42. package/lib/projects/__tests__/upload.test.js +2 -2
  43. package/lib/projects/add/__tests__/{v3AddComponent.test.js → v2AddComponent.test.js} +35 -35
  44. package/lib/projects/add/{v3AddComponent.d.ts → v2AddComponent.d.ts} +1 -1
  45. package/lib/projects/add/{v3AddComponent.js → v2AddComponent.js} +5 -5
  46. package/lib/projects/create/__tests__/v2.test.d.ts +1 -0
  47. package/lib/projects/create/__tests__/{v3.test.js → v2.test.js} +2 -2
  48. package/lib/projects/create/index.js +2 -2
  49. package/lib/projects/create/{v3.d.ts → v2.d.ts} +3 -3
  50. package/lib/projects/create/{v3.js → v2.js} +3 -3
  51. package/lib/projects/deploy.d.ts +1 -1
  52. package/lib/projects/deploy.js +2 -2
  53. package/lib/projects/localDev/AppDevModeInterface.d.ts +8 -1
  54. package/lib/projects/localDev/AppDevModeInterface.js +106 -86
  55. package/lib/projects/localDev/DevServerManager.d.ts +11 -29
  56. package/lib/projects/localDev/DevServerManager.js +19 -61
  57. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +40 -0
  58. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +120 -0
  59. package/lib/projects/localDev/{LocalDevManager.js → LocalDevManager_DEPRECATED.js} +6 -6
  60. package/lib/projects/localDev/LocalDevProcess.js +3 -2
  61. package/lib/projects/localDev/LocalDevState.d.ts +3 -0
  62. package/lib/projects/localDev/LocalDevState.js +9 -0
  63. package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +4 -0
  64. package/lib/projects/localDev/LocalDevWebsocketServer.js +34 -2
  65. package/lib/projects/localDev/helpers/account.d.ts +1 -1
  66. package/lib/projects/localDev/helpers/account.js +2 -2
  67. package/lib/projects/localDev/helpers/project.js +2 -3
  68. package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +3 -0
  69. package/lib/projects/localDev/localDevWebsocketServerUtils.js +9 -0
  70. package/lib/projects/urls.d.ts +0 -1
  71. package/lib/projects/urls.js +0 -3
  72. package/lib/prompts/__tests__/downloadProjectPrompt.test.js +1 -0
  73. package/lib/prompts/__tests__/projectAddPrompt.test.js +10 -10
  74. package/lib/prompts/installAppPrompt.d.ts +1 -6
  75. package/lib/prompts/installAppPrompt.js +1 -6
  76. package/lib/prompts/projectAddPrompt.d.ts +2 -2
  77. package/lib/prompts/projectAddPrompt.js +1 -1
  78. package/lib/prompts/projectDevTargetAccountPrompt.js +1 -1
  79. package/lib/theme/__tests__/migrate.test.js +4 -4
  80. package/lib/ui/index.d.ts +4 -0
  81. package/lib/ui/index.js +9 -1
  82. package/lib/ui/uiMessages.d.ts +4 -0
  83. package/lib/ui/uiMessages.js +4 -0
  84. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
  85. package/package.json +6 -5
  86. package/lib/projects/localDev/DevServerManagerV2.d.ts +0 -22
  87. package/lib/projects/localDev/DevServerManagerV2.js +0 -81
  88. /package/{lib/projects/add/__tests__/v3AddComponent.test.d.ts → commands/project/__tests__/list.test.d.ts} +0 -0
  89. /package/lib/projects/{create/__tests__/v3.test.d.ts → add/__tests__/v2AddComponent.test.d.ts} +0 -0
  90. /package/lib/projects/localDev/{LocalDevManager.d.ts → LocalDevManager_DEPRECATED.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { ProjectConfig } from '../../../types/Projects.js';
2
- export declare function v3AddComponent(args: {
2
+ export declare function v2AddComponent(args: {
3
3
  name?: string;
4
4
  type?: string;
5
5
  features?: string[];
@@ -1,10 +1,10 @@
1
1
  import { commands, lib } from '../../../lang/en.js';
2
2
  import { getConfigForPlatformVersion } from '../create/legacy.js';
3
- import { calculateComponentTemplateChoices, createV3App, } from '../create/v3.js';
3
+ import { calculateComponentTemplateChoices, createV2App, } from '../create/v2.js';
4
4
  import { PROJECT_WITH_APP } from '../../constants.js';
5
5
  import path from 'path';
6
6
  import fs from 'fs';
7
- import { projectAddPromptV3 } from '../../prompts/projectAddPrompt.js';
7
+ import { projectAddPromptV2 } from '../../prompts/projectAddPrompt.js';
8
8
  import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, DEFAULT_PROJECT_TEMPLATE_BRANCH, } from '../../constants.js';
9
9
  import { updateHsMetaFilesWithAutoGeneratedFields, handleComponentCollision, } from '../components.js';
10
10
  import { getProjectMetadata, } from '@hubspot/project-parsing-lib/src/lib/project.js';
@@ -13,7 +13,7 @@ import { cloneGithubRepo } from '@hubspot/local-dev-lib/github';
13
13
  import { debugError } from '../../errorHandlers/index.js';
14
14
  import { uiLogger } from '../../ui/logger.js';
15
15
  import { trackCommandUsage } from '../../usageTracking.js';
16
- export async function v3AddComponent(args, projectDir, projectConfig, accountId) {
16
+ export async function v2AddComponent(args, projectDir, projectConfig, accountId) {
17
17
  uiLogger.log(commands.project.add.creatingComponent(projectConfig.name));
18
18
  const config = await getConfigForPlatformVersion(projectConfig.platformVersion);
19
19
  const { components, parentComponents } = config;
@@ -27,7 +27,7 @@ export async function v3AddComponent(args, projectDir, projectConfig, accountId)
27
27
  const appsMetadata = currentProjectMetadata.components[AppKey];
28
28
  const shouldCreateApp = appsMetadata.count === 0;
29
29
  if (shouldCreateApp) {
30
- const { authType, distribution } = await createV3App(args.auth, args.distribution);
30
+ const { authType, distribution } = await createV2App(args.auth, args.distribution);
31
31
  derivedDistribution = distribution;
32
32
  derivedAuthType = authType;
33
33
  }
@@ -47,7 +47,7 @@ export async function v3AddComponent(args, projectDir, projectConfig, accountId)
47
47
  derivedAuthType = apps[0].config?.auth?.type;
48
48
  }
49
49
  const componentTemplateChoices = await calculateComponentTemplateChoices(components, derivedAuthType, derivedDistribution, args.derivedAccountId, currentProjectMetadata);
50
- const projectAddPromptResponse = await projectAddPromptV3(componentTemplateChoices, args.features);
50
+ const projectAddPromptResponse = await projectAddPromptV2(componentTemplateChoices, args.features);
51
51
  const componentTypes = projectAddPromptResponse.componentTemplate?.map(componentTemplate => componentTemplate.cliSelector || componentTemplate.type);
52
52
  await trackCommandUsage('project-add', {
53
53
  type: componentTypes?.join(','),
@@ -0,0 +1 @@
1
+ export {};
@@ -1,10 +1,10 @@
1
- import { calculateComponentTemplateChoices } from '../v3.js';
1
+ import { calculateComponentTemplateChoices } from '../v2.js';
2
2
  import { hasFeature } from '../../../hasFeature.js';
3
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);
7
- describe('lib/projects/create/v3', () => {
7
+ describe('lib/projects/create/v2', () => {
8
8
  beforeEach(() => {
9
9
  mockHasFeature.mockResolvedValue(true);
10
10
  });
@@ -2,7 +2,7 @@ import { selectProjectTemplatePrompt, } from '../../prompts/selectProjectTemplat
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
4
  import { isV2Project } from '../platformVersion.js';
5
- import { v3ComponentFlow } from './v3.js';
5
+ import { v2ComponentFlow } from './v2.js';
6
6
  import { getProjectTemplateListFromRepo } from './legacy.js';
7
7
  import { uiLogger } from '../../ui/logger.js';
8
8
  import { commands } from '../../../lang/en.js';
@@ -12,7 +12,7 @@ export async function handleProjectCreationFlow(args) {
12
12
  const repo = templateSource || HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
13
13
  const projectNameAndDestPromptResponse = await projectNameAndDestPrompt(args);
14
14
  if (isV2Project(platformVersion)) {
15
- const { componentTemplateChoices, authType, distribution, repoConfig, projectContents, } = await v3ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution, args.derivedAccountId);
15
+ const { componentTemplateChoices, authType, distribution, repoConfig, projectContents, } = await v2ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution, args.derivedAccountId);
16
16
  const selectProjectTemplatePromptResponse = await selectProjectTemplatePrompt(args, undefined, projectContents !== EMPTY_PROJECT ? componentTemplateChoices : undefined);
17
17
  return {
18
18
  authType,
@@ -2,19 +2,19 @@ import { Separator } from '@inquirer/prompts';
2
2
  import { ComponentTemplate, ComponentTemplateChoice, ProjectTemplateRepoConfig } from '../../../types/Projects.js';
3
3
  import { ProjectMetadata } from '@hubspot/project-parsing-lib/src/lib/project.js';
4
4
  import { SelectProjectTemplatePromptResponse } from '../../prompts/selectProjectTemplatePrompt.js';
5
- export declare function createV3App(providedAuth: string | undefined, providedDistribution: string | undefined): Promise<{
5
+ export declare function createV2App(providedAuth: string | undefined, providedDistribution: string | undefined): Promise<{
6
6
  authType: string;
7
7
  distribution: string;
8
8
  }>;
9
9
  export declare function calculateComponentTemplateChoices(components: ComponentTemplate[], authType: string | undefined, distribution: string | undefined, accountId: number, projectMetadata?: ProjectMetadata): Promise<(ComponentTemplateChoice | Separator)[]>;
10
- type V3ComponentInfo = {
10
+ type V2ComponentInfo = {
11
11
  authType?: string;
12
12
  distribution?: string;
13
13
  repoConfig?: ProjectTemplateRepoConfig;
14
14
  projectContents?: string;
15
15
  componentTemplateChoices?: (ComponentTemplateChoice | Separator)[];
16
16
  };
17
- export declare function v3ComponentFlow(platformVersion: string, projectBase: string | undefined, providedAuth: string | undefined, providedDistribution: string | undefined, accountId: number): Promise<V3ComponentInfo>;
17
+ export declare function v2ComponentFlow(platformVersion: string, projectBase: string | undefined, providedAuth: string | undefined, providedDistribution: string | undefined, accountId: number): Promise<V2ComponentInfo>;
18
18
  export declare function generateComponentPaths({ selectProjectTemplatePromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }: {
19
19
  selectProjectTemplatePromptResponse: SelectProjectTemplatePromptResponse;
20
20
  platformVersion: string;
@@ -10,7 +10,7 @@ import { logError } from '../../errorHandlers/index.js';
10
10
  import { EXIT_CODES } from '../../enums/exitCodes.js';
11
11
  import { hasFeature } from '../../hasFeature.js';
12
12
  import { AppEventsKey, PagesKey, } from '@hubspot/project-parsing-lib/src/lib/constants.js';
13
- export async function createV3App(providedAuth, providedDistribution) {
13
+ export async function createV2App(providedAuth, providedDistribution) {
14
14
  let authType;
15
15
  if (providedAuth &&
16
16
  providedDistribution === marketplaceDistribution &&
@@ -112,7 +112,7 @@ export async function calculateComponentTemplateChoices(components, authType, di
112
112
  ]
113
113
  : [...enabledComponents];
114
114
  }
115
- export async function v3ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution, accountId) {
115
+ export async function v2ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution, accountId) {
116
116
  let repoConfig = undefined;
117
117
  let authType;
118
118
  let distribution;
@@ -134,7 +134,7 @@ export async function v3ComponentFlow(platformVersion, projectBase, providedAuth
134
134
  ],
135
135
  }));
136
136
  if (projectContentsChoice === PROJECT_WITH_APP) {
137
- const { authType: selectedAuthType, distribution: selectedDistribution } = await createV3App(providedAuth, providedDistribution);
137
+ const { authType: selectedAuthType, distribution: selectedDistribution } = await createV2App(providedAuth, providedDistribution);
138
138
  authType = selectedAuthType;
139
139
  distribution = selectedDistribution;
140
140
  }
@@ -10,4 +10,4 @@ export declare function logDeployErrors(errorData: {
10
10
  };
11
11
  }>;
12
12
  }): void;
13
- export declare function handleProjectDeploy(targetAccountId: number, projectName: string, buildId: number, useV3Api: boolean, force: boolean): Promise<Deploy | undefined>;
13
+ export declare function handleProjectDeploy(targetAccountId: number, projectName: string, buildId: number, isV2Project: boolean, force: boolean): Promise<Deploy | undefined>;
@@ -47,8 +47,8 @@ function handleBlockedDeploy(deployResp) {
47
47
  uiLogger.log('');
48
48
  });
49
49
  }
50
- export async function handleProjectDeploy(targetAccountId, projectName, buildId, useV3Api, force) {
51
- const { data: deployResp } = await deployProject(targetAccountId, projectName, buildId, useV3Api, force);
50
+ export async function handleProjectDeploy(targetAccountId, projectName, buildId, isV2Project, force) {
51
+ const { data: deployResp } = await deployProject(targetAccountId, projectName, buildId, isV2Project, force);
52
52
  if (!deployResp || deployResp.buildResultType !== 'DEPLOY_QUEUED') {
53
53
  if (deployResp?.buildResultType === 'DEPLOY_BLOCKED') {
54
54
  handleBlockedDeploy(deployResp);
@@ -10,6 +10,7 @@ declare class AppDevModeInterface {
10
10
  localDevLogger: LocalDevLogger;
11
11
  _appNode?: AppIRNode | null;
12
12
  marketplaceAppInstalls?: number;
13
+ private appInstallResolve?;
13
14
  constructor(options: AppDevModeInterfaceConstructorOptions);
14
15
  private getAppNodeFromProjectNodes;
15
16
  private get appNode();
@@ -17,14 +18,20 @@ declare class AppDevModeInterface {
17
18
  private set appData(value);
18
19
  private isStaticAuthApp;
19
20
  private isOAuthApp;
21
+ private isAutomaticallyInstallable;
20
22
  private getAppInstallUrl;
21
23
  private fetchAppData;
22
24
  private checkMarketplaceAppInstalls;
25
+ private waitUntilAppIsInstalled;
26
+ private autoInstallStaticAuthApp;
23
27
  private installAppOrOpenInstallUrl;
24
28
  private checkTestAccountAppInstallation;
29
+ private resolveAppInstallPromise;
30
+ private handleAppInstallSuccessDevServerMessage;
31
+ private handleAppInstallInitiatedDevServerMessage;
32
+ private handleAppInstallFailureDevServerMessage;
25
33
  private onDevServerMessage;
26
34
  private onChangeProjectNodes;
27
- private setUpStateListeners;
28
35
  private removeStateListeners;
29
36
  setup(args: any): Promise<void>;
30
37
  start(): Promise<void>;
@@ -1,27 +1,26 @@
1
1
  import { fetchAppInstallationData } from '@hubspot/local-dev-lib/api/localDevAuth';
2
- import { fetchPublicAppsForPortal, fetchPublicAppProductionInstallCounts,
3
- // installStaticAuthAppOnTestAccount,
4
- } from '@hubspot/local-dev-lib/api/appsDev';
2
+ import { fetchAppMetadataByUid, fetchPublicAppProductionInstallCounts, installStaticAuthAppOnTestAccount, } from '@hubspot/local-dev-lib/api/appsDev';
5
3
  import { DevModeUnifiedInterface as UIEDevModeInterface } from '@hubspot/ui-extensions-dev-server';
6
4
  import { requestPorts } from '@hubspot/local-dev-lib/portManager';
5
+ import { getAccountConfig } from '@hubspot/local-dev-lib/config';
7
6
  import { APP_AUTH_TYPES, APP_DISTRIBUTION_TYPES, APP_INSTALLATION_STATES, LOCAL_DEV_SERVER_MESSAGE_TYPES, } from '../../constants.js';
8
7
  import { EXIT_CODES } from '../../enums/exitCodes.js';
9
8
  import { isAppIRNode } from '../../projects/structure.js';
10
9
  import { uiLine } from '../../ui/index.js';
11
10
  import { logError } from '../../errorHandlers/index.js';
12
- import {
13
- // installAppAutoPrompt,
14
- installAppBrowserPrompt, } from '../../prompts/installAppPrompt.js';
11
+ import { installAppAutoPrompt, installAppBrowserPrompt, } from '../../prompts/installAppPrompt.js';
15
12
  import { confirmPrompt } from '../../prompts/promptUtils.js';
16
13
  import { lib } from '../../../lang/en.js';
17
14
  import { uiLogger } from '../../ui/logger.js';
18
15
  import { getOauthAppInstallUrl, getStaticAuthAppInstallUrl, } from '../../app/urls.js';
16
+ import { isDeveloperTestAccount, isSandbox } from '../../accountTypes.js';
19
17
  import SpinniesManager from '../../ui/SpinniesManager.js';
20
18
  class AppDevModeInterface {
21
19
  localDevState;
22
20
  localDevLogger;
23
21
  _appNode;
24
22
  marketplaceAppInstalls;
23
+ appInstallResolve;
25
24
  constructor(options) {
26
25
  this.localDevState = options.localDevState;
27
26
  this.localDevLogger = options.localDevLogger;
@@ -60,26 +59,17 @@ class AppDevModeInterface {
60
59
  isOAuthApp() {
61
60
  return (this.appNode?.config.auth.type.toLowerCase() === APP_AUTH_TYPES.OAUTH);
62
61
  }
63
- // @TODO: Restore test account auto install functionality
64
- // private isAutomaticallyInstallable(): boolean {
65
- // const targetTestingAccount = getAccountConfig(
66
- // this.localDevState.targetTestingAccountId
67
- // );
68
- // if (!targetTestingAccount) {
69
- // return false;
70
- // }
71
- // const isTestAccount =
72
- // isDeveloperTestAccount(targetTestingAccount) ||
73
- // isSandbox(targetTestingAccount);
74
- // const hasCorrectParent =
75
- // targetTestingAccount.parentAccountId ===
76
- // this.localDevState.targetProjectAccountId;
77
- // return (
78
- // isTestAccount &&
79
- // hasCorrectParent &&
80
- // this.isStaticAuthApp()
81
- // );
82
- // }
62
+ isAutomaticallyInstallable() {
63
+ const targetTestingAccount = getAccountConfig(this.localDevState.targetTestingAccountId);
64
+ if (!targetTestingAccount) {
65
+ return false;
66
+ }
67
+ const isTestAccount = isDeveloperTestAccount(targetTestingAccount) ||
68
+ isSandbox(targetTestingAccount);
69
+ const hasCorrectParent = targetTestingAccount.parentAccountId ===
70
+ this.localDevState.targetProjectAccountId;
71
+ return isTestAccount && hasCorrectParent && this.isStaticAuthApp();
72
+ }
83
73
  async getAppInstallUrl() {
84
74
  if (this.appNode && this.isOAuthApp()) {
85
75
  return getOauthAppInstallUrl({
@@ -90,26 +80,20 @@ class AppDevModeInterface {
90
80
  redirectUrls: this.appNode.config.auth.redirectUrls,
91
81
  });
92
82
  }
93
- const { data: { results }, } = await fetchPublicAppsForPortal(this.localDevState.targetProjectAccountId);
94
- const app = results.find(app => app.sourceId === this.appNode?.uid);
95
- if (!app) {
96
- uiLogger.error(lib.LocalDevManager.appNotFound(this.localDevState.targetProjectAccountId, this.appNode?.uid));
97
- process.exit(EXIT_CODES.ERROR);
98
- }
99
83
  return getStaticAuthAppInstallUrl({
100
84
  targetAccountId: this.localDevState.targetTestingAccountId,
101
85
  env: this.localDevState.env,
102
- appId: app.id,
86
+ appId: this.appData.id,
103
87
  });
104
88
  }
105
89
  async fetchAppData() {
106
90
  SpinniesManager.add('fetchAppData', {
107
91
  text: lib.AppDevModeInterface.fetchAppData.checking(this.appNode?.config.name || ''),
108
92
  });
109
- let portalApps = [];
93
+ let appData;
110
94
  try {
111
- const { data: { results }, } = await fetchPublicAppsForPortal(this.localDevState.targetProjectAccountId);
112
- portalApps = results;
95
+ const { data } = await fetchAppMetadataByUid(this.appNode.uid, this.localDevState.targetProjectAccountId);
96
+ appData = data;
113
97
  }
114
98
  catch (e) {
115
99
  SpinniesManager.fail('fetchAppData', {
@@ -118,7 +102,6 @@ class AppDevModeInterface {
118
102
  logError(e);
119
103
  process.exit(EXIT_CODES.ERROR);
120
104
  }
121
- const appData = portalApps.find(({ sourceId }) => sourceId === this.appNode?.uid);
122
105
  if (!appData) {
123
106
  return;
124
107
  }
@@ -127,7 +110,7 @@ class AppDevModeInterface {
127
110
  id: appData.id,
128
111
  clientId: appData.clientId,
129
112
  name: appData.name,
130
- installationState: APP_INSTALLATION_STATES.NOT_INSTALLED,
113
+ installationState: APP_INSTALLATION_STATES.UNKNOWN,
131
114
  scopeGroupIds: appData.scopeGroupIds,
132
115
  };
133
116
  this.marketplaceAppInstalls = uniquePortalInstallCount;
@@ -149,50 +132,55 @@ class AppDevModeInterface {
149
132
  }
150
133
  this.localDevState.addUploadWarning(lib.AppDevModeInterface.defaultMarketplaceAppWarning(this.marketplaceAppInstalls));
151
134
  }
152
- // @TODO: Restore test account auto install functionality
153
- // private async autoInstallStaticAuthApp(): Promise<void> {
154
- // const shouldInstall = await installAppAutoPrompt();
155
- // if (!shouldInstall) {
156
- // uiLogger.log(lib.AppDevModeInterface.autoInstallDeclined);
157
- // process.exit(EXIT_CODES.SUCCESS);
158
- // }
159
- // await installStaticAuthAppOnTestAccount(
160
- // this.appData!.id,
161
- // this.localDevState.targetTestingAccountId,
162
- // this.appData!.scopeGroupIds
163
- // );
164
- // }
135
+ async waitUntilAppIsInstalled(installUrl) {
136
+ uiLogger.log(lib.AppDevModeInterface.waitUntilAppIsInstalled.link(installUrl));
137
+ SpinniesManager.add('waitUntilAppIsInstalled', {
138
+ text: lib.AppDevModeInterface.waitUntilAppIsInstalled.waiting,
139
+ });
140
+ await new Promise(resolve => {
141
+ this.appInstallResolve = resolve;
142
+ });
143
+ SpinniesManager.succeed('waitUntilAppIsInstalled', {
144
+ text: lib.AppDevModeInterface.waitUntilAppIsInstalled.success(this.appNode?.config.name || '', this.localDevState.targetTestingAccountId),
145
+ });
146
+ }
147
+ async autoInstallStaticAuthApp() {
148
+ const shouldInstall = await installAppAutoPrompt();
149
+ if (!shouldInstall) {
150
+ uiLogger.log(lib.AppDevModeInterface.autoInstallDeclined);
151
+ process.exit(EXIT_CODES.SUCCESS);
152
+ }
153
+ uiLogger.log('');
154
+ SpinniesManager.add('autoInstallStaticAuthApp', {
155
+ text: lib.AppDevModeInterface.autoInstallStaticAuthApp.installing(this.appData.name, this.localDevState.targetTestingAccountId),
156
+ });
157
+ try {
158
+ await installStaticAuthAppOnTestAccount(this.appData.id, this.localDevState.targetTestingAccountId, this.appData.scopeGroupIds);
159
+ SpinniesManager.succeed('autoInstallStaticAuthApp', {
160
+ text: lib.AppDevModeInterface.autoInstallStaticAuthApp.success(this.appData.name, this.localDevState.targetTestingAccountId),
161
+ });
162
+ return true;
163
+ }
164
+ catch (e) {
165
+ SpinniesManager.fail('autoInstallStaticAuthApp', {
166
+ text: lib.AppDevModeInterface.autoInstallStaticAuthApp.error(this.appData.name, this.localDevState.targetTestingAccountId),
167
+ failColor: 'white',
168
+ });
169
+ return false;
170
+ }
171
+ }
165
172
  async installAppOrOpenInstallUrl(isReinstall) {
166
- // @TODO: Restore test account auto install functionality
167
- // if (this.isAutomaticallyInstallable()) {
168
- // try {
169
- // await this.autoInstallStaticAuthApp();
170
- // uiLogger.success(
171
- // lib.AppDevModeInterface.autoInstallSuccess(
172
- // this.appData!.name,
173
- // this.localDevState.targetTestingAccountId
174
- // )
175
- // );
176
- // return;
177
- // } catch (e) {
178
- // uiLogger.error(
179
- // lib.AppDevModeInterface.autoInstallError(
180
- // this.appData!.name,
181
- // this.localDevState.targetTestingAccountId
182
- // )
183
- // );
184
- // }
185
- // }
186
- const staticAuthInstallOptions = this.isStaticAuthApp()
187
- ? {
188
- testingAccountId: this.localDevState.targetTestingAccountId,
189
- projectAccountId: this.localDevState.targetProjectAccountId,
190
- projectName: this.localDevState.projectConfig.name,
191
- appUid: this.appNode.uid,
173
+ if (this.isAutomaticallyInstallable()) {
174
+ const installSuccess = await this.autoInstallStaticAuthApp();
175
+ if (installSuccess) {
176
+ return;
192
177
  }
193
- : undefined;
178
+ }
194
179
  const installUrl = await this.getAppInstallUrl();
195
- await installAppBrowserPrompt(installUrl, isReinstall, staticAuthInstallOptions);
180
+ await installAppBrowserPrompt(installUrl, isReinstall);
181
+ if (!isReinstall) {
182
+ await this.waitUntilAppIsInstalled(installUrl);
183
+ }
196
184
  }
197
185
  async checkTestAccountAppInstallation() {
198
186
  if (!this.appNode || !this.appData) {
@@ -212,11 +200,46 @@ class AppDevModeInterface {
212
200
  installationState: APP_INSTALLATION_STATES.INSTALLED_WITH_OUTDATED_SCOPES,
213
201
  };
214
202
  }
203
+ else {
204
+ this.appData = {
205
+ ...this.appData,
206
+ installationState: APP_INSTALLATION_STATES.NOT_INSTALLED,
207
+ };
208
+ }
215
209
  return { needsInstall: !isInstalledWithScopeGroups, isReinstall };
216
210
  }
217
- onDevServerMessage = (message) => {
211
+ resolveAppInstallPromise() {
212
+ if (this.appInstallResolve) {
213
+ this.appInstallResolve();
214
+ this.appInstallResolve = undefined;
215
+ }
216
+ }
217
+ handleAppInstallSuccessDevServerMessage() {
218
+ this.resolveAppInstallPromise();
219
+ this.appData = {
220
+ ...this.appData,
221
+ installationState: APP_INSTALLATION_STATES.INSTALLED,
222
+ };
223
+ }
224
+ handleAppInstallInitiatedDevServerMessage() {
225
+ this.resolveAppInstallPromise();
226
+ }
227
+ handleAppInstallFailureDevServerMessage() {
228
+ uiLogger.error(lib.AppDevModeInterface.installationFailed);
229
+ process.exit(EXIT_CODES.ERROR);
230
+ }
231
+ onDevServerMessage = async (message) => {
218
232
  if (message === LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED) {
219
- this.checkTestAccountAppInstallation();
233
+ await this.checkTestAccountAppInstallation();
234
+ }
235
+ else if (message === LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_SUCCESS) {
236
+ this.handleAppInstallSuccessDevServerMessage();
237
+ }
238
+ else if (message === LOCAL_DEV_SERVER_MESSAGE_TYPES.STATIC_AUTH_APP_INSTALL_FAILURE) {
239
+ this.handleAppInstallFailureDevServerMessage();
240
+ }
241
+ else if (message === LOCAL_DEV_SERVER_MESSAGE_TYPES.OAUTH_APP_INSTALL_INITIATED) {
242
+ this.handleAppInstallInitiatedDevServerMessage();
220
243
  }
221
244
  };
222
245
  onChangeProjectNodes = (nodes) => {
@@ -234,10 +257,6 @@ class AppDevModeInterface {
234
257
  this.localDevState.addUploadWarning(lib.AppDevModeInterface.authTypeChanged);
235
258
  }
236
259
  };
237
- setUpStateListeners() {
238
- this.localDevState.addListener('devServerMessage', this.onDevServerMessage);
239
- this.localDevState.addListener('projectNodes', this.onChangeProjectNodes);
240
- }
241
260
  removeStateListeners() {
242
261
  this.localDevState.removeListener('devServerMessage', this.onDevServerMessage);
243
262
  this.localDevState.removeListener('projectNodes', this.onChangeProjectNodes);
@@ -261,6 +280,7 @@ class AppDevModeInterface {
261
280
  failColor: 'white',
262
281
  });
263
282
  }
283
+ this.localDevState.addListener('devServerMessage', this.onDevServerMessage);
264
284
  await this.installAppOrOpenInstallUrl(isReinstall || false);
265
285
  }
266
286
  else {
@@ -275,7 +295,7 @@ class AppDevModeInterface {
275
295
  catch (e) {
276
296
  logError(e);
277
297
  }
278
- this.setUpStateListeners();
298
+ this.localDevState.addListener('projectNodes', this.onChangeProjectNodes);
279
299
  return UIEDevModeInterface.setup(args);
280
300
  }
281
301
  async start() {
@@ -1,40 +1,22 @@
1
- import { ProjectConfig, ComponentTypes, Component } from '../../../types/Projects.js';
2
- type DevServerInterface = {
3
- setup?: Function;
4
- start?: (options: object) => Promise<void>;
5
- fileChange?: (filePath: string, event: string) => Promise<void>;
6
- cleanup?: () => Promise<void>;
7
- };
8
- type ComponentsByType = {
9
- [key in ComponentTypes]?: {
10
- [key: string]: Component;
11
- };
1
+ import LocalDevState from './LocalDevState.js';
2
+ import LocalDevLogger from './LocalDevLogger.js';
3
+ type DevServerManagerConstructorOptions = {
4
+ localDevState: LocalDevState;
5
+ logger: LocalDevLogger;
12
6
  };
13
7
  declare class DevServerManager {
14
8
  private initialized;
15
9
  private started;
16
- private componentsByType;
17
10
  private devServers;
18
- constructor();
19
- iterateDevServers(callback: (serverInterface: DevServerInterface, compatibleComponents: {
20
- [key: string]: Component;
21
- }) => Promise<void>): Promise<void>;
22
- arrangeComponentsByType(components: Component[]): ComponentsByType;
23
- setup({ components, onUploadRequired, accountId, setActiveApp, }: {
24
- components: Component[];
25
- onUploadRequired: () => void;
26
- accountId: number;
27
- setActiveApp: (appUid: string | undefined) => Promise<void>;
28
- }): Promise<void>;
29
- start({ accountId, projectConfig, }: {
30
- accountId: number;
31
- projectConfig: ProjectConfig;
32
- }): Promise<void>;
11
+ private localDevState;
12
+ constructor(options: DevServerManagerConstructorOptions);
13
+ private iterateDevServers;
14
+ setup(): Promise<void>;
15
+ start(): Promise<void>;
33
16
  fileChange({ filePath, event, }: {
34
17
  filePath: string;
35
18
  event: string;
36
19
  }): Promise<void>;
37
20
  cleanup(): Promise<void>;
38
21
  }
39
- declare const Manager: DevServerManager;
40
- export default Manager;
22
+ export default DevServerManager;
@@ -1,93 +1,53 @@
1
1
  import { logger } from '@hubspot/local-dev-lib/logger';
2
- import { DevModeInterface as UIEDevModeInterface } from '@hubspot/ui-extensions-dev-server';
3
- import { startPortManagerServer, stopPortManagerServer, requestPorts, } from '@hubspot/local-dev-lib/portManager';
4
2
  import { getHubSpotApiOrigin, getHubSpotWebsiteOrigin, } from '@hubspot/local-dev-lib/urls';
5
3
  import { getAccountConfig } from '@hubspot/local-dev-lib/config';
6
- import { ComponentTypes, } from '../../../types/Projects.js';
4
+ import AppDevModeInterface from './AppDevModeInterface.js';
7
5
  import { lib } from '../../../lang/en.js';
8
- import { uiLogger } from '../../ui/logger.js';
9
- const SERVER_KEYS = {
10
- privateApp: 'privateApp',
11
- publicApp: 'publicApp',
12
- };
13
6
  class DevServerManager {
14
7
  initialized;
15
8
  started;
16
- componentsByType;
17
9
  devServers;
18
- constructor() {
10
+ localDevState;
11
+ constructor(options) {
19
12
  this.initialized = false;
20
13
  this.started = false;
21
- this.componentsByType = {};
22
- this.devServers = {
23
- [SERVER_KEYS.privateApp]: {
24
- componentType: ComponentTypes.PrivateApp,
25
- serverInterface: UIEDevModeInterface,
26
- },
27
- [SERVER_KEYS.publicApp]: {
28
- componentType: ComponentTypes.PublicApp,
29
- serverInterface: UIEDevModeInterface,
30
- },
31
- };
14
+ this.localDevState = options.localDevState;
15
+ const AppsDevServer = new AppDevModeInterface({
16
+ localDevState: options.localDevState,
17
+ localDevLogger: options.logger,
18
+ });
19
+ this.devServers = [AppsDevServer];
32
20
  }
33
21
  async iterateDevServers(callback) {
34
- const serverKeys = Object.keys(this.devServers);
35
- for (let i = 0; i < serverKeys.length; i++) {
36
- const serverKey = serverKeys[i];
37
- const devServer = this.devServers[serverKey];
38
- const compatibleComponents = this.componentsByType[devServer.componentType] || {};
39
- if (Object.keys(compatibleComponents).length) {
40
- await callback(devServer.serverInterface, compatibleComponents);
41
- }
42
- else {
43
- uiLogger.debug(lib.DevServerManager.noCompatibleComponents(serverKey));
44
- }
45
- }
46
- }
47
- arrangeComponentsByType(components) {
48
- return components.reduce((acc, component) => {
49
- if (!acc[component.type]) {
50
- acc[component.type] = {};
51
- }
52
- if ('name' in component.config && component.config.name) {
53
- acc[component.type][component.config.name] = component;
54
- }
55
- return acc;
56
- }, {});
22
+ await Promise.all(this.devServers.map(devServer => callback(devServer)));
57
23
  }
58
- async setup({ components, onUploadRequired, accountId, setActiveApp, }) {
59
- this.componentsByType = this.arrangeComponentsByType(components);
24
+ async setup() {
60
25
  let env;
61
- const accountConfig = getAccountConfig(accountId);
26
+ const accountConfig = getAccountConfig(this.localDevState.targetTestingAccountId);
62
27
  if (accountConfig) {
63
28
  env = accountConfig.env;
64
29
  }
65
- await startPortManagerServer();
66
- await this.iterateDevServers(async (serverInterface, compatibleComponents) => {
30
+ await this.iterateDevServers(async (serverInterface) => {
67
31
  if (serverInterface.setup) {
32
+ // @TODO: In the future, update UIE Dev Server to use LocalDevState
68
33
  await serverInterface.setup({
69
- components: compatibleComponents,
70
- onUploadRequired,
34
+ components: this.localDevState.projectNodes,
35
+ profileData: this.localDevState.projectProfileData,
71
36
  logger,
72
37
  urls: {
73
38
  api: getHubSpotApiOrigin(env),
74
39
  web: getHubSpotWebsiteOrigin(env),
75
40
  },
76
- setActiveApp,
77
41
  });
78
42
  }
79
43
  });
80
44
  this.initialized = true;
81
45
  }
82
- async start({ accountId, projectConfig, }) {
46
+ async start() {
83
47
  if (this.initialized) {
84
48
  await this.iterateDevServers(async (serverInterface) => {
85
49
  if (serverInterface.start) {
86
- await serverInterface.start({
87
- accountId,
88
- projectConfig,
89
- requestPorts,
90
- });
50
+ await serverInterface.start();
91
51
  }
92
52
  });
93
53
  }
@@ -112,9 +72,7 @@ class DevServerManager {
112
72
  await serverInterface.cleanup();
113
73
  }
114
74
  });
115
- await stopPortManagerServer();
116
75
  }
117
76
  }
118
77
  }
119
- const Manager = new DevServerManager();
120
- export default Manager;
78
+ export default DevServerManager;