@hubspot/cli 7.6.0-beta.11 → 7.6.0-beta.13
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.
- package/commands/app/__tests__/migrate.test.js +1 -0
- package/commands/getStarted.js +7 -20
- package/commands/mcp/setup.d.ts +0 -1
- package/commands/mcp/setup.js +11 -11
- package/commands/project/__tests__/add.test.js +64 -0
- package/commands/project/__tests__/create.test.js +57 -0
- package/commands/project/__tests__/deploy.test.js +3 -2
- package/commands/project/add.d.ts +1 -1
- package/commands/project/add.js +3 -5
- package/commands/project/create.js +7 -2
- package/commands/project/deploy.js +9 -61
- package/commands/project/dev/index.js +1 -1
- package/commands/project/dev/unifiedFlow.js +4 -1
- package/commands/project/migrate.js +26 -7
- package/commands/project/upload.js +2 -2
- package/commands/project/validate.js +1 -1
- package/commands/project/watch.js +2 -2
- package/lang/en.d.ts +20 -5
- package/lang/en.js +38 -22
- package/lang/en.lyaml +12 -12
- package/lib/__tests__/hasFeature.test.js +145 -7
- package/lib/__tests__/importData.test.js +1 -1
- package/lib/app/__tests__/migrate.test.js +14 -51
- package/lib/app/migrate.d.ts +2 -8
- package/lib/app/migrate.js +5 -73
- package/lib/constants.d.ts +4 -0
- package/lib/constants.js +4 -0
- package/lib/errorHandlers/index.d.ts +4 -0
- package/lib/errorHandlers/index.js +1 -1
- package/lib/hasFeature.js +6 -0
- package/lib/importData.js +1 -1
- package/lib/links.d.ts +1 -0
- package/lib/links.js +10 -3
- package/lib/mcp/setup.d.ts +0 -2
- package/lib/mcp/setup.js +4 -29
- package/lib/projects/__tests__/AppDevModeInterface.test.js +71 -44
- package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
- package/lib/projects/__tests__/components.test.js +164 -7
- package/lib/projects/__tests__/deploy.test.js +164 -0
- package/lib/projects/__tests__/platformVersion.test.d.ts +1 -0
- package/lib/projects/__tests__/{buildAndDeploy.test.js → platformVersion.test.js} +2 -2
- package/lib/projects/add/__tests__/legacyAddComponent.test.js +49 -6
- package/lib/projects/add/__tests__/v3AddComponent.test.js +142 -8
- package/lib/projects/add/legacyAddComponent.d.ts +1 -1
- package/lib/projects/add/legacyAddComponent.js +5 -1
- package/lib/projects/add/v3AddComponent.d.ts +2 -1
- package/lib/projects/add/v3AddComponent.js +22 -5
- package/lib/projects/components.d.ts +1 -0
- package/lib/projects/components.js +27 -1
- package/lib/projects/create/__tests__/v3.test.js +97 -9
- package/lib/projects/create/index.js +2 -2
- package/lib/projects/create/legacy.js +1 -1
- package/lib/projects/create/v3.d.ts +2 -2
- package/lib/projects/create/v3.js +35 -12
- package/lib/projects/deploy.d.ts +13 -0
- package/lib/projects/deploy.js +63 -0
- package/lib/projects/localDev/AppDevModeInterface.d.ts +5 -3
- package/lib/projects/localDev/AppDevModeInterface.js +110 -47
- package/lib/projects/localDev/DevServerManagerV2.js +1 -0
- package/lib/projects/localDev/LocalDevProcess.js +3 -1
- package/lib/projects/localDev/LocalDevState.d.ts +5 -2
- package/lib/projects/localDev/LocalDevState.js +9 -1
- package/lib/projects/localDev/helpers/project.d.ts +2 -2
- package/lib/projects/localDev/helpers/project.js +6 -8
- package/lib/projects/platformVersion.d.ts +1 -0
- package/lib/projects/platformVersion.js +10 -0
- package/lib/projects/{buildAndDeploy.d.ts → pollProjectBuildAndDeploy.d.ts} +0 -1
- package/lib/projects/{buildAndDeploy.js → pollProjectBuildAndDeploy.js} +0 -10
- package/lib/projects/upload.js +1 -1
- package/lib/projects/urls.d.ts +1 -0
- package/lib/projects/urls.js +3 -0
- package/lib/prompts/__tests__/projectAddPrompt.test.d.ts +1 -0
- package/lib/prompts/__tests__/projectAddPrompt.test.js +143 -0
- package/lib/prompts/__tests__/selectProjectTemplatePrompt.test.d.ts +1 -0
- package/lib/prompts/__tests__/selectProjectTemplatePrompt.test.js +160 -0
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +1 -0
- package/lib/prompts/importDataFilePathPrompt.js +4 -2
- package/lib/prompts/installAppPrompt.d.ts +6 -1
- package/lib/prompts/installAppPrompt.js +6 -1
- package/lib/prompts/projectAddPrompt.js +1 -1
- package/lib/prompts/promptUtils.d.ts +5 -0
- package/lib/prompts/promptUtils.js +9 -0
- package/lib/prompts/selectProjectTemplatePrompt.js +1 -1
- package/lib/theme/__tests__/migrate.test.d.ts +1 -0
- package/lib/theme/__tests__/migrate.test.js +233 -0
- package/lib/theme/migrate.d.ts +13 -0
- package/lib/theme/migrate.js +90 -0
- package/lib/ui/index.js +3 -6
- package/lib/usageTracking.js +2 -2
- package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +32 -0
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +96 -0
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +38 -0
- package/mcp-server/tools/cms/HsCreateModuleTool.js +118 -0
- package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +26 -0
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +75 -0
- package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +32 -0
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +76 -0
- package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +23 -0
- package/mcp-server/tools/cms/HsListFunctionsTool.js +58 -0
- package/mcp-server/tools/cms/HsListTool.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +251 -0
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +224 -0
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +206 -0
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +183 -0
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +120 -0
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +1 -1
- package/mcp-server/tools/index.js +13 -1
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +3 -3
- package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/CreateProjectTool.js +5 -5
- package/mcp-server/tools/project/DeployProjectTool.js +1 -1
- package/mcp-server/tools/project/DocFetchTool.js +2 -2
- package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
- package/mcp-server/tools/project/DocsSearchTool.js +7 -7
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +14 -8
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.js +2 -2
- package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
- package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +2 -2
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +14 -12
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +9 -8
- package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -1
- package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/constants.d.ts +1 -1
- package/mcp-server/tools/project/constants.js +14 -6
- package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
- package/mcp-server/utils/cliConfig.d.ts +1 -0
- package/mcp-server/utils/cliConfig.js +12 -0
- package/package.json +4 -3
- package/types/LocalDev.d.ts +2 -1
- package/types/Projects.d.ts +1 -0
- package/ui/components/BoxWithTitle.d.ts +8 -0
- package/ui/components/BoxWithTitle.js +9 -0
- package/ui/components/HorizontalSelectPrompt.d.ts +8 -0
- package/ui/components/HorizontalSelectPrompt.js +30 -0
- package/ui/components/StatusMessageBoxes.d.ts +12 -0
- package/ui/components/StatusMessageBoxes.js +31 -0
- package/ui/lib/ui-testing-utils.d.ts +9 -0
- package/ui/lib/ui-testing-utils.js +47 -0
- package/ui/lib/useTerminalSize.d.ts +13 -0
- package/ui/lib/useTerminalSize.js +31 -0
- package/ui/styles.d.ts +18 -0
- package/ui/styles.js +18 -0
- package/ui/views/UiSandbox.d.ts +5 -0
- package/ui/views/UiSandbox.js +25 -0
- /package/lib/projects/__tests__/{buildAndDeploy.test.d.ts → deploy.test.d.ts} +0 -0
|
@@ -26,9 +26,9 @@ describe('lib/projects/create/v3', () => {
|
|
|
26
26
|
card: { count: 3, maxCount: 3, hsMetaFiles: [] },
|
|
27
27
|
},
|
|
28
28
|
};
|
|
29
|
-
it('returns enabled components when they meet all requirements', () => {
|
|
30
|
-
const choices = calculateComponentTemplateChoices(mockComponents, 'oauth', 'private', mockProjectMetadataForChoices);
|
|
31
|
-
expect(choices).toHaveLength(
|
|
29
|
+
it('returns enabled components when they meet all requirements', async () => {
|
|
30
|
+
const choices = await calculateComponentTemplateChoices(mockComponents, 'oauth', 'private', 123, mockProjectMetadataForChoices);
|
|
31
|
+
expect(choices).toHaveLength(4); // includes separator
|
|
32
32
|
expect(choices[0]).toEqual({
|
|
33
33
|
name: 'Module Component',
|
|
34
34
|
value: mockComponents[0],
|
|
@@ -39,8 +39,8 @@ describe('lib/projects/create/v3', () => {
|
|
|
39
39
|
disabled: expect.stringContaining('maximum'),
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
|
-
it('disables components when auth type is not supported', () => {
|
|
43
|
-
const choices = calculateComponentTemplateChoices(mockComponents, 'privatekey', 'private', mockProjectMetadataForChoices);
|
|
42
|
+
it('disables components when auth type is not supported', async () => {
|
|
43
|
+
const choices = await calculateComponentTemplateChoices(mockComponents, 'privatekey', 'private', 123, mockProjectMetadataForChoices);
|
|
44
44
|
// All components should be disabled, so they come after the separator
|
|
45
45
|
expect(choices[1]).toEqual({
|
|
46
46
|
name: expect.stringContaining('Module Component'),
|
|
@@ -48,8 +48,8 @@ describe('lib/projects/create/v3', () => {
|
|
|
48
48
|
disabled: expect.stringContaining('privatekey'),
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
|
-
it('disables components when distribution is not supported', () => {
|
|
52
|
-
const choices = calculateComponentTemplateChoices(mockComponents, 'oauth', 'enterprise', mockProjectMetadataForChoices);
|
|
51
|
+
it('disables components when distribution is not supported', async () => {
|
|
52
|
+
const choices = await calculateComponentTemplateChoices(mockComponents, 'oauth', 'enterprise', 123, mockProjectMetadataForChoices);
|
|
53
53
|
// All components should be disabled, so they come after the separator
|
|
54
54
|
expect(choices[1]).toEqual({
|
|
55
55
|
name: expect.stringContaining('Module Component'),
|
|
@@ -57,7 +57,7 @@ describe('lib/projects/create/v3', () => {
|
|
|
57
57
|
disabled: expect.stringContaining('enterprise'),
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
|
-
it('handles components without auth type or distribution restrictions', () => {
|
|
60
|
+
it('handles components without auth type or distribution restrictions', async () => {
|
|
61
61
|
const componentsWithoutRestrictions = [
|
|
62
62
|
{
|
|
63
63
|
label: 'Unrestricted Component',
|
|
@@ -65,7 +65,7 @@ describe('lib/projects/create/v3', () => {
|
|
|
65
65
|
type: 'module',
|
|
66
66
|
},
|
|
67
67
|
];
|
|
68
|
-
const choices = calculateComponentTemplateChoices(componentsWithoutRestrictions, 'oauth', 'private', {
|
|
68
|
+
const choices = await calculateComponentTemplateChoices(componentsWithoutRestrictions, 'oauth', 'private', 123, {
|
|
69
69
|
hsMetaFiles: [],
|
|
70
70
|
components: { module: { count: 0, maxCount: 5, hsMetaFiles: [] } },
|
|
71
71
|
});
|
|
@@ -74,5 +74,93 @@ describe('lib/projects/create/v3', () => {
|
|
|
74
74
|
value: componentsWithoutRestrictions[0],
|
|
75
75
|
});
|
|
76
76
|
});
|
|
77
|
+
it('handles components with cliSelector field (metadata compatibility)', async () => {
|
|
78
|
+
const componentWithCliSelector = [
|
|
79
|
+
{
|
|
80
|
+
label: 'Workflow Action Tool',
|
|
81
|
+
path: 'workflow-action-tool',
|
|
82
|
+
type: 'workflow-action',
|
|
83
|
+
cliSelector: 'workflow-action-tool',
|
|
84
|
+
supportedAuthTypes: ['oauth'],
|
|
85
|
+
supportedDistributions: ['private'],
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
const projectMetadataWithWorkflowAction = {
|
|
89
|
+
hsMetaFiles: [],
|
|
90
|
+
components: {
|
|
91
|
+
'workflow-action': { count: 2, maxCount: 3, hsMetaFiles: [] },
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
const choices = await calculateComponentTemplateChoices(componentWithCliSelector, 'oauth', 'private', 213, projectMetadataWithWorkflowAction);
|
|
95
|
+
expect(choices).toHaveLength(1); // no disabled components
|
|
96
|
+
expect(choices[0]).toEqual({
|
|
97
|
+
name: 'Workflow Action Tool',
|
|
98
|
+
value: componentWithCliSelector[0],
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
it('disables component when project metadata count exceeds maximum', async () => {
|
|
102
|
+
const componentWithCliSelector = [
|
|
103
|
+
{
|
|
104
|
+
label: 'Workflow Action Tool',
|
|
105
|
+
path: 'workflow-action-tool',
|
|
106
|
+
type: 'workflow-action',
|
|
107
|
+
cliSelector: 'workflow-action-tool',
|
|
108
|
+
supportedAuthTypes: ['oauth'],
|
|
109
|
+
supportedDistributions: ['private'],
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
const projectMetadataAtMaxWorkflowAction = {
|
|
113
|
+
hsMetaFiles: [],
|
|
114
|
+
components: {
|
|
115
|
+
'workflow-action': { count: 3, maxCount: 3, hsMetaFiles: [] },
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
const choices = await calculateComponentTemplateChoices(componentWithCliSelector, 'oauth', 'private', 123, projectMetadataAtMaxWorkflowAction);
|
|
119
|
+
expect(choices).toHaveLength(3); // includes separators
|
|
120
|
+
expect(choices[1]).toEqual({
|
|
121
|
+
name: expect.stringContaining('Workflow Action Tool'),
|
|
122
|
+
value: componentWithCliSelector[0],
|
|
123
|
+
disabled: expect.stringContaining('maximum'),
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
it('handles undefined projectMetadata without throwing errors', async () => {
|
|
127
|
+
const componentWithCliSelector = [
|
|
128
|
+
{
|
|
129
|
+
label: 'Workflow Action Tool',
|
|
130
|
+
path: 'workflow-action-tool',
|
|
131
|
+
type: 'workflow-action',
|
|
132
|
+
cliSelector: 'workflow-action-tool',
|
|
133
|
+
supportedAuthTypes: ['oauth'],
|
|
134
|
+
supportedDistributions: ['private'],
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
const choices = await calculateComponentTemplateChoices(componentWithCliSelector, 'oauth', 'private', 123, undefined);
|
|
138
|
+
expect(choices).toHaveLength(1); // no disabled components
|
|
139
|
+
expect(choices[0]).toEqual({
|
|
140
|
+
name: 'Workflow Action Tool',
|
|
141
|
+
value: componentWithCliSelector[0],
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
it('handles projectMetadata with undefined components property (after fix)', async () => {
|
|
145
|
+
const componentWithCliSelector = [
|
|
146
|
+
{
|
|
147
|
+
label: 'Workflow Action Tool',
|
|
148
|
+
path: 'workflow-action-tool',
|
|
149
|
+
type: 'workflow-action',
|
|
150
|
+
cliSelector: 'workflow-action-tool',
|
|
151
|
+
supportedAuthTypes: ['oauth'],
|
|
152
|
+
supportedDistributions: ['private'],
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
const projectMetadataWithoutComponents = {
|
|
156
|
+
hsMetaFiles: [],
|
|
157
|
+
components: undefined,
|
|
158
|
+
};
|
|
159
|
+
// This test verifies the null check fix works
|
|
160
|
+
// Currently this will fail because the fix checks for projectMetadata.components
|
|
161
|
+
await expect(async () => calculateComponentTemplateChoices(componentWithCliSelector, 'oauth', 'private', 123,
|
|
162
|
+
// @ts-expect-error breaking stuff on purpose
|
|
163
|
+
projectMetadataWithoutComponents)).rejects.toThrow();
|
|
164
|
+
});
|
|
77
165
|
});
|
|
78
166
|
});
|
|
@@ -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 '../
|
|
4
|
+
import { useV3Api } 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';
|
|
@@ -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 (useV3Api(platformVersion)) {
|
|
15
|
-
const { componentTemplateChoices, authType, distribution, repoConfig, projectContents, } = await v3ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution);
|
|
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 {
|
|
18
18
|
authType,
|
|
@@ -3,7 +3,7 @@ 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 '../
|
|
6
|
+
import { useV3Api } 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';
|
|
@@ -6,7 +6,7 @@ export declare function createV3App(providedAuth: string | undefined, providedDi
|
|
|
6
6
|
authType: string;
|
|
7
7
|
distribution: string;
|
|
8
8
|
}>;
|
|
9
|
-
export declare function calculateComponentTemplateChoices(components: ComponentTemplate[], authType: string | undefined, distribution: string | undefined, projectMetadata?: ProjectMetadata): (ComponentTemplateChoice | Separator)[]
|
|
9
|
+
export declare function calculateComponentTemplateChoices(components: ComponentTemplate[], authType: string | undefined, distribution: string | undefined, accountId: number, projectMetadata?: ProjectMetadata): Promise<(ComponentTemplateChoice | Separator)[]>;
|
|
10
10
|
type V3ComponentInfo = {
|
|
11
11
|
authType?: string;
|
|
12
12
|
distribution?: string;
|
|
@@ -14,7 +14,7 @@ type V3ComponentInfo = {
|
|
|
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): Promise<V3ComponentInfo>;
|
|
17
|
+
export declare function v3ComponentFlow(platformVersion: string, projectBase: string | undefined, providedAuth: string | undefined, providedDistribution: string | undefined, accountId: number): Promise<V3ComponentInfo>;
|
|
18
18
|
export declare function generateComponentPaths({ selectProjectTemplatePromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }: {
|
|
19
19
|
selectProjectTemplatePromptResponse: SelectProjectTemplatePromptResponse;
|
|
20
20
|
platformVersion: string;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Separator } from '@inquirer/prompts';
|
|
2
|
-
import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, EMPTY_PROJECT, PROJECT_WITH_APP, } from '../../constants.js';
|
|
2
|
+
import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, EMPTY_PROJECT, PROJECT_WITH_APP, FEATURES, } from '../../constants.js';
|
|
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 '../
|
|
6
|
+
import { useV3Api } from '../platformVersion.js';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import { getConfigForPlatformVersion } from './legacy.js';
|
|
9
9
|
import { logError } from '../../errorHandlers/index.js';
|
|
10
10
|
import { EXIT_CODES } from '../../enums/exitCodes.js';
|
|
11
|
+
import { hasFeature } from '../../hasFeature.js';
|
|
12
|
+
import { AppEventsKey, PagesKey, } from '@hubspot/project-parsing-lib/src/lib/constants.js';
|
|
11
13
|
export async function createV3App(providedAuth, providedDistribution) {
|
|
12
14
|
let authType;
|
|
13
15
|
if (providedAuth &&
|
|
@@ -47,16 +49,26 @@ export async function createV3App(providedAuth, providedDistribution) {
|
|
|
47
49
|
authType: authType,
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
|
-
|
|
52
|
+
const componentTypeToGateMap = {
|
|
53
|
+
[AppEventsKey]: FEATURES.APP_EVENTS,
|
|
54
|
+
[PagesKey]: FEATURES.APPS_HOME,
|
|
55
|
+
};
|
|
56
|
+
export async function calculateComponentTemplateChoices(components, authType, distribution, accountId, projectMetadata) {
|
|
51
57
|
const enabledComponents = [];
|
|
52
58
|
const disabledComponents = [];
|
|
53
|
-
|
|
59
|
+
for (const template of components) {
|
|
54
60
|
const { supportedAuthTypes, supportedDistributions } = template;
|
|
55
61
|
const disabledReasons = [];
|
|
56
62
|
if (projectMetadata) {
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
disabledReasons.push(commands.project.add.error.
|
|
63
|
+
const componentMetadata = projectMetadata.components[template.type];
|
|
64
|
+
if (!componentMetadata) {
|
|
65
|
+
disabledReasons.push(commands.project.add.error.invalidComponentType(template.type));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const { count, maxCount } = componentMetadata;
|
|
69
|
+
if (count >= maxCount) {
|
|
70
|
+
disabledReasons.push(commands.project.add.error.maxExceeded(maxCount));
|
|
71
|
+
}
|
|
60
72
|
}
|
|
61
73
|
}
|
|
62
74
|
if (Array.isArray(supportedAuthTypes) &&
|
|
@@ -69,9 +81,15 @@ export function calculateComponentTemplateChoices(components, authType, distribu
|
|
|
69
81
|
!supportedDistributions.includes(distribution)) {
|
|
70
82
|
disabledReasons.push(commands.project.add.error.distributionNotAllowed(distribution));
|
|
71
83
|
}
|
|
84
|
+
if (componentTypeToGateMap[template.type]) {
|
|
85
|
+
const isUngated = await hasFeature(accountId, componentTypeToGateMap[template.type]);
|
|
86
|
+
if (!isUngated) {
|
|
87
|
+
disabledReasons.push(commands.project.add.error.portalDoesNotHaveAccessToThisFeature(accountId));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
72
90
|
if (disabledReasons.length > 0) {
|
|
73
91
|
disabledComponents.push({
|
|
74
|
-
name: `[${chalk.yellow('DISABLED')}] ${template.label}
|
|
92
|
+
name: `[${chalk.yellow('DISABLED')}] ${template.label} -`,
|
|
75
93
|
value: template,
|
|
76
94
|
disabled: disabledReasons.join(' '),
|
|
77
95
|
});
|
|
@@ -82,12 +100,17 @@ export function calculateComponentTemplateChoices(components, authType, distribu
|
|
|
82
100
|
value: template,
|
|
83
101
|
});
|
|
84
102
|
}
|
|
85
|
-
}
|
|
103
|
+
}
|
|
86
104
|
return disabledComponents.length
|
|
87
|
-
? [
|
|
105
|
+
? [
|
|
106
|
+
...enabledComponents,
|
|
107
|
+
new Separator(),
|
|
108
|
+
...disabledComponents,
|
|
109
|
+
new Separator(),
|
|
110
|
+
]
|
|
88
111
|
: [...enabledComponents];
|
|
89
112
|
}
|
|
90
|
-
export async function v3ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution) {
|
|
113
|
+
export async function v3ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution, accountId) {
|
|
91
114
|
let repoConfig = undefined;
|
|
92
115
|
let authType;
|
|
93
116
|
let distribution;
|
|
@@ -113,7 +136,7 @@ export async function v3ComponentFlow(platformVersion, projectBase, providedAuth
|
|
|
113
136
|
authType = selectedAuthType;
|
|
114
137
|
distribution = selectedDistribution;
|
|
115
138
|
}
|
|
116
|
-
const componentTemplateChoices = calculateComponentTemplateChoices(repoConfig?.components || [], authType, distribution);
|
|
139
|
+
const componentTemplateChoices = await calculateComponentTemplateChoices(repoConfig?.components || [], authType, distribution, accountId);
|
|
117
140
|
return {
|
|
118
141
|
componentTemplateChoices,
|
|
119
142
|
authType,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Deploy } from '@hubspot/local-dev-lib/types/Deploy';
|
|
2
|
+
export declare function validateBuildIdForDeploy(buildId: number, deployedBuildId: number | undefined, latestBuildId: number, projectName: string | undefined, accountId: number): boolean | string;
|
|
3
|
+
export declare function logDeployErrors(errorData: {
|
|
4
|
+
message: string;
|
|
5
|
+
errors: Array<{
|
|
6
|
+
message: string;
|
|
7
|
+
subCategory: string;
|
|
8
|
+
context: {
|
|
9
|
+
COMPONENT_NAME: string;
|
|
10
|
+
};
|
|
11
|
+
}>;
|
|
12
|
+
}): void;
|
|
13
|
+
export declare function handleProjectDeploy(targetAccountId: number, projectName: string, buildId: number, useV3Api: boolean, force: boolean): Promise<Deploy | undefined>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { uiLogger } from '../ui/logger.js';
|
|
2
|
+
import { commands } from '../../lang/en.js';
|
|
3
|
+
import { PROJECT_ERROR_TYPES } from '../constants.js';
|
|
4
|
+
import { deployProject } from '@hubspot/local-dev-lib/api/projects';
|
|
5
|
+
import { pollDeployStatus } from './pollProjectBuildAndDeploy.js';
|
|
6
|
+
export function validateBuildIdForDeploy(buildId, deployedBuildId, latestBuildId, projectName, accountId) {
|
|
7
|
+
if (Number(buildId) > latestBuildId) {
|
|
8
|
+
return commands.project.deploy.errors.buildIdDoesNotExist(accountId, buildId, projectName);
|
|
9
|
+
}
|
|
10
|
+
if (Number(buildId) === deployedBuildId) {
|
|
11
|
+
return commands.project.deploy.errors.buildAlreadyDeployed(accountId, buildId, projectName);
|
|
12
|
+
}
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
export function logDeployErrors(errorData) {
|
|
16
|
+
uiLogger.error(errorData.message);
|
|
17
|
+
errorData.errors.forEach(err => {
|
|
18
|
+
// This is how the pre-deploy check manifests itself in < 2025.2 projects
|
|
19
|
+
if (err.subCategory === PROJECT_ERROR_TYPES.DEPLOY_CONTAINS_REMOVALS) {
|
|
20
|
+
uiLogger.log(commands.project.deploy.errors.deployContainsRemovals(err.context.COMPONENT_NAME));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
uiLogger.log(err.message);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function handleBlockedDeploy(deployResp) {
|
|
28
|
+
const deployCanBeForced = deployResp.issues.every(issue => issue.blockingMessages.every(message => message.isWarning));
|
|
29
|
+
uiLogger.log('');
|
|
30
|
+
if (deployCanBeForced) {
|
|
31
|
+
uiLogger.warn(commands.project.deploy.errors.deployWarningsHeader);
|
|
32
|
+
uiLogger.log('');
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
uiLogger.error(commands.project.deploy.errors.deployBlockedHeader);
|
|
36
|
+
uiLogger.log('');
|
|
37
|
+
}
|
|
38
|
+
deployResp.issues.forEach(issue => {
|
|
39
|
+
if (issue.blockingMessages.length > 0) {
|
|
40
|
+
issue.blockingMessages.forEach(message => {
|
|
41
|
+
uiLogger.log(commands.project.deploy.errors.deployIssueComponentWarning(issue.uid, issue.componentTypeName, message.message));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
uiLogger.log(commands.project.deploy.errors.deployIssueComponentGeneric(issue.uid, issue.componentTypeName));
|
|
46
|
+
}
|
|
47
|
+
uiLogger.log('');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export async function handleProjectDeploy(targetAccountId, projectName, buildId, useV3Api, force) {
|
|
51
|
+
const { data: deployResp } = await deployProject(targetAccountId, projectName, buildId, useV3Api, force);
|
|
52
|
+
if (!deployResp || deployResp.buildResultType !== 'DEPLOY_QUEUED') {
|
|
53
|
+
if (deployResp?.buildResultType === 'DEPLOY_BLOCKED') {
|
|
54
|
+
handleBlockedDeploy(deployResp);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
uiLogger.error(commands.project.deploy.errors.deploy);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const deployResult = await pollDeployStatus(targetAccountId, projectName, Number(deployResp.id), buildId);
|
|
62
|
+
return deployResult;
|
|
63
|
+
}
|
|
@@ -11,17 +11,19 @@ declare class AppDevModeInterface {
|
|
|
11
11
|
_appNode?: AppIRNode | null;
|
|
12
12
|
marketplaceAppInstalls?: number;
|
|
13
13
|
constructor(options: AppDevModeInterfaceConstructorOptions);
|
|
14
|
+
private getAppNodeFromProjectNodes;
|
|
14
15
|
private get appNode();
|
|
15
16
|
private get appData();
|
|
16
17
|
private set appData(value);
|
|
17
|
-
private isAutomaticallyInstallable;
|
|
18
18
|
private getAppInstallUrl;
|
|
19
19
|
private fetchAppData;
|
|
20
20
|
private checkMarketplaceAppInstalls;
|
|
21
|
-
private autoInstallStaticAuthApp;
|
|
22
21
|
private installAppOrOpenInstallUrl;
|
|
23
22
|
private checkTestAccountAppInstallation;
|
|
24
|
-
private
|
|
23
|
+
private onDevServerMessage;
|
|
24
|
+
private onChangeProjectNodes;
|
|
25
|
+
private setUpStateListeners;
|
|
26
|
+
private removeStateListeners;
|
|
25
27
|
setup(args: any): Promise<void>;
|
|
26
28
|
start(): Promise<void>;
|
|
27
29
|
fileChange(filePath: string, event: string): Promise<void>;
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { fetchAppInstallationData } from '@hubspot/local-dev-lib/api/localDevAuth';
|
|
2
|
-
import { fetchPublicAppsForPortal, fetchPublicAppProductionInstallCounts,
|
|
2
|
+
import { fetchPublicAppsForPortal, fetchPublicAppProductionInstallCounts,
|
|
3
|
+
// installStaticAuthAppOnTestAccount,
|
|
4
|
+
} from '@hubspot/local-dev-lib/api/appsDev';
|
|
3
5
|
import { DevModeUnifiedInterface as UIEDevModeInterface } from '@hubspot/ui-extensions-dev-server';
|
|
4
6
|
import { requestPorts } from '@hubspot/local-dev-lib/portManager';
|
|
5
|
-
import { getAccountConfig } from '@hubspot/local-dev-lib/config';
|
|
6
7
|
import { APP_AUTH_TYPES, APP_DISTRIBUTION_TYPES, APP_INSTALLATION_STATES, LOCAL_DEV_SERVER_MESSAGE_TYPES, } from '../../constants.js';
|
|
7
8
|
import { EXIT_CODES } from '../../enums/exitCodes.js';
|
|
8
9
|
import { isAppIRNode } from '../../projects/structure.js';
|
|
9
10
|
import { uiLine } from '../../ui/index.js';
|
|
10
11
|
import { logError } from '../../errorHandlers/index.js';
|
|
11
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
// installAppAutoPrompt,
|
|
14
|
+
installAppBrowserPrompt, } from '../../prompts/installAppPrompt.js';
|
|
12
15
|
import { confirmPrompt } from '../../prompts/promptUtils.js';
|
|
13
16
|
import { lib } from '../../../lang/en.js';
|
|
14
17
|
import { uiLogger } from '../../ui/logger.js';
|
|
15
18
|
import { getOauthAppInstallUrl, getStaticAuthAppInstallUrl, } from '../../app/urls.js';
|
|
16
|
-
import { isDeveloperTestAccount, isSandbox } from '../../accountTypes.js';
|
|
17
19
|
import SpinniesManager from '../../ui/SpinniesManager.js';
|
|
18
20
|
class AppDevModeInterface {
|
|
19
21
|
localDevState;
|
|
@@ -30,12 +32,13 @@ class AppDevModeInterface {
|
|
|
30
32
|
process.exit(EXIT_CODES.ERROR);
|
|
31
33
|
}
|
|
32
34
|
}
|
|
35
|
+
getAppNodeFromProjectNodes(projectNodes) {
|
|
36
|
+
return Object.values(projectNodes).find(isAppIRNode) || null;
|
|
37
|
+
}
|
|
33
38
|
// Assumes only one app per project
|
|
34
39
|
get appNode() {
|
|
35
40
|
if (this._appNode === undefined) {
|
|
36
|
-
this._appNode =
|
|
37
|
-
Object.values(this.localDevState.projectNodes).find(isAppIRNode) ||
|
|
38
|
-
null;
|
|
41
|
+
this._appNode = this.getAppNodeFromProjectNodes(this.localDevState.projectNodes);
|
|
39
42
|
}
|
|
40
43
|
return this._appNode;
|
|
41
44
|
}
|
|
@@ -51,19 +54,26 @@ class AppDevModeInterface {
|
|
|
51
54
|
}
|
|
52
55
|
this.localDevState.setAppDataForUid(this.appNode.uid, appData);
|
|
53
56
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
// @TODO: Restore test account auto install functionality
|
|
58
|
+
// private isAutomaticallyInstallable(): boolean {
|
|
59
|
+
// const targetTestingAccount = getAccountConfig(
|
|
60
|
+
// this.localDevState.targetTestingAccountId
|
|
61
|
+
// );
|
|
62
|
+
// if (!targetTestingAccount) {
|
|
63
|
+
// return false;
|
|
64
|
+
// }
|
|
65
|
+
// const isTestAccount =
|
|
66
|
+
// isDeveloperTestAccount(targetTestingAccount) ||
|
|
67
|
+
// isSandbox(targetTestingAccount);
|
|
68
|
+
// const hasCorrectParent =
|
|
69
|
+
// targetTestingAccount.parentAccountId ===
|
|
70
|
+
// this.localDevState.targetProjectAccountId;
|
|
71
|
+
// return (
|
|
72
|
+
// isTestAccount &&
|
|
73
|
+
// hasCorrectParent &&
|
|
74
|
+
// this.appNode?.config.auth.type === APP_AUTH_TYPES.STATIC
|
|
75
|
+
// );
|
|
76
|
+
// }
|
|
67
77
|
async getAppInstallUrl() {
|
|
68
78
|
if (this.appNode?.config.auth.type === APP_AUTH_TYPES.OAUTH) {
|
|
69
79
|
return getOauthAppInstallUrl({
|
|
@@ -90,7 +100,18 @@ class AppDevModeInterface {
|
|
|
90
100
|
SpinniesManager.add('fetchAppData', {
|
|
91
101
|
text: lib.AppDevModeInterface.fetchAppData.checking(this.appNode?.config.name || ''),
|
|
92
102
|
});
|
|
93
|
-
|
|
103
|
+
let portalApps = [];
|
|
104
|
+
try {
|
|
105
|
+
const { data: { results }, } = await fetchPublicAppsForPortal(this.localDevState.targetProjectAccountId);
|
|
106
|
+
portalApps = results;
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
SpinniesManager.fail('fetchAppData', {
|
|
110
|
+
text: lib.AppDevModeInterface.fetchAppData.error,
|
|
111
|
+
});
|
|
112
|
+
logError(e);
|
|
113
|
+
process.exit(EXIT_CODES.ERROR);
|
|
114
|
+
}
|
|
94
115
|
const appData = portalApps.find(({ sourceId }) => sourceId === this.appNode?.uid);
|
|
95
116
|
if (!appData) {
|
|
96
117
|
return;
|
|
@@ -122,27 +143,47 @@ class AppDevModeInterface {
|
|
|
122
143
|
}
|
|
123
144
|
this.localDevState.addUploadWarning(lib.AppDevModeInterface.defaultMarketplaceAppWarning(this.marketplaceAppInstalls));
|
|
124
145
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
146
|
+
// @TODO: Restore test account auto install functionality
|
|
147
|
+
// private async autoInstallStaticAuthApp(): Promise<void> {
|
|
148
|
+
// const shouldInstall = await installAppAutoPrompt();
|
|
149
|
+
// if (!shouldInstall) {
|
|
150
|
+
// uiLogger.log(lib.AppDevModeInterface.autoInstallDeclined);
|
|
151
|
+
// process.exit(EXIT_CODES.SUCCESS);
|
|
152
|
+
// }
|
|
153
|
+
// await installStaticAuthAppOnTestAccount(
|
|
154
|
+
// this.appData!.id,
|
|
155
|
+
// this.localDevState.targetTestingAccountId,
|
|
156
|
+
// this.appData!.scopeGroupIds
|
|
157
|
+
// );
|
|
158
|
+
// }
|
|
133
159
|
async installAppOrOpenInstallUrl(isReinstall) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
160
|
+
// @TODO: Restore test account auto install functionality
|
|
161
|
+
// if (this.isAutomaticallyInstallable()) {
|
|
162
|
+
// try {
|
|
163
|
+
// await this.autoInstallStaticAuthApp();
|
|
164
|
+
// uiLogger.success(
|
|
165
|
+
// lib.AppDevModeInterface.autoInstallSuccess(
|
|
166
|
+
// this.appData!.name,
|
|
167
|
+
// this.localDevState.targetTestingAccountId
|
|
168
|
+
// )
|
|
169
|
+
// );
|
|
170
|
+
// return;
|
|
171
|
+
// } catch (e) {
|
|
172
|
+
// uiLogger.error(
|
|
173
|
+
// lib.AppDevModeInterface.autoInstallError(
|
|
174
|
+
// this.appData!.name,
|
|
175
|
+
// this.localDevState.targetTestingAccountId
|
|
176
|
+
// )
|
|
177
|
+
// );
|
|
178
|
+
// }
|
|
179
|
+
// }
|
|
144
180
|
const installUrl = await this.getAppInstallUrl();
|
|
145
|
-
await installAppBrowserPrompt(installUrl, isReinstall
|
|
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
|
+
});
|
|
146
187
|
}
|
|
147
188
|
async checkTestAccountAppInstallation() {
|
|
148
189
|
if (!this.appNode || !this.appData) {
|
|
@@ -164,12 +205,33 @@ class AppDevModeInterface {
|
|
|
164
205
|
}
|
|
165
206
|
return { needsInstall: !isInstalledWithScopeGroups, isReinstall };
|
|
166
207
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
208
|
+
onDevServerMessage = (message) => {
|
|
209
|
+
if (message === LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED) {
|
|
210
|
+
this.checkTestAccountAppInstallation();
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
onChangeProjectNodes = (nodes) => {
|
|
214
|
+
const newAppNode = this.getAppNodeFromProjectNodes(nodes);
|
|
215
|
+
const oldDistribution = this.appNode?.config.distribution;
|
|
216
|
+
const newDistribution = newAppNode?.config.distribution;
|
|
217
|
+
const oldAuthType = this.appNode?.config.auth.type;
|
|
218
|
+
const newAuthType = newAppNode?.config.auth.type;
|
|
219
|
+
if (newDistribution === APP_DISTRIBUTION_TYPES.MARKETPLACE &&
|
|
220
|
+
oldDistribution !== APP_DISTRIBUTION_TYPES.MARKETPLACE) {
|
|
221
|
+
this.localDevState.addUploadWarning(lib.AppDevModeInterface.distributionChanged);
|
|
222
|
+
}
|
|
223
|
+
else if (newAuthType === APP_AUTH_TYPES.OAUTH &&
|
|
224
|
+
oldAuthType !== APP_AUTH_TYPES.OAUTH) {
|
|
225
|
+
this.localDevState.addUploadWarning(lib.AppDevModeInterface.authTypeChanged);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
setUpStateListeners() {
|
|
229
|
+
this.localDevState.addListener('devServerMessage', this.onDevServerMessage);
|
|
230
|
+
this.localDevState.addListener('projectNodes', this.onChangeProjectNodes);
|
|
231
|
+
}
|
|
232
|
+
removeStateListeners() {
|
|
233
|
+
this.localDevState.removeListener('devServerMessage', this.onDevServerMessage);
|
|
234
|
+
this.localDevState.removeListener('projectNodes', this.onChangeProjectNodes);
|
|
173
235
|
}
|
|
174
236
|
// @ts-expect-error TODO: reconcile types between CLI and UIE Dev Server
|
|
175
237
|
// In the future, update UIE Dev Server to use LocalDevState
|
|
@@ -204,7 +266,7 @@ class AppDevModeInterface {
|
|
|
204
266
|
catch (e) {
|
|
205
267
|
logError(e);
|
|
206
268
|
}
|
|
207
|
-
this.
|
|
269
|
+
this.setUpStateListeners();
|
|
208
270
|
return UIEDevModeInterface.setup(args);
|
|
209
271
|
}
|
|
210
272
|
async start() {
|
|
@@ -228,6 +290,7 @@ class AppDevModeInterface {
|
|
|
228
290
|
if (!this.appNode) {
|
|
229
291
|
return;
|
|
230
292
|
}
|
|
293
|
+
this.removeStateListeners();
|
|
231
294
|
return UIEDevModeInterface.cleanup();
|
|
232
295
|
}
|
|
233
296
|
}
|
|
@@ -34,6 +34,7 @@ class DevServerManagerV2 {
|
|
|
34
34
|
// @TODO: In the future, update UIE Dev Server to use LocalDevState
|
|
35
35
|
await serverInterface.setup({
|
|
36
36
|
components: this.localDevState.projectNodes,
|
|
37
|
+
profileData: this.localDevState.projectProfileData,
|
|
37
38
|
logger,
|
|
38
39
|
urls: {
|
|
39
40
|
api: getHubSpotApiOrigin(env),
|
|
@@ -8,7 +8,7 @@ import DevServerManagerV2 from './DevServerManagerV2.js';
|
|
|
8
8
|
import { EXIT_CODES } from '../../enums/exitCodes.js';
|
|
9
9
|
import { getProjectConfig } from '../config.js';
|
|
10
10
|
import { handleProjectUpload } from '../upload.js';
|
|
11
|
-
import { pollProjectBuildAndDeploy } from '../
|
|
11
|
+
import { pollProjectBuildAndDeploy } from '../pollProjectBuildAndDeploy.js';
|
|
12
12
|
import { getLocalDevUiUrl } from '../urls.js';
|
|
13
13
|
import { CONFIG_LOCAL_STATE_FLAGS } from '../../constants.js';
|
|
14
14
|
import { isAutoOpenBrowserEnabled } from '../../configOptions.js';
|
|
@@ -101,11 +101,13 @@ class LocalDevProcess {
|
|
|
101
101
|
const intermediateRepresentation = await this.getIntermediateRepresentation(this.state.projectNodesAtLastUpload);
|
|
102
102
|
this.state.projectNodes =
|
|
103
103
|
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
104
|
+
this.state.projectProfileData = intermediateRepresentation.profileData;
|
|
104
105
|
}
|
|
105
106
|
async updateProjectNodesAfterUpload() {
|
|
106
107
|
const intermediateRepresentation = await this.getIntermediateRepresentation();
|
|
107
108
|
this.state.projectNodes =
|
|
108
109
|
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
110
|
+
this.state.projectProfileData = intermediateRepresentation.profileData;
|
|
109
111
|
this.state.projectNodesAtLastUpload =
|
|
110
112
|
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
111
113
|
}
|