@hubspot/cli 7.7.27-experimental.2 → 7.7.29-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/README.md +0 -4
- package/api/__tests__/migrate.test.js +5 -5
- package/api/migrate.d.ts +10 -4
- package/api/migrate.js +2 -2
- package/commands/__tests__/create.test.js +20 -0
- package/commands/__tests__/testAccount.test.js +2 -0
- package/commands/app/__tests__/migrate.test.js +1 -0
- package/commands/create/function.js +2 -2
- package/commands/create/module.js +2 -2
- package/commands/create/template.js +2 -2
- package/commands/create.js +47 -0
- package/commands/getStarted.js +66 -4
- package/commands/mcp/setup.d.ts +0 -1
- package/commands/mcp/setup.js +3 -11
- package/commands/project/__tests__/create.test.js +57 -0
- package/commands/project/__tests__/devUnifiedFlow.test.js +18 -30
- package/commands/project/create.js +6 -1
- package/commands/project/deploy.js +31 -1
- package/commands/project/dev/deprecatedFlow.js +2 -1
- package/commands/project/dev/index.js +32 -12
- package/commands/project/dev/unifiedFlow.d.ts +1 -1
- package/commands/project/dev/unifiedFlow.js +10 -16
- package/commands/project/profile/delete.js +26 -14
- package/commands/testAccount/__tests__/importData.test.d.ts +1 -0
- package/commands/testAccount/__tests__/importData.test.js +93 -0
- package/commands/testAccount/create.js +23 -13
- package/commands/testAccount/importData.d.ts +9 -0
- package/commands/testAccount/importData.js +61 -0
- package/commands/testAccount.js +2 -0
- package/lang/en.d.ts +162 -46
- package/lang/en.js +177 -59
- package/lang/en.lyaml +35 -14
- package/lib/__tests__/importData.test.d.ts +1 -0
- package/lib/__tests__/importData.test.js +89 -0
- package/lib/accountTypes.js +2 -3
- package/lib/app/__tests__/migrate.test.js +81 -36
- package/lib/app/migrate.d.ts +17 -4
- package/lib/app/migrate.js +97 -19
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +1 -0
- package/lib/hasFeature.d.ts +1 -0
- package/lib/hasFeature.js +7 -0
- package/lib/importData.d.ts +3 -0
- package/lib/importData.js +50 -0
- package/lib/mcp/setup.d.ts +3 -5
- package/lib/mcp/setup.js +39 -139
- package/lib/process.js +15 -4
- package/lib/projects/__tests__/AppDevModeInterface.test.js +3 -3
- package/lib/projects/__tests__/LocalDevProcess.test.js +5 -95
- package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +6 -6
- package/lib/projects/__tests__/components.test.js +164 -7
- package/lib/projects/__tests__/localDevProjectHelpers.test.d.ts +1 -0
- package/lib/projects/__tests__/localDevProjectHelpers.test.js +118 -0
- package/lib/projects/add/v3AddComponent.js +16 -4
- package/lib/projects/components.d.ts +1 -0
- package/lib/projects/components.js +27 -1
- package/lib/projects/localDev/AppDevModeInterface.js +35 -3
- package/lib/projects/localDev/LocalDevLogger.d.ts +0 -4
- package/lib/projects/localDev/LocalDevLogger.js +2 -19
- package/lib/projects/localDev/LocalDevManager.js +1 -1
- package/lib/projects/localDev/LocalDevProcess.d.ts +1 -2
- package/lib/projects/localDev/LocalDevProcess.js +3 -26
- package/lib/projects/localDev/LocalDevState.d.ts +6 -7
- package/lib/projects/localDev/LocalDevState.js +16 -15
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +1 -0
- package/lib/projects/localDev/LocalDevWebsocketServer.js +17 -2
- package/lib/projects/localDev/{helpers.d.ts → helpers/account.d.ts} +1 -7
- package/lib/projects/localDev/{helpers.js → helpers/account.js} +44 -144
- package/lib/projects/localDev/helpers/project.d.ts +12 -0
- package/lib/projects/localDev/helpers/project.js +173 -0
- package/lib/projects/urls.d.ts +1 -0
- package/lib/projects/urls.js +4 -0
- package/lib/prompts/__tests__/createFunctionPrompt.test.d.ts +1 -0
- package/lib/prompts/__tests__/createFunctionPrompt.test.js +129 -0
- package/lib/prompts/__tests__/createModulePrompt.test.d.ts +1 -0
- package/lib/prompts/__tests__/createModulePrompt.test.js +187 -0
- package/lib/prompts/__tests__/createTemplatePrompt.test.d.ts +1 -0
- package/lib/prompts/__tests__/createTemplatePrompt.test.js +102 -0
- package/lib/prompts/confirmImportDataPrompt.d.ts +1 -0
- package/lib/prompts/confirmImportDataPrompt.js +12 -0
- package/lib/prompts/createFunctionPrompt.d.ts +2 -1
- package/lib/prompts/createFunctionPrompt.js +36 -7
- package/lib/prompts/createModulePrompt.d.ts +2 -1
- package/lib/prompts/createModulePrompt.js +48 -1
- package/lib/prompts/createTemplatePrompt.d.ts +3 -24
- package/lib/prompts/createTemplatePrompt.js +9 -1
- package/lib/prompts/importDataFilePathPrompt.d.ts +1 -0
- package/lib/prompts/importDataFilePathPrompt.js +24 -0
- package/lib/prompts/importDataTestAccountSelectPrompt.d.ts +3 -0
- package/lib/prompts/importDataTestAccountSelectPrompt.js +29 -0
- package/lib/prompts/projectDevTargetAccountPrompt.js +1 -0
- package/lib/prompts/promptUtils.d.ts +7 -1
- package/lib/prompts/promptUtils.js +14 -1
- package/lib/ui/__tests__/removeAnsiCodes.test.d.ts +1 -0
- package/lib/ui/__tests__/removeAnsiCodes.test.js +84 -0
- package/lib/ui/index.js +3 -6
- package/lib/ui/removeAnsiCodes.d.ts +1 -0
- package/lib/ui/removeAnsiCodes.js +4 -0
- package/mcp-server/server.js +2 -1
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +38 -0
- package/mcp-server/tools/cms/HsCreateModuleTool.js +118 -0
- package/mcp-server/tools/cms/HsListTool.d.ts +23 -0
- package/mcp-server/tools/cms/HsListTool.js +58 -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__/HsListTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +120 -0
- package/mcp-server/tools/index.d.ts +1 -0
- package/mcp-server/tools/index.js +12 -0
- package/mcp-server/tools/project/DocFetchTool.d.ts +17 -0
- package/mcp-server/tools/project/DocFetchTool.js +49 -0
- package/mcp-server/tools/project/DocsSearchTool.d.ts +26 -0
- package/mcp-server/tools/project/DocsSearchTool.js +62 -0
- package/mcp-server/tools/project/GetConfigValuesTool.js +3 -2
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +117 -0
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +190 -0
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +1 -1
- package/mcp-server/tools/project/constants.d.ts +2 -0
- package/mcp-server/tools/project/constants.js +6 -0
- package/mcp-server/utils/toolUsageTracking.d.ts +3 -1
- package/mcp-server/utils/toolUsageTracking.js +2 -1
- package/package.json +9 -6
- package/types/Cms.d.ts +16 -0
- package/types/Cms.js +25 -1
- package/types/LocalDev.d.ts +0 -3
- package/types/Prompts.d.ts +1 -0
- package/ui/index.d.ts +1 -0
- package/ui/index.js +6 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Build } from '@hubspot/local-dev-lib/types/Build';
|
|
2
1
|
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types.js';
|
|
3
2
|
import { Environment } from '@hubspot/local-dev-lib/types/Config';
|
|
4
3
|
import { ProjectConfig } from '../../../types/Projects.js';
|
|
@@ -12,15 +11,14 @@ declare class LocalDevState {
|
|
|
12
11
|
private _projectId;
|
|
13
12
|
private _projectName;
|
|
14
13
|
private _debug;
|
|
15
|
-
private _deployedBuild?;
|
|
16
|
-
private _isGithubLinked;
|
|
17
14
|
private _projectNodes;
|
|
18
15
|
private _projectNodesAtLastUpload;
|
|
19
16
|
private _env;
|
|
20
17
|
private _listeners;
|
|
21
18
|
private _appData;
|
|
22
19
|
private _devServerMessage;
|
|
23
|
-
|
|
20
|
+
private _uploadWarnings;
|
|
21
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, initialProjectNodes, profile, env, }: LocalDevStateConstructorOptions);
|
|
24
22
|
private runListeners;
|
|
25
23
|
get targetProjectAccountId(): number;
|
|
26
24
|
get targetTestingAccountId(): number;
|
|
@@ -30,8 +28,6 @@ declare class LocalDevState {
|
|
|
30
28
|
get projectId(): number;
|
|
31
29
|
get projectName(): string;
|
|
32
30
|
get debug(): boolean;
|
|
33
|
-
get deployedBuild(): Build | undefined;
|
|
34
|
-
get isGithubLinked(): boolean;
|
|
35
31
|
get projectNodes(): {
|
|
36
32
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
37
33
|
};
|
|
@@ -50,7 +46,10 @@ declare class LocalDevState {
|
|
|
50
46
|
setAppDataForUid(uid: string, appData: AppLocalDevData): void;
|
|
51
47
|
get devServerMessage(): string;
|
|
52
48
|
set devServerMessage(message: LocalDevServerMessage);
|
|
53
|
-
|
|
49
|
+
get uploadWarnings(): Set<string>;
|
|
50
|
+
addUploadWarning(warning: string): void;
|
|
51
|
+
clearUploadWarnings(): void;
|
|
52
|
+
addListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>): void;
|
|
54
53
|
removeListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>): void;
|
|
55
54
|
}
|
|
56
55
|
export default LocalDevState;
|
|
@@ -8,15 +8,14 @@ class LocalDevState {
|
|
|
8
8
|
_projectId;
|
|
9
9
|
_projectName;
|
|
10
10
|
_debug;
|
|
11
|
-
_deployedBuild;
|
|
12
|
-
_isGithubLinked;
|
|
13
11
|
_projectNodes;
|
|
14
12
|
_projectNodesAtLastUpload;
|
|
15
13
|
_env;
|
|
16
14
|
_listeners;
|
|
17
15
|
_appData;
|
|
18
16
|
_devServerMessage;
|
|
19
|
-
|
|
17
|
+
_uploadWarnings;
|
|
18
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, initialProjectNodes, profile, env, }) {
|
|
20
19
|
this._targetProjectAccountId = targetProjectAccountId;
|
|
21
20
|
this._targetTestingAccountId = targetTestingAccountId;
|
|
22
21
|
this._profile = profile;
|
|
@@ -25,13 +24,12 @@ class LocalDevState {
|
|
|
25
24
|
this._projectId = projectId;
|
|
26
25
|
this._projectName = projectName;
|
|
27
26
|
this._debug = debug || false;
|
|
28
|
-
this._deployedBuild = deployedBuild;
|
|
29
|
-
this._isGithubLinked = isGithubLinked;
|
|
30
27
|
this._projectNodes = initialProjectNodes;
|
|
31
28
|
this._projectNodesAtLastUpload = initialProjectNodes;
|
|
32
29
|
this._env = env;
|
|
33
30
|
this._appData = {};
|
|
34
31
|
this._devServerMessage = LOCAL_DEV_SERVER_MESSAGE_TYPES.INITIAL;
|
|
32
|
+
this._uploadWarnings = new Set();
|
|
35
33
|
this._listeners = {};
|
|
36
34
|
}
|
|
37
35
|
runListeners(key) {
|
|
@@ -63,12 +61,6 @@ class LocalDevState {
|
|
|
63
61
|
get debug() {
|
|
64
62
|
return this._debug;
|
|
65
63
|
}
|
|
66
|
-
get deployedBuild() {
|
|
67
|
-
return this._deployedBuild && structuredClone(this._deployedBuild);
|
|
68
|
-
}
|
|
69
|
-
get isGithubLinked() {
|
|
70
|
-
return this._isGithubLinked;
|
|
71
|
-
}
|
|
72
64
|
get projectNodes() {
|
|
73
65
|
return structuredClone(this._projectNodes);
|
|
74
66
|
}
|
|
@@ -102,14 +94,23 @@ class LocalDevState {
|
|
|
102
94
|
this._devServerMessage = message;
|
|
103
95
|
this.runListeners('devServerMessage');
|
|
104
96
|
}
|
|
105
|
-
|
|
97
|
+
get uploadWarnings() {
|
|
98
|
+
return this._uploadWarnings;
|
|
99
|
+
}
|
|
100
|
+
addUploadWarning(warning) {
|
|
101
|
+
this.uploadWarnings.add(warning);
|
|
102
|
+
this.runListeners('uploadWarnings');
|
|
103
|
+
}
|
|
104
|
+
clearUploadWarnings() {
|
|
105
|
+
this.uploadWarnings.clear();
|
|
106
|
+
this.runListeners('uploadWarnings');
|
|
107
|
+
}
|
|
108
|
+
addListener(key, listener) {
|
|
106
109
|
if (!this._listeners[key]) {
|
|
107
110
|
this._listeners[key] = [];
|
|
108
111
|
}
|
|
109
112
|
this._listeners[key].push(listener);
|
|
110
|
-
|
|
111
|
-
listener(this[key]);
|
|
112
|
-
}
|
|
113
|
+
listener(this[key]);
|
|
113
114
|
}
|
|
114
115
|
removeListener(key, listener) {
|
|
115
116
|
if (this._listeners[key]) {
|
|
@@ -4,6 +4,7 @@ import { logger } from '@hubspot/local-dev-lib/logger';
|
|
|
4
4
|
import { addLocalStateFlag } from '@hubspot/local-dev-lib/config';
|
|
5
5
|
import { LOCAL_DEV_UI_MESSAGE_SEND_TYPES, LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES, LOCAL_DEV_SERVER_MESSAGE_TYPES, CONFIG_LOCAL_STATE_FLAGS, } from '../../constants.js';
|
|
6
6
|
import { lib } from '../../../lang/en.js';
|
|
7
|
+
import { removeAnsiCodes } from '../../ui/removeAnsiCodes.js';
|
|
7
8
|
const SERVER_INSTANCE_ID = 'local-dev-ui-websocket-server';
|
|
8
9
|
const LOG_PREFIX = '[LocalDevWebsocketServer]';
|
|
9
10
|
class LocalDevWebsocketServer {
|
|
@@ -88,7 +89,7 @@ class LocalDevWebsocketServer {
|
|
|
88
89
|
data: nodes,
|
|
89
90
|
});
|
|
90
91
|
};
|
|
91
|
-
this.localDevProcess.addStateListener('projectNodes', listener
|
|
92
|
+
this.localDevProcess.addStateListener('projectNodes', listener);
|
|
92
93
|
websocket.on('close', () => {
|
|
93
94
|
this.localDevProcess.removeStateListener('projectNodes', listener);
|
|
94
95
|
});
|
|
@@ -100,14 +101,28 @@ class LocalDevWebsocketServer {
|
|
|
100
101
|
data: appData,
|
|
101
102
|
});
|
|
102
103
|
};
|
|
103
|
-
this.localDevProcess.addStateListener('appData', listener
|
|
104
|
+
this.localDevProcess.addStateListener('appData', listener);
|
|
104
105
|
websocket.on('close', () => {
|
|
105
106
|
this.localDevProcess.removeStateListener('appData', listener);
|
|
106
107
|
});
|
|
107
108
|
}
|
|
109
|
+
setupUploadWarningsListener(websocket) {
|
|
110
|
+
const listener = (uploadWarnings) => {
|
|
111
|
+
const formattedUploadWarnings = Array.from(uploadWarnings).map(removeAnsiCodes);
|
|
112
|
+
this.sendMessage(websocket, {
|
|
113
|
+
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_UPLOAD_WARNINGS,
|
|
114
|
+
data: { uploadWarnings: formattedUploadWarnings },
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
this.localDevProcess.addStateListener('uploadWarnings', listener);
|
|
118
|
+
websocket.on('close', () => {
|
|
119
|
+
this.localDevProcess.removeStateListener('uploadWarnings', listener);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
108
122
|
setupStateListeners(websocket) {
|
|
109
123
|
this.setupProjectNodesListener(websocket);
|
|
110
124
|
this.setupAppDataListener(websocket);
|
|
125
|
+
this.setupUploadWarningsListener(websocket);
|
|
111
126
|
}
|
|
112
127
|
async start() {
|
|
113
128
|
const portManagerIsRunning = await isPortManagerServerRunning();
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { CLIAccount } from '@hubspot/local-dev-lib/types/Accounts';
|
|
2
2
|
import { Environment } from '@hubspot/local-dev-lib/types/Config';
|
|
3
3
|
import { DeveloperTestAccount } from '@hubspot/local-dev-lib/types/developerTestAccounts.js';
|
|
4
|
-
import {
|
|
5
|
-
import { Build } from '@hubspot/local-dev-lib/types/Build';
|
|
6
|
-
import { ProjectConfig } from '../../../types/Projects.js';
|
|
7
|
-
import { ProjectDevTargetAccountPromptResponse } from '../../prompts/projectDevTargetAccountPrompt.js';
|
|
4
|
+
import { ProjectDevTargetAccountPromptResponse } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
8
5
|
export declare function confirmDefaultAccountIsTarget(accountConfig: CLIAccount): Promise<void>;
|
|
9
6
|
export declare function checkIfDefaultAccountIsSupported(accountConfig: CLIAccount, hasPublicApps: boolean): Promise<void>;
|
|
10
7
|
export declare function checkIfParentAccountIsAuthed(accountConfig: CLIAccount): void;
|
|
@@ -13,8 +10,5 @@ export declare function suggestRecommendedNestedAccount(accounts: CLIAccount[],
|
|
|
13
10
|
export declare function createSandboxForLocalDev(accountId: number, accountConfig: CLIAccount, env: Environment): Promise<number>;
|
|
14
11
|
export declare function createDeveloperTestAccountForLocalDev(accountId: number, accountConfig: CLIAccount, env: Environment, useV3?: boolean): Promise<number>;
|
|
15
12
|
export declare function useExistingDevTestAccount(env: Environment, account: DeveloperTestAccount): Promise<void>;
|
|
16
|
-
export declare function createNewProjectForLocalDev(projectConfig: ProjectConfig, targetAccountId: number, shouldCreateWithoutConfirmation: boolean, hasPublicApps: boolean): Promise<Project>;
|
|
17
|
-
export declare function createInitialBuildForNewProject(projectConfig: ProjectConfig, projectDir: string, targetAccountId: number, sendIR?: boolean, profile?: string): Promise<Build>;
|
|
18
|
-
export declare function getAccountHomeUrl(accountId: number): string;
|
|
19
13
|
export declare function hasSandboxes(account: CLIAccount): Promise<boolean>;
|
|
20
14
|
export declare function selectAccountTypePrompt(accountConfig: CLIAccount): Promise<string | null>;
|
|
@@ -1,41 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { HUBSPOT_ACCOUNT_TYPE_STRINGS } from '@hubspot/local-dev-lib/constants/config';
|
|
2
|
+
import { getAccountConfig } from '@hubspot/local-dev-lib/config';
|
|
3
|
+
import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountIdentifier';
|
|
4
|
+
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
3
5
|
import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
|
|
4
|
-
import {
|
|
5
|
-
import { createProject } from '@hubspot/local-dev-lib/api/projects';
|
|
6
|
-
import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
|
|
6
|
+
import { isMissingScopeError } from '@hubspot/local-dev-lib/errors/index';
|
|
7
7
|
import { PERSONAL_ACCESS_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
|
|
8
|
-
import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountIdentifier';
|
|
9
8
|
import { getSandboxUsageLimits } from '@hubspot/local-dev-lib/api/sandboxHubs';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { hubspotAccountNamePrompt } from '
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
9
|
+
import { uiLogger } from '../../../ui/logger.js';
|
|
10
|
+
import { lib } from '../../../../lang/en.js';
|
|
11
|
+
import { EXIT_CODES } from '../../../enums/exitCodes.js';
|
|
12
|
+
import { confirmDefaultAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
13
|
+
import { isUnifiedAccount } from '../../../accountTypes.js';
|
|
14
|
+
import { isAppDeveloperAccount } from '../../../accountTypes.js';
|
|
15
|
+
import { isDeveloperTestAccount } from '../../../accountTypes.js';
|
|
16
|
+
import { uiAccountDescription } from '../../../ui/index.js';
|
|
17
|
+
import { uiLine } from '../../../ui/index.js';
|
|
18
|
+
import { selectDeveloperTestTargetAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
19
|
+
import { selectSandboxTargetAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
20
|
+
import { validateSandboxUsageLimits } from '../../../sandboxes.js';
|
|
21
|
+
import { logError } from '../../../errorHandlers/index.js';
|
|
22
|
+
import { syncSandbox } from '../../../sandboxSync.js';
|
|
23
|
+
import { getAvailableSyncTypes } from '../../../sandboxes.js';
|
|
24
|
+
import { hubspotAccountNamePrompt } from '../../../prompts/accountNamePrompt.js';
|
|
25
|
+
import { trackCommandMetadataUsage } from '../../../usageTracking.js';
|
|
26
|
+
import { validateDevTestAccountUsageLimits } from '../../../developerTestAccounts.js';
|
|
27
|
+
import { buildSandbox, buildDeveloperTestAccount, saveAccountToConfig, } from '../../../buildAccount.js';
|
|
28
|
+
import { debugError } from '../../../errorHandlers/index.js';
|
|
29
|
+
import { listPrompt } from '../../../prompts/promptUtils.js';
|
|
30
|
+
import { confirmUseExistingDeveloperTestAccountPrompt } from '../../../prompts/projectDevTargetAccountPrompt.js';
|
|
28
31
|
// If the user passed in the --account flag, confirm they want to use that account as
|
|
29
32
|
// their target account, otherwise exit
|
|
30
33
|
export async function confirmDefaultAccountIsTarget(accountConfig) {
|
|
31
34
|
if (!accountConfig.name || !accountConfig.accountType) {
|
|
32
|
-
uiLogger.error(lib.localDevHelpers.confirmDefaultAccountIsTarget.configError);
|
|
35
|
+
uiLogger.error(lib.localDevHelpers.account.confirmDefaultAccountIsTarget.configError);
|
|
33
36
|
process.exit(EXIT_CODES.ERROR);
|
|
34
37
|
}
|
|
35
38
|
uiLogger.log('');
|
|
36
39
|
const useDefaultAccount = await confirmDefaultAccountPrompt(accountConfig.name, HUBSPOT_ACCOUNT_TYPE_STRINGS[accountConfig.accountType]);
|
|
37
40
|
if (!useDefaultAccount) {
|
|
38
|
-
uiLogger.log(lib.localDevHelpers.confirmDefaultAccountIsTarget
|
|
41
|
+
uiLogger.log(lib.localDevHelpers.account.confirmDefaultAccountIsTarget
|
|
39
42
|
.declineDefaultAccountExplanation);
|
|
40
43
|
process.exit(EXIT_CODES.SUCCESS);
|
|
41
44
|
}
|
|
@@ -47,18 +50,18 @@ export async function checkIfDefaultAccountIsSupported(accountConfig, hasPublicA
|
|
|
47
50
|
!(isAppDeveloperAccount(accountConfig) ||
|
|
48
51
|
isDeveloperTestAccount(accountConfig) ||
|
|
49
52
|
defaultAccountIsUnified)) {
|
|
50
|
-
uiLogger.error(lib.localDevHelpers.checkIfDefaultAccountIsSupported.publicApp);
|
|
53
|
+
uiLogger.error(lib.localDevHelpers.account.checkIfDefaultAccountIsSupported.publicApp);
|
|
51
54
|
process.exit(EXIT_CODES.SUCCESS);
|
|
52
55
|
}
|
|
53
56
|
else if (!hasPublicApps && isAppDeveloperAccount(accountConfig)) {
|
|
54
|
-
uiLogger.error(lib.localDevHelpers.checkIfDefaultAccountIsSupported.privateApp);
|
|
57
|
+
uiLogger.error(lib.localDevHelpers.account.checkIfDefaultAccountIsSupported.privateApp);
|
|
55
58
|
process.exit(EXIT_CODES.SUCCESS);
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
61
|
export function checkIfParentAccountIsAuthed(accountConfig) {
|
|
59
62
|
if (!accountConfig.parentAccountId ||
|
|
60
63
|
!getAccountConfig(accountConfig.parentAccountId)) {
|
|
61
|
-
uiLogger.error(lib.localDevHelpers.checkIfParentAccountIsAuthed.notAuthedError(accountConfig.parentAccountId || '', uiAccountDescription(getAccountIdentifier(accountConfig))));
|
|
64
|
+
uiLogger.error(lib.localDevHelpers.account.checkIfParentAccountIsAuthed.notAuthedError(accountConfig.parentAccountId || '', uiAccountDescription(getAccountIdentifier(accountConfig))));
|
|
62
65
|
process.exit(EXIT_CODES.SUCCESS);
|
|
63
66
|
}
|
|
64
67
|
}
|
|
@@ -66,13 +69,14 @@ export function checkIfParentAccountIsAuthed(accountConfig) {
|
|
|
66
69
|
export function checkIfAccountFlagIsSupported(accountConfig, hasPublicApps) {
|
|
67
70
|
if (hasPublicApps) {
|
|
68
71
|
if (!isDeveloperTestAccount(accountConfig)) {
|
|
69
|
-
uiLogger.error(lib.localDevHelpers.validateAccountOption
|
|
72
|
+
uiLogger.error(lib.localDevHelpers.account.validateAccountOption
|
|
73
|
+
.invalidPublicAppAccount);
|
|
70
74
|
process.exit(EXIT_CODES.SUCCESS);
|
|
71
75
|
}
|
|
72
76
|
checkIfParentAccountIsAuthed(accountConfig);
|
|
73
77
|
}
|
|
74
78
|
else if (isAppDeveloperAccount(accountConfig)) {
|
|
75
|
-
uiLogger.error(lib.localDevHelpers.validateAccountOption.invalidPrivateAppAccount);
|
|
79
|
+
uiLogger.error(lib.localDevHelpers.account.validateAccountOption.invalidPrivateAppAccount);
|
|
76
80
|
process.exit(EXIT_CODES.SUCCESS);
|
|
77
81
|
}
|
|
78
82
|
}
|
|
@@ -81,11 +85,11 @@ export async function suggestRecommendedNestedAccount(accounts, accountConfig, h
|
|
|
81
85
|
uiLogger.log('');
|
|
82
86
|
uiLine();
|
|
83
87
|
if (hasPublicApps) {
|
|
84
|
-
uiLogger.log(lib.localDevHelpers.validateAccountOption
|
|
88
|
+
uiLogger.log(lib.localDevHelpers.account.validateAccountOption
|
|
85
89
|
.publicAppNonDeveloperTestAccountWarning);
|
|
86
90
|
}
|
|
87
91
|
else {
|
|
88
|
-
uiLogger.log(lib.localDevHelpers.validateAccountOption.nonSandboxWarning);
|
|
92
|
+
uiLogger.log(lib.localDevHelpers.account.validateAccountOption.nonSandboxWarning);
|
|
89
93
|
}
|
|
90
94
|
uiLine();
|
|
91
95
|
uiLogger.log('');
|
|
@@ -177,7 +181,7 @@ export async function useExistingDevTestAccount(env, account) {
|
|
|
177
181
|
const useExistingDevTestAcct = await confirmUseExistingDeveloperTestAccountPrompt(account);
|
|
178
182
|
if (!useExistingDevTestAcct) {
|
|
179
183
|
uiLogger.log('');
|
|
180
|
-
uiLogger.log(lib.localDevHelpers.confirmDefaultAccountIsTarget
|
|
184
|
+
uiLogger.log(lib.localDevHelpers.account.confirmDefaultAccountIsTarget
|
|
181
185
|
.declineDefaultAccountExplanation);
|
|
182
186
|
uiLogger.log('');
|
|
183
187
|
process.exit(EXIT_CODES.SUCCESS);
|
|
@@ -185,110 +189,6 @@ export async function useExistingDevTestAccount(env, account) {
|
|
|
185
189
|
const devTestAcctConfigName = await saveAccountToConfig(account.id, account.accountName, env);
|
|
186
190
|
uiLogger.success(lib.developerTestAccount.create.success.configFileUpdated(devTestAcctConfigName, PERSONAL_ACCESS_KEY_AUTH_METHOD.name));
|
|
187
191
|
}
|
|
188
|
-
// Prompt the user to create a new project if one doesn't exist on their target account
|
|
189
|
-
export async function createNewProjectForLocalDev(projectConfig, targetAccountId, shouldCreateWithoutConfirmation, hasPublicApps) {
|
|
190
|
-
// Create the project without prompting if this is a newly created sandbox
|
|
191
|
-
let shouldCreateProject = shouldCreateWithoutConfirmation;
|
|
192
|
-
if (!shouldCreateProject) {
|
|
193
|
-
const explanationLangFunction = hasPublicApps
|
|
194
|
-
? lib.localDevHelpers.createNewProjectForLocalDev
|
|
195
|
-
.publicAppProjectMustExistExplanation
|
|
196
|
-
: lib.localDevHelpers.createNewProjectForLocalDev
|
|
197
|
-
.projectMustExistExplanation;
|
|
198
|
-
const explanationString = explanationLangFunction(projectConfig.name, targetAccountId);
|
|
199
|
-
uiLogger.log('');
|
|
200
|
-
uiLine();
|
|
201
|
-
uiLogger.log(explanationString);
|
|
202
|
-
uiLine();
|
|
203
|
-
shouldCreateProject = await confirmPrompt(lib.localDevHelpers.createNewProjectForLocalDev.createProject(projectConfig.name, uiAccountDescription(targetAccountId)));
|
|
204
|
-
}
|
|
205
|
-
if (shouldCreateProject) {
|
|
206
|
-
SpinniesManager.add('createProject', {
|
|
207
|
-
text: lib.localDevHelpers.createNewProjectForLocalDev.creatingProject(projectConfig.name, uiAccountDescription(targetAccountId)),
|
|
208
|
-
});
|
|
209
|
-
try {
|
|
210
|
-
const { data: project } = await createProject(targetAccountId, projectConfig.name);
|
|
211
|
-
SpinniesManager.succeed('createProject', {
|
|
212
|
-
text: lib.localDevHelpers.createNewProjectForLocalDev.createdProject(projectConfig.name, uiAccountDescription(targetAccountId)),
|
|
213
|
-
succeedColor: 'white',
|
|
214
|
-
});
|
|
215
|
-
return project;
|
|
216
|
-
}
|
|
217
|
-
catch (err) {
|
|
218
|
-
SpinniesManager.fail('createProject');
|
|
219
|
-
uiLogger.log(lib.localDevHelpers.createNewProjectForLocalDev.failedToCreateProject);
|
|
220
|
-
process.exit(EXIT_CODES.ERROR);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
// We cannot continue if the project does not exist in the target account
|
|
225
|
-
uiLogger.log('');
|
|
226
|
-
uiLogger.log(lib.localDevHelpers.createNewProjectForLocalDev.choseNotToCreateProject);
|
|
227
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
function projectUploadCallback(accountId, projectConfig, tempFile, buildId) {
|
|
231
|
-
if (!buildId) {
|
|
232
|
-
uiLogger.error(lib.localDevHelpers.createInitialBuildForNewProject.genericError);
|
|
233
|
-
process.exit(EXIT_CODES.ERROR);
|
|
234
|
-
}
|
|
235
|
-
return pollProjectBuildAndDeploy(accountId, projectConfig, tempFile, buildId, true);
|
|
236
|
-
}
|
|
237
|
-
// Create an initial build if the project was newly created in the account
|
|
238
|
-
// Return the newly deployed build
|
|
239
|
-
export async function createInitialBuildForNewProject(projectConfig, projectDir, targetAccountId, sendIR, profile) {
|
|
240
|
-
const { result: initialUploadResult, uploadError } = await handleProjectUpload({
|
|
241
|
-
accountId: targetAccountId,
|
|
242
|
-
projectConfig,
|
|
243
|
-
projectDir,
|
|
244
|
-
callbackFunc: projectUploadCallback,
|
|
245
|
-
uploadMessage: lib.localDevHelpers.createInitialBuildForNewProject
|
|
246
|
-
.initialUploadMessage,
|
|
247
|
-
forceCreate: true,
|
|
248
|
-
skipValidation: true,
|
|
249
|
-
sendIR,
|
|
250
|
-
profile,
|
|
251
|
-
});
|
|
252
|
-
if (uploadError) {
|
|
253
|
-
if (isSpecifiedError(uploadError, {
|
|
254
|
-
subCategory: PROJECT_ERROR_TYPES.PROJECT_LOCKED,
|
|
255
|
-
})) {
|
|
256
|
-
uiLogger.log('');
|
|
257
|
-
uiLogger.error(lib.localDevHelpers.createInitialBuildForNewProject.projectLockedError);
|
|
258
|
-
uiLogger.log('');
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
logError(uploadError, new ApiErrorContext({
|
|
262
|
-
accountId: targetAccountId,
|
|
263
|
-
projectName: projectConfig.name,
|
|
264
|
-
}));
|
|
265
|
-
}
|
|
266
|
-
process.exit(EXIT_CODES.ERROR);
|
|
267
|
-
}
|
|
268
|
-
if (!initialUploadResult?.succeeded) {
|
|
269
|
-
let subTasks = [];
|
|
270
|
-
if (initialUploadResult?.buildResult.status === 'FAILURE') {
|
|
271
|
-
subTasks =
|
|
272
|
-
initialUploadResult.buildResult[PROJECT_BUILD_TEXT.SUBTASK_KEY];
|
|
273
|
-
}
|
|
274
|
-
else if (initialUploadResult?.deployResult?.status === 'FAILURE') {
|
|
275
|
-
subTasks =
|
|
276
|
-
initialUploadResult.deployResult[PROJECT_DEPLOY_TEXT.SUBTASK_KEY];
|
|
277
|
-
}
|
|
278
|
-
const failedSubTasks = subTasks.filter(task => task.status === 'FAILURE');
|
|
279
|
-
uiLogger.log('');
|
|
280
|
-
failedSubTasks.forEach(failedSubTask => {
|
|
281
|
-
uiLogger.error(failedSubTask.errorMessage);
|
|
282
|
-
});
|
|
283
|
-
uiLogger.log('');
|
|
284
|
-
process.exit(EXIT_CODES.ERROR);
|
|
285
|
-
}
|
|
286
|
-
return initialUploadResult.buildResult;
|
|
287
|
-
}
|
|
288
|
-
export function getAccountHomeUrl(accountId) {
|
|
289
|
-
const baseUrl = getHubSpotWebsiteOrigin(getEnv(accountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD);
|
|
290
|
-
return `${baseUrl}/home?portalId=${accountId}`;
|
|
291
|
-
}
|
|
292
192
|
export async function hasSandboxes(account) {
|
|
293
193
|
const accountId = getAccountIdentifier(account);
|
|
294
194
|
if (!accountId) {
|
|
@@ -306,25 +206,25 @@ export async function hasSandboxes(account) {
|
|
|
306
206
|
// Top level prompt to choose the type of account to test on
|
|
307
207
|
export async function selectAccountTypePrompt(accountConfig) {
|
|
308
208
|
const hasAccessToSandboxes = await hasSandboxes(accountConfig);
|
|
309
|
-
const
|
|
209
|
+
const accountId = getAccountIdentifier(accountConfig);
|
|
210
|
+
const result = await listPrompt(lib.localDevHelpers.account.selectAccountTypePrompt.message, {
|
|
310
211
|
choices: [
|
|
311
212
|
{
|
|
312
|
-
name: lib.localDevHelpers.selectAccountTypePrompt
|
|
213
|
+
name: lib.localDevHelpers.account.selectAccountTypePrompt
|
|
313
214
|
.developerTestAccountOption,
|
|
314
215
|
value: HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST,
|
|
315
216
|
},
|
|
316
217
|
{
|
|
317
|
-
name: lib.localDevHelpers.selectAccountTypePrompt
|
|
218
|
+
name: lib.localDevHelpers.account.selectAccountTypePrompt
|
|
318
219
|
.sandboxAccountOption,
|
|
319
220
|
value: HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX,
|
|
320
221
|
disabled: !hasAccessToSandboxes
|
|
321
|
-
? lib.localDevHelpers.selectAccountTypePrompt
|
|
222
|
+
? lib.localDevHelpers.account.selectAccountTypePrompt
|
|
322
223
|
.sandboxAccountOptionDisabled
|
|
323
224
|
: false,
|
|
324
225
|
},
|
|
325
226
|
{
|
|
326
|
-
name: lib.localDevHelpers.selectAccountTypePrompt
|
|
327
|
-
.productionAccountOption,
|
|
227
|
+
name: lib.localDevHelpers.account.selectAccountTypePrompt.productionAccountOption(accountId),
|
|
328
228
|
value: null,
|
|
329
229
|
},
|
|
330
230
|
],
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Build } from '@hubspot/local-dev-lib/types/Build';
|
|
2
|
+
import { Project } from '@hubspot/local-dev-lib/types/Project';
|
|
3
|
+
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types.js';
|
|
4
|
+
import { ProjectConfig } from '../../../../types/Projects.js';
|
|
5
|
+
export declare function createNewProjectForLocalDev(projectConfig: ProjectConfig, targetAccountId: number, shouldCreateWithoutConfirmation: boolean, hasPublicApps: boolean): Promise<Project>;
|
|
6
|
+
export declare function createInitialBuildForNewProject(projectConfig: ProjectConfig, projectDir: string, targetAccountId: number, sendIR?: boolean, profile?: string): Promise<Build>;
|
|
7
|
+
export declare function compareLocalProjectToDeployed(projectConfig: ProjectConfig, accountId: number, deployedBuildId: number | undefined, localProjectNodes: {
|
|
8
|
+
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
export declare function isDeployedProjectUpToDateWithLocal(projectConfig: ProjectConfig, accountId: number, deployedBuildId: number, localProjectNodes: {
|
|
11
|
+
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
12
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { createProject } from '@hubspot/local-dev-lib/api/projects';
|
|
5
|
+
import { downloadProject } from '@hubspot/local-dev-lib/api/projects';
|
|
6
|
+
import { extractZipArchive } from '@hubspot/local-dev-lib/archive';
|
|
7
|
+
import { sanitizeFileName } from '@hubspot/local-dev-lib/path';
|
|
8
|
+
import { isDeepEqual } from '@hubspot/local-dev-lib/isDeepEqual';
|
|
9
|
+
import { translate } from '@hubspot/project-parsing-lib';
|
|
10
|
+
import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
|
|
11
|
+
import { PROJECT_ERROR_TYPES, PROJECT_BUILD_TEXT, PROJECT_DEPLOY_TEXT, } from '../../../constants.js';
|
|
12
|
+
import { lib } from '../../../../lang/en.js';
|
|
13
|
+
import { uiLogger } from '../../../ui/logger.js';
|
|
14
|
+
import { uiLine } from '../../../ui/index.js';
|
|
15
|
+
import { confirmPrompt } from '../../../prompts/promptUtils.js';
|
|
16
|
+
import { uiAccountDescription } from '../../../ui/index.js';
|
|
17
|
+
import SpinniesManager from '../../../ui/SpinniesManager.js';
|
|
18
|
+
import { EXIT_CODES } from '../../../enums/exitCodes.js';
|
|
19
|
+
import { handleProjectUpload } from '../../upload.js';
|
|
20
|
+
import { pollProjectBuildAndDeploy } from '../../buildAndDeploy.js';
|
|
21
|
+
import { logError } from '../../../errorHandlers/index.js';
|
|
22
|
+
import { ApiErrorContext } from '../../../errorHandlers/index.js';
|
|
23
|
+
// Prompt the user to create a new project if one doesn't exist on their target account
|
|
24
|
+
export async function createNewProjectForLocalDev(projectConfig, targetAccountId, shouldCreateWithoutConfirmation, hasPublicApps) {
|
|
25
|
+
// Create the project without prompting if this is a newly created sandbox
|
|
26
|
+
let shouldCreateProject = shouldCreateWithoutConfirmation;
|
|
27
|
+
if (!shouldCreateProject) {
|
|
28
|
+
const explanationLangFunction = hasPublicApps
|
|
29
|
+
? lib.localDevHelpers.project.createNewProjectForLocalDev
|
|
30
|
+
.publicAppProjectMustExistExplanation
|
|
31
|
+
: lib.localDevHelpers.project.createNewProjectForLocalDev
|
|
32
|
+
.projectMustExistExplanation;
|
|
33
|
+
const explanationString = explanationLangFunction(projectConfig.name, targetAccountId);
|
|
34
|
+
uiLogger.log('');
|
|
35
|
+
uiLine();
|
|
36
|
+
uiLogger.log(explanationString);
|
|
37
|
+
uiLine();
|
|
38
|
+
shouldCreateProject = await confirmPrompt(lib.localDevHelpers.project.createNewProjectForLocalDev.createProject(projectConfig.name, uiAccountDescription(targetAccountId)));
|
|
39
|
+
}
|
|
40
|
+
if (shouldCreateProject) {
|
|
41
|
+
SpinniesManager.add('createProject', {
|
|
42
|
+
text: lib.localDevHelpers.project.createNewProjectForLocalDev.creatingProject(projectConfig.name, uiAccountDescription(targetAccountId)),
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
const { data: project } = await createProject(targetAccountId, projectConfig.name);
|
|
46
|
+
SpinniesManager.succeed('createProject', {
|
|
47
|
+
text: lib.localDevHelpers.project.createNewProjectForLocalDev.createdProject(projectConfig.name, uiAccountDescription(targetAccountId)),
|
|
48
|
+
succeedColor: 'white',
|
|
49
|
+
});
|
|
50
|
+
return project;
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
SpinniesManager.fail('createProject');
|
|
54
|
+
uiLogger.log(lib.localDevHelpers.project.createNewProjectForLocalDev
|
|
55
|
+
.failedToCreateProject);
|
|
56
|
+
process.exit(EXIT_CODES.ERROR);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// We cannot continue if the project does not exist in the target account
|
|
61
|
+
uiLogger.log('');
|
|
62
|
+
uiLogger.log(lib.localDevHelpers.project.createNewProjectForLocalDev
|
|
63
|
+
.choseNotToCreateProject);
|
|
64
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function projectUploadCallback(accountId, projectConfig, tempFile, buildId) {
|
|
68
|
+
if (!buildId) {
|
|
69
|
+
uiLogger.error(lib.localDevHelpers.project.createInitialBuildForNewProject.genericError);
|
|
70
|
+
process.exit(EXIT_CODES.ERROR);
|
|
71
|
+
}
|
|
72
|
+
return pollProjectBuildAndDeploy(accountId, projectConfig, tempFile, buildId, true);
|
|
73
|
+
}
|
|
74
|
+
// Create an initial build if the project was newly created in the account
|
|
75
|
+
// Return the newly deployed build
|
|
76
|
+
export async function createInitialBuildForNewProject(projectConfig, projectDir, targetAccountId, sendIR, profile) {
|
|
77
|
+
const { result: initialUploadResult, uploadError } = await handleProjectUpload({
|
|
78
|
+
accountId: targetAccountId,
|
|
79
|
+
projectConfig,
|
|
80
|
+
projectDir,
|
|
81
|
+
callbackFunc: projectUploadCallback,
|
|
82
|
+
uploadMessage: lib.localDevHelpers.project.createInitialBuildForNewProject
|
|
83
|
+
.initialUploadMessage,
|
|
84
|
+
forceCreate: true,
|
|
85
|
+
skipValidation: true,
|
|
86
|
+
sendIR,
|
|
87
|
+
profile,
|
|
88
|
+
});
|
|
89
|
+
if (uploadError) {
|
|
90
|
+
if (isSpecifiedError(uploadError, {
|
|
91
|
+
subCategory: PROJECT_ERROR_TYPES.PROJECT_LOCKED,
|
|
92
|
+
})) {
|
|
93
|
+
uiLogger.log('');
|
|
94
|
+
uiLogger.error(lib.localDevHelpers.project.createInitialBuildForNewProject
|
|
95
|
+
.projectLockedError);
|
|
96
|
+
uiLogger.log('');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
logError(uploadError, new ApiErrorContext({
|
|
100
|
+
accountId: targetAccountId,
|
|
101
|
+
projectName: projectConfig.name,
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
process.exit(EXIT_CODES.ERROR);
|
|
105
|
+
}
|
|
106
|
+
if (!initialUploadResult?.succeeded) {
|
|
107
|
+
let subTasks = [];
|
|
108
|
+
if (initialUploadResult?.buildResult.status === 'FAILURE') {
|
|
109
|
+
subTasks =
|
|
110
|
+
initialUploadResult.buildResult[PROJECT_BUILD_TEXT.SUBTASK_KEY];
|
|
111
|
+
}
|
|
112
|
+
else if (initialUploadResult?.deployResult?.status === 'FAILURE') {
|
|
113
|
+
subTasks =
|
|
114
|
+
initialUploadResult.deployResult[PROJECT_DEPLOY_TEXT.SUBTASK_KEY];
|
|
115
|
+
}
|
|
116
|
+
const failedSubTasks = subTasks.filter(task => task.status === 'FAILURE');
|
|
117
|
+
uiLogger.log('');
|
|
118
|
+
failedSubTasks.forEach(failedSubTask => {
|
|
119
|
+
uiLogger.error(failedSubTask.errorMessage);
|
|
120
|
+
});
|
|
121
|
+
uiLogger.log('');
|
|
122
|
+
process.exit(EXIT_CODES.ERROR);
|
|
123
|
+
}
|
|
124
|
+
return initialUploadResult.buildResult;
|
|
125
|
+
}
|
|
126
|
+
export async function compareLocalProjectToDeployed(projectConfig, accountId, deployedBuildId, localProjectNodes) {
|
|
127
|
+
uiLogger.log('');
|
|
128
|
+
if (!deployedBuildId) {
|
|
129
|
+
uiLogger.error(lib.localDevHelpers.project.compareLocalProjectToDeployed.noDeployedBuild(projectConfig.name, uiAccountDescription(accountId)));
|
|
130
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
131
|
+
}
|
|
132
|
+
SpinniesManager.add('compareLocalProjectToDeployed', {
|
|
133
|
+
text: lib.localDevHelpers.project.compareLocalProjectToDeployed.checking,
|
|
134
|
+
});
|
|
135
|
+
const isUpToDate = await isDeployedProjectUpToDateWithLocal(projectConfig, accountId, deployedBuildId, localProjectNodes);
|
|
136
|
+
if (isUpToDate) {
|
|
137
|
+
SpinniesManager.succeed('compareLocalProjectToDeployed', {
|
|
138
|
+
text: lib.localDevHelpers.project.compareLocalProjectToDeployed.upToDate,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
SpinniesManager.fail('compareLocalProjectToDeployed', {
|
|
143
|
+
text: lib.localDevHelpers.project.compareLocalProjectToDeployed
|
|
144
|
+
.notUpToDate,
|
|
145
|
+
});
|
|
146
|
+
uiLogger.log('');
|
|
147
|
+
uiLogger.log(lib.localDevHelpers.project.compareLocalProjectToDeployed
|
|
148
|
+
.notUpToDateExplanation);
|
|
149
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export async function isDeployedProjectUpToDateWithLocal(projectConfig, accountId, deployedBuildId, localProjectNodes) {
|
|
153
|
+
let tempDir = null;
|
|
154
|
+
try {
|
|
155
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'hubspot-project-compare-'));
|
|
156
|
+
const { data: zippedProject } = await downloadProject(accountId, projectConfig.name, deployedBuildId);
|
|
157
|
+
const extractedProjectPath = path.join(tempDir, sanitizeFileName(projectConfig.name));
|
|
158
|
+
await extractZipArchive(zippedProject, sanitizeFileName(projectConfig.name), tempDir, { includesRootDir: false, hideLogs: true });
|
|
159
|
+
const deployedProjectSourceDir = path.join(extractedProjectPath, projectConfig.srcDir);
|
|
160
|
+
const { intermediateNodesIndexedByUid: deployedProjectNodes } = await translate({
|
|
161
|
+
projectSourceDir: deployedProjectSourceDir,
|
|
162
|
+
platformVersion: projectConfig.platformVersion,
|
|
163
|
+
accountId: accountId,
|
|
164
|
+
}, {});
|
|
165
|
+
return isDeepEqual(localProjectNodes, deployedProjectNodes, ['localDev']);
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
// Clean up temporary directory
|
|
169
|
+
if (tempDir && (await fs.pathExists(tempDir))) {
|
|
170
|
+
await fs.remove(tempDir);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|