@hubspot/cli 7.7.22-experimental.0 → 7.7.24-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 +15 -4
- package/commands/auth.js +1 -1
- package/commands/config/set.d.ts +1 -0
- package/commands/config/set.js +19 -9
- package/commands/mcp/start.d.ts +1 -0
- package/commands/mcp/start.js +12 -4
- package/commands/project/create.js +2 -2
- package/commands/project/validate.js +1 -0
- package/commands/sandbox/__tests__/create.test.js +207 -0
- package/commands/sandbox/create.d.ts +1 -1
- package/commands/sandbox/create.js +31 -16
- package/commands/testAccount/createConfig.js +1 -1
- package/lang/en.d.ts +17 -4
- package/lang/en.js +22 -6
- package/lang/en.lyaml +4 -2
- package/lib/__tests__/buildAccount.test.js +62 -4
- package/lib/__tests__/yargsUtils.test.js +12 -1
- package/lib/buildAccount.d.ts +4 -1
- package/lib/buildAccount.js +57 -2
- package/lib/commonOpts.js +25 -0
- package/lib/configOptions.d.ts +5 -0
- package/lib/configOptions.js +11 -1
- package/lib/constants.d.ts +8 -0
- package/lib/constants.js +8 -0
- package/lib/errorHandlers/index.js +1 -3
- package/lib/errors/ProjectValidationError.d.ts +4 -0
- package/lib/errors/ProjectValidationError.js +9 -0
- package/lib/mcp/setup.d.ts +4 -0
- package/lib/mcp/setup.js +36 -0
- package/lib/projects/__tests__/LocalDevProcess.test.js +35 -0
- package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +170 -1
- package/lib/projects/add/legacyAddComponent.js +1 -1
- package/lib/projects/add/v3AddComponent.js +3 -2
- package/lib/projects/create/index.js +3 -3
- package/lib/projects/create/legacy.js +2 -2
- package/lib/projects/create/v3.d.ts +0 -2
- package/lib/projects/create/v3.js +1 -3
- package/lib/projects/localDev/LocalDevLogger.js +11 -2
- package/lib/projects/localDev/LocalDevProcess.d.ts +2 -0
- package/lib/projects/localDev/LocalDevProcess.js +15 -0
- package/lib/projects/localDev/LocalDevState.d.ts +1 -0
- package/lib/projects/localDev/LocalDevState.js +5 -0
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +2 -2
- package/lib/projects/localDev/LocalDevWebsocketServer.js +40 -30
- package/lib/projects/upload.js +5 -12
- package/lib/projects/urls.d.ts +1 -1
- package/lib/projects/urls.js +2 -2
- package/lib/sandboxes.d.ts +4 -0
- package/lib/sandboxes.js +4 -0
- package/lib/ui/index.d.ts +6 -0
- package/lib/ui/index.js +3 -5
- package/lib/yargsUtils.d.ts +1 -0
- package/lib/yargsUtils.js +6 -0
- package/mcp-server/tools/index.js +6 -4
- package/mcp-server/tools/project/{AddFeatureToProject.d.ts → AddFeatureToProjectTool.d.ts} +4 -4
- package/mcp-server/tools/project/{AddFeatureToProject.js → AddFeatureToProjectTool.js} +6 -14
- package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/CreateProjectTool.js +4 -14
- package/mcp-server/tools/project/{DeployProject.d.ts → DeployProjectTool.d.ts} +1 -1
- package/mcp-server/tools/project/{DeployProject.js → DeployProjectTool.js} +2 -2
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +20 -0
- package/mcp-server/tools/project/GetConfigValuesTool.js +51 -0
- package/mcp-server/tools/project/UploadProjectTools.js +1 -1
- package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
- package/mcp-server/tools/project/__tests__/{AddFeatureToProject.test.js → AddFeatureToProjectTool.test.js} +7 -7
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +3 -4
- package/mcp-server/tools/project/__tests__/{DeployProject.test.js → DeployProjectTool.test.js} +4 -4
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +198 -0
- package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +2 -2
- package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +2 -2
- package/mcp-server/tools/project/constants.d.ts +1 -0
- package/mcp-server/tools/project/constants.js +11 -0
- package/mcp-server/utils/__tests__/command.test.js +76 -3
- package/mcp-server/utils/command.d.ts +6 -0
- package/mcp-server/utils/command.js +19 -0
- package/package.json +3 -3
- package/mcp-server/utils/__tests__/project.test.js +0 -79
- package/mcp-server/utils/project.d.ts +0 -5
- package/mcp-server/utils/project.js +0 -14
- /package/mcp-server/tools/project/__tests__/{AddFeatureToProject.test.d.ts → AddFeatureToProjectTool.test.d.ts} +0 -0
- /package/mcp-server/tools/project/__tests__/{DeployProject.test.d.ts → DeployProjectTool.test.d.ts} +0 -0
- /package/mcp-server/{utils/__tests__/project.test.d.ts → tools/project/__tests__/GetConfigValuesTool.test.d.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { WebSocketServer } from 'ws';
|
|
2
2
|
import { isPortManagerServerRunning, requestPorts, } from '@hubspot/local-dev-lib/portManager';
|
|
3
3
|
import { logger } from '@hubspot/local-dev-lib/logger';
|
|
4
|
-
import { LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES, LOCAL_DEV_SERVER_MESSAGE_TYPES, } from '../../constants.js';
|
|
4
|
+
import { LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES, LOCAL_DEV_UI_MESSAGE_SEND_TYPES, LOCAL_DEV_SERVER_MESSAGE_TYPES, } from '../../constants.js';
|
|
5
5
|
import LocalDevWebsocketServer from '../localDev/LocalDevWebsocketServer.js';
|
|
6
6
|
import { lib } from '../../../lang/en.js';
|
|
7
7
|
vi.mock('ws');
|
|
@@ -29,6 +29,7 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
29
29
|
// Setup mock LocalDevProcess
|
|
30
30
|
mockLocalDevProcess = {
|
|
31
31
|
addStateListener: vi.fn(),
|
|
32
|
+
removeStateListener: vi.fn(),
|
|
32
33
|
uploadProject: vi.fn(),
|
|
33
34
|
sendDevServerMessage: vi.fn(),
|
|
34
35
|
};
|
|
@@ -167,4 +168,172 @@ describe('LocalDevWebsocketServer', () => {
|
|
|
167
168
|
expect(mockWebSocketServer.close).toHaveBeenCalled();
|
|
168
169
|
});
|
|
169
170
|
});
|
|
171
|
+
describe('multiple connections', () => {
|
|
172
|
+
let mockWebSocket1;
|
|
173
|
+
let mockWebSocket2;
|
|
174
|
+
let mockWebSocket3;
|
|
175
|
+
let connectionCallback;
|
|
176
|
+
beforeEach(async () => {
|
|
177
|
+
// Setup multiple mock WebSockets
|
|
178
|
+
mockWebSocket1 = {
|
|
179
|
+
on: vi.fn(),
|
|
180
|
+
send: vi.fn(),
|
|
181
|
+
close: vi.fn(),
|
|
182
|
+
};
|
|
183
|
+
mockWebSocket2 = {
|
|
184
|
+
on: vi.fn(),
|
|
185
|
+
send: vi.fn(),
|
|
186
|
+
close: vi.fn(),
|
|
187
|
+
};
|
|
188
|
+
mockWebSocket3 = {
|
|
189
|
+
on: vi.fn(),
|
|
190
|
+
send: vi.fn(),
|
|
191
|
+
close: vi.fn(),
|
|
192
|
+
};
|
|
193
|
+
// Start the server
|
|
194
|
+
isPortManagerServerRunning.mockResolvedValue(true);
|
|
195
|
+
requestPorts.mockResolvedValue({
|
|
196
|
+
'local-dev-ui-websocket-server': 1234,
|
|
197
|
+
});
|
|
198
|
+
await server.start();
|
|
199
|
+
// Get the connection callback
|
|
200
|
+
connectionCallback = mockWebSocketServer.on.mock.calls[0][1];
|
|
201
|
+
});
|
|
202
|
+
it('should handle multiple valid connections simultaneously', () => {
|
|
203
|
+
// Establish three connections from valid origins
|
|
204
|
+
connectionCallback(mockWebSocket1, {
|
|
205
|
+
headers: { origin: 'https://app.hubspot.com' },
|
|
206
|
+
});
|
|
207
|
+
connectionCallback(mockWebSocket2, {
|
|
208
|
+
headers: { origin: 'https://app.hubspotqa.com' },
|
|
209
|
+
});
|
|
210
|
+
connectionCallback(mockWebSocket3, {
|
|
211
|
+
headers: { origin: 'https://local.hubspot.com' },
|
|
212
|
+
});
|
|
213
|
+
// All connections should be established with proper setup
|
|
214
|
+
expect(mockWebSocket1.on).toHaveBeenCalledWith('message', expect.any(Function));
|
|
215
|
+
expect(mockWebSocket2.on).toHaveBeenCalledWith('message', expect.any(Function));
|
|
216
|
+
expect(mockWebSocket3.on).toHaveBeenCalledWith('message', expect.any(Function));
|
|
217
|
+
// Each connection should trigger state listener setup
|
|
218
|
+
expect(mockLocalDevProcess.addStateListener).toHaveBeenCalledTimes(6); // 2 listeners per connection * 3 connections
|
|
219
|
+
// Each connection should trigger dev server message
|
|
220
|
+
expect(mockLocalDevProcess.sendDevServerMessage).toHaveBeenCalledTimes(3);
|
|
221
|
+
expect(mockLocalDevProcess.sendDevServerMessage).toHaveBeenCalledWith(LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED);
|
|
222
|
+
// No connections should be closed
|
|
223
|
+
expect(mockWebSocket1.close).not.toHaveBeenCalled();
|
|
224
|
+
expect(mockWebSocket2.close).not.toHaveBeenCalled();
|
|
225
|
+
expect(mockWebSocket3.close).not.toHaveBeenCalled();
|
|
226
|
+
});
|
|
227
|
+
it('should send project data to each connection independently', () => {
|
|
228
|
+
// Setup mock project data properties as getters
|
|
229
|
+
Object.defineProperty(mockLocalDevProcess, 'projectName', {
|
|
230
|
+
get: () => 'test-project',
|
|
231
|
+
configurable: true,
|
|
232
|
+
});
|
|
233
|
+
Object.defineProperty(mockLocalDevProcess, 'projectId', {
|
|
234
|
+
get: () => 123,
|
|
235
|
+
configurable: true,
|
|
236
|
+
});
|
|
237
|
+
Object.defineProperty(mockLocalDevProcess, 'targetProjectAccountId', {
|
|
238
|
+
get: () => 456,
|
|
239
|
+
configurable: true,
|
|
240
|
+
});
|
|
241
|
+
Object.defineProperty(mockLocalDevProcess, 'targetTestingAccountId', {
|
|
242
|
+
get: () => 789,
|
|
243
|
+
configurable: true,
|
|
244
|
+
});
|
|
245
|
+
// Establish multiple connections
|
|
246
|
+
connectionCallback(mockWebSocket1, {
|
|
247
|
+
headers: { origin: 'https://app.hubspot.com' },
|
|
248
|
+
});
|
|
249
|
+
connectionCallback(mockWebSocket2, {
|
|
250
|
+
headers: { origin: 'https://app.hubspotqa.com' },
|
|
251
|
+
});
|
|
252
|
+
// Each websocket should receive project data
|
|
253
|
+
expect(mockWebSocket1.send).toHaveBeenCalledWith(JSON.stringify({
|
|
254
|
+
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_DATA,
|
|
255
|
+
data: {
|
|
256
|
+
projectName: 'test-project',
|
|
257
|
+
projectId: 123,
|
|
258
|
+
targetProjectAccountId: 456,
|
|
259
|
+
targetTestingAccountId: 789,
|
|
260
|
+
},
|
|
261
|
+
}));
|
|
262
|
+
expect(mockWebSocket2.send).toHaveBeenCalledWith(JSON.stringify({
|
|
263
|
+
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_DATA,
|
|
264
|
+
data: {
|
|
265
|
+
projectName: 'test-project',
|
|
266
|
+
projectId: 123,
|
|
267
|
+
targetProjectAccountId: 456,
|
|
268
|
+
targetTestingAccountId: 789,
|
|
269
|
+
},
|
|
270
|
+
}));
|
|
271
|
+
});
|
|
272
|
+
it('should properly cleanup listeners when connections close', () => {
|
|
273
|
+
// Establish connections
|
|
274
|
+
connectionCallback(mockWebSocket1, {
|
|
275
|
+
headers: { origin: 'https://app.hubspot.com' },
|
|
276
|
+
});
|
|
277
|
+
connectionCallback(mockWebSocket2, {
|
|
278
|
+
headers: { origin: 'https://app.hubspotqa.com' },
|
|
279
|
+
});
|
|
280
|
+
// Get all the close callbacks for both connections (there should be 2 per connection)
|
|
281
|
+
const closeCallbacks1 = mockWebSocket1.on.mock.calls
|
|
282
|
+
.filter(call => call[0] === 'close')
|
|
283
|
+
.map(call => call[1]);
|
|
284
|
+
const closeCallbacks2 = mockWebSocket2.on.mock.calls
|
|
285
|
+
.filter(call => call[0] === 'close')
|
|
286
|
+
.map(call => call[1]);
|
|
287
|
+
expect(closeCallbacks1).toHaveLength(2); // projectNodes and appData listeners
|
|
288
|
+
expect(closeCallbacks2).toHaveLength(2); // projectNodes and appData listeners
|
|
289
|
+
// Simulate first connection closing (call all close callbacks)
|
|
290
|
+
closeCallbacks1.forEach(callback => callback());
|
|
291
|
+
// Should have removed listeners for first connection (2 listeners: projectNodes and appData)
|
|
292
|
+
expect(mockLocalDevProcess.removeStateListener).toHaveBeenCalledTimes(2);
|
|
293
|
+
// Simulate second connection closing
|
|
294
|
+
closeCallbacks2.forEach(callback => callback());
|
|
295
|
+
// Should have removed listeners for second connection as well
|
|
296
|
+
expect(mockLocalDevProcess.removeStateListener).toHaveBeenCalledTimes(4);
|
|
297
|
+
});
|
|
298
|
+
it('should broadcast state changes to all connected clients', () => {
|
|
299
|
+
// Establish connections
|
|
300
|
+
connectionCallback(mockWebSocket1, {
|
|
301
|
+
headers: { origin: 'https://app.hubspot.com' },
|
|
302
|
+
});
|
|
303
|
+
connectionCallback(mockWebSocket2, {
|
|
304
|
+
headers: { origin: 'https://app.hubspotqa.com' },
|
|
305
|
+
});
|
|
306
|
+
// Get the projectNodes listeners that were registered
|
|
307
|
+
const projectNodesListeners = mockLocalDevProcess.addStateListener.mock.calls
|
|
308
|
+
.filter(call => call[0] === 'projectNodes')
|
|
309
|
+
.map(call => call[1]);
|
|
310
|
+
expect(projectNodesListeners).toHaveLength(2);
|
|
311
|
+
// Simulate a project nodes update by calling the listeners
|
|
312
|
+
const mockProjectNodes = {
|
|
313
|
+
component1: {
|
|
314
|
+
uid: 'component1',
|
|
315
|
+
componentType: 'APP',
|
|
316
|
+
localDev: {
|
|
317
|
+
componentRoot: '/test/path',
|
|
318
|
+
componentConfigPath: '/test/path/config.json',
|
|
319
|
+
configUpdatedSinceLastUpload: false,
|
|
320
|
+
},
|
|
321
|
+
componentDeps: {},
|
|
322
|
+
metaFilePath: '/test/path',
|
|
323
|
+
config: {},
|
|
324
|
+
files: [],
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
projectNodesListeners.forEach(listener => listener(mockProjectNodes));
|
|
328
|
+
// Both websockets should receive the update
|
|
329
|
+
expect(mockWebSocket1.send).toHaveBeenCalledWith(JSON.stringify({
|
|
330
|
+
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_NODES,
|
|
331
|
+
data: mockProjectNodes,
|
|
332
|
+
}));
|
|
333
|
+
expect(mockWebSocket2.send).toHaveBeenCalledWith(JSON.stringify({
|
|
334
|
+
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_NODES,
|
|
335
|
+
data: mockProjectNodes,
|
|
336
|
+
}));
|
|
337
|
+
});
|
|
338
|
+
});
|
|
170
339
|
});
|
|
@@ -5,7 +5,7 @@ import { commands } from '../../../lang/en.js';
|
|
|
5
5
|
import { getProjectComponentListFromRepo } from '../create/legacy.js';
|
|
6
6
|
import { projectAddPrompt } from '../../prompts/projectAddPrompt.js';
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, DEFAULT_PROJECT_TEMPLATE_BRANCH } from '../../constants.js';
|
|
8
|
+
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, DEFAULT_PROJECT_TEMPLATE_BRANCH, } from '../../constants.js';
|
|
9
9
|
import { cloneGithubRepo } from '@hubspot/local-dev-lib/github';
|
|
10
10
|
import { uiLogger } from '../../ui/logger.js';
|
|
11
11
|
export async function legacyAddComponent(args, projectDir, projectConfig) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { commands, lib } from '../../../lang/en.js';
|
|
2
2
|
import { getConfigForPlatformVersion } from '../create/legacy.js';
|
|
3
|
-
import { calculateComponentTemplateChoices, createV3App,
|
|
3
|
+
import { calculateComponentTemplateChoices, createV3App, } from '../create/v3.js';
|
|
4
|
+
import { PROJECT_WITH_APP } from '../../constants.js';
|
|
4
5
|
import path from 'path';
|
|
5
6
|
import fs from 'fs';
|
|
6
7
|
import { projectAddPromptV3 } from '../../prompts/projectAddPrompt.js';
|
|
7
|
-
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, DEFAULT_PROJECT_TEMPLATE_BRANCH } from '../../constants.js';
|
|
8
|
+
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, DEFAULT_PROJECT_TEMPLATE_BRANCH, } from '../../constants.js';
|
|
8
9
|
import { handleComponentCollision } from '../components.js';
|
|
9
10
|
import { getProjectMetadata, } from '@hubspot/project-parsing-lib/src/lib/project.js';
|
|
10
11
|
import { AppKey } from '@hubspot/project-parsing-lib/src/lib/constants.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { selectProjectTemplatePrompt, } from '../../prompts/selectProjectTemplatePrompt.js';
|
|
2
2
|
import { projectNameAndDestPrompt } from '../../prompts/projectNameAndDestPrompt.js';
|
|
3
|
-
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH } from '../../constants.js';
|
|
3
|
+
import { DEFAULT_PROJECT_TEMPLATE_BRANCH, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, EMPTY_PROJECT, } from '../../constants.js';
|
|
4
4
|
import { useV3Api } from '../buildAndDeploy.js';
|
|
5
|
-
import {
|
|
5
|
+
import { v3ComponentFlow } from './v3.js';
|
|
6
6
|
import { getProjectTemplateListFromRepo } from './legacy.js';
|
|
7
7
|
import { uiLogger } from '../../ui/logger.js';
|
|
8
8
|
import { commands } from '../../../lang/en.js';
|
|
@@ -23,7 +23,7 @@ export async function handleProjectCreationFlow(args) {
|
|
|
23
23
|
projectNameAndDestPromptResponse,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
-
const projectTemplates = await getProjectTemplateListFromRepo(repo,
|
|
26
|
+
const projectTemplates = await getProjectTemplateListFromRepo(repo, DEFAULT_PROJECT_TEMPLATE_BRANCH);
|
|
27
27
|
if (!projectTemplates.length) {
|
|
28
28
|
uiLogger.error(commands.project.create.errors.failedToFetchProjectList);
|
|
29
29
|
process.exit(EXIT_CODES.ERROR);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fetchRepoFile } from '@hubspot/local-dev-lib/api/github';
|
|
2
|
-
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_COMPONENT_TYPES, } from '../../constants.js';
|
|
2
|
+
import { DEFAULT_PROJECT_TEMPLATE_BRANCH, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_COMPONENT_TYPES, } from '../../constants.js';
|
|
3
3
|
import { EXIT_CODES } from '../../enums/exitCodes.js';
|
|
4
4
|
import { debugError } from '../../errorHandlers/index.js';
|
|
5
5
|
import { uiLogger } from '../../ui/logger.js';
|
|
@@ -12,7 +12,7 @@ export async function getConfigForPlatformVersion(platformVersion) {
|
|
|
12
12
|
if (useV3Api(platformVersion)) {
|
|
13
13
|
path = `${platformVersion}/`;
|
|
14
14
|
}
|
|
15
|
-
const { data } = await fetchRepoFile(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, `${path}config.json`,
|
|
15
|
+
const { data } = await fetchRepoFile(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, `${path}config.json`, DEFAULT_PROJECT_TEMPLATE_BRANCH);
|
|
16
16
|
return data;
|
|
17
17
|
}
|
|
18
18
|
export async function getProjectComponentListFromRepo(platformVersion) {
|
|
@@ -2,8 +2,6 @@ import { Separator } from '@inquirer/prompts';
|
|
|
2
2
|
import { ComponentTemplate, ComponentTemplateChoice, ProjectTemplateRepoConfig } from '../../../types/Projects.js';
|
|
3
3
|
import { ProjectMetadata } from '@hubspot/project-parsing-lib/src/lib/project.js';
|
|
4
4
|
import { SelectProjectTemplatePromptResponse } from '../../prompts/selectProjectTemplatePrompt.js';
|
|
5
|
-
export declare const EMPTY_PROJECT = "empty";
|
|
6
|
-
export declare const PROJECT_WITH_APP = "app";
|
|
7
5
|
export declare function createV3App(providedAuth: string | undefined, providedDistribution: string | undefined): Promise<{
|
|
8
6
|
authType: string;
|
|
9
7
|
distribution: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Separator } from '@inquirer/prompts';
|
|
2
|
-
import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, } from '../../constants.js';
|
|
2
|
+
import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, EMPTY_PROJECT, PROJECT_WITH_APP, } from '../../constants.js';
|
|
3
3
|
import { commands, lib } from '../../../lang/en.js';
|
|
4
4
|
import { listPrompt } from '../../prompts/promptUtils.js';
|
|
5
5
|
import chalk from 'chalk';
|
|
@@ -8,8 +8,6 @@ import path from 'path';
|
|
|
8
8
|
import { getConfigForPlatformVersion } from './legacy.js';
|
|
9
9
|
import { logError } from '../../errorHandlers/index.js';
|
|
10
10
|
import { EXIT_CODES } from '../../enums/exitCodes.js';
|
|
11
|
-
export const EMPTY_PROJECT = 'empty';
|
|
12
|
-
export const PROJECT_WITH_APP = 'app';
|
|
13
11
|
export async function createV3App(providedAuth, providedDistribution) {
|
|
14
12
|
let authType;
|
|
15
13
|
if (providedAuth &&
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAccountId } from '@hubspot/local-dev-lib/config';
|
|
1
|
+
import { getAccountId, hasLocalStateFlag } from '@hubspot/local-dev-lib/config';
|
|
2
2
|
import { getConfigDefaultAccount } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { logger } from '@hubspot/local-dev-lib/logger';
|
|
4
4
|
import { uiLogger } from '../../ui/logger.js';
|
|
@@ -6,6 +6,8 @@ import { uiBetaTag, uiLine, uiAccountDescription, uiCommandReference, } from '..
|
|
|
6
6
|
import { lib } from '../../../lang/en.js';
|
|
7
7
|
import SpinniesManager from '../../ui/SpinniesManager.js';
|
|
8
8
|
import { logError } from '../../errorHandlers/index.js';
|
|
9
|
+
import { isAutoOpenBrowserEnabled } from '../../configOptions.js';
|
|
10
|
+
import { CONFIG_LOCAL_STATE_FLAGS } from '../../constants.js';
|
|
9
11
|
class LocalDevLogger {
|
|
10
12
|
state;
|
|
11
13
|
mostRecentUploadWarning;
|
|
@@ -96,7 +98,14 @@ class LocalDevLogger {
|
|
|
96
98
|
uiLogger.log('');
|
|
97
99
|
uiLogger.log(lib.LocalDevManager.running(this.state.projectConfig.name, uiAccountDescription(this.state.targetProjectAccountId)));
|
|
98
100
|
uiLogger.log(lib.LocalDevManager.viewProjectLink(this.state.projectConfig.name, this.state.targetProjectAccountId));
|
|
99
|
-
|
|
101
|
+
const showWelcomeScreen = !hasLocalStateFlag(CONFIG_LOCAL_STATE_FLAGS.LOCAL_DEV_UI_WELCOME);
|
|
102
|
+
if (!isAutoOpenBrowserEnabled()) {
|
|
103
|
+
uiLogger.log(lib.LocalDevManager.viewLocalDevUILink(this.state.targetTestingAccountId, showWelcomeScreen));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
uiLogger.log('');
|
|
107
|
+
uiLogger.log(lib.LocalDevManager.localDevUIAutoMessage(this.state.targetTestingAccountId, showWelcomeScreen));
|
|
108
|
+
}
|
|
100
109
|
uiLogger.log('');
|
|
101
110
|
uiLogger.log(lib.LocalDevManager.quitHelper);
|
|
102
111
|
uiLine();
|
|
@@ -24,6 +24,7 @@ declare class LocalDevProcess {
|
|
|
24
24
|
private getIntermediateRepresentation;
|
|
25
25
|
private updateProjectNodes;
|
|
26
26
|
private updateProjectNodesAfterUpload;
|
|
27
|
+
private openLocalDevUi;
|
|
27
28
|
handleFileChange(filePath: string, event: string): Promise<void>;
|
|
28
29
|
handleConfigFileChange(): Promise<void>;
|
|
29
30
|
start(): Promise<void>;
|
|
@@ -31,5 +32,6 @@ declare class LocalDevProcess {
|
|
|
31
32
|
uploadProject(): Promise<boolean>;
|
|
32
33
|
addStateListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>, callOnInit?: boolean): void;
|
|
33
34
|
sendDevServerMessage(message: LocalDevServerMessage): void;
|
|
35
|
+
removeStateListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>): void;
|
|
34
36
|
}
|
|
35
37
|
export default LocalDevProcess;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { translateForLocalDev } from '@hubspot/project-parsing-lib';
|
|
2
|
+
import { hasLocalStateFlag } from '@hubspot/local-dev-lib/config';
|
|
2
3
|
import path from 'path';
|
|
4
|
+
import open from 'open';
|
|
3
5
|
import LocalDevState from './LocalDevState.js';
|
|
4
6
|
import LocalDevLogger from './LocalDevLogger.js';
|
|
5
7
|
import DevServerManagerV2 from './DevServerManagerV2.js';
|
|
@@ -8,6 +10,9 @@ import { mapToUserFriendlyName } from '@hubspot/project-parsing-lib/src/lib/tran
|
|
|
8
10
|
import { getProjectConfig } from '../config.js';
|
|
9
11
|
import { handleProjectUpload } from '../upload.js';
|
|
10
12
|
import { pollProjectBuildAndDeploy } from '../buildAndDeploy.js';
|
|
13
|
+
import { getLocalDevUiUrl } from '../urls.js';
|
|
14
|
+
import { CONFIG_LOCAL_STATE_FLAGS } from '../../constants.js';
|
|
15
|
+
import { isAutoOpenBrowserEnabled } from '../../configOptions.js';
|
|
11
16
|
class LocalDevProcess {
|
|
12
17
|
state;
|
|
13
18
|
_logger;
|
|
@@ -119,6 +124,10 @@ class LocalDevProcess {
|
|
|
119
124
|
this.state.projectNodesAtLastUpload =
|
|
120
125
|
intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
121
126
|
}
|
|
127
|
+
openLocalDevUi() {
|
|
128
|
+
const showWelcomeScreen = !hasLocalStateFlag(CONFIG_LOCAL_STATE_FLAGS.LOCAL_DEV_UI_WELCOME);
|
|
129
|
+
open(getLocalDevUiUrl(this.state.targetTestingAccountId, showWelcomeScreen));
|
|
130
|
+
}
|
|
122
131
|
async handleFileChange(filePath, event) {
|
|
123
132
|
await this.updateProjectNodes();
|
|
124
133
|
try {
|
|
@@ -144,6 +153,9 @@ class LocalDevProcess {
|
|
|
144
153
|
process.exit(EXIT_CODES.ERROR);
|
|
145
154
|
}
|
|
146
155
|
this.logger.startupMessage();
|
|
156
|
+
if (isAutoOpenBrowserEnabled()) {
|
|
157
|
+
this.openLocalDevUi();
|
|
158
|
+
}
|
|
147
159
|
await this.startDevServers();
|
|
148
160
|
this.logger.monitorConsoleOutput();
|
|
149
161
|
// Verify that there are no mismatches between components in the local project
|
|
@@ -196,5 +208,8 @@ class LocalDevProcess {
|
|
|
196
208
|
sendDevServerMessage(message) {
|
|
197
209
|
this.state.devServerMessage = message;
|
|
198
210
|
}
|
|
211
|
+
removeStateListener(key, listener) {
|
|
212
|
+
this.state.removeListener(key, listener);
|
|
213
|
+
}
|
|
199
214
|
}
|
|
200
215
|
export default LocalDevProcess;
|
|
@@ -51,5 +51,6 @@ declare class LocalDevState {
|
|
|
51
51
|
get devServerMessage(): string;
|
|
52
52
|
set devServerMessage(message: LocalDevServerMessage);
|
|
53
53
|
addListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>, callOnInit?: boolean): void;
|
|
54
|
+
removeListener<K extends keyof LocalDevState>(key: K, listener: LocalDevStateListener<K>): void;
|
|
54
55
|
}
|
|
55
56
|
export default LocalDevState;
|
|
@@ -111,5 +111,10 @@ class LocalDevState {
|
|
|
111
111
|
listener(this[key]);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
+
removeListener(key, listener) {
|
|
115
|
+
if (this._listeners[key]) {
|
|
116
|
+
this._listeners[key].splice(this._listeners[key].indexOf(listener), 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
114
119
|
}
|
|
115
120
|
export default LocalDevState;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import LocalDevProcess from './LocalDevProcess.js';
|
|
2
2
|
declare class LocalDevWebsocketServer {
|
|
3
3
|
private server?;
|
|
4
|
-
private _websocket?;
|
|
5
4
|
private debug?;
|
|
6
5
|
private localDevProcess;
|
|
7
6
|
private ALLOWED_ORIGINS;
|
|
8
7
|
constructor(localDevProcess: LocalDevProcess, debug?: boolean);
|
|
9
|
-
private websocket;
|
|
10
8
|
private log;
|
|
11
9
|
private logError;
|
|
12
10
|
private sendMessage;
|
|
13
11
|
private handleUpload;
|
|
14
12
|
private setupMessageHandlers;
|
|
15
13
|
private sendProjectData;
|
|
14
|
+
private setupProjectNodesListener;
|
|
15
|
+
private setupAppDataListener;
|
|
16
16
|
private setupStateListeners;
|
|
17
17
|
start(): Promise<void>;
|
|
18
18
|
shutdown(): void;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { WebSocketServer } from 'ws';
|
|
2
2
|
import { isPortManagerServerRunning, requestPorts, } from '@hubspot/local-dev-lib/portManager';
|
|
3
3
|
import { logger } from '@hubspot/local-dev-lib/logger';
|
|
4
|
-
import {
|
|
4
|
+
import { addLocalStateFlag } from '@hubspot/local-dev-lib/config';
|
|
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';
|
|
5
6
|
import { lib } from '../../../lang/en.js';
|
|
6
7
|
const SERVER_INSTANCE_ID = 'local-dev-ui-websocket-server';
|
|
7
8
|
const LOG_PREFIX = '[LocalDevWebsocketServer]';
|
|
8
9
|
class LocalDevWebsocketServer {
|
|
9
10
|
server;
|
|
10
|
-
_websocket;
|
|
11
11
|
debug;
|
|
12
12
|
localDevProcess;
|
|
13
13
|
ALLOWED_ORIGINS = [
|
|
@@ -20,12 +20,6 @@ class LocalDevWebsocketServer {
|
|
|
20
20
|
this.localDevProcess = localDevProcess;
|
|
21
21
|
this.debug = debug;
|
|
22
22
|
}
|
|
23
|
-
websocket() {
|
|
24
|
-
if (!this._websocket) {
|
|
25
|
-
throw new Error(lib.LocalDevWebsocketServer.errors.notInitialized(LOG_PREFIX));
|
|
26
|
-
}
|
|
27
|
-
return this._websocket;
|
|
28
|
-
}
|
|
29
23
|
log(message) {
|
|
30
24
|
if (this.debug) {
|
|
31
25
|
logger.log(LOG_PREFIX, message);
|
|
@@ -36,24 +30,24 @@ class LocalDevWebsocketServer {
|
|
|
36
30
|
logger.error(LOG_PREFIX, message);
|
|
37
31
|
}
|
|
38
32
|
}
|
|
39
|
-
sendMessage(message) {
|
|
40
|
-
|
|
33
|
+
sendMessage(websocket, message) {
|
|
34
|
+
websocket.send(JSON.stringify(message));
|
|
41
35
|
}
|
|
42
|
-
async handleUpload() {
|
|
36
|
+
async handleUpload(websocket) {
|
|
43
37
|
const uploadSuccess = await this.localDevProcess.uploadProject();
|
|
44
38
|
if (uploadSuccess) {
|
|
45
|
-
this.sendMessage({
|
|
39
|
+
this.sendMessage(websocket, {
|
|
46
40
|
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPLOAD_SUCCESS,
|
|
47
41
|
});
|
|
48
42
|
}
|
|
49
43
|
else {
|
|
50
|
-
this.sendMessage({
|
|
44
|
+
this.sendMessage(websocket, {
|
|
51
45
|
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPLOAD_FAILURE,
|
|
52
46
|
});
|
|
53
47
|
}
|
|
54
48
|
}
|
|
55
|
-
setupMessageHandlers() {
|
|
56
|
-
|
|
49
|
+
setupMessageHandlers(websocket) {
|
|
50
|
+
websocket.on('message', data => {
|
|
57
51
|
try {
|
|
58
52
|
const message = JSON.parse(data.toString());
|
|
59
53
|
if (!message.type) {
|
|
@@ -62,7 +56,10 @@ class LocalDevWebsocketServer {
|
|
|
62
56
|
}
|
|
63
57
|
switch (message.type) {
|
|
64
58
|
case LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.UPLOAD:
|
|
65
|
-
this.handleUpload();
|
|
59
|
+
this.handleUpload(websocket);
|
|
60
|
+
break;
|
|
61
|
+
case LOCAL_DEV_UI_MESSAGE_RECEIVE_TYPES.VIEWED_WELCOME_SCREEN:
|
|
62
|
+
addLocalStateFlag(CONFIG_LOCAL_STATE_FLAGS.LOCAL_DEV_UI_WELCOME);
|
|
66
63
|
break;
|
|
67
64
|
default:
|
|
68
65
|
this.logError(lib.LocalDevWebsocketServer.errors.unknownMessageType(message.type));
|
|
@@ -73,8 +70,8 @@ class LocalDevWebsocketServer {
|
|
|
73
70
|
}
|
|
74
71
|
});
|
|
75
72
|
}
|
|
76
|
-
sendProjectData() {
|
|
77
|
-
this.sendMessage({
|
|
73
|
+
sendProjectData(websocket) {
|
|
74
|
+
this.sendMessage(websocket, {
|
|
78
75
|
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_DATA,
|
|
79
76
|
data: {
|
|
80
77
|
projectName: this.localDevProcess.projectName,
|
|
@@ -84,19 +81,33 @@ class LocalDevWebsocketServer {
|
|
|
84
81
|
},
|
|
85
82
|
});
|
|
86
83
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.sendMessage({
|
|
84
|
+
setupProjectNodesListener(websocket) {
|
|
85
|
+
const listener = (nodes) => {
|
|
86
|
+
this.sendMessage(websocket, {
|
|
90
87
|
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_PROJECT_NODES,
|
|
91
88
|
data: nodes,
|
|
92
89
|
});
|
|
93
|
-
}
|
|
94
|
-
this.localDevProcess.addStateListener('
|
|
95
|
-
|
|
90
|
+
};
|
|
91
|
+
this.localDevProcess.addStateListener('projectNodes', listener, true);
|
|
92
|
+
websocket.on('close', () => {
|
|
93
|
+
this.localDevProcess.removeStateListener('projectNodes', listener);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
setupAppDataListener(websocket) {
|
|
97
|
+
const listener = (appData) => {
|
|
98
|
+
this.sendMessage(websocket, {
|
|
96
99
|
type: LOCAL_DEV_UI_MESSAGE_SEND_TYPES.UPDATE_APP_DATA,
|
|
97
100
|
data: appData,
|
|
98
101
|
});
|
|
99
|
-
}
|
|
102
|
+
};
|
|
103
|
+
this.localDevProcess.addStateListener('appData', listener, true);
|
|
104
|
+
websocket.on('close', () => {
|
|
105
|
+
this.localDevProcess.removeStateListener('appData', listener);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
setupStateListeners(websocket) {
|
|
109
|
+
this.setupProjectNodesListener(websocket);
|
|
110
|
+
this.setupAppDataListener(websocket);
|
|
100
111
|
}
|
|
101
112
|
async start() {
|
|
102
113
|
const portManagerIsRunning = await isPortManagerServerRunning();
|
|
@@ -113,17 +124,16 @@ class LocalDevWebsocketServer {
|
|
|
113
124
|
ws.close(1008, lib.LocalDevWebsocketServer.errors.originNotAllowed(origin));
|
|
114
125
|
return;
|
|
115
126
|
}
|
|
116
|
-
this.
|
|
117
|
-
this.
|
|
118
|
-
this.
|
|
119
|
-
this.setupStateListeners();
|
|
127
|
+
this.sendProjectData(ws);
|
|
128
|
+
this.setupMessageHandlers(ws);
|
|
129
|
+
this.setupStateListeners(ws);
|
|
120
130
|
this.localDevProcess.sendDevServerMessage(LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED);
|
|
121
131
|
});
|
|
132
|
+
this.server.on('close', () => { });
|
|
122
133
|
}
|
|
123
134
|
shutdown() {
|
|
124
135
|
this.server?.close();
|
|
125
136
|
this.server = undefined;
|
|
126
|
-
this._websocket = undefined;
|
|
127
137
|
}
|
|
128
138
|
}
|
|
129
139
|
export default LocalDevWebsocketServer;
|
package/lib/projects/upload.js
CHANGED
|
@@ -14,6 +14,7 @@ import { ensureProjectExists } from './ensureProjectExists.js';
|
|
|
14
14
|
import { uiLogger } from '../ui/logger.js';
|
|
15
15
|
import { useV3Api } from './buildAndDeploy.js';
|
|
16
16
|
import { EXIT_CODES } from '../enums/exitCodes.js';
|
|
17
|
+
import ProjectValidationError from '../errors/ProjectValidationError.js';
|
|
17
18
|
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
|
|
18
19
|
SpinniesManager.init({});
|
|
19
20
|
const accountIdentifier = uiAccountDescription(accountId) || `${accountId}`;
|
|
@@ -107,17 +108,13 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
|
|
|
107
108
|
export function validateSourceDirectory(srcDir, projectConfig) {
|
|
108
109
|
const filenames = fs.readdirSync(srcDir);
|
|
109
110
|
if (!filenames || filenames.length === 0) {
|
|
110
|
-
|
|
111
|
-
validationError.name = 'ProjectValidationError';
|
|
112
|
-
throw validationError;
|
|
111
|
+
throw new ProjectValidationError(lib.projectUpload.handleProjectUpload.emptySource(projectConfig.srcDir));
|
|
113
112
|
}
|
|
114
113
|
}
|
|
115
114
|
export async function validateNoHSMetaMismatch(srcDir, projectConfig) {
|
|
116
115
|
const hasHsMetaFiles = await projectContainsHsMetaFiles(srcDir);
|
|
117
116
|
if (!useV3Api(projectConfig.platformVersion) && hasHsMetaFiles) {
|
|
118
|
-
|
|
119
|
-
validationError.name = 'ProjectValidationError';
|
|
120
|
-
throw validationError;
|
|
117
|
+
throw new ProjectValidationError(lib.projectUpload.wrongPlatformVersionMetaFiles);
|
|
121
118
|
}
|
|
122
119
|
}
|
|
123
120
|
export async function handleTranslate(projectDir, projectConfig, accountId, skipValidation, profile) {
|
|
@@ -132,12 +129,8 @@ export async function handleTranslate(projectDir, projectConfig, accountId, skip
|
|
|
132
129
|
}
|
|
133
130
|
catch (e) {
|
|
134
131
|
if (isTranslationError(e)) {
|
|
135
|
-
|
|
136
|
-
validationError.name = 'ProjectValidationError';
|
|
137
|
-
throw validationError;
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
logError(e);
|
|
132
|
+
throw new ProjectValidationError(e.toString(), { cause: e });
|
|
141
133
|
}
|
|
134
|
+
throw e;
|
|
142
135
|
}
|
|
143
136
|
}
|
package/lib/projects/urls.d.ts
CHANGED
|
@@ -5,4 +5,4 @@ export declare function getProjectSettingsUrl(projectName: string, accountId: nu
|
|
|
5
5
|
export declare function getProjectActivityUrl(projectName: string, accountId: number): string;
|
|
6
6
|
export declare function getProjectBuildDetailUrl(projectName: string, buildId: number, accountId: number): string;
|
|
7
7
|
export declare function getProjectDeployDetailUrl(projectName: string, deployId: number, accountId: number): string;
|
|
8
|
-
export declare function getLocalDevUiUrl(accountId: number): string;
|
|
8
|
+
export declare function getLocalDevUiUrl(accountId: number, showWelcomeScreen?: boolean): string;
|
package/lib/projects/urls.js
CHANGED
|
@@ -34,6 +34,6 @@ export function getProjectBuildDetailUrl(projectName, buildId, accountId) {
|
|
|
34
34
|
export function getProjectDeployDetailUrl(projectName, deployId, accountId) {
|
|
35
35
|
return `${getProjectActivityUrl(projectName, accountId)}/deploy/${deployId}`;
|
|
36
36
|
}
|
|
37
|
-
export function getLocalDevUiUrl(accountId) {
|
|
38
|
-
return `${getBaseUrl(accountId)}/developer-projects-local-dev/${accountId}`;
|
|
37
|
+
export function getLocalDevUiUrl(accountId, showWelcomeScreen) {
|
|
38
|
+
return `${getBaseUrl(accountId)}/developer-projects-local-dev/${accountId}${showWelcomeScreen ? '?welcome' : ''}`;
|
|
39
39
|
}
|
package/lib/sandboxes.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ export declare const SANDBOX_API_TYPE_MAP: {
|
|
|
11
11
|
readonly STANDARD_SANDBOX: 1;
|
|
12
12
|
readonly DEVELOPMENT_SANDBOX: 2;
|
|
13
13
|
};
|
|
14
|
+
export declare const SANDBOX_TYPE_MAP_V2: {
|
|
15
|
+
readonly STANDARD_SANDBOX: "STANDARD";
|
|
16
|
+
readonly DEVELOPMENT_SANDBOX: "DEVELOPER";
|
|
17
|
+
};
|
|
14
18
|
export declare function getSandboxTypeAsString(accountType?: AccountType): string;
|
|
15
19
|
export declare function getHasSandboxesByType(parentAccountConfig: CLIAccount, type: AccountType): boolean;
|
|
16
20
|
export declare function getAvailableSyncTypes(parentAccountConfig: CLIAccount, config: CLIAccount): Promise<Array<SandboxSyncTask>>;
|
package/lib/sandboxes.js
CHANGED
|
@@ -22,6 +22,10 @@ export const SANDBOX_API_TYPE_MAP = {
|
|
|
22
22
|
[HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX]: 1,
|
|
23
23
|
[HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX]: 2,
|
|
24
24
|
};
|
|
25
|
+
export const SANDBOX_TYPE_MAP_V2 = {
|
|
26
|
+
[HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX]: 'STANDARD',
|
|
27
|
+
[HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX]: 'DEVELOPER',
|
|
28
|
+
};
|
|
25
29
|
export function getSandboxTypeAsString(accountType) {
|
|
26
30
|
if (accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX) {
|
|
27
31
|
return 'development'; // Only place we're using this specific name
|