@hubspot/cli 7.7.1-experimental.0 → 7.7.2-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/account/auth.js +51 -82
- package/commands/auth.js +2 -15
- package/commands/config/migrate.js +17 -36
- package/commands/init.js +1 -2
- package/commands/module/marketplace-validate.js +6 -8
- package/commands/module.js +2 -1
- package/commands/project/add.d.ts +5 -2
- package/commands/project/add.js +43 -80
- package/commands/project/create.d.ts +2 -8
- package/commands/project/create.js +84 -55
- package/commands/project/dev/unifiedFlow.js +1 -0
- package/commands/remove.js +6 -12
- package/commands/theme/generate-selectors.js +7 -10
- package/commands/theme/marketplace-validate.js +6 -8
- package/commands/theme/preview.js +17 -18
- package/commands/theme.js +2 -2
- package/commands/upload.js +26 -63
- package/commands/watch.js +20 -32
- package/lang/en.d.ts +140 -92
- package/lang/en.js +143 -98
- package/lang/en.lyaml +3 -186
- package/lib/configMigrate.d.ts +2 -2
- package/lib/configMigrate.js +34 -69
- package/lib/constants.d.ts +23 -5
- package/lib/constants.js +24 -6
- package/lib/generateSelectors.js +3 -5
- package/lib/marketplaceValidate.d.ts +12 -2
- package/lib/marketplaceValidate.js +22 -29
- package/lib/middleware/configMiddleware.js +1 -0
- package/lib/projects/add/legacyAddComponent.d.ts +5 -0
- package/lib/projects/add/legacyAddComponent.js +48 -0
- package/lib/projects/add/v3AddComponent.d.ts +8 -0
- package/lib/projects/add/v3AddComponent.js +85 -0
- package/lib/projects/components.d.ts +2 -0
- package/lib/projects/components.js +82 -0
- package/lib/projects/create/index.d.ts +23 -0
- package/lib/projects/create/index.js +33 -0
- package/lib/projects/create/legacy.d.ts +6 -0
- package/lib/projects/{create.js → create/legacy.js} +20 -11
- package/lib/projects/create/v3.d.ts +27 -0
- package/lib/projects/create/v3.js +158 -0
- package/lib/projects/localDev/AppDevModeInterface.d.ts +3 -2
- package/lib/projects/localDev/AppDevModeInterface.js +38 -2
- package/lib/projects/localDev/LocalDevProcess.d.ts +12 -5
- package/lib/projects/localDev/LocalDevProcess.js +47 -17
- package/lib/projects/localDev/LocalDevState.d.ts +16 -3
- package/lib/projects/localDev/LocalDevState.js +43 -2
- package/lib/projects/localDev/LocalDevWatcher.js +3 -6
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +3 -0
- package/lib/projects/localDev/LocalDevWebsocketServer.js +48 -9
- package/lib/prompts/createProjectPrompt.d.ts +14 -5
- package/lib/prompts/createProjectPrompt.js +36 -13
- package/lib/prompts/projectAddPrompt.d.ts +5 -1
- package/lib/prompts/projectAddPrompt.js +35 -7
- package/lib/prompts/setAsDefaultAccountPrompt.js +10 -0
- package/package.json +6 -5
- package/types/LocalDev.d.ts +11 -1
- package/types/Projects.d.ts +19 -2
- package/lib/projects/create.d.ts +0 -5
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
|
|
2
2
|
import LocalDevState from './LocalDevState';
|
|
3
3
|
import LocalDevLogger from './LocalDevLogger';
|
|
4
|
-
import { LocalDevStateConstructorOptions, LocalDevStateListener } from '../../../types/LocalDev';
|
|
4
|
+
import { LocalDevStateConstructorOptions, LocalDevStateListener, LocalDevServerMessage } from '../../../types/LocalDev';
|
|
5
5
|
declare class LocalDevProcess {
|
|
6
6
|
private state;
|
|
7
7
|
private _logger;
|
|
8
8
|
private devServerManager;
|
|
9
9
|
constructor(options: LocalDevStateConstructorOptions);
|
|
10
10
|
get projectDir(): string;
|
|
11
|
+
get projectId(): number;
|
|
12
|
+
get projectName(): string;
|
|
13
|
+
get targetProjectAccountId(): number;
|
|
14
|
+
get targetTestingAccountId(): number;
|
|
11
15
|
get projectNodes(): {
|
|
12
16
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
13
17
|
};
|
|
14
18
|
get logger(): LocalDevLogger;
|
|
19
|
+
get configFilesUpdatedSinceLastUpload(): Set<string>;
|
|
15
20
|
private setupDevServers;
|
|
16
21
|
private startDevServers;
|
|
17
22
|
private cleanupDevServers;
|
|
18
23
|
private compareLocalProjectToDeployed;
|
|
19
24
|
private projectConfigValidForUpload;
|
|
20
|
-
|
|
25
|
+
private updateProjectNodes;
|
|
26
|
+
handleFileChange(filePath: string, event: string): Promise<void>;
|
|
27
|
+
handleConfigFileChange(filePath: string, event: string): Promise<void>;
|
|
21
28
|
start(): Promise<void>;
|
|
22
29
|
stop(showProgress?: boolean): Promise<void>;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
uploadProject(): Promise<boolean>;
|
|
31
|
+
addStateListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>, callOnInit?: boolean): void;
|
|
32
|
+
sendDevServerMessage(message: LocalDevServerMessage): void;
|
|
26
33
|
}
|
|
27
34
|
export default LocalDevProcess;
|
|
@@ -28,12 +28,27 @@ class LocalDevProcess {
|
|
|
28
28
|
get projectDir() {
|
|
29
29
|
return this.state.projectDir;
|
|
30
30
|
}
|
|
31
|
+
get projectId() {
|
|
32
|
+
return this.state.projectId;
|
|
33
|
+
}
|
|
34
|
+
get projectName() {
|
|
35
|
+
return this.state.projectName;
|
|
36
|
+
}
|
|
37
|
+
get targetProjectAccountId() {
|
|
38
|
+
return this.state.targetProjectAccountId;
|
|
39
|
+
}
|
|
40
|
+
get targetTestingAccountId() {
|
|
41
|
+
return this.state.targetTestingAccountId;
|
|
42
|
+
}
|
|
31
43
|
get projectNodes() {
|
|
32
44
|
return this.state.projectNodes;
|
|
33
45
|
}
|
|
34
46
|
get logger() {
|
|
35
47
|
return this._logger;
|
|
36
48
|
}
|
|
49
|
+
get configFilesUpdatedSinceLastUpload() {
|
|
50
|
+
return this.state.configFilesUpdatedSinceLastUpload;
|
|
51
|
+
}
|
|
37
52
|
async setupDevServers() {
|
|
38
53
|
try {
|
|
39
54
|
await this.devServerManager.setup();
|
|
@@ -90,7 +105,19 @@ class LocalDevProcess {
|
|
|
90
105
|
});
|
|
91
106
|
return true;
|
|
92
107
|
}
|
|
93
|
-
|
|
108
|
+
async updateProjectNodes() {
|
|
109
|
+
const intermediateRepresentation = await (0, project_parsing_lib_1.translateForLocalDev)({
|
|
110
|
+
projectSourceDir: path_1.default.join(this.state.projectDir, this.state.projectConfig.srcDir),
|
|
111
|
+
platformVersion: this.state.projectConfig.platformVersion,
|
|
112
|
+
accountId: this.state.targetProjectAccountId,
|
|
113
|
+
}, {
|
|
114
|
+
configFilesUpdatedSinceLastUpload: this.state.configFilesUpdatedSinceLastUpload,
|
|
115
|
+
});
|
|
116
|
+
this.state.projectNodes =
|
|
117
|
+
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
118
|
+
}
|
|
119
|
+
async handleFileChange(filePath, event) {
|
|
120
|
+
await this.updateProjectNodes();
|
|
94
121
|
try {
|
|
95
122
|
this.devServerManager.fileChange({ filePath, event });
|
|
96
123
|
}
|
|
@@ -98,6 +125,13 @@ class LocalDevProcess {
|
|
|
98
125
|
this.logger.fileChangeError(e);
|
|
99
126
|
}
|
|
100
127
|
}
|
|
128
|
+
async handleConfigFileChange(filePath, event) {
|
|
129
|
+
if (event === 'add' || event === 'change') {
|
|
130
|
+
this.state.addUpdatedConfigFileUpdatedSinceLastUpload(filePath);
|
|
131
|
+
}
|
|
132
|
+
await this.updateProjectNodes();
|
|
133
|
+
this.logger.uploadWarning();
|
|
134
|
+
}
|
|
101
135
|
async start() {
|
|
102
136
|
this.logger.resetSpinnies();
|
|
103
137
|
// Local dev currently relies on the existence of a deployed build in the target account
|
|
@@ -132,21 +166,12 @@ class LocalDevProcess {
|
|
|
132
166
|
}
|
|
133
167
|
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
134
168
|
}
|
|
135
|
-
async updateProjectNodes() {
|
|
136
|
-
const intermediateRepresentation = await (0, project_parsing_lib_1.translateForLocalDev)({
|
|
137
|
-
projectSourceDir: path_1.default.join(this.state.projectDir, this.state.projectConfig.srcDir),
|
|
138
|
-
platformVersion: this.state.projectConfig.platformVersion,
|
|
139
|
-
accountId: this.state.targetProjectAccountId,
|
|
140
|
-
});
|
|
141
|
-
this.state.projectNodes =
|
|
142
|
-
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
143
|
-
}
|
|
144
169
|
async uploadProject() {
|
|
145
170
|
this.logger.uploadInitiated();
|
|
146
171
|
const isUploadable = await this.projectConfigValidForUpload();
|
|
147
172
|
if (!isUploadable) {
|
|
148
173
|
this.logger.projectConfigMismatch();
|
|
149
|
-
return;
|
|
174
|
+
return false;
|
|
150
175
|
}
|
|
151
176
|
const { uploadError } = await (0, upload_1.handleProjectUpload)({
|
|
152
177
|
accountId: this.state.targetProjectAccountId,
|
|
@@ -158,14 +183,19 @@ class LocalDevProcess {
|
|
|
158
183
|
});
|
|
159
184
|
if (uploadError) {
|
|
160
185
|
this.logger.uploadError(uploadError);
|
|
186
|
+
return false;
|
|
161
187
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
188
|
+
this.state.resetConfigFilesUpdatedSinceLastUpload();
|
|
189
|
+
this.updateProjectNodes();
|
|
190
|
+
this.logger.uploadSuccess();
|
|
191
|
+
this.logger.clearUploadWarnings();
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
addStateListener(key, listener, callOnInit = false) {
|
|
195
|
+
this.state.addListener(key, listener, callOnInit);
|
|
166
196
|
}
|
|
167
|
-
|
|
168
|
-
this.state.
|
|
197
|
+
sendDevServerMessage(message) {
|
|
198
|
+
this.state.devServerMessage = message;
|
|
169
199
|
}
|
|
170
200
|
}
|
|
171
201
|
exports.default = LocalDevProcess;
|
|
@@ -2,26 +2,31 @@ import { Build } from '@hubspot/local-dev-lib/types/Build';
|
|
|
2
2
|
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
|
|
3
3
|
import { Environment } from '@hubspot/local-dev-lib/types/Config';
|
|
4
4
|
import { ProjectConfig } from '../../../types/Projects';
|
|
5
|
-
import { LocalDevStateConstructorOptions, LocalDevStateListener } from '../../../types/LocalDev';
|
|
5
|
+
import { LocalDevStateConstructorOptions, LocalDevStateListener, AppLocalDevData, LocalDevServerMessage } from '../../../types/LocalDev';
|
|
6
6
|
declare class LocalDevState {
|
|
7
7
|
private _targetProjectAccountId;
|
|
8
8
|
private _targetTestingAccountId;
|
|
9
9
|
private _projectConfig;
|
|
10
10
|
private _projectDir;
|
|
11
11
|
private _projectId;
|
|
12
|
+
private _projectName;
|
|
12
13
|
private _debug;
|
|
13
14
|
private _deployedBuild?;
|
|
14
15
|
private _isGithubLinked;
|
|
15
16
|
private _projectNodes;
|
|
16
17
|
private _env;
|
|
17
18
|
private _listeners;
|
|
18
|
-
|
|
19
|
+
private _configFilesUpdatedSinceLastUpload;
|
|
20
|
+
private _appData;
|
|
21
|
+
private _devServerMessage;
|
|
22
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, env, }: LocalDevStateConstructorOptions);
|
|
19
23
|
private runListeners;
|
|
20
24
|
get targetProjectAccountId(): number;
|
|
21
25
|
get targetTestingAccountId(): number;
|
|
22
26
|
get projectConfig(): ProjectConfig;
|
|
23
27
|
get projectDir(): string;
|
|
24
28
|
get projectId(): number;
|
|
29
|
+
get projectName(): string;
|
|
25
30
|
get debug(): boolean;
|
|
26
31
|
get deployedBuild(): Build | undefined;
|
|
27
32
|
get isGithubLinked(): boolean;
|
|
@@ -32,6 +37,14 @@ declare class LocalDevState {
|
|
|
32
37
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
33
38
|
});
|
|
34
39
|
get env(): Environment;
|
|
35
|
-
|
|
40
|
+
get configFilesUpdatedSinceLastUpload(): Set<string>;
|
|
41
|
+
addUpdatedConfigFileUpdatedSinceLastUpload(filePath: string): void;
|
|
42
|
+
resetConfigFilesUpdatedSinceLastUpload(): void;
|
|
43
|
+
get appData(): Record<string, AppLocalDevData>;
|
|
44
|
+
getAppDataByUid(uid: string): AppLocalDevData | undefined;
|
|
45
|
+
setAppDataForUid(uid: string, appData: AppLocalDevData): void;
|
|
46
|
+
get devServerMessage(): string;
|
|
47
|
+
set devServerMessage(message: LocalDevServerMessage);
|
|
48
|
+
addListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>, callOnInit?: boolean): void;
|
|
36
49
|
}
|
|
37
50
|
export default LocalDevState;
|
|
@@ -1,28 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const constants_1 = require("../../constants");
|
|
3
4
|
class LocalDevState {
|
|
4
5
|
_targetProjectAccountId;
|
|
5
6
|
_targetTestingAccountId;
|
|
6
7
|
_projectConfig;
|
|
7
8
|
_projectDir;
|
|
8
9
|
_projectId;
|
|
10
|
+
_projectName;
|
|
9
11
|
_debug;
|
|
10
12
|
_deployedBuild;
|
|
11
13
|
_isGithubLinked;
|
|
12
14
|
_projectNodes;
|
|
13
15
|
_env;
|
|
14
16
|
_listeners;
|
|
15
|
-
|
|
17
|
+
_configFilesUpdatedSinceLastUpload;
|
|
18
|
+
_appData;
|
|
19
|
+
_devServerMessage;
|
|
20
|
+
constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, env, }) {
|
|
16
21
|
this._targetProjectAccountId = targetProjectAccountId;
|
|
17
22
|
this._targetTestingAccountId = targetTestingAccountId;
|
|
18
23
|
this._projectConfig = projectConfig;
|
|
19
24
|
this._projectDir = projectDir;
|
|
20
25
|
this._projectId = projectId;
|
|
26
|
+
this._projectName = projectName;
|
|
21
27
|
this._debug = debug || false;
|
|
22
28
|
this._deployedBuild = deployedBuild;
|
|
23
29
|
this._isGithubLinked = isGithubLinked;
|
|
24
30
|
this._projectNodes = initialProjectNodes;
|
|
25
31
|
this._env = env;
|
|
32
|
+
this._configFilesUpdatedSinceLastUpload = new Set();
|
|
33
|
+
this._appData = {};
|
|
34
|
+
this._devServerMessage = constants_1.LOCAL_DEV_SERVER_MESSAGE_TYPES.INITIAL;
|
|
26
35
|
this._listeners = {};
|
|
27
36
|
}
|
|
28
37
|
runListeners(key) {
|
|
@@ -47,6 +56,9 @@ class LocalDevState {
|
|
|
47
56
|
get projectId() {
|
|
48
57
|
return this._projectId;
|
|
49
58
|
}
|
|
59
|
+
get projectName() {
|
|
60
|
+
return this._projectName;
|
|
61
|
+
}
|
|
50
62
|
get debug() {
|
|
51
63
|
return this._debug;
|
|
52
64
|
}
|
|
@@ -68,11 +80,40 @@ class LocalDevState {
|
|
|
68
80
|
get env() {
|
|
69
81
|
return this._env;
|
|
70
82
|
}
|
|
71
|
-
|
|
83
|
+
get configFilesUpdatedSinceLastUpload() {
|
|
84
|
+
return this._configFilesUpdatedSinceLastUpload;
|
|
85
|
+
}
|
|
86
|
+
addUpdatedConfigFileUpdatedSinceLastUpload(filePath) {
|
|
87
|
+
this._configFilesUpdatedSinceLastUpload.add(filePath);
|
|
88
|
+
}
|
|
89
|
+
resetConfigFilesUpdatedSinceLastUpload() {
|
|
90
|
+
this._configFilesUpdatedSinceLastUpload.clear();
|
|
91
|
+
}
|
|
92
|
+
get appData() {
|
|
93
|
+
return { ...this._appData };
|
|
94
|
+
}
|
|
95
|
+
getAppDataByUid(uid) {
|
|
96
|
+
return { ...this._appData[uid] };
|
|
97
|
+
}
|
|
98
|
+
setAppDataForUid(uid, appData) {
|
|
99
|
+
this._appData[uid] = appData;
|
|
100
|
+
this.runListeners('appData');
|
|
101
|
+
}
|
|
102
|
+
get devServerMessage() {
|
|
103
|
+
return this._devServerMessage;
|
|
104
|
+
}
|
|
105
|
+
set devServerMessage(message) {
|
|
106
|
+
this._devServerMessage = message;
|
|
107
|
+
this.runListeners('devServerMessage');
|
|
108
|
+
}
|
|
109
|
+
addListener(key, listener, callOnInit = false) {
|
|
72
110
|
if (!this._listeners[key]) {
|
|
73
111
|
this._listeners[key] = [];
|
|
74
112
|
}
|
|
75
113
|
this._listeners[key].push(listener);
|
|
114
|
+
if (callOnInit) {
|
|
115
|
+
listener(this[key]);
|
|
116
|
+
}
|
|
76
117
|
}
|
|
77
118
|
}
|
|
78
119
|
exports.default = LocalDevState;
|
|
@@ -19,14 +19,11 @@ class LocalDevWatcher {
|
|
|
19
19
|
this.localDevProcess = localDevProcess;
|
|
20
20
|
this.watcher = null;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
await this.localDevProcess.updateProjectNodes();
|
|
22
|
+
handleWatchEvent(filePath, event, configPaths) {
|
|
24
23
|
if (configPaths.includes(filePath)) {
|
|
25
|
-
this.localDevProcess.
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
this.localDevProcess.handleFileChange(filePath, event);
|
|
24
|
+
return this.localDevProcess.handleConfigFileChange(filePath, event);
|
|
29
25
|
}
|
|
26
|
+
return this.localDevProcess.handleFileChange(filePath, event);
|
|
30
27
|
}
|
|
31
28
|
start() {
|
|
32
29
|
this.watcher = chokidar_1.default.watch(this.localDevProcess.projectDir, {
|
|
@@ -4,12 +4,15 @@ declare class LocalDevWebsocketServer {
|
|
|
4
4
|
private _websocket?;
|
|
5
5
|
private debug?;
|
|
6
6
|
private localDevProcess;
|
|
7
|
+
private ALLOWED_ORIGINS;
|
|
7
8
|
constructor(localDevProcess: LocalDevProcess, debug?: boolean);
|
|
8
9
|
private websocket;
|
|
9
10
|
private log;
|
|
10
11
|
private logError;
|
|
11
12
|
private sendMessage;
|
|
13
|
+
private handleUpload;
|
|
12
14
|
private setupMessageHandlers;
|
|
15
|
+
private sendProjectData;
|
|
13
16
|
private setupStateListeners;
|
|
14
17
|
start(): Promise<void>;
|
|
15
18
|
shutdown(): void;
|
|
@@ -12,6 +12,12 @@ class LocalDevWebsocketServer {
|
|
|
12
12
|
_websocket;
|
|
13
13
|
debug;
|
|
14
14
|
localDevProcess;
|
|
15
|
+
ALLOWED_ORIGINS = [
|
|
16
|
+
'https://hubspot.com',
|
|
17
|
+
'https://hubspotqa.com',
|
|
18
|
+
'https://local.hubspot.com',
|
|
19
|
+
'https://local.hubspotqa.com',
|
|
20
|
+
];
|
|
15
21
|
constructor(localDevProcess, debug) {
|
|
16
22
|
this.localDevProcess = localDevProcess;
|
|
17
23
|
this.debug = debug;
|
|
@@ -35,6 +41,19 @@ class LocalDevWebsocketServer {
|
|
|
35
41
|
sendMessage(message) {
|
|
36
42
|
this.websocket().send(JSON.stringify(message));
|
|
37
43
|
}
|
|
44
|
+
async handleUpload() {
|
|
45
|
+
const uploadSuccess = await this.localDevProcess.uploadProject();
|
|
46
|
+
if (uploadSuccess) {
|
|
47
|
+
this.sendMessage({
|
|
48
|
+
type: constants_1.LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPLOAD_SUCCESS,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.sendMessage({
|
|
53
|
+
type: constants_1.LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPLOAD_FAILURE,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
38
57
|
setupMessageHandlers() {
|
|
39
58
|
this.websocket().on('message', data => {
|
|
40
59
|
try {
|
|
@@ -44,12 +63,8 @@ class LocalDevWebsocketServer {
|
|
|
44
63
|
return;
|
|
45
64
|
}
|
|
46
65
|
switch (message.type) {
|
|
47
|
-
case constants_1.
|
|
48
|
-
this.
|
|
49
|
-
break;
|
|
50
|
-
case constants_1.LOCAL_DEV_UI_WEBSOCKET_MESSAGE_TYPES.INSTALL_DEPS:
|
|
51
|
-
break;
|
|
52
|
-
case constants_1.LOCAL_DEV_UI_WEBSOCKET_MESSAGE_TYPES.APP_INSTALLED:
|
|
66
|
+
case constants_1.LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.UPLOAD:
|
|
67
|
+
this.handleUpload();
|
|
53
68
|
break;
|
|
54
69
|
default:
|
|
55
70
|
this.logError(en_1.lib.LocalDevWebsocketServer.errors.unknownMessageType(message.type));
|
|
@@ -60,13 +75,30 @@ class LocalDevWebsocketServer {
|
|
|
60
75
|
}
|
|
61
76
|
});
|
|
62
77
|
}
|
|
78
|
+
sendProjectData() {
|
|
79
|
+
this.sendMessage({
|
|
80
|
+
type: constants_1.LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_DATA,
|
|
81
|
+
data: {
|
|
82
|
+
projectName: this.localDevProcess.projectName,
|
|
83
|
+
projectId: this.localDevProcess.projectId,
|
|
84
|
+
targetProjectAccountId: this.localDevProcess.targetProjectAccountId,
|
|
85
|
+
targetTestingAccountId: this.localDevProcess.targetTestingAccountId,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
63
89
|
setupStateListeners() {
|
|
64
90
|
this.localDevProcess.addStateListener('projectNodes', nodes => {
|
|
65
91
|
this.sendMessage({
|
|
66
|
-
type: constants_1.
|
|
92
|
+
type: constants_1.LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_NODES,
|
|
67
93
|
data: nodes,
|
|
68
94
|
});
|
|
69
|
-
});
|
|
95
|
+
}, true);
|
|
96
|
+
this.localDevProcess.addStateListener('appData', appData => {
|
|
97
|
+
this.sendMessage({
|
|
98
|
+
type: constants_1.LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_APP_DATA,
|
|
99
|
+
data: appData,
|
|
100
|
+
});
|
|
101
|
+
}, true);
|
|
70
102
|
}
|
|
71
103
|
async start() {
|
|
72
104
|
const portManagerIsRunning = await (0, portManager_1.isPortManagerServerRunning)();
|
|
@@ -77,10 +109,17 @@ class LocalDevWebsocketServer {
|
|
|
77
109
|
const port = portData[SERVER_INSTANCE_ID];
|
|
78
110
|
this.server = new ws_1.WebSocketServer({ port });
|
|
79
111
|
this.log(en_1.lib.LocalDevWebsocketServer.logs.startup(port));
|
|
80
|
-
this.server.on('connection', ws => {
|
|
112
|
+
this.server.on('connection', (ws, req) => {
|
|
113
|
+
const origin = req.headers.origin;
|
|
114
|
+
if (!origin || !this.ALLOWED_ORIGINS.includes(origin)) {
|
|
115
|
+
ws.close(1008, en_1.lib.LocalDevWebsocketServer.errors.originNotAllowed(origin));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
81
118
|
this._websocket = ws;
|
|
119
|
+
this.sendProjectData();
|
|
82
120
|
this.setupMessageHandlers();
|
|
83
121
|
this.setupStateListeners();
|
|
122
|
+
this.localDevProcess.sendDevServerMessage(constants_1.LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED);
|
|
84
123
|
});
|
|
85
124
|
}
|
|
86
125
|
shutdown() {
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
import { ProjectTemplate } from '../../types/Projects';
|
|
2
|
-
type
|
|
1
|
+
import { ComponentTemplate, ComponentTemplateChoice, ProjectTemplate } from '../../types/Projects';
|
|
2
|
+
export type CreateProjectPromptResponse = {
|
|
3
|
+
name: string;
|
|
4
|
+
dest: string;
|
|
5
|
+
projectTemplate?: ProjectTemplate;
|
|
6
|
+
componentTemplates?: ComponentTemplate[];
|
|
7
|
+
};
|
|
8
|
+
type CreateProjectPromptResponseProjectTemplate = {
|
|
3
9
|
name: string;
|
|
4
10
|
dest: string;
|
|
5
11
|
projectTemplate: ProjectTemplate;
|
|
12
|
+
componentTemplates: undefined;
|
|
6
13
|
};
|
|
7
|
-
type
|
|
14
|
+
type CreateProjectPromptResponseComponentTemplates = {
|
|
8
15
|
name: string;
|
|
9
16
|
dest: string;
|
|
10
17
|
projectTemplate?: undefined;
|
|
18
|
+
componentTemplates?: ComponentTemplate[];
|
|
11
19
|
};
|
|
12
20
|
type PromptOptionsArg = {
|
|
13
21
|
name?: string;
|
|
14
22
|
dest?: string;
|
|
15
23
|
template?: string;
|
|
24
|
+
features?: string[];
|
|
16
25
|
};
|
|
17
|
-
export declare function createProjectPrompt(promptOptions: PromptOptionsArg, projectTemplates
|
|
18
|
-
export declare function createProjectPrompt(promptOptions: PromptOptionsArg, projectTemplates?: undefined): Promise<
|
|
26
|
+
export declare function createProjectPrompt(promptOptions: PromptOptionsArg, projectTemplates?: ProjectTemplate[], componentTemplates?: undefined): Promise<CreateProjectPromptResponseProjectTemplate>;
|
|
27
|
+
export declare function createProjectPrompt(promptOptions: PromptOptionsArg, projectTemplates?: undefined, componentTemplates?: ComponentTemplateChoice[]): Promise<CreateProjectPromptResponseComponentTemplates>;
|
|
19
28
|
export {};
|
|
@@ -8,43 +8,58 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const path_2 = require("@hubspot/local-dev-lib/path");
|
|
10
10
|
const promptUtils_1 = require("./promptUtils");
|
|
11
|
-
const lang_1 = require("../lang");
|
|
12
11
|
const constants_1 = require("../constants");
|
|
12
|
+
const en_1 = require("../../lang/en");
|
|
13
13
|
function validateProjectDirectory(input) {
|
|
14
14
|
if (!input) {
|
|
15
|
-
return
|
|
15
|
+
return en_1.lib.prompts.createProjectPrompt.errors.destRequired;
|
|
16
16
|
}
|
|
17
17
|
if (fs_1.default.existsSync(path_1.default.resolve((0, path_2.getCwd)(), path_1.default.join(input, constants_1.PROJECT_CONFIG_FILE)))) {
|
|
18
|
-
return
|
|
18
|
+
return en_1.lib.prompts.createProjectPrompt.errors.invalidDest;
|
|
19
19
|
}
|
|
20
20
|
if (!(0, path_2.isValidPath)(input)) {
|
|
21
|
-
return
|
|
21
|
+
return en_1.lib.prompts.createProjectPrompt.errors.invalidCharacters;
|
|
22
22
|
}
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
function findTemplateByNameOrLabel(projectTemplates, templateNameOrLabel) {
|
|
26
26
|
return projectTemplates.find(t => t.name === templateNameOrLabel || t.label === templateNameOrLabel);
|
|
27
27
|
}
|
|
28
|
-
async function createProjectPrompt(promptOptions, projectTemplates) {
|
|
28
|
+
async function createProjectPrompt(promptOptions, projectTemplates, componentTemplates) {
|
|
29
29
|
const createProjectFromTemplate = !!projectTemplates && projectTemplates.length > 0;
|
|
30
|
+
const createProjectFromComponents = Array.isArray(componentTemplates) && componentTemplates?.length > 0;
|
|
31
|
+
const selectedComponents = [];
|
|
32
|
+
if (createProjectFromComponents && promptOptions.features) {
|
|
33
|
+
componentTemplates.forEach(template => {
|
|
34
|
+
if (!template.value) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (promptOptions.features?.includes(template.value.type)) {
|
|
38
|
+
if (template.disabled) {
|
|
39
|
+
throw new Error(`Cannot create project with template '${template.value.type}'. Reasons: ${template.disabled}`);
|
|
40
|
+
}
|
|
41
|
+
selectedComponents.push(template.value);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
30
45
|
const providedTemplateIsValid = createProjectFromTemplate &&
|
|
31
46
|
!!promptOptions.template &&
|
|
32
47
|
!!findTemplateByNameOrLabel(projectTemplates, promptOptions.template);
|
|
33
48
|
const result = await (0, promptUtils_1.promptUser)([
|
|
34
49
|
{
|
|
35
50
|
name: 'name',
|
|
36
|
-
message:
|
|
51
|
+
message: en_1.lib.prompts.createProjectPrompt.enterName,
|
|
37
52
|
when: !promptOptions.name,
|
|
38
53
|
validate: (input) => {
|
|
39
54
|
if (!input) {
|
|
40
|
-
return
|
|
55
|
+
return en_1.lib.prompts.createProjectPrompt.errors.nameRequired;
|
|
41
56
|
}
|
|
42
57
|
return true;
|
|
43
58
|
},
|
|
44
59
|
},
|
|
45
60
|
{
|
|
46
61
|
name: 'dest',
|
|
47
|
-
message:
|
|
62
|
+
message: en_1.lib.prompts.createProjectPrompt.enterDest,
|
|
48
63
|
when: !promptOptions.dest,
|
|
49
64
|
default: answers => {
|
|
50
65
|
const projectName = (0, path_2.sanitizeFileName)(promptOptions.name || answers.name);
|
|
@@ -59,10 +74,8 @@ async function createProjectPrompt(promptOptions, projectTemplates) {
|
|
|
59
74
|
name: 'projectTemplate',
|
|
60
75
|
message: () => {
|
|
61
76
|
return promptOptions.template && !providedTemplateIsValid
|
|
62
|
-
?
|
|
63
|
-
|
|
64
|
-
})
|
|
65
|
-
: (0, lang_1.i18n)(`lib.prompts.createProjectPrompt.selectTemplate`);
|
|
77
|
+
? en_1.lib.prompts.createProjectPrompt.errors.invalidTemplate(promptOptions.template)
|
|
78
|
+
: en_1.lib.prompts.createProjectPrompt.selectTemplate;
|
|
66
79
|
},
|
|
67
80
|
when: createProjectFromTemplate && !providedTemplateIsValid,
|
|
68
81
|
type: 'list',
|
|
@@ -75,6 +88,13 @@ async function createProjectPrompt(promptOptions, projectTemplates) {
|
|
|
75
88
|
})
|
|
76
89
|
: undefined,
|
|
77
90
|
},
|
|
91
|
+
{
|
|
92
|
+
name: 'componentTemplates',
|
|
93
|
+
message: '[--features] Which features would you like your app to include?',
|
|
94
|
+
when: createProjectFromComponents && selectedComponents.length === 0,
|
|
95
|
+
type: 'checkbox',
|
|
96
|
+
choices: componentTemplates,
|
|
97
|
+
},
|
|
78
98
|
]);
|
|
79
99
|
if (!result.name) {
|
|
80
100
|
result.name = promptOptions.name;
|
|
@@ -82,12 +102,15 @@ async function createProjectPrompt(promptOptions, projectTemplates) {
|
|
|
82
102
|
if (!result.dest) {
|
|
83
103
|
result.dest = promptOptions.dest;
|
|
84
104
|
}
|
|
105
|
+
if (!result.componentTemplates) {
|
|
106
|
+
result.componentTemplates = selectedComponents;
|
|
107
|
+
}
|
|
85
108
|
if (providedTemplateIsValid) {
|
|
86
109
|
result.projectTemplate = findTemplateByNameOrLabel(projectTemplates, promptOptions.template);
|
|
87
110
|
}
|
|
88
111
|
if (projectTemplates && projectTemplates.length > 0) {
|
|
89
112
|
if (!result.projectTemplate) {
|
|
90
|
-
throw new Error(
|
|
113
|
+
throw new Error(en_1.lib.prompts.createProjectPrompt.errors.projectTemplateRequired);
|
|
91
114
|
}
|
|
92
115
|
return result;
|
|
93
116
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { ComponentTemplate } from '../../types/Projects';
|
|
1
|
+
import { ComponentTemplate, ComponentTemplateChoice } from '../../types/Projects';
|
|
2
2
|
type ProjectAddPromptResponse = {
|
|
3
3
|
componentTemplate: ComponentTemplate;
|
|
4
4
|
name: string;
|
|
5
5
|
};
|
|
6
|
+
type ProjectAddPromptResponseV3 = {
|
|
7
|
+
componentTemplate: ComponentTemplate[];
|
|
8
|
+
};
|
|
6
9
|
export declare function projectAddPrompt(components: ComponentTemplate[], promptOptions?: {
|
|
7
10
|
name?: string;
|
|
8
11
|
type?: string;
|
|
9
12
|
}): Promise<ProjectAddPromptResponse>;
|
|
13
|
+
export declare function projectAddPromptV3(components: ComponentTemplateChoice[], selectedFeatures: string[] | undefined): Promise<ProjectAddPromptResponseV3>;
|
|
10
14
|
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.projectAddPrompt = projectAddPrompt;
|
|
4
|
+
exports.projectAddPromptV3 = projectAddPromptV3;
|
|
4
5
|
const promptUtils_1 = require("./promptUtils");
|
|
5
|
-
const
|
|
6
|
+
const en_1 = require("../../lang/en");
|
|
6
7
|
function findComponentByPathOrLabel(components, componentPathOrLabel) {
|
|
7
8
|
return components.find(c => c.path === componentPathOrLabel || c.label === componentPathOrLabel);
|
|
8
9
|
}
|
|
@@ -14,10 +15,8 @@ async function projectAddPrompt(components, promptOptions = {}) {
|
|
|
14
15
|
name: 'componentTemplate',
|
|
15
16
|
message: () => {
|
|
16
17
|
return promptOptions.type && !providedTypeIsValid
|
|
17
|
-
?
|
|
18
|
-
|
|
19
|
-
})
|
|
20
|
-
: (0, lang_1.i18n)(`lib.prompts.projectAddPrompt.selectType`);
|
|
18
|
+
? en_1.lib.prompts.projectAddPrompt.errors.invalidType(promptOptions.type)
|
|
19
|
+
: en_1.lib.prompts.projectAddPrompt.selectType;
|
|
21
20
|
},
|
|
22
21
|
when: !providedTypeIsValid,
|
|
23
22
|
type: 'list',
|
|
@@ -30,11 +29,11 @@ async function projectAddPrompt(components, promptOptions = {}) {
|
|
|
30
29
|
},
|
|
31
30
|
{
|
|
32
31
|
name: 'name',
|
|
33
|
-
message:
|
|
32
|
+
message: en_1.lib.prompts.projectAddPrompt.enterName,
|
|
34
33
|
when: !promptOptions.name,
|
|
35
34
|
validate: (input) => {
|
|
36
35
|
if (!input) {
|
|
37
|
-
return
|
|
36
|
+
return en_1.lib.prompts.projectAddPrompt.errors.nameRequired;
|
|
38
37
|
}
|
|
39
38
|
return true;
|
|
40
39
|
},
|
|
@@ -48,3 +47,32 @@ async function projectAddPrompt(components, promptOptions = {}) {
|
|
|
48
47
|
}
|
|
49
48
|
return result;
|
|
50
49
|
}
|
|
50
|
+
async function projectAddPromptV3(components, selectedFeatures) {
|
|
51
|
+
const selectedComponents = [];
|
|
52
|
+
if (selectedFeatures) {
|
|
53
|
+
components.forEach(template => {
|
|
54
|
+
if (!template.value) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (selectedFeatures?.includes(template.value.type)) {
|
|
58
|
+
if (template.disabled) {
|
|
59
|
+
throw new Error(en_1.lib.prompts.projectAddPrompt.errors.cannotAddFeature(template.value.type, template.disabled));
|
|
60
|
+
}
|
|
61
|
+
selectedComponents.push(template.value);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const result = await (0, promptUtils_1.promptUser)([
|
|
66
|
+
{
|
|
67
|
+
name: 'componentTemplate',
|
|
68
|
+
message: en_1.lib.prompts.projectAddPrompt.selectType,
|
|
69
|
+
when: selectedComponents.length === 0,
|
|
70
|
+
type: 'checkbox',
|
|
71
|
+
choices: components,
|
|
72
|
+
},
|
|
73
|
+
]);
|
|
74
|
+
if (!result.componentTemplate) {
|
|
75
|
+
result.componentTemplate = selectedComponents;
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|