@hubspot/cli 7.7.32-experimental.0 → 7.7.34-experimental.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/app/__tests__/install.test.js +47 -0
- package/commands/app/install.d.ts +8 -0
- package/commands/app/install.js +122 -0
- package/commands/app.js +6 -1
- package/commands/getStarted.js +7 -20
- package/commands/project/__tests__/add.test.js +3 -5
- package/commands/project/__tests__/deploy.test.js +3 -2
- package/commands/project/add.js +2 -4
- 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/upload.d.ts +2 -2
- package/commands/project/upload.js +3 -3
- package/commands/project/validate.js +1 -1
- package/commands/project/watch.js +2 -2
- package/commands/testAccount/create.js +3 -0
- package/lang/en.d.ts +30 -4
- package/lang/en.js +31 -5
- package/lib/__tests__/hasFeature.test.js +145 -7
- package/lib/__tests__/importData.test.js +1 -1
- package/lib/app/migrate.js +9 -2
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +2 -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/mcp/setup.js +1 -1
- package/lib/projectProfiles.d.ts +1 -1
- package/lib/projectProfiles.js +10 -2
- package/lib/projects/__tests__/AppDevModeInterface.test.js +61 -44
- package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
- package/lib/projects/__tests__/deploy.test.d.ts +1 -0
- 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 +71 -1
- package/lib/projects/add/legacyAddComponent.d.ts +1 -1
- package/lib/projects/add/legacyAddComponent.js +5 -1
- package/lib/projects/add/v3AddComponent.d.ts +1 -0
- package/lib/projects/add/v3AddComponent.js +2 -2
- 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 +0 -2
- package/lib/projects/localDev/AppDevModeInterface.js +65 -36
- 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 -7
- 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/structure.d.ts +2 -2
- package/lib/projects/upload.d.ts +2 -1
- package/lib/projects/upload.js +2 -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/selectProjectTemplatePrompt.js +1 -1
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +1 -1
- package/mcp-server/tools/cms/HsCreateModuleTool.js +1 -1
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +1 -1
- 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.js +1 -1
- package/mcp-server/tools/cms/HsListTool.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +1 -1
- 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.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +1 -1
- package/mcp-server/tools/index.js +2 -0
- 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.js +2 -2
- package/mcp-server/tools/project/GetConfigValuesTool.js +4 -4
- 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 +2 -2
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +1 -1
- 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/package.json +3 -3
- package/types/LocalDev.d.ts +2 -1
- package/types/Projects.d.ts +1 -0
- package/types/Yargs.d.ts +1 -1
- /package/{lib/projects/__tests__/buildAndDeploy.test.d.ts → commands/app/__tests__/install.test.d.ts} +0 -0
|
@@ -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
|
+
}
|
|
@@ -15,11 +15,9 @@ declare class AppDevModeInterface {
|
|
|
15
15
|
private get appNode();
|
|
16
16
|
private get appData();
|
|
17
17
|
private set appData(value);
|
|
18
|
-
private isAutomaticallyInstallable;
|
|
19
18
|
private getAppInstallUrl;
|
|
20
19
|
private fetchAppData;
|
|
21
20
|
private checkMarketplaceAppInstalls;
|
|
22
|
-
private autoInstallStaticAuthApp;
|
|
23
21
|
private installAppOrOpenInstallUrl;
|
|
24
22
|
private checkTestAccountAppInstallation;
|
|
25
23
|
private onDevServerMessage;
|
|
@@ -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;
|
|
@@ -52,19 +54,26 @@ class AppDevModeInterface {
|
|
|
52
54
|
}
|
|
53
55
|
this.localDevState.setAppDataForUid(this.appNode.uid, appData);
|
|
54
56
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
+
// }
|
|
68
77
|
async getAppInstallUrl() {
|
|
69
78
|
if (this.appNode?.config.auth.type === APP_AUTH_TYPES.OAUTH) {
|
|
70
79
|
return getOauthAppInstallUrl({
|
|
@@ -134,27 +143,47 @@ class AppDevModeInterface {
|
|
|
134
143
|
}
|
|
135
144
|
this.localDevState.addUploadWarning(lib.AppDevModeInterface.defaultMarketplaceAppWarning(this.marketplaceAppInstalls));
|
|
136
145
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
+
// }
|
|
145
159
|
async installAppOrOpenInstallUrl(isReinstall) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
+
// }
|
|
156
180
|
const installUrl = await this.getAppInstallUrl();
|
|
157
|
-
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
|
+
});
|
|
158
187
|
}
|
|
159
188
|
async checkTestAccountAppInstallation() {
|
|
160
189
|
if (!this.appNode || !this.appData) {
|
|
@@ -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
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types.js';
|
|
1
|
+
import { IntermediateRepresentationNodeLocalDev, HSProfileVariables } from '@hubspot/project-parsing-lib/src/lib/types.js';
|
|
2
2
|
import { Environment } from '@hubspot/local-dev-lib/types/Config';
|
|
3
3
|
import { ProjectConfig } from '../../../types/Projects.js';
|
|
4
4
|
import { LocalDevStateConstructorOptions, LocalDevStateListener, AppLocalDevData, LocalDevServerMessage } from '../../../types/LocalDev.js';
|
|
@@ -12,13 +12,14 @@ declare class LocalDevState {
|
|
|
12
12
|
private _projectName;
|
|
13
13
|
private _debug;
|
|
14
14
|
private _projectNodes;
|
|
15
|
+
private _projectProfileData;
|
|
15
16
|
private _projectNodesAtLastUpload;
|
|
16
17
|
private _env;
|
|
17
18
|
private _listeners;
|
|
18
19
|
private _appData;
|
|
19
20
|
private _devServerMessage;
|
|
20
21
|
private _uploadWarnings;
|
|
21
|
-
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, initialProjectNodes, profile, env, }: LocalDevStateConstructorOptions);
|
|
22
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, initialProjectNodes, initialProjectProfileData, profile, env, }: LocalDevStateConstructorOptions);
|
|
22
23
|
private runListeners;
|
|
23
24
|
get targetProjectAccountId(): number;
|
|
24
25
|
get targetTestingAccountId(): number;
|
|
@@ -34,6 +35,8 @@ declare class LocalDevState {
|
|
|
34
35
|
set projectNodes(nodes: {
|
|
35
36
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
36
37
|
});
|
|
38
|
+
get projectProfileData(): HSProfileVariables;
|
|
39
|
+
set projectProfileData(profileData: HSProfileVariables);
|
|
37
40
|
get projectNodesAtLastUpload(): {
|
|
38
41
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
39
42
|
};
|
|
@@ -9,13 +9,14 @@ class LocalDevState {
|
|
|
9
9
|
_projectName;
|
|
10
10
|
_debug;
|
|
11
11
|
_projectNodes;
|
|
12
|
+
_projectProfileData;
|
|
12
13
|
_projectNodesAtLastUpload;
|
|
13
14
|
_env;
|
|
14
15
|
_listeners;
|
|
15
16
|
_appData;
|
|
16
17
|
_devServerMessage;
|
|
17
18
|
_uploadWarnings;
|
|
18
|
-
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, initialProjectNodes, profile, env, }) {
|
|
19
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, initialProjectNodes, initialProjectProfileData, profile, env, }) {
|
|
19
20
|
this._targetProjectAccountId = targetProjectAccountId;
|
|
20
21
|
this._targetTestingAccountId = targetTestingAccountId;
|
|
21
22
|
this._profile = profile;
|
|
@@ -26,6 +27,7 @@ class LocalDevState {
|
|
|
26
27
|
this._debug = debug || false;
|
|
27
28
|
this._projectNodes = initialProjectNodes;
|
|
28
29
|
this._projectNodesAtLastUpload = initialProjectNodes;
|
|
30
|
+
this._projectProfileData = initialProjectProfileData;
|
|
29
31
|
this._env = env;
|
|
30
32
|
this._appData = {};
|
|
31
33
|
this._devServerMessage = LOCAL_DEV_SERVER_MESSAGE_TYPES.INITIAL;
|
|
@@ -68,6 +70,12 @@ class LocalDevState {
|
|
|
68
70
|
this._projectNodes = nodes;
|
|
69
71
|
this.runListeners('projectNodes');
|
|
70
72
|
}
|
|
73
|
+
get projectProfileData() {
|
|
74
|
+
return structuredClone(this._projectProfileData);
|
|
75
|
+
}
|
|
76
|
+
set projectProfileData(profileData) {
|
|
77
|
+
this._projectProfileData = profileData;
|
|
78
|
+
}
|
|
71
79
|
get projectNodesAtLastUpload() {
|
|
72
80
|
return structuredClone(this._projectNodesAtLastUpload);
|
|
73
81
|
}
|
|
@@ -6,7 +6,7 @@ export declare function createNewProjectForLocalDev(projectConfig: ProjectConfig
|
|
|
6
6
|
export declare function createInitialBuildForNewProject(projectConfig: ProjectConfig, projectDir: string, targetAccountId: number, sendIR?: boolean, profile?: string): Promise<Build>;
|
|
7
7
|
export declare function compareLocalProjectToDeployed(projectConfig: ProjectConfig, accountId: number, deployedBuildId: number | undefined, localProjectNodes: {
|
|
8
8
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
9
|
-
}): Promise<void>;
|
|
9
|
+
}, profile?: string): Promise<void>;
|
|
10
10
|
export declare function isDeployedProjectUpToDateWithLocal(projectConfig: ProjectConfig, accountId: number, deployedBuildId: number, localProjectNodes: {
|
|
11
11
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
12
|
-
}): Promise<boolean>;
|
|
12
|
+
}, profile?: string): Promise<boolean>;
|
|
@@ -17,7 +17,7 @@ import { uiAccountDescription } from '../../../ui/index.js';
|
|
|
17
17
|
import SpinniesManager from '../../../ui/SpinniesManager.js';
|
|
18
18
|
import { EXIT_CODES } from '../../../enums/exitCodes.js';
|
|
19
19
|
import { handleProjectUpload } from '../../upload.js';
|
|
20
|
-
import { pollProjectBuildAndDeploy } from '../../
|
|
20
|
+
import { pollProjectBuildAndDeploy } from '../../pollProjectBuildAndDeploy.js';
|
|
21
21
|
import { logError } from '../../../errorHandlers/index.js';
|
|
22
22
|
import { ApiErrorContext } from '../../../errorHandlers/index.js';
|
|
23
23
|
// Prompt the user to create a new project if one doesn't exist on their target account
|
|
@@ -123,7 +123,7 @@ export async function createInitialBuildForNewProject(projectConfig, projectDir,
|
|
|
123
123
|
}
|
|
124
124
|
return initialUploadResult.buildResult;
|
|
125
125
|
}
|
|
126
|
-
export async function compareLocalProjectToDeployed(projectConfig, accountId, deployedBuildId, localProjectNodes) {
|
|
126
|
+
export async function compareLocalProjectToDeployed(projectConfig, accountId, deployedBuildId, localProjectNodes, profile) {
|
|
127
127
|
uiLogger.log('');
|
|
128
128
|
if (!deployedBuildId) {
|
|
129
129
|
uiLogger.error(lib.localDevHelpers.project.compareLocalProjectToDeployed.noDeployedBuild(projectConfig.name, uiAccountDescription(accountId)));
|
|
@@ -132,7 +132,7 @@ export async function compareLocalProjectToDeployed(projectConfig, accountId, de
|
|
|
132
132
|
SpinniesManager.add('compareLocalProjectToDeployed', {
|
|
133
133
|
text: lib.localDevHelpers.project.compareLocalProjectToDeployed.checking,
|
|
134
134
|
});
|
|
135
|
-
const isUpToDate = await isDeployedProjectUpToDateWithLocal(projectConfig, accountId, deployedBuildId, localProjectNodes);
|
|
135
|
+
const isUpToDate = await isDeployedProjectUpToDateWithLocal(projectConfig, accountId, deployedBuildId, localProjectNodes, profile);
|
|
136
136
|
if (isUpToDate) {
|
|
137
137
|
SpinniesManager.succeed('compareLocalProjectToDeployed', {
|
|
138
138
|
text: lib.localDevHelpers.project.compareLocalProjectToDeployed.upToDate,
|
|
@@ -144,12 +144,11 @@ export async function compareLocalProjectToDeployed(projectConfig, accountId, de
|
|
|
144
144
|
.notUpToDate,
|
|
145
145
|
});
|
|
146
146
|
uiLogger.log('');
|
|
147
|
-
uiLogger.log(lib.localDevHelpers.project.compareLocalProjectToDeployed
|
|
148
|
-
.notUpToDateExplanation);
|
|
147
|
+
uiLogger.log(lib.localDevHelpers.project.compareLocalProjectToDeployed.notUpToDateExplanation(profile));
|
|
149
148
|
process.exit(EXIT_CODES.SUCCESS);
|
|
150
149
|
}
|
|
151
150
|
}
|
|
152
|
-
export async function isDeployedProjectUpToDateWithLocal(projectConfig, accountId, deployedBuildId, localProjectNodes) {
|
|
151
|
+
export async function isDeployedProjectUpToDateWithLocal(projectConfig, accountId, deployedBuildId, localProjectNodes, profile) {
|
|
153
152
|
let tempDir = null;
|
|
154
153
|
try {
|
|
155
154
|
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'hubspot-project-compare-'));
|
|
@@ -161,7 +160,7 @@ export async function isDeployedProjectUpToDateWithLocal(projectConfig, accountI
|
|
|
161
160
|
projectSourceDir: deployedProjectSourceDir,
|
|
162
161
|
platformVersion: projectConfig.platformVersion,
|
|
163
162
|
accountId: accountId,
|
|
164
|
-
}, {});
|
|
163
|
+
}, { profile });
|
|
165
164
|
return isDeepEqual(localProjectNodes, deployedProjectNodes, ['localDev']);
|
|
166
165
|
}
|
|
167
166
|
finally {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useV3Api(platformVersion?: string | null): boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function useV3Api(platformVersion) {
|
|
2
|
+
if (!platformVersion || typeof platformVersion !== 'string') {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
if (platformVersion.toLowerCase() === 'unstable') {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
const [year, minor] = platformVersion.split('.');
|
|
9
|
+
return Number(year) >= 2025 && Number(minor) >= 2;
|
|
10
|
+
}
|
|
@@ -2,7 +2,6 @@ import { FileResult } from 'tmp';
|
|
|
2
2
|
import { Build } from '@hubspot/local-dev-lib/types/Build';
|
|
3
3
|
import { Deploy } from '@hubspot/local-dev-lib/types/Deploy';
|
|
4
4
|
import { ProjectConfig, ProjectTask, ProjectPollResult } from '../../types/Projects.js';
|
|
5
|
-
export declare function useV3Api(platformVersion?: string | null): boolean;
|
|
6
5
|
type PollTaskStatusFunction<T extends ProjectTask> = (accountId: number, taskName: string, taskId: number, deployedBuildId: number | null, silenceLogs?: boolean) => Promise<T>;
|
|
7
6
|
export declare const pollBuildStatus: PollTaskStatusFunction<Build>;
|
|
8
7
|
export declare const pollDeployStatus: PollTaskStatusFunction<Deploy>;
|
|
@@ -13,16 +13,6 @@ import { mapToInternalType } from '@hubspot/project-parsing-lib';
|
|
|
13
13
|
const SPINNER_STATUS = {
|
|
14
14
|
SPINNING: 'spinning',
|
|
15
15
|
};
|
|
16
|
-
export function useV3Api(platformVersion) {
|
|
17
|
-
if (!platformVersion || typeof platformVersion !== 'string') {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
if (platformVersion.toLowerCase() === 'unstable') {
|
|
21
|
-
return true;
|
|
22
|
-
}
|
|
23
|
-
const [year, minor] = platformVersion.split('.');
|
|
24
|
-
return Number(year) >= 2025 && Number(minor) >= 2;
|
|
25
|
-
}
|
|
26
16
|
function getSubtasks(task) {
|
|
27
17
|
if ('subbuildStatuses' in task) {
|
|
28
18
|
return task.subbuildStatuses;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentTypes, Component, GenericComponentConfig, PublicAppComponentConfig, PrivateAppComponentConfig, AppCardComponentConfig } from '../../types/Projects.js';
|
|
2
|
-
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types.js';
|
|
2
|
+
import { IntermediateRepresentationNode, 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): component is AppIRNode;
|
|
18
|
+
export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev | IntermediateRepresentationNode): component is AppIRNode;
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FileResult } from 'tmp';
|
|
2
|
+
import { IntermediateRepresentation } from '@hubspot/project-parsing-lib';
|
|
2
3
|
import { ProjectConfig } from '../../types/Projects.js';
|
|
3
4
|
type ProjectUploadCallbackFunction<T> = (accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number) => Promise<T>;
|
|
4
5
|
type ProjectUploadResult<T> = {
|
|
@@ -20,5 +21,5 @@ type HandleProjectUploadArg<T> = {
|
|
|
20
21
|
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
|
|
21
22
|
export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig): void;
|
|
22
23
|
export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
23
|
-
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<
|
|
24
|
+
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<IntermediateRepresentation | undefined>;
|
|
24
25
|
export {};
|
package/lib/projects/upload.js
CHANGED
|
@@ -12,7 +12,7 @@ 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 './
|
|
15
|
+
import { useV3Api } from './platformVersion.js';
|
|
16
16
|
import { EXIT_CODES } from '../enums/exitCodes.js';
|
|
17
17
|
import ProjectValidationError from '../errors/ProjectValidationError.js';
|
|
18
18
|
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
|
|
@@ -133,4 +133,5 @@ export async function handleTranslate(projectDir, projectConfig, accountId, skip
|
|
|
133
133
|
}
|
|
134
134
|
throw e;
|
|
135
135
|
}
|
|
136
|
+
return undefined;
|
|
136
137
|
}
|
package/lib/projects/urls.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export declare function getProjectBuildDetailUrl(projectName: string, buildId: n
|
|
|
7
7
|
export declare function getProjectDeployDetailUrl(projectName: string, deployId: number, accountId: number): string;
|
|
8
8
|
export declare function getLocalDevUiUrl(accountId: number, showWelcomeScreen?: boolean): string;
|
|
9
9
|
export declare function getAccountHomeUrl(accountId: number): string;
|
|
10
|
+
export declare function getAppAllowlistUrl(accountId: number, projectName: string, appUid: string): string;
|
package/lib/projects/urls.js
CHANGED
|
@@ -41,3 +41,6 @@ export function getAccountHomeUrl(accountId) {
|
|
|
41
41
|
const baseUrl = getHubSpotWebsiteOrigin(getEnv(accountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD);
|
|
42
42
|
return `${baseUrl}/home?portalId=${accountId}`;
|
|
43
43
|
}
|
|
44
|
+
export function getAppAllowlistUrl(accountId, projectName, appUid) {
|
|
45
|
+
return `${getProjectHomeUrl(accountId)}/project/${projectName}/component/${appUid}/distribution?panel=static-token-allowlist`;
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|