@hubspot/cli 8.0.10-experimental.7 → 8.0.11-experimental.1
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 +2 -0
- package/commands/account/auth.js +12 -22
- package/commands/account/clean.js +5 -6
- package/commands/account/createOverride.js +7 -7
- package/commands/account/info.js +2 -1
- package/commands/account/list.js +3 -5
- package/commands/account/remove.js +2 -3
- package/commands/account/removeOverride.js +8 -10
- package/commands/account/rename.js +5 -6
- package/commands/account/use.js +8 -19
- package/commands/api.d.ts +10 -0
- package/commands/api.js +164 -0
- package/commands/app/migrate.js +8 -8
- package/commands/app/secret/add.js +6 -7
- package/commands/app/secret/delete.js +9 -10
- package/commands/app/secret/list.js +6 -7
- package/commands/app/secret/update.js +8 -9
- package/commands/auth.js +12 -12
- package/commands/cms/app/create.js +9 -5
- package/commands/cms/convertFields.js +8 -8
- package/commands/cms/delete.js +2 -3
- package/commands/cms/fetch.js +7 -7
- package/commands/cms/function/create.js +9 -5
- package/commands/cms/function/deploy.js +2 -3
- package/commands/cms/function/list.js +11 -7
- package/commands/cms/function/logs.js +17 -23
- package/commands/cms/function/server.js +2 -3
- package/commands/cms/getReactModule.js +7 -8
- package/commands/cms/lighthouseScore.js +25 -24
- package/commands/cms/lint.js +4 -5
- package/commands/cms/list.js +5 -6
- package/commands/cms/module/create.js +9 -5
- package/commands/cms/module/marketplace-validate.js +7 -8
- package/commands/cms/mv.js +2 -3
- package/commands/cms/template/create.js +10 -6
- package/commands/cms/theme/create.js +5 -5
- package/commands/cms/theme/generate-selectors.js +5 -4
- package/commands/cms/theme/marketplace-validate.js +8 -9
- package/commands/cms/theme/preview.js +16 -8
- package/commands/cms/upload.js +15 -12
- package/commands/cms/watch.js +5 -5
- package/commands/cms/webpack/create.js +5 -5
- package/commands/completion.js +3 -5
- package/commands/config/migrate.js +6 -7
- package/commands/config/set.js +5 -6
- package/commands/customObject/create.js +4 -5
- package/commands/customObject/createSchema.js +4 -5
- package/commands/customObject/deleteSchema.js +4 -5
- package/commands/customObject/fetchAllSchemas.js +2 -3
- package/commands/customObject/fetchSchema.js +2 -3
- package/commands/customObject/listSchemas.js +2 -3
- package/commands/customObject/updateSchema.js +4 -5
- package/commands/doctor.js +8 -8
- package/commands/feedback.js +6 -4
- package/commands/filemanager/fetch.js +5 -6
- package/commands/filemanager/upload.js +5 -5
- package/commands/getStarted.js +14 -16
- package/commands/hubdb/clear.js +5 -6
- package/commands/hubdb/create.js +4 -5
- package/commands/hubdb/delete.js +8 -9
- package/commands/hubdb/fetch.js +5 -6
- package/commands/hubdb/list.js +16 -14
- package/commands/init.js +14 -17
- package/commands/mcp/setup.js +5 -6
- package/commands/mcp/start.js +2 -3
- package/commands/open.js +4 -5
- package/commands/project/add.js +10 -5
- package/commands/project/create.js +10 -10
- package/commands/project/delete.d.ts +7 -0
- package/commands/project/delete.js +74 -0
- package/commands/project/deploy.js +36 -34
- package/commands/project/dev/deprecatedFlow.js +42 -15
- package/commands/project/dev/index.d.ts +3 -3
- package/commands/project/dev/index.js +24 -30
- package/commands/project/dev/unifiedFlow.js +37 -14
- package/commands/project/download.js +10 -11
- package/commands/project/info.d.ts +4 -0
- package/commands/project/info.js +67 -0
- package/commands/project/installDeps.js +9 -6
- package/commands/project/lint.js +11 -8
- package/commands/project/list.js +14 -14
- package/commands/project/listBuilds.js +8 -6
- package/commands/project/logs.js +5 -6
- package/commands/project/migrate.js +8 -8
- package/commands/project/open.js +5 -6
- package/commands/project/profile/add.js +12 -8
- package/commands/project/profile/delete.js +15 -11
- package/commands/project/updateDeps.js +9 -6
- package/commands/project/upload.js +31 -17
- package/commands/project/validate.js +11 -11
- package/commands/project/watch.js +20 -20
- package/commands/project.js +4 -0
- package/commands/sandbox/create.js +15 -15
- package/commands/sandbox/delete.js +13 -14
- package/commands/secret/addSecret.js +6 -7
- package/commands/secret/deleteSecret.js +5 -6
- package/commands/secret/listSecret.js +2 -3
- package/commands/secret/updateSecret.js +4 -5
- package/commands/testAccount/create.d.ts +1 -1
- package/commands/testAccount/create.js +20 -16
- package/commands/testAccount/createConfig.js +7 -8
- package/commands/testAccount/delete.js +27 -18
- package/commands/testAccount/importData.js +6 -7
- package/commands/upgrade.js +9 -10
- package/lang/en.d.ts +123 -5
- package/lang/en.js +121 -6
- package/lib/accountAuth.js +2 -2
- package/lib/buildAccount.js +3 -3
- package/lib/constants.d.ts +0 -1
- package/lib/constants.js +0 -1
- package/lib/doctor/Diagnosis.js +5 -5
- package/lib/errorHandlers/index.js +4 -3
- package/lib/errorHandlers/suppressError.js +4 -0
- package/lib/errors/PromptExitError.d.ts +4 -2
- package/lib/errors/PromptExitError.js +3 -0
- package/lib/hasFeature.js +1 -2
- package/lib/middleware/autoUpdateMiddleware.js +6 -3
- package/lib/process.d.ts +1 -1
- package/lib/process.js +10 -3
- package/lib/projects/create/v2.js +1 -2
- package/lib/projects/delete.d.ts +13 -0
- package/lib/projects/delete.js +193 -0
- package/lib/projects/localDev/AppDevModeInterface.js +11 -11
- package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +3 -1
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +2 -2
- package/lib/projects/localDev/DevSessionManager.d.ts +6 -3
- package/lib/projects/localDev/DevSessionManager.js +31 -19
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +3 -0
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +16 -12
- package/lib/projects/localDev/LocalDevProcess.js +6 -5
- package/lib/projects/localDev/LocalDevState.d.ts +3 -2
- package/lib/projects/localDev/LocalDevState.js +3 -1
- package/lib/projects/localDev/helpers/account.d.ts +4 -3
- package/lib/projects/localDev/helpers/account.js +16 -19
- package/lib/projects/localDev/helpers/process.d.ts +1 -1
- package/lib/projects/localDev/helpers/process.js +4 -10
- package/lib/projects/localDev/helpers/project.d.ts +4 -3
- package/lib/projects/localDev/helpers/project.js +31 -15
- package/lib/projects/projectInfo.d.ts +5 -0
- package/lib/projects/projectInfo.js +82 -0
- package/lib/projects/projectProfiles.d.ts +1 -2
- package/lib/projects/projectProfiles.js +5 -17
- package/lib/projects/upload.js +19 -0
- package/lib/projects/workspaces.d.ts +42 -0
- package/lib/projects/workspaces.js +350 -0
- package/lib/prompts/createApiSamplePrompt.js +4 -0
- package/lib/prompts/projectProfilePrompt.d.ts +2 -0
- package/lib/prompts/projectProfilePrompt.js +46 -0
- package/lib/prompts/promptUtils.js +3 -2
- package/lib/prompts/selectHubDBTablePrompt.js +2 -2
- package/lib/prompts/selectPublicAppForMigrationPrompt.js +2 -2
- package/lib/theme/cmsDevServerProcess.d.ts +2 -0
- package/lib/theme/cmsDevServerProcess.js +7 -6
- package/lib/ui/SpinniesManager.d.ts +1 -0
- package/lib/ui/SpinniesManager.js +20 -6
- package/lib/ui/spinniesUtils.d.ts +0 -1
- package/lib/ui/spinniesUtils.js +6 -16
- package/lib/usageTracking.d.ts +3 -4
- package/lib/yargs/makeYargsBuilder.d.ts +13 -0
- package/lib/yargs/makeYargsBuilder.js +33 -0
- package/lib/yargs/makeYargsHandlerWithUsageTracking.d.ts +3 -0
- package/lib/yargs/makeYargsHandlerWithUsageTracking.js +95 -0
- package/lib/yargs/strictEnforceBoolean.d.ts +1 -0
- package/lib/yargs/strictEnforceBoolean.js +13 -0
- package/lib/yargsUtils.d.ts +3 -16
- package/lib/yargsUtils.js +3 -48
- package/package.json +5 -4
- package/types/LocalDev.d.ts +5 -0
- package/types/Projects.d.ts +19 -0
- package/types/Yargs.d.ts +18 -1
package/lib/hasFeature.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { http } from '@hubspot/local-dev-lib/http';
|
|
2
2
|
import { fetchEnabledFeatures } from '@hubspot/local-dev-lib/api/localDevAuth';
|
|
3
|
-
|
|
4
|
-
const FEATURES_THAT_DEFAULT_ON = [FEATURES.APPS_HOME];
|
|
3
|
+
const FEATURES_THAT_DEFAULT_ON = [];
|
|
5
4
|
export async function hasFeature(accountId, feature) {
|
|
6
5
|
const { data: { enabledFeatures }, } = await fetchEnabledFeatures(accountId);
|
|
7
6
|
if (enabledFeatures[feature] === undefined &&
|
|
@@ -42,6 +42,10 @@ export async function autoUpdateCLI(argv) {
|
|
|
42
42
|
debugError(e);
|
|
43
43
|
}
|
|
44
44
|
const cliUpgradeInfo = getCliUpgradeInfo();
|
|
45
|
+
// Ignore all update notifications if the current version is a pre-release (contains a hyphen)
|
|
46
|
+
if (cliUpgradeInfo.current && cliUpgradeInfo.current.includes('-')) {
|
|
47
|
+
showManualInstallHelp = false;
|
|
48
|
+
}
|
|
45
49
|
if (isAllowAutoUpdatesEnabled &&
|
|
46
50
|
cliUpgradeInfo.current &&
|
|
47
51
|
cliUpgradeInfo.latest &&
|
|
@@ -49,9 +53,8 @@ export async function autoUpdateCLI(argv) {
|
|
|
49
53
|
!argv.useEnv &&
|
|
50
54
|
!process.env.SKIP_HUBSPOT_CLI_AUTO_UPDATES &&
|
|
51
55
|
!preventAutoUpdateForCommand(argv._)) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
showManualInstallHelp = false;
|
|
56
|
+
if (!showManualInstallHelp) {
|
|
57
|
+
// Pre-release version detected, skip auto-update
|
|
55
58
|
}
|
|
56
59
|
else if (!['major', 'latest'].includes(cliUpgradeInfo.type)) {
|
|
57
60
|
// type "latest" => current installed version is latest
|
package/lib/process.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ interface KeyPress {
|
|
|
8
8
|
export declare const TERMINATION_SIGNALS: string[];
|
|
9
9
|
export declare function handleExit(callback: (onTerminate: {
|
|
10
10
|
isSIGHUP: boolean;
|
|
11
|
-
}) => void): void;
|
|
11
|
+
}) => void): () => void;
|
|
12
12
|
export declare function handleKeypress(callback: (onKeyPress: KeyPress) => void): void;
|
|
13
13
|
export {};
|
package/lib/process.js
CHANGED
|
@@ -16,9 +16,9 @@ export const TERMINATION_SIGNALS = [
|
|
|
16
16
|
];
|
|
17
17
|
export function handleExit(callback) {
|
|
18
18
|
let exitInProgress = false;
|
|
19
|
+
const listeners = [];
|
|
19
20
|
TERMINATION_SIGNALS.forEach(signal => {
|
|
20
|
-
|
|
21
|
-
process.on(signal, async (...args) => {
|
|
21
|
+
const handler = async (...args) => {
|
|
22
22
|
// Prevent duplicate exit handling
|
|
23
23
|
if (!exitInProgress) {
|
|
24
24
|
exitInProgress = true;
|
|
@@ -38,8 +38,15 @@ export function handleExit(callback) {
|
|
|
38
38
|
}
|
|
39
39
|
await callback({ isSIGHUP });
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
};
|
|
42
|
+
listeners.push({ signal, handler });
|
|
43
|
+
process.on(signal, handler);
|
|
42
44
|
});
|
|
45
|
+
return () => {
|
|
46
|
+
for (const { signal, handler } of listeners) {
|
|
47
|
+
process.removeListener(signal, handler);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
43
50
|
}
|
|
44
51
|
export function handleKeypress(callback) {
|
|
45
52
|
readline.createInterface(process.stdin, process.stdout);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, EMPTY_PROJECT, PROJECT_WITH_APP, FEATURES, } from '../../constants.js';
|
|
2
2
|
import { commands, lib } from '../../../lang/en.js';
|
|
3
3
|
import { listPrompt } from '../../prompts/promptUtils.js';
|
|
4
|
-
import { APP_EVENTS_KEY as AppEventsKey
|
|
4
|
+
import { APP_EVENTS_KEY as AppEventsKey } from '@hubspot/project-parsing-lib/constants';
|
|
5
5
|
import { isV2Project } from '../platformVersion.js';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
import { getConfigForPlatformVersion } from './legacy.js';
|
|
@@ -47,7 +47,6 @@ export async function createV2App(providedAuth, providedDistribution) {
|
|
|
47
47
|
}
|
|
48
48
|
const componentTypeToGateMap = {
|
|
49
49
|
[AppEventsKey]: FEATURES.APP_EVENTS,
|
|
50
|
-
[PagesKey]: FEATURES.APPS_HOME,
|
|
51
50
|
'workflow-action-tool': FEATURES.AGENT_TOOLS,
|
|
52
51
|
};
|
|
53
52
|
export async function calculateComponentTemplateChoices(components, authType, distribution, accountId, projectMetadata) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const DELETION_POLL_TIMEOUT_MS: number;
|
|
2
|
+
export declare const DELETION_DEPLOY_SUCCESS_STATES: string[];
|
|
3
|
+
export declare const DELETION_DEPLOY_ERROR_STATES: ("FAILURE" | "ERROR" | "REVERTED")[];
|
|
4
|
+
export declare function resolveProjectName(accountId: number, projectArg: string | undefined): Promise<string>;
|
|
5
|
+
export declare function fetchProjectInstallCount(accountId: number, projectId: number): Promise<number>;
|
|
6
|
+
export declare function checkDeployedComponents(accountId: number, projectName: string): Promise<{
|
|
7
|
+
platformVersion: string;
|
|
8
|
+
hasUnifiedComponents: boolean;
|
|
9
|
+
projectId: number;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function deleteDeployedComponents(accountId: number, projectName: string): Promise<void>;
|
|
12
|
+
export declare function handleProjectDeletion(accountId: number, projectName: string): Promise<void>;
|
|
13
|
+
export declare function confirmDeletion(projectName: string, accountId: number, projectId: number): Promise<void>;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { fetchProjects, fetchProject, stageProjectForDeletion, getDeployStatus, deleteProject, } from '@hubspot/local-dev-lib/api/projects';
|
|
2
|
+
import { fetchPublicAppsForPortal } from '@hubspot/local-dev-lib/api/appsDev';
|
|
3
|
+
import { debugError, getErrorMessage } from '../errorHandlers/index.js';
|
|
4
|
+
import { uiLogger } from '../ui/logger.js';
|
|
5
|
+
import SpinniesManager from '../ui/SpinniesManager.js';
|
|
6
|
+
import { commands } from '../../lang/en.js';
|
|
7
|
+
import { confirmPrompt, listPrompt } from '../prompts/promptUtils.js';
|
|
8
|
+
import { poll, DEFAULT_POLLING_STATES, DEFAULT_POLLING_STATUS_LOOKUP, } from '../polling.js';
|
|
9
|
+
import { PromptExitError } from '../errors/PromptExitError.js';
|
|
10
|
+
import { EXIT_CODES } from '../enums/exitCodes.js';
|
|
11
|
+
import { AUTO_GENERATED_COMPONENT_TYPES } from '@hubspot/project-parsing-lib/constants';
|
|
12
|
+
import { mapToUserFacingType } from '@hubspot/project-parsing-lib/transform';
|
|
13
|
+
import { isV2Project } from './platformVersion.js';
|
|
14
|
+
import { COMPONENT_TYPES, SUBCOMPONENT_TYPES, } from '@hubspot/local-dev-lib/enums/build';
|
|
15
|
+
export const DELETION_POLL_TIMEOUT_MS = 5 * 60 * 1000;
|
|
16
|
+
export const DELETION_DEPLOY_SUCCESS_STATES = [
|
|
17
|
+
DEFAULT_POLLING_STATES.SUCCESS,
|
|
18
|
+
'FINISHED',
|
|
19
|
+
];
|
|
20
|
+
export const DELETION_DEPLOY_ERROR_STATES = DEFAULT_POLLING_STATUS_LOOKUP.errorStates;
|
|
21
|
+
const LEGACY_COMPONENTS_TO_FILTER = [
|
|
22
|
+
SUBCOMPONENT_TYPES.SERVERLESS_PKG,
|
|
23
|
+
SUBCOMPONENT_TYPES.REACT_EXTENSION,
|
|
24
|
+
SUBCOMPONENT_TYPES.PACKAGE_LOCK_FILE,
|
|
25
|
+
COMPONENT_TYPES.PRIVATE_APP,
|
|
26
|
+
COMPONENT_TYPES.PUBLIC_APP,
|
|
27
|
+
];
|
|
28
|
+
const legacyComponentFriendlyNames = {
|
|
29
|
+
[SUBCOMPONENT_TYPES.APP_ID]: 'Private App',
|
|
30
|
+
[SUBCOMPONENT_TYPES.PUBLIC_APP_ID]: 'Public App',
|
|
31
|
+
[SUBCOMPONENT_TYPES.CRM_CARD_V2]: 'Card',
|
|
32
|
+
[SUBCOMPONENT_TYPES.CARD_V2]: 'Card',
|
|
33
|
+
[SUBCOMPONENT_TYPES.SERVERLESS_FUNCTION]: 'Serverless Function',
|
|
34
|
+
[SUBCOMPONENT_TYPES.APP_FUNCTION]: 'App Function',
|
|
35
|
+
[SUBCOMPONENT_TYPES.AUTOMATION_ACTION]: 'Automation Action',
|
|
36
|
+
[SUBCOMPONENT_TYPES.WEBHOOKS]: 'Webhooks',
|
|
37
|
+
[COMPONENT_TYPES.THEME]: 'Theme',
|
|
38
|
+
[COMPONENT_TYPES.REACT_THEME]: 'React Theme',
|
|
39
|
+
};
|
|
40
|
+
function mapLegacyComponentToUserFriendlyName(type) {
|
|
41
|
+
return legacyComponentFriendlyNames[type] || 'unknown';
|
|
42
|
+
}
|
|
43
|
+
export async function resolveProjectName(accountId, projectArg) {
|
|
44
|
+
const { data } = await fetchProjects(accountId);
|
|
45
|
+
const projects = data.results;
|
|
46
|
+
if (projectArg) {
|
|
47
|
+
if (!projects.some(p => p.name === projectArg)) {
|
|
48
|
+
throw new Error(commands.project.delete.errors.projectNotFound(projectArg, accountId));
|
|
49
|
+
}
|
|
50
|
+
return projectArg;
|
|
51
|
+
}
|
|
52
|
+
if (projects.length === 0) {
|
|
53
|
+
throw new Error(commands.project.delete.errors.noProjectsFound(accountId));
|
|
54
|
+
}
|
|
55
|
+
const selected = await listPrompt(commands.project.delete.prompts.selectProject(accountId), {
|
|
56
|
+
choices: projects.map(p => ({ name: p.name, value: p.name })),
|
|
57
|
+
validate: value => !!value || commands.project.delete.prompts.validation.projectRequired,
|
|
58
|
+
});
|
|
59
|
+
if (!selected) {
|
|
60
|
+
throw new Error(commands.project.delete.prompts.validation.projectRequired);
|
|
61
|
+
}
|
|
62
|
+
return selected;
|
|
63
|
+
}
|
|
64
|
+
export async function fetchProjectInstallCount(accountId, projectId) {
|
|
65
|
+
try {
|
|
66
|
+
const { data } = await fetchPublicAppsForPortal(accountId);
|
|
67
|
+
return data.results
|
|
68
|
+
.filter(app => app.projectId === projectId)
|
|
69
|
+
.reduce((sum, app) => sum + app.publicApplicationInstallCounts.uniquePortalInstallCount, 0);
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
debugError(e);
|
|
73
|
+
uiLogger.warn(commands.project.delete.logs.installCountUnknown);
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function checkDeployedComponents(accountId, projectName) {
|
|
78
|
+
const { data: projectData } = await fetchProject(accountId, projectName);
|
|
79
|
+
const platformVersion = projectData.deployedBuild?.platformVersion ||
|
|
80
|
+
projectData.latestBuild?.platformVersion;
|
|
81
|
+
if (!platformVersion) {
|
|
82
|
+
throw new Error(commands.project.delete.errors.noPlatformVersion);
|
|
83
|
+
}
|
|
84
|
+
if (!isV2Project(platformVersion)) {
|
|
85
|
+
const userVisibleComponents = [];
|
|
86
|
+
projectData.deployedBuild?.subbuildStatuses?.forEach(item => {
|
|
87
|
+
if (LEGACY_COMPONENTS_TO_FILTER.includes(item.buildType)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
userVisibleComponents.push(`${item.buildName} - (${mapLegacyComponentToUserFriendlyName(item.buildType)})`);
|
|
91
|
+
});
|
|
92
|
+
if (userVisibleComponents.length > 0) {
|
|
93
|
+
uiLogger.log(commands.project.delete.logs.componentsToDeleteLegacy(userVisibleComponents));
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
platformVersion,
|
|
97
|
+
hasUnifiedComponents: false,
|
|
98
|
+
projectId: projectData.id,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const { data } = await stageProjectForDeletion(accountId, projectName, true);
|
|
103
|
+
if (data.hasDeployedComponents) {
|
|
104
|
+
const userVisibleComponents = data.componentsToRemove.filter(item => !AUTO_GENERATED_COMPONENT_TYPES.includes(mapToUserFacingType(item.componentType)));
|
|
105
|
+
uiLogger.log(commands.project.delete.logs.componentsToDeleteUnified(userVisibleComponents));
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
hasUnifiedComponents: data.hasDeployedComponents,
|
|
109
|
+
platformVersion,
|
|
110
|
+
projectId: projectData.id,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
debugError(e);
|
|
115
|
+
throw new Error(commands.project.delete.errors.cannotDelete(projectName, getErrorMessage(e)));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export async function deleteDeployedComponents(accountId, projectName) {
|
|
119
|
+
SpinniesManager.add('removeComponents', {
|
|
120
|
+
text: commands.project.delete.logs.deletingComponents(projectName),
|
|
121
|
+
});
|
|
122
|
+
let projectDeletionResponse;
|
|
123
|
+
try {
|
|
124
|
+
const { data } = await stageProjectForDeletion(accountId, projectName, false);
|
|
125
|
+
projectDeletionResponse = data;
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
debugError(e);
|
|
129
|
+
SpinniesManager.fail('removeComponents', {
|
|
130
|
+
text: commands.project.delete.errors.componentDeletionFailed(projectName),
|
|
131
|
+
});
|
|
132
|
+
throw new Error(commands.project.delete.errors.componentDeletionFailed(projectName));
|
|
133
|
+
}
|
|
134
|
+
const { deployId, hasDeployedComponents } = projectDeletionResponse;
|
|
135
|
+
if (deployId === undefined) {
|
|
136
|
+
if (hasDeployedComponents) {
|
|
137
|
+
SpinniesManager.fail('removeComponents', {
|
|
138
|
+
text: commands.project.delete.logs.unableToDetermineIfComponentsWereDeleted(projectName),
|
|
139
|
+
});
|
|
140
|
+
throw new Error(commands.project.delete.logs.unableToDetermineIfComponentsWereDeleted(projectName));
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
SpinniesManager.succeed('removeComponents', {
|
|
144
|
+
text: commands.project.delete.logs.componentsDeleted(projectName),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
await poll(() => getDeployStatus(accountId, projectName, deployId), {
|
|
151
|
+
successStates: DELETION_DEPLOY_SUCCESS_STATES,
|
|
152
|
+
errorStates: DELETION_DEPLOY_ERROR_STATES,
|
|
153
|
+
}, DELETION_POLL_TIMEOUT_MS);
|
|
154
|
+
SpinniesManager.succeed('removeComponents', {
|
|
155
|
+
text: commands.project.delete.logs.componentsDeleted(projectName),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
debugError(e);
|
|
160
|
+
SpinniesManager.fail('removeComponents', {
|
|
161
|
+
text: commands.project.delete.errors.componentDeletionFailed(projectName),
|
|
162
|
+
});
|
|
163
|
+
throw new Error(commands.project.delete.errors.componentDeletionFailed(projectName));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
export async function handleProjectDeletion(accountId, projectName) {
|
|
167
|
+
try {
|
|
168
|
+
SpinniesManager.add('deleteProject', {
|
|
169
|
+
text: commands.project.delete.logs.deleting(projectName),
|
|
170
|
+
});
|
|
171
|
+
await deleteProject(accountId, projectName);
|
|
172
|
+
SpinniesManager.succeed('deleteProject', {
|
|
173
|
+
text: commands.project.delete.logs.deleted(projectName, accountId),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
SpinniesManager.fail('deleteProject', {
|
|
178
|
+
text: commands.project.delete.errors.deleteFailed(projectName),
|
|
179
|
+
});
|
|
180
|
+
throw e;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export async function confirmDeletion(projectName, accountId, projectId) {
|
|
184
|
+
const installCount = await fetchProjectInstallCount(accountId, projectId);
|
|
185
|
+
if (installCount > 0) {
|
|
186
|
+
uiLogger.warn(commands.project.delete.logs.installWarning(installCount));
|
|
187
|
+
}
|
|
188
|
+
const confirmed = await confirmPrompt(commands.project.delete.prompts.confirmDelete(projectName, accountId), { defaultAnswer: false });
|
|
189
|
+
if (!confirmed) {
|
|
190
|
+
uiLogger.log(commands.project.delete.logs.cancelled);
|
|
191
|
+
throw new PromptExitError(commands.project.delete.logs.cancelled, EXIT_CODES.SUCCESS);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -6,7 +6,7 @@ import { EXIT_CODES } from '../../enums/exitCodes.js';
|
|
|
6
6
|
import { isAppIRNode } from '../../projects/structure.js';
|
|
7
7
|
import { uiLine } from '../../ui/index.js';
|
|
8
8
|
import { logError } from '../../errorHandlers/index.js';
|
|
9
|
-
import {
|
|
9
|
+
import { isPromptExitError } from '../../errors/PromptExitError.js';
|
|
10
10
|
import { installAppAutoPrompt, installAppBrowserPrompt, } from '../../prompts/installAppPrompt.js';
|
|
11
11
|
import { confirmPrompt } from '../../prompts/promptUtils.js';
|
|
12
12
|
import { lib } from '../../../lang/en.js';
|
|
@@ -28,7 +28,7 @@ class AppDevModeInterface {
|
|
|
28
28
|
!this.localDevState.projectConfig ||
|
|
29
29
|
!this.localDevState.projectDir) {
|
|
30
30
|
uiLogger.error(lib.LocalDevManager.failedToInitialize);
|
|
31
|
-
|
|
31
|
+
throw new Error(lib.LocalDevManager.failedToInitialize);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
getAppNodeFromProjectNodes(projectNodes) {
|
|
@@ -46,12 +46,12 @@ class AppDevModeInterface {
|
|
|
46
46
|
// App data will never be accessed before being set
|
|
47
47
|
if (!this.appNode) {
|
|
48
48
|
uiLogger.log(lib.AppDevModeInterface.appDataNotFound);
|
|
49
|
-
|
|
49
|
+
throw new Error(lib.AppDevModeInterface.appDataNotFound);
|
|
50
50
|
}
|
|
51
51
|
const data = this.localDevState.getAppDataByUid(this.appNode.uid);
|
|
52
52
|
if (!data) {
|
|
53
53
|
uiLogger.log(lib.AppDevModeInterface.appDataNotFound);
|
|
54
|
-
|
|
54
|
+
throw new Error(lib.AppDevModeInterface.appDataNotFound);
|
|
55
55
|
}
|
|
56
56
|
return data;
|
|
57
57
|
}
|
|
@@ -108,7 +108,7 @@ class AppDevModeInterface {
|
|
|
108
108
|
text: lib.AppDevModeInterface.fetchAppData.error,
|
|
109
109
|
});
|
|
110
110
|
logError(e);
|
|
111
|
-
|
|
111
|
+
return this.localDevState.actions.exit(EXIT_CODES.ERROR);
|
|
112
112
|
}
|
|
113
113
|
if (!appData) {
|
|
114
114
|
return;
|
|
@@ -136,7 +136,7 @@ class AppDevModeInterface {
|
|
|
136
136
|
uiLine();
|
|
137
137
|
const proceed = await confirmPrompt(lib.LocalDevManager.activeInstallWarning.confirmationPrompt, { defaultAnswer: false });
|
|
138
138
|
if (!proceed) {
|
|
139
|
-
|
|
139
|
+
return this.localDevState.actions.exit(EXIT_CODES.SUCCESS);
|
|
140
140
|
}
|
|
141
141
|
this.localDevState.addUploadWarning(lib.AppDevModeInterface.defaultMarketplaceAppWarning(this.marketplaceAppInstalls));
|
|
142
142
|
}
|
|
@@ -156,7 +156,7 @@ class AppDevModeInterface {
|
|
|
156
156
|
const shouldInstall = await installAppAutoPrompt();
|
|
157
157
|
if (!shouldInstall) {
|
|
158
158
|
uiLogger.log(lib.AppDevModeInterface.autoInstallDeclined);
|
|
159
|
-
|
|
159
|
+
return this.localDevState.actions.exit(EXIT_CODES.SUCCESS);
|
|
160
160
|
}
|
|
161
161
|
uiLogger.log('');
|
|
162
162
|
SpinniesManager.add('autoInstallStaticAuthApp', {
|
|
@@ -225,7 +225,7 @@ class AppDevModeInterface {
|
|
|
225
225
|
if (!serverIsRunningAtRedirectUrl) {
|
|
226
226
|
uiLogger.log('');
|
|
227
227
|
uiLogger.error(lib.AppDevModeInterface.oauthAppRedirectUrlError(redirectUrl));
|
|
228
|
-
|
|
228
|
+
return this.localDevState.actions.exit(EXIT_CODES.ERROR);
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
resolveAppInstallPromise() {
|
|
@@ -246,7 +246,7 @@ class AppDevModeInterface {
|
|
|
246
246
|
}
|
|
247
247
|
handleAppInstallFailureDevServerMessage() {
|
|
248
248
|
uiLogger.error(lib.AppDevModeInterface.installationFailed);
|
|
249
|
-
|
|
249
|
+
this.localDevState.actions.exit(EXIT_CODES.ERROR);
|
|
250
250
|
}
|
|
251
251
|
onDevServerMessage = async (message) => {
|
|
252
252
|
if (message === LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED) {
|
|
@@ -314,7 +314,7 @@ class AppDevModeInterface {
|
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
catch (e) {
|
|
317
|
-
if (e
|
|
317
|
+
if (isPromptExitError(e)) {
|
|
318
318
|
throw e;
|
|
319
319
|
}
|
|
320
320
|
if (SpinniesManager.pick('fetchAppData')) {
|
|
@@ -324,7 +324,7 @@ class AppDevModeInterface {
|
|
|
324
324
|
});
|
|
325
325
|
}
|
|
326
326
|
logError(e);
|
|
327
|
-
|
|
327
|
+
return this.localDevState.actions.exit(EXIT_CODES.ERROR);
|
|
328
328
|
}
|
|
329
329
|
}
|
|
330
330
|
async start() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ProjectConfig, ComponentTypes, Component } from '../../../types/Projects.js';
|
|
2
|
+
import { ExitFunction } from '../../../types/Yargs.js';
|
|
2
3
|
type DevServerInterface = {
|
|
3
4
|
setup?: Function;
|
|
4
5
|
start?: (options: object) => Promise<void>;
|
|
@@ -20,11 +21,12 @@ declare class DevServerManager_DEPRECATED {
|
|
|
20
21
|
[key: string]: Component;
|
|
21
22
|
}) => Promise<void>): Promise<void>;
|
|
22
23
|
arrangeComponentsByType(components: Component[]): ComponentsByType;
|
|
23
|
-
setup({ components, onUploadRequired, accountId, setActiveApp, }: {
|
|
24
|
+
setup({ components, onUploadRequired, accountId, setActiveApp, exit, }: {
|
|
24
25
|
components: Component[];
|
|
25
26
|
onUploadRequired: () => void;
|
|
26
27
|
accountId: number;
|
|
27
28
|
setActiveApp: (appUid: string | undefined) => Promise<void>;
|
|
29
|
+
exit: ExitFunction;
|
|
28
30
|
}): Promise<void>;
|
|
29
31
|
start({ accountId, projectConfig, }: {
|
|
30
32
|
accountId: number;
|
|
@@ -57,7 +57,7 @@ class DevServerManager_DEPRECATED {
|
|
|
57
57
|
return acc;
|
|
58
58
|
}, {});
|
|
59
59
|
}
|
|
60
|
-
async setup({ components, onUploadRequired, accountId, setActiveApp, }) {
|
|
60
|
+
async setup({ components, onUploadRequired, accountId, setActiveApp, exit, }) {
|
|
61
61
|
this.componentsByType = this.arrangeComponentsByType(components);
|
|
62
62
|
let env;
|
|
63
63
|
const accountConfig = getConfigAccountById(accountId);
|
|
@@ -69,7 +69,7 @@ class DevServerManager_DEPRECATED {
|
|
|
69
69
|
}
|
|
70
70
|
catch (e) {
|
|
71
71
|
logError(e);
|
|
72
|
-
|
|
72
|
+
return exit(EXIT_CODES.ERROR);
|
|
73
73
|
}
|
|
74
74
|
await this.iterateDevServers(async (serverInterface, compatibleComponents) => {
|
|
75
75
|
if (serverInterface.setup) {
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import LocalDevLogger from './LocalDevLogger.js';
|
|
2
|
+
import { ExitFunction } from '../../../types/Yargs.js';
|
|
2
3
|
type DevSessionManagerConstructorOptions = {
|
|
3
4
|
targetTestingAccountId: number;
|
|
4
5
|
localDevLogger?: LocalDevLogger;
|
|
6
|
+
exit: ExitFunction;
|
|
5
7
|
};
|
|
6
8
|
declare class DevSessionManager {
|
|
7
9
|
localDevLogger?: LocalDevLogger;
|
|
8
10
|
targetTestingAccountId: number;
|
|
9
|
-
protected
|
|
10
|
-
private
|
|
11
|
-
private
|
|
11
|
+
protected devSessionId: number | undefined;
|
|
12
|
+
private heartbeatInterval;
|
|
13
|
+
private heartbeatRetries;
|
|
14
|
+
private exit;
|
|
12
15
|
constructor(options: DevSessionManagerConstructorOptions);
|
|
13
16
|
private validateSessionIdExists;
|
|
14
17
|
registerSession(): Promise<boolean>;
|
|
@@ -7,18 +7,20 @@ import { getErrorMessage } from '../../errorHandlers/index.js';
|
|
|
7
7
|
class DevSessionManager {
|
|
8
8
|
localDevLogger;
|
|
9
9
|
targetTestingAccountId;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
devSessionId;
|
|
11
|
+
heartbeatInterval;
|
|
12
|
+
heartbeatRetries;
|
|
13
|
+
exit;
|
|
13
14
|
constructor(options) {
|
|
14
15
|
this.targetTestingAccountId = options.targetTestingAccountId;
|
|
15
16
|
this.localDevLogger = options.localDevLogger;
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
17
|
+
this.exit = options.exit;
|
|
18
|
+
this.devSessionId = undefined;
|
|
19
|
+
this.heartbeatInterval = undefined;
|
|
20
|
+
this.heartbeatRetries = 0;
|
|
19
21
|
}
|
|
20
22
|
validateSessionIdExists() {
|
|
21
|
-
if (!this.
|
|
23
|
+
if (!this.devSessionId) {
|
|
22
24
|
if (this.localDevLogger) {
|
|
23
25
|
this.localDevLogger.devSessionMissingSessionIdError();
|
|
24
26
|
}
|
|
@@ -26,7 +28,7 @@ class DevSessionManager {
|
|
|
26
28
|
// Fallback for deprecated local dev manager
|
|
27
29
|
uiLogger.error(lib.LocalDevManager.devSession.missingSessionIdError);
|
|
28
30
|
}
|
|
29
|
-
|
|
31
|
+
throw new Error(lib.LocalDevManager.devSession.missingSessionIdError);
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
async registerSession() {
|
|
@@ -34,7 +36,7 @@ class DevSessionManager {
|
|
|
34
36
|
const activeServers = await getActiveServers();
|
|
35
37
|
const portData = Object.entries(activeServers).map(([serverId, port]) => ({ serverId, port }));
|
|
36
38
|
const registerDevSessionResponse = await registerDevSession(this.targetTestingAccountId, portData);
|
|
37
|
-
this.
|
|
39
|
+
this.devSessionId = registerDevSessionResponse.data.sessionId;
|
|
38
40
|
}
|
|
39
41
|
catch (e) {
|
|
40
42
|
if (this.localDevLogger) {
|
|
@@ -46,19 +48,29 @@ class DevSessionManager {
|
|
|
46
48
|
}
|
|
47
49
|
return false;
|
|
48
50
|
}
|
|
49
|
-
|
|
51
|
+
try {
|
|
52
|
+
this.validateSessionIdExists();
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return this.exit(EXIT_CODES.ERROR);
|
|
56
|
+
}
|
|
50
57
|
this.initializeHeartbeat();
|
|
51
58
|
return true;
|
|
52
59
|
}
|
|
53
60
|
initializeHeartbeat() {
|
|
54
|
-
this.
|
|
55
|
-
|
|
61
|
+
this.heartbeatInterval = setInterval(async () => {
|
|
62
|
+
try {
|
|
63
|
+
this.validateSessionIdExists();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return this.exit(EXIT_CODES.ERROR);
|
|
67
|
+
}
|
|
56
68
|
try {
|
|
57
|
-
await devSessionHeartbeat(this.targetTestingAccountId, this.
|
|
69
|
+
await devSessionHeartbeat(this.targetTestingAccountId, this.devSessionId);
|
|
58
70
|
}
|
|
59
71
|
catch (e) {
|
|
60
|
-
if (this.
|
|
61
|
-
this.
|
|
72
|
+
if (this.heartbeatRetries < 3) {
|
|
73
|
+
this.heartbeatRetries++;
|
|
62
74
|
return;
|
|
63
75
|
}
|
|
64
76
|
if (this.localDevLogger) {
|
|
@@ -68,15 +80,15 @@ class DevSessionManager {
|
|
|
68
80
|
// Fallback for deprecated local dev manager
|
|
69
81
|
uiLogger.error(lib.LocalDevManager.devSession.heartbeatError(getErrorMessage(e)));
|
|
70
82
|
}
|
|
71
|
-
|
|
83
|
+
return this.exit(EXIT_CODES.ERROR);
|
|
72
84
|
}
|
|
73
85
|
}, 30000);
|
|
74
86
|
}
|
|
75
87
|
async deleteDevSession() {
|
|
76
|
-
if (this.
|
|
77
|
-
clearInterval(this.
|
|
88
|
+
if (this.devSessionId) {
|
|
89
|
+
clearInterval(this.heartbeatInterval);
|
|
78
90
|
try {
|
|
79
|
-
await deleteDevSession(this.targetTestingAccountId, this.
|
|
91
|
+
await deleteDevSession(this.targetTestingAccountId, this.devSessionId);
|
|
80
92
|
}
|
|
81
93
|
catch (e) {
|
|
82
94
|
if (this.localDevLogger) {
|
|
@@ -3,6 +3,7 @@ import { Build } from '@hubspot/local-dev-lib/types/Build';
|
|
|
3
3
|
import { PublicApp } from '@hubspot/local-dev-lib/types/Apps';
|
|
4
4
|
import { Environment } from '@hubspot/local-dev-lib/types/Accounts';
|
|
5
5
|
import { Component, ProjectConfig } from '../../../types/Projects.js';
|
|
6
|
+
import { ExitFunction } from '../../../types/Yargs.js';
|
|
6
7
|
type LocalDevManagerConstructorOptions = {
|
|
7
8
|
targetAccountId: number;
|
|
8
9
|
parentAccountId: number;
|
|
@@ -14,6 +15,7 @@ type LocalDevManagerConstructorOptions = {
|
|
|
14
15
|
isGithubLinked: boolean;
|
|
15
16
|
runnableComponents: Component[];
|
|
16
17
|
env: Environment;
|
|
18
|
+
exit: ExitFunction;
|
|
17
19
|
};
|
|
18
20
|
declare class LocalDevManager_DEPRECATED {
|
|
19
21
|
targetAccountId: number;
|
|
@@ -36,6 +38,7 @@ declare class LocalDevManager_DEPRECATED {
|
|
|
36
38
|
projectSourceDir: string;
|
|
37
39
|
mostRecentUploadWarning: string | null;
|
|
38
40
|
private devSessionManager;
|
|
41
|
+
private exit;
|
|
39
42
|
constructor(options: LocalDevManagerConstructorOptions);
|
|
40
43
|
setActiveApp(appUid?: string): Promise<void>;
|
|
41
44
|
setActivePublicAppData(): Promise<void>;
|