@hubspot/cli 7.7.16-experimental.0 → 7.7.16-experimental.10
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/bin/cli.js +4 -0
- package/bin/hs +1 -1
- package/commands/account/auth.js +3 -3
- package/commands/app/install.d.ts +8 -0
- package/commands/app/install.js +127 -0
- package/commands/app.js +6 -1
- package/commands/auth.js +23 -25
- package/commands/getStarted.d.ts +9 -0
- package/commands/getStarted.js +274 -0
- package/commands/init.js +35 -32
- package/commands/mcp/setup.d.ts +2 -2
- package/commands/mcp/setup.js +2 -0
- package/commands/mcp/start.d.ts +2 -2
- package/commands/mcp/start.js +3 -1
- package/commands/project/cloneApp.js +4 -4
- package/commands/project/create.js +9 -9
- package/commands/project/deploy.d.ts +1 -0
- package/commands/project/deploy.js +29 -3
- package/commands/project/dev/deprecatedFlow.js +4 -4
- package/commands/project/dev/index.js +5 -5
- package/commands/project/dev/unifiedFlow.js +8 -0
- package/commands/project/upload.d.ts +2 -2
- package/commands/project/upload.js +18 -23
- package/commands/project/validate.d.ts +6 -0
- package/commands/project/validate.js +82 -0
- package/commands/project.js +2 -0
- package/commands/sandbox/delete.js +5 -5
- package/commands/testAccount/create.d.ts +6 -0
- package/commands/testAccount/create.js +160 -0
- package/commands/testAccount/createConfig.d.ts +10 -0
- package/commands/testAccount/createConfig.js +98 -0
- package/commands/testAccount/delete.d.ts +6 -0
- package/commands/testAccount/delete.js +48 -0
- package/commands/testAccount.d.ts +3 -0
- package/commands/testAccount.js +28 -0
- package/lang/en.d.ts +201 -35
- package/lang/en.js +201 -38
- package/lang/en.lyaml +9 -14
- package/lib/accountTypes.d.ts +1 -0
- package/lib/accountTypes.js +20 -9
- package/lib/app/migrate.js +15 -3
- package/lib/app/migrate_legacy.js +2 -3
- package/lib/app/urls.d.ts +1 -1
- package/lib/commonOpts.d.ts +2 -0
- package/lib/commonOpts.js +21 -9
- package/lib/constants.d.ts +5 -0
- package/lib/constants.js +6 -1
- package/lib/doctor/Doctor.js +1 -1
- package/lib/errorHandlers/index.js +7 -0
- package/lib/mcp/setup.d.ts +9 -0
- package/lib/mcp/setup.js +23 -21
- package/lib/middleware/__test__/configMiddleware.test.js +2 -2
- package/lib/middleware/configMiddleware.js +10 -2
- package/lib/parsing.d.ts +1 -0
- package/lib/parsing.js +11 -0
- package/lib/polling.d.ts +1 -1
- package/lib/polling.js +11 -1
- package/lib/projectProfiles.d.ts +1 -0
- package/lib/projectProfiles.js +18 -0
- package/lib/projects/add/v3AddComponent.js +4 -0
- package/lib/projects/buildAndDeploy.js +1 -1
- package/lib/projects/create/index.d.ts +3 -2
- package/lib/projects/create/index.js +11 -5
- package/lib/projects/create/v3.d.ts +3 -3
- package/lib/projects/create/v3.js +2 -2
- package/lib/projects/localDev/AppDevModeInterface.d.ts +3 -0
- package/lib/projects/localDev/AppDevModeInterface.js +46 -17
- package/lib/projects/localDev/LocalDevManager.js +1 -1
- package/lib/projects/localDev/LocalDevProcess.d.ts +3 -2
- package/lib/projects/localDev/LocalDevProcess.js +16 -12
- package/lib/projects/localDev/LocalDevState.d.ts +10 -5
- package/lib/projects/localDev/LocalDevState.js +18 -20
- package/lib/projects/localDev/LocalDevWatcher.js +1 -1
- package/lib/projects/structure.d.ts +2 -2
- package/lib/projects/upload.d.ts +4 -0
- package/lib/projects/upload.js +57 -22
- package/lib/projects/urls.d.ts +2 -0
- package/lib/projects/urls.js +10 -0
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +17 -0
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +96 -0
- package/lib/prompts/installAppPrompt.d.ts +2 -1
- package/lib/prompts/installAppPrompt.js +12 -2
- package/lib/prompts/personalAccessKeyPrompt.js +2 -2
- package/lib/prompts/projectNameAndDestPrompt.d.ts +3 -0
- package/lib/prompts/projectNameAndDestPrompt.js +60 -0
- package/lib/prompts/promptUtils.d.ts +1 -0
- package/lib/prompts/promptUtils.js +2 -0
- package/lib/prompts/selectProjectTemplatePrompt.d.ts +26 -0
- package/lib/prompts/{createProjectPrompt.js → selectProjectTemplatePrompt.js} +6 -55
- package/lib/ui/logger.d.ts +1 -0
- package/lib/ui/logger.js +1 -0
- package/lib/validation.d.ts +1 -1
- package/lib/validation.js +4 -4
- package/lib/yargsUtils.d.ts +1 -0
- package/lib/yargsUtils.js +3 -0
- package/mcp-server/tools/index.js +2 -0
- package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/CreateProjectTool.js +5 -1
- package/mcp-server/tools/project/DeployProject.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.js +1 -1
- package/mcp-server/tools/project/ValidateProjectTool.d.ts +17 -0
- package/mcp-server/tools/project/ValidateProjectTool.js +35 -0
- package/package.json +10 -9
- package/types/LocalDev.d.ts +2 -0
- package/types/Yargs.d.ts +5 -1
- package/lib/prompts/createProjectPrompt.d.ts +0 -28
|
@@ -4,6 +4,7 @@ const localDevAuth_1 = require("@hubspot/local-dev-lib/api/localDevAuth");
|
|
|
4
4
|
const appsDev_1 = require("@hubspot/local-dev-lib/api/appsDev");
|
|
5
5
|
const ui_extensions_dev_server_1 = require("@hubspot/ui-extensions-dev-server");
|
|
6
6
|
const portManager_1 = require("@hubspot/local-dev-lib/portManager");
|
|
7
|
+
const config_1 = require("@hubspot/local-dev-lib/config");
|
|
7
8
|
const constants_1 = require("../../constants");
|
|
8
9
|
const exitCodes_1 = require("../../enums/exitCodes");
|
|
9
10
|
const structure_1 = require("../../projects/structure");
|
|
@@ -14,6 +15,7 @@ const promptUtils_1 = require("../../prompts/promptUtils");
|
|
|
14
15
|
const en_1 = require("../../../lang/en");
|
|
15
16
|
const logger_1 = require("../../ui/logger");
|
|
16
17
|
const urls_1 = require("../../app/urls");
|
|
18
|
+
const accountTypes_1 = require("../../accountTypes");
|
|
17
19
|
class AppDevModeInterface {
|
|
18
20
|
localDevState;
|
|
19
21
|
localDevLogger;
|
|
@@ -22,15 +24,6 @@ class AppDevModeInterface {
|
|
|
22
24
|
constructor(options) {
|
|
23
25
|
this.localDevState = options.localDevState;
|
|
24
26
|
this.localDevLogger = options.localDevLogger;
|
|
25
|
-
// Static auth apps are currently only installable in the portal that the project resides in
|
|
26
|
-
// This limitation will eventually be removed, but in the meantime we need this check or the install
|
|
27
|
-
// will always fail with a confusing message
|
|
28
|
-
if (this.appNode?.config.auth.type === constants_1.APP_AUTH_TYPES.STATIC &&
|
|
29
|
-
this.localDevState.targetTestingAccountId !==
|
|
30
|
-
this.localDevState.targetProjectAccountId) {
|
|
31
|
-
logger_1.uiLogger.error(en_1.lib.LocalDevManager.staticAuthAccountsMustMatch);
|
|
32
|
-
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
33
|
-
}
|
|
34
27
|
if (!this.localDevState.targetProjectAccountId ||
|
|
35
28
|
!this.localDevState.projectConfig ||
|
|
36
29
|
!this.localDevState.projectDir) {
|
|
@@ -59,6 +52,19 @@ class AppDevModeInterface {
|
|
|
59
52
|
}
|
|
60
53
|
this.localDevState.setAppDataForUid(this.appNode.uid, appData);
|
|
61
54
|
}
|
|
55
|
+
isAutomaticallyInstallable() {
|
|
56
|
+
const targetTestingAccount = (0, config_1.getAccountConfig)(this.localDevState.targetTestingAccountId);
|
|
57
|
+
if (!targetTestingAccount) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
const isTestAccount = (0, accountTypes_1.isDeveloperTestAccount)(targetTestingAccount) ||
|
|
61
|
+
(0, accountTypes_1.isSandbox)(targetTestingAccount);
|
|
62
|
+
const hasCorrectParent = targetTestingAccount.parentAccountId ===
|
|
63
|
+
this.localDevState.targetProjectAccountId;
|
|
64
|
+
return (isTestAccount &&
|
|
65
|
+
hasCorrectParent &&
|
|
66
|
+
this.appNode?.config.auth.type === constants_1.APP_AUTH_TYPES.STATIC);
|
|
67
|
+
}
|
|
62
68
|
async getAppInstallUrl() {
|
|
63
69
|
if (this.appNode?.config.auth.type === constants_1.APP_AUTH_TYPES.OAUTH) {
|
|
64
70
|
return (0, urls_1.getOauthAppInstallUrl)({
|
|
@@ -72,13 +78,13 @@ class AppDevModeInterface {
|
|
|
72
78
|
const { data: { results }, } = await (0, appsDev_1.fetchPublicAppsForPortal)(this.localDevState.targetProjectAccountId);
|
|
73
79
|
const app = results.find(app => app.sourceId === this.appNode?.uid);
|
|
74
80
|
if (!app) {
|
|
75
|
-
logger_1.uiLogger.error(en_1.lib.LocalDevManager.
|
|
81
|
+
logger_1.uiLogger.error(en_1.lib.LocalDevManager.appNotFound(this.localDevState.targetProjectAccountId, this.appNode?.uid));
|
|
76
82
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
77
83
|
}
|
|
78
84
|
return (0, urls_1.getStaticAuthAppInstallUrl)({
|
|
79
85
|
targetAccountId: this.localDevState.targetTestingAccountId,
|
|
80
86
|
env: this.localDevState.env,
|
|
81
|
-
appId:
|
|
87
|
+
appId: app.id,
|
|
82
88
|
});
|
|
83
89
|
}
|
|
84
90
|
async fetchAppData() {
|
|
@@ -93,6 +99,7 @@ class AppDevModeInterface {
|
|
|
93
99
|
clientId: appData.clientId,
|
|
94
100
|
name: appData.name,
|
|
95
101
|
installationState: constants_1.APP_INSTALLATION_STATES.NOT_INSTALLED,
|
|
102
|
+
scopeGroupIds: appData.scopeGroupIds,
|
|
96
103
|
};
|
|
97
104
|
this.marketplaceAppInstalls = uniquePortalInstallCount;
|
|
98
105
|
}
|
|
@@ -110,9 +117,31 @@ class AppDevModeInterface {
|
|
|
110
117
|
}
|
|
111
118
|
this.localDevLogger.addUploadWarning(en_1.lib.AppDevModeInterface.defaultMarketplaceAppWarning(this.marketplaceAppInstalls));
|
|
112
119
|
}
|
|
120
|
+
async autoInstallStaticAuthApp() {
|
|
121
|
+
const shouldInstall = await (0, installAppPrompt_1.installAppAutoPrompt)();
|
|
122
|
+
if (!shouldInstall) {
|
|
123
|
+
logger_1.uiLogger.log(en_1.lib.AppDevModeInterface.autoInstallDeclined);
|
|
124
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
125
|
+
}
|
|
126
|
+
await (0, appsDev_1.installStaticAuthAppOnTestAccount)(this.appData.id, this.localDevState.targetTestingAccountId, this.appData.scopeGroupIds);
|
|
127
|
+
}
|
|
128
|
+
async installAppOrOpenInstallUrl(isReinstall) {
|
|
129
|
+
if (this.isAutomaticallyInstallable()) {
|
|
130
|
+
try {
|
|
131
|
+
await this.autoInstallStaticAuthApp();
|
|
132
|
+
logger_1.uiLogger.success(en_1.lib.AppDevModeInterface.autoInstallSuccess(this.appData.name, this.localDevState.targetTestingAccountId));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
logger_1.uiLogger.error(en_1.lib.AppDevModeInterface.autoInstallError(this.appData.name, this.localDevState.targetTestingAccountId));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const installUrl = await this.getAppInstallUrl();
|
|
140
|
+
await (0, installAppPrompt_1.installAppBrowserPrompt)(installUrl, isReinstall);
|
|
141
|
+
}
|
|
113
142
|
async checkTestAccountAppInstallation() {
|
|
114
143
|
if (!this.appNode || !this.appData) {
|
|
115
|
-
return;
|
|
144
|
+
return {};
|
|
116
145
|
}
|
|
117
146
|
const { data: { isInstalledWithScopeGroups, previouslyAuthorizedScopeGroups }, } = await (0, localDevAuth_1.fetchAppInstallationData)(this.localDevState.targetTestingAccountId, this.localDevState.projectId, this.appNode.uid, this.appNode.config.auth.requiredScopes, this.appNode.config.auth.optionalScopes);
|
|
118
147
|
const isReinstall = previouslyAuthorizedScopeGroups.length > 0;
|
|
@@ -128,10 +157,7 @@ class AppDevModeInterface {
|
|
|
128
157
|
installationState: constants_1.APP_INSTALLATION_STATES.INSTALLED_WITH_OUTDATED_SCOPES,
|
|
129
158
|
};
|
|
130
159
|
}
|
|
131
|
-
|
|
132
|
-
const installUrl = await this.getAppInstallUrl();
|
|
133
|
-
await (0, installAppPrompt_1.installAppPrompt)(installUrl, isReinstall);
|
|
134
|
-
}
|
|
160
|
+
return { needsInstall: !isInstalledWithScopeGroups, isReinstall };
|
|
135
161
|
}
|
|
136
162
|
setUpLocalDevServerMessageListeners() {
|
|
137
163
|
this.localDevState.addListener('devServerMessage', message => {
|
|
@@ -151,7 +177,10 @@ class AppDevModeInterface {
|
|
|
151
177
|
if (this.appNode.config.distribution === constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE) {
|
|
152
178
|
await this.checkMarketplaceAppInstalls();
|
|
153
179
|
}
|
|
154
|
-
await this.checkTestAccountAppInstallation();
|
|
180
|
+
const { needsInstall, isReinstall } = await this.checkTestAccountAppInstallation();
|
|
181
|
+
if (needsInstall) {
|
|
182
|
+
await this.installAppOrOpenInstallUrl(isReinstall || false);
|
|
183
|
+
}
|
|
155
184
|
}
|
|
156
185
|
catch (e) {
|
|
157
186
|
(0, index_1.logError)(e);
|
|
@@ -195,7 +195,7 @@ class LocalDevManager {
|
|
|
195
195
|
scopes: this.activeApp.config.auth.requiredScopes,
|
|
196
196
|
redirectUrls: this.activeApp.config.auth.redirectUrls,
|
|
197
197
|
});
|
|
198
|
-
await (0, installAppPrompt_1.
|
|
198
|
+
await (0, installAppPrompt_1.installAppBrowserPrompt)(installUrl, isReinstall);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
updateKeypressListeners() {
|
|
@@ -16,15 +16,16 @@ declare class LocalDevProcess {
|
|
|
16
16
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
17
17
|
};
|
|
18
18
|
get logger(): LocalDevLogger;
|
|
19
|
-
get configFilesUpdatedSinceLastUpload(): Set<string>;
|
|
20
19
|
private setupDevServers;
|
|
21
20
|
private startDevServers;
|
|
22
21
|
private cleanupDevServers;
|
|
23
22
|
private compareLocalProjectToDeployed;
|
|
24
23
|
private projectConfigValidForUpload;
|
|
24
|
+
private getIntermediateRepresentation;
|
|
25
25
|
private updateProjectNodes;
|
|
26
|
+
private updateProjectNodesAfterUpload;
|
|
26
27
|
handleFileChange(filePath: string, event: string): Promise<void>;
|
|
27
|
-
handleConfigFileChange(
|
|
28
|
+
handleConfigFileChange(): Promise<void>;
|
|
28
29
|
start(): Promise<void>;
|
|
29
30
|
stop(showProgress?: boolean): Promise<void>;
|
|
30
31
|
uploadProject(): Promise<boolean>;
|
|
@@ -46,9 +46,6 @@ class LocalDevProcess {
|
|
|
46
46
|
get logger() {
|
|
47
47
|
return this._logger;
|
|
48
48
|
}
|
|
49
|
-
get configFilesUpdatedSinceLastUpload() {
|
|
50
|
-
return this.state.configFilesUpdatedSinceLastUpload;
|
|
51
|
-
}
|
|
52
49
|
async setupDevServers() {
|
|
53
50
|
try {
|
|
54
51
|
await this.devServerManager.setup();
|
|
@@ -105,17 +102,28 @@ class LocalDevProcess {
|
|
|
105
102
|
});
|
|
106
103
|
return true;
|
|
107
104
|
}
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
getIntermediateRepresentation(projectNodesAtLastUpload) {
|
|
106
|
+
return (0, project_parsing_lib_1.translateForLocalDev)({
|
|
110
107
|
projectSourceDir: path_1.default.join(this.state.projectDir, this.state.projectConfig.srcDir),
|
|
111
108
|
platformVersion: this.state.projectConfig.platformVersion,
|
|
112
109
|
accountId: this.state.targetProjectAccountId,
|
|
113
110
|
}, {
|
|
114
|
-
|
|
111
|
+
projectNodesAtLastUpload,
|
|
112
|
+
profile: this.state.profile,
|
|
115
113
|
});
|
|
114
|
+
}
|
|
115
|
+
async updateProjectNodes() {
|
|
116
|
+
const intermediateRepresentation = await this.getIntermediateRepresentation(this.state.projectNodesAtLastUpload);
|
|
116
117
|
this.state.projectNodes =
|
|
117
118
|
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
118
119
|
}
|
|
120
|
+
async updateProjectNodesAfterUpload() {
|
|
121
|
+
const intermediateRepresentation = await this.getIntermediateRepresentation();
|
|
122
|
+
this.state.projectNodes =
|
|
123
|
+
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
124
|
+
this.state.projectNodesAtLastUpload =
|
|
125
|
+
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
126
|
+
}
|
|
119
127
|
async handleFileChange(filePath, event) {
|
|
120
128
|
await this.updateProjectNodes();
|
|
121
129
|
try {
|
|
@@ -125,10 +133,7 @@ class LocalDevProcess {
|
|
|
125
133
|
this.logger.fileChangeError(e);
|
|
126
134
|
}
|
|
127
135
|
}
|
|
128
|
-
async handleConfigFileChange(
|
|
129
|
-
if (event === 'add' || event === 'change') {
|
|
130
|
-
this.state.addUpdatedConfigFileUpdatedSinceLastUpload(filePath);
|
|
131
|
-
}
|
|
136
|
+
async handleConfigFileChange() {
|
|
132
137
|
await this.updateProjectNodes();
|
|
133
138
|
this.logger.uploadWarning();
|
|
134
139
|
}
|
|
@@ -185,8 +190,7 @@ class LocalDevProcess {
|
|
|
185
190
|
this.logger.uploadError(uploadError);
|
|
186
191
|
return false;
|
|
187
192
|
}
|
|
188
|
-
this.
|
|
189
|
-
this.updateProjectNodes();
|
|
193
|
+
await this.updateProjectNodesAfterUpload();
|
|
190
194
|
this.logger.uploadSuccess();
|
|
191
195
|
this.logger.clearUploadWarnings();
|
|
192
196
|
return true;
|
|
@@ -6,6 +6,7 @@ import { LocalDevStateConstructorOptions, LocalDevStateListener, AppLocalDevData
|
|
|
6
6
|
declare class LocalDevState {
|
|
7
7
|
private _targetProjectAccountId;
|
|
8
8
|
private _targetTestingAccountId;
|
|
9
|
+
private _profile?;
|
|
9
10
|
private _projectConfig;
|
|
10
11
|
private _projectDir;
|
|
11
12
|
private _projectId;
|
|
@@ -14,15 +15,16 @@ declare class LocalDevState {
|
|
|
14
15
|
private _deployedBuild?;
|
|
15
16
|
private _isGithubLinked;
|
|
16
17
|
private _projectNodes;
|
|
18
|
+
private _projectNodesAtLastUpload;
|
|
17
19
|
private _env;
|
|
18
20
|
private _listeners;
|
|
19
|
-
private _configFilesUpdatedSinceLastUpload;
|
|
20
21
|
private _appData;
|
|
21
22
|
private _devServerMessage;
|
|
22
|
-
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, env, }: LocalDevStateConstructorOptions);
|
|
23
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, profile, env, }: LocalDevStateConstructorOptions);
|
|
23
24
|
private runListeners;
|
|
24
25
|
get targetProjectAccountId(): number;
|
|
25
26
|
get targetTestingAccountId(): number;
|
|
27
|
+
get profile(): string | undefined;
|
|
26
28
|
get projectConfig(): ProjectConfig;
|
|
27
29
|
get projectDir(): string;
|
|
28
30
|
get projectId(): number;
|
|
@@ -36,10 +38,13 @@ declare class LocalDevState {
|
|
|
36
38
|
set projectNodes(nodes: {
|
|
37
39
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
38
40
|
});
|
|
41
|
+
get projectNodesAtLastUpload(): {
|
|
42
|
+
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
43
|
+
};
|
|
44
|
+
set projectNodesAtLastUpload(nodes: {
|
|
45
|
+
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
46
|
+
});
|
|
39
47
|
get env(): Environment;
|
|
40
|
-
get configFilesUpdatedSinceLastUpload(): Set<string>;
|
|
41
|
-
addUpdatedConfigFileUpdatedSinceLastUpload(filePath: string): void;
|
|
42
|
-
resetConfigFilesUpdatedSinceLastUpload(): void;
|
|
43
48
|
get appData(): Record<string, AppLocalDevData>;
|
|
44
49
|
getAppDataByUid(uid: string): AppLocalDevData | undefined;
|
|
45
50
|
setAppDataForUid(uid: string, appData: AppLocalDevData): void;
|
|
@@ -4,6 +4,7 @@ const constants_1 = require("../../constants");
|
|
|
4
4
|
class LocalDevState {
|
|
5
5
|
_targetProjectAccountId;
|
|
6
6
|
_targetTestingAccountId;
|
|
7
|
+
_profile;
|
|
7
8
|
_projectConfig;
|
|
8
9
|
_projectDir;
|
|
9
10
|
_projectId;
|
|
@@ -12,14 +13,15 @@ class LocalDevState {
|
|
|
12
13
|
_deployedBuild;
|
|
13
14
|
_isGithubLinked;
|
|
14
15
|
_projectNodes;
|
|
16
|
+
_projectNodesAtLastUpload;
|
|
15
17
|
_env;
|
|
16
18
|
_listeners;
|
|
17
|
-
_configFilesUpdatedSinceLastUpload;
|
|
18
19
|
_appData;
|
|
19
20
|
_devServerMessage;
|
|
20
|
-
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, env, }) {
|
|
21
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, profile, env, }) {
|
|
21
22
|
this._targetProjectAccountId = targetProjectAccountId;
|
|
22
23
|
this._targetTestingAccountId = targetTestingAccountId;
|
|
24
|
+
this._profile = profile;
|
|
23
25
|
this._projectConfig = projectConfig;
|
|
24
26
|
this._projectDir = projectDir;
|
|
25
27
|
this._projectId = projectId;
|
|
@@ -28,8 +30,8 @@ class LocalDevState {
|
|
|
28
30
|
this._deployedBuild = deployedBuild;
|
|
29
31
|
this._isGithubLinked = isGithubLinked;
|
|
30
32
|
this._projectNodes = initialProjectNodes;
|
|
33
|
+
this._projectNodesAtLastUpload = initialProjectNodes;
|
|
31
34
|
this._env = env;
|
|
32
|
-
this._configFilesUpdatedSinceLastUpload = new Set();
|
|
33
35
|
this._appData = {};
|
|
34
36
|
this._devServerMessage = constants_1.LOCAL_DEV_SERVER_MESSAGE_TYPES.INITIAL;
|
|
35
37
|
this._listeners = {};
|
|
@@ -45,10 +47,11 @@ class LocalDevState {
|
|
|
45
47
|
get targetTestingAccountId() {
|
|
46
48
|
return this._targetTestingAccountId;
|
|
47
49
|
}
|
|
50
|
+
get profile() {
|
|
51
|
+
return this._profile;
|
|
52
|
+
}
|
|
48
53
|
get projectConfig() {
|
|
49
|
-
return
|
|
50
|
-
...this._projectConfig,
|
|
51
|
-
};
|
|
54
|
+
return structuredClone(this._projectConfig);
|
|
52
55
|
}
|
|
53
56
|
get projectDir() {
|
|
54
57
|
return this._projectDir;
|
|
@@ -63,34 +66,29 @@ class LocalDevState {
|
|
|
63
66
|
return this._debug;
|
|
64
67
|
}
|
|
65
68
|
get deployedBuild() {
|
|
66
|
-
return
|
|
67
|
-
...this._deployedBuild,
|
|
68
|
-
});
|
|
69
|
+
return this._deployedBuild && structuredClone(this._deployedBuild);
|
|
69
70
|
}
|
|
70
71
|
get isGithubLinked() {
|
|
71
72
|
return this._isGithubLinked;
|
|
72
73
|
}
|
|
73
74
|
get projectNodes() {
|
|
74
|
-
return
|
|
75
|
+
return structuredClone(this._projectNodes);
|
|
75
76
|
}
|
|
76
77
|
set projectNodes(nodes) {
|
|
77
78
|
this._projectNodes = nodes;
|
|
78
79
|
this.runListeners('projectNodes');
|
|
79
80
|
}
|
|
80
|
-
get
|
|
81
|
-
return this.
|
|
82
|
-
}
|
|
83
|
-
get configFilesUpdatedSinceLastUpload() {
|
|
84
|
-
return this._configFilesUpdatedSinceLastUpload;
|
|
81
|
+
get projectNodesAtLastUpload() {
|
|
82
|
+
return structuredClone(this._projectNodesAtLastUpload);
|
|
85
83
|
}
|
|
86
|
-
|
|
87
|
-
this.
|
|
84
|
+
set projectNodesAtLastUpload(nodes) {
|
|
85
|
+
this._projectNodesAtLastUpload = nodes;
|
|
88
86
|
}
|
|
89
|
-
|
|
90
|
-
this.
|
|
87
|
+
get env() {
|
|
88
|
+
return this._env;
|
|
91
89
|
}
|
|
92
90
|
get appData() {
|
|
93
|
-
return
|
|
91
|
+
return structuredClone(this._appData);
|
|
94
92
|
}
|
|
95
93
|
getAppDataByUid(uid) {
|
|
96
94
|
return { ...this._appData[uid] };
|
|
@@ -21,7 +21,7 @@ class LocalDevWatcher {
|
|
|
21
21
|
}
|
|
22
22
|
handleWatchEvent(filePath, event, configPaths) {
|
|
23
23
|
if (configPaths.includes(filePath)) {
|
|
24
|
-
return this.localDevProcess.handleConfigFileChange(
|
|
24
|
+
return this.localDevProcess.handleConfigFileChange();
|
|
25
25
|
}
|
|
26
26
|
return this.localDevProcess.handleFileChange(filePath, event);
|
|
27
27
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentTypes, Component, GenericComponentConfig, PublicAppComponentConfig, PrivateAppComponentConfig, AppCardComponentConfig } from '../../types/Projects';
|
|
2
|
-
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
|
|
2
|
+
import { IntermediateRepresentationNode, IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
|
|
3
3
|
import { AppIRNode } from '../../types/ProjectComponents';
|
|
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';
|
|
3
4
|
type ProjectUploadCallbackFunction<T> = (accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number) => Promise<T>;
|
|
4
5
|
type ProjectUploadResult<T> = {
|
|
@@ -18,4 +19,7 @@ type HandleProjectUploadArg<T> = {
|
|
|
18
19
|
profile?: string;
|
|
19
20
|
};
|
|
20
21
|
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
|
|
22
|
+
export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig): void;
|
|
23
|
+
export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
24
|
+
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<IntermediateRepresentation | undefined>;
|
|
21
25
|
export {};
|
package/lib/projects/upload.js
CHANGED
|
@@ -4,22 +4,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.handleProjectUpload = handleProjectUpload;
|
|
7
|
+
exports.validateSourceDirectory = validateSourceDirectory;
|
|
8
|
+
exports.validateNoHSMetaMismatch = validateNoHSMetaMismatch;
|
|
9
|
+
exports.handleTranslate = handleTranslate;
|
|
7
10
|
const archiver_1 = __importDefault(require("archiver"));
|
|
8
11
|
const tmp_1 = __importDefault(require("tmp"));
|
|
9
12
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
13
|
const path_1 = __importDefault(require("path"));
|
|
11
14
|
const projects_1 = require("@hubspot/local-dev-lib/api/projects");
|
|
12
15
|
const ignoreRules_1 = require("@hubspot/local-dev-lib/ignoreRules");
|
|
16
|
+
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
13
17
|
const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
|
|
14
18
|
const ui_1 = require("../ui");
|
|
15
|
-
const exitCodes_1 = require("../enums/exitCodes");
|
|
16
|
-
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
17
19
|
const errorHandlers_1 = require("../errorHandlers");
|
|
18
20
|
const node_util_1 = __importDefault(require("node:util"));
|
|
19
21
|
const en_1 = require("../../lang/en");
|
|
20
22
|
const ensureProjectExists_1 = require("./ensureProjectExists");
|
|
21
23
|
const logger_1 = require("../ui/logger");
|
|
22
24
|
const buildAndDeploy_1 = require("./buildAndDeploy");
|
|
25
|
+
const exitCodes_1 = require("../enums/exitCodes");
|
|
23
26
|
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
|
|
24
27
|
SpinniesManager_1.default.init({});
|
|
25
28
|
const accountIdentifier = (0, ui_1.uiAccountDescription)(accountId);
|
|
@@ -49,14 +52,18 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
|
|
|
49
52
|
}
|
|
50
53
|
async function handleProjectUpload({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage = '', forceCreate = false, isUploadCommand = false, sendIR = false, skipValidation = false, }) {
|
|
51
54
|
const srcDir = path_1.default.resolve(projectDir, projectConfig.srcDir);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
logger_1.uiLogger.log(en_1.lib.projectUpload.handleProjectUpload.emptySource(projectConfig.srcDir));
|
|
55
|
-
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
55
|
+
try {
|
|
56
|
+
validateSourceDirectory(srcDir, projectConfig);
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
catch (e) {
|
|
59
|
+
(0, errorHandlers_1.logError)(e);
|
|
60
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
await validateNoHSMetaMismatch(srcDir, projectConfig);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
(0, errorHandlers_1.logError)(e);
|
|
60
67
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
61
68
|
}
|
|
62
69
|
const tempFile = tmp_1.default.fileSync({ postfix: '.zip' });
|
|
@@ -68,21 +75,11 @@ async function handleProjectUpload({ accountId, projectConfig, projectDir, callb
|
|
|
68
75
|
let intermediateRepresentation;
|
|
69
76
|
if (sendIR) {
|
|
70
77
|
try {
|
|
71
|
-
intermediateRepresentation = await (
|
|
72
|
-
projectSourceDir: path_1.default.join(projectDir, projectConfig.srcDir),
|
|
73
|
-
platformVersion: projectConfig.platformVersion,
|
|
74
|
-
accountId,
|
|
75
|
-
}, { skipValidation, profile });
|
|
76
|
-
logger_1.uiLogger.debug(node_util_1.default.inspect(intermediateRepresentation, false, null, true));
|
|
78
|
+
intermediateRepresentation = await handleTranslate(projectDir, projectConfig, accountId, skipValidation, profile);
|
|
77
79
|
}
|
|
78
80
|
catch (e) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
(0, errorHandlers_1.logError)(e);
|
|
84
|
-
}
|
|
85
|
-
return process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
81
|
+
(0, errorHandlers_1.logError)(e);
|
|
82
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
86
83
|
}
|
|
87
84
|
}
|
|
88
85
|
await (0, ensureProjectExists_1.ensureProjectExists)(accountId, projectConfig.name, {
|
|
@@ -116,3 +113,41 @@ async function handleProjectUpload({ accountId, projectConfig, projectDir, callb
|
|
|
116
113
|
archive.finalize();
|
|
117
114
|
return result;
|
|
118
115
|
}
|
|
116
|
+
function validateSourceDirectory(srcDir, projectConfig) {
|
|
117
|
+
const filenames = fs_extra_1.default.readdirSync(srcDir);
|
|
118
|
+
if (!filenames || filenames.length === 0) {
|
|
119
|
+
const validationError = new Error(en_1.lib.projectUpload.handleProjectUpload.emptySource(projectConfig.srcDir));
|
|
120
|
+
validationError.name = 'ProjectValidationError';
|
|
121
|
+
throw validationError;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function validateNoHSMetaMismatch(srcDir, projectConfig) {
|
|
125
|
+
const hasHsMetaFiles = await (0, project_parsing_lib_1.projectContainsHsMetaFiles)(srcDir);
|
|
126
|
+
if (!(0, buildAndDeploy_1.useV3Api)(projectConfig.platformVersion) && hasHsMetaFiles) {
|
|
127
|
+
const validationError = new Error(en_1.lib.projectUpload.wrongPlatformVersionMetaFiles);
|
|
128
|
+
validationError.name = 'ProjectValidationError';
|
|
129
|
+
throw validationError;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function handleTranslate(projectDir, projectConfig, accountId, skipValidation, profile) {
|
|
133
|
+
try {
|
|
134
|
+
const intermediateRepresentation = await (0, project_parsing_lib_1.translate)({
|
|
135
|
+
projectSourceDir: path_1.default.join(projectDir, projectConfig.srcDir),
|
|
136
|
+
platformVersion: projectConfig.platformVersion,
|
|
137
|
+
accountId,
|
|
138
|
+
}, { skipValidation, profile });
|
|
139
|
+
logger_1.uiLogger.debug(node_util_1.default.inspect(intermediateRepresentation, false, null, true));
|
|
140
|
+
return intermediateRepresentation;
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
if ((0, project_parsing_lib_1.isTranslationError)(e)) {
|
|
144
|
+
const validationError = new Error(e.toString());
|
|
145
|
+
validationError.name = 'ProjectValidationError';
|
|
146
|
+
throw validationError;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
(0, errorHandlers_1.logError)(e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
package/lib/projects/urls.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export declare function getProjectComponentDistributionUrl(projectName: string, componentName: string, accountId: number): string;
|
|
2
|
+
export declare function getDeveloperOverviewUrl(accountId: number): string;
|
|
1
3
|
export declare function getProjectDetailUrl(projectName: string, accountId: number): string | undefined;
|
|
2
4
|
export declare function getProjectSettingsUrl(projectName: string, accountId: number): string | undefined;
|
|
3
5
|
export declare function getProjectActivityUrl(projectName: string, accountId: number): string;
|
package/lib/projects/urls.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getProjectComponentDistributionUrl = getProjectComponentDistributionUrl;
|
|
4
|
+
exports.getDeveloperOverviewUrl = getDeveloperOverviewUrl;
|
|
3
5
|
exports.getProjectDetailUrl = getProjectDetailUrl;
|
|
4
6
|
exports.getProjectSettingsUrl = getProjectSettingsUrl;
|
|
5
7
|
exports.getProjectActivityUrl = getProjectActivityUrl;
|
|
@@ -15,6 +17,14 @@ function getBaseUrl(accountId) {
|
|
|
15
17
|
function getProjectHomeUrl(accountId) {
|
|
16
18
|
return `${getBaseUrl(accountId)}/developer-projects/${accountId}`;
|
|
17
19
|
}
|
|
20
|
+
function getProjectComponentDistributionUrl(projectName, componentName, accountId) {
|
|
21
|
+
const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)((0, config_1.getEnv)(accountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD);
|
|
22
|
+
return `${baseUrl}/developer-projects/${accountId}/project/${projectName}/component/${componentName}/distribution`;
|
|
23
|
+
}
|
|
24
|
+
function getDeveloperOverviewUrl(accountId) {
|
|
25
|
+
const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)((0, config_1.getEnv)(accountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD);
|
|
26
|
+
return `${baseUrl}/developer-overview/${accountId}`;
|
|
27
|
+
}
|
|
18
28
|
function getProjectDetailUrl(projectName, accountId) {
|
|
19
29
|
if (!projectName)
|
|
20
30
|
return;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DeveloperTestAccountConfig } from '@hubspot/local-dev-lib/types/developerTestAccounts';
|
|
2
|
+
declare const hubs: {
|
|
3
|
+
readonly MARKETING: "marketingLevel";
|
|
4
|
+
readonly OPS: "opsLevel";
|
|
5
|
+
readonly SERVICE: "serviceLevel";
|
|
6
|
+
readonly SALES: "salesLevel";
|
|
7
|
+
readonly CONTENT: "contentLevel";
|
|
8
|
+
};
|
|
9
|
+
type HubName = keyof typeof hubs;
|
|
10
|
+
type HubTier = 'STARTER' | 'PROFESSIONAL' | 'ENTERPRISE';
|
|
11
|
+
export type HubConfig = `${HubName}:${HubTier}`;
|
|
12
|
+
export declare function createDeveloperTestAccountConfigPrompt(args?: {
|
|
13
|
+
name?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
tiers?: HubConfig[];
|
|
16
|
+
}): Promise<DeveloperTestAccountConfig>;
|
|
17
|
+
export {};
|