@hubspot/cli 8.5.0 → 8.6.0-beta.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/clean.js +2 -0
- package/commands/account/createOverride.js +3 -0
- package/commands/account/info.js +34 -16
- package/commands/account/link.d.ts +4 -0
- package/commands/account/link.js +89 -0
- package/commands/account/list.js +29 -71
- package/commands/account/remove.js +2 -0
- package/commands/account/removeOverride.js +3 -0
- package/commands/account/unlink.d.ts +4 -0
- package/commands/account/unlink.js +70 -0
- package/commands/account/use.js +71 -1
- package/commands/account.js +4 -0
- package/commands/project/appInstallStatus.d.ts +4 -0
- package/commands/project/appInstallStatus.js +132 -0
- package/commands/project/create.js +8 -0
- package/commands/project/dev/deprecatedFlow.js +20 -2
- package/commands/project/dev/index.js +6 -0
- package/commands/project/dev/unifiedFlow.js +20 -3
- package/commands/project/lint.js +20 -2
- package/commands/project.js +2 -0
- package/lang/en.d.ts +102 -0
- package/lang/en.js +116 -8
- package/lib/app/migrate.js +2 -1
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +3 -0
- package/lib/doctor/Doctor.js +5 -5
- package/lib/link/accountTableUtils.d.ts +10 -0
- package/lib/link/accountTableUtils.js +39 -0
- package/lib/link/index.d.ts +18 -0
- package/lib/link/index.js +185 -0
- package/lib/link/linkUtils.d.ts +5 -0
- package/lib/link/linkUtils.js +49 -0
- package/lib/link/prompts.d.ts +7 -0
- package/lib/link/prompts.js +126 -0
- package/lib/link/renderLinkedAccountsTable.d.ts +2 -0
- package/lib/link/renderLinkedAccountsTable.js +14 -0
- package/lib/link/warnIfLinkedDirectory.d.ts +1 -0
- package/lib/link/warnIfLinkedDirectory.js +9 -0
- package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +2 -1
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +2 -2
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +2 -0
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +3 -0
- package/lib/projects/uieLinting.d.ts +17 -3
- package/lib/projects/uieLinting.js +93 -28
- package/lib/prompts/promptUtils.js +1 -0
- package/lib/ui/accountTable.d.ts +8 -0
- package/lib/ui/accountTable.js +67 -0
- package/mcp-server/server.js +39 -1
- package/mcp-server/tools/index.js +2 -0
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +1 -1
- package/mcp-server/tools/project/CreateTestAccountTool.js +1 -1
- package/mcp-server/tools/project/DeployProjectTool.js +1 -1
- package/mcp-server/tools/project/FindProjectsTool.d.ts +15 -0
- package/mcp-server/tools/project/FindProjectsTool.js +60 -0
- package/mcp-server/tools/project/GetBuildLogsTool.js +1 -1
- package/mcp-server/tools/project/GetBuildStatusTool.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.js +1 -1
- package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
- package/package.json +2 -2
- package/types/Link.d.ts +32 -0
- package/types/Link.js +5 -0
- package/types/PackageJson.d.ts +1 -0
- package/types/Prompts.d.ts +1 -0
- package/types/Yargs.d.ts +1 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fetchAppInstallationData } from '@hubspot/local-dev-lib/api/localDevAuth';
|
|
3
|
+
import { fetchProject } from '@hubspot/local-dev-lib/api/projects';
|
|
4
|
+
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
5
|
+
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
6
|
+
import { translateForLocalDev } from '@hubspot/project-parsing-lib/translate';
|
|
7
|
+
import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
|
|
8
|
+
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
9
|
+
import { uiLogger } from '../../lib/ui/logger.js';
|
|
10
|
+
import { ApiErrorContext, debugError, logError, } from '../../lib/errorHandlers/index.js';
|
|
11
|
+
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
12
|
+
import { commands } from '../../lang/en.js';
|
|
13
|
+
import { getProjectConfig } from '../../lib/projects/config.js';
|
|
14
|
+
import { isAppIRNode } from '../../lib/projects/structure.js';
|
|
15
|
+
import { APP_AUTH_TYPES } from '../../lib/constants.js';
|
|
16
|
+
const command = 'app-install-status';
|
|
17
|
+
const describe = commands.project.installStatus.describe;
|
|
18
|
+
async function handler(args) {
|
|
19
|
+
const { derivedAccountId, formatOutputAsJson, exit } = args;
|
|
20
|
+
const { projectConfig, projectDir } = await getProjectConfig();
|
|
21
|
+
if (!projectConfig || !projectDir) {
|
|
22
|
+
uiLogger.error(commands.project.installStatus.errors.noProjectConfig);
|
|
23
|
+
return exit(EXIT_CODES.ERROR);
|
|
24
|
+
}
|
|
25
|
+
if (isLegacyProject(projectConfig.platformVersion)) {
|
|
26
|
+
uiLogger.error(commands.project.installStatus.errors.unsupportedPlatformVersion(projectConfig.platformVersion));
|
|
27
|
+
return exit(EXIT_CODES.ERROR);
|
|
28
|
+
}
|
|
29
|
+
let appNode;
|
|
30
|
+
try {
|
|
31
|
+
const { intermediateNodesIndexedByUid } = await translateForLocalDev({
|
|
32
|
+
projectSourceDir: path.join(projectDir, projectConfig.srcDir),
|
|
33
|
+
platformVersion: projectConfig.platformVersion,
|
|
34
|
+
accountId: derivedAccountId,
|
|
35
|
+
}, { skipValidation: true });
|
|
36
|
+
appNode = Object.values(intermediateNodesIndexedByUid).find(isAppIRNode);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
debugError(error);
|
|
40
|
+
uiLogger.error(commands.project.installStatus.errors.failedToParseProject);
|
|
41
|
+
return exit(EXIT_CODES.ERROR);
|
|
42
|
+
}
|
|
43
|
+
if (!appNode) {
|
|
44
|
+
uiLogger.error(commands.project.installStatus.errors.noAppInProject);
|
|
45
|
+
return exit(EXIT_CODES.ERROR);
|
|
46
|
+
}
|
|
47
|
+
if (appNode.config.auth.type.toLowerCase() !== APP_AUTH_TYPES.STATIC) {
|
|
48
|
+
uiLogger.error(commands.project.installStatus.errors.unsupportedAuthType(appNode.config.auth.type));
|
|
49
|
+
return exit(EXIT_CODES.ERROR);
|
|
50
|
+
}
|
|
51
|
+
let projectId;
|
|
52
|
+
try {
|
|
53
|
+
const response = await fetchProject(derivedAccountId, projectConfig.name);
|
|
54
|
+
projectId = response.data.id;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
logError(error, new ApiErrorContext({
|
|
58
|
+
accountId: derivedAccountId,
|
|
59
|
+
projectName: projectConfig.name,
|
|
60
|
+
}));
|
|
61
|
+
return exit(EXIT_CODES.ERROR);
|
|
62
|
+
}
|
|
63
|
+
let isInstalledWithScopeGroups = false;
|
|
64
|
+
let previouslyAuthorizedScopeGroups = [];
|
|
65
|
+
let appId;
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetchAppInstallationData(derivedAccountId, projectId, appNode.uid, appNode.config.auth.requiredScopes, appNode.config.auth.optionalScopes);
|
|
68
|
+
isInstalledWithScopeGroups = response.data.isInstalledWithScopeGroups;
|
|
69
|
+
previouslyAuthorizedScopeGroups =
|
|
70
|
+
response.data.previouslyAuthorizedScopeGroups;
|
|
71
|
+
appId = response.data.appId;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (!isHubSpotHttpError(error) || error.status !== 404) {
|
|
75
|
+
logError(error, new ApiErrorContext({
|
|
76
|
+
accountId: derivedAccountId,
|
|
77
|
+
projectName: projectConfig.name,
|
|
78
|
+
}));
|
|
79
|
+
return exit(EXIT_CODES.ERROR);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const isInstalled = isInstalledWithScopeGroups || previouslyAuthorizedScopeGroups.length > 0;
|
|
83
|
+
if (formatOutputAsJson) {
|
|
84
|
+
uiLogger.json({
|
|
85
|
+
appId,
|
|
86
|
+
appUid: appNode.uid,
|
|
87
|
+
accountId: derivedAccountId,
|
|
88
|
+
projectId,
|
|
89
|
+
isInstalled,
|
|
90
|
+
isInstalledWithCurrentScopes: isInstalledWithScopeGroups,
|
|
91
|
+
previouslyAuthorizedScopeGroups,
|
|
92
|
+
});
|
|
93
|
+
return exit(isInstalled ? EXIT_CODES.SUCCESS : EXIT_CODES.WARNING);
|
|
94
|
+
}
|
|
95
|
+
if (isInstalled) {
|
|
96
|
+
if (isInstalledWithScopeGroups) {
|
|
97
|
+
uiLogger.success(commands.project.installStatus.success.installed(appNode.config.name, derivedAccountId));
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
uiLogger.success(commands.project.installStatus.success.installedWithOutdatedScopes(appNode.config.name, derivedAccountId));
|
|
101
|
+
}
|
|
102
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
103
|
+
}
|
|
104
|
+
uiLogger.log(commands.project.installStatus.notInstalled(appNode.config.name, derivedAccountId));
|
|
105
|
+
return exit(EXIT_CODES.WARNING);
|
|
106
|
+
}
|
|
107
|
+
function projectInstallStatusBuilder(yargs) {
|
|
108
|
+
yargs.example([
|
|
109
|
+
[
|
|
110
|
+
'$0 project app-install-status',
|
|
111
|
+
commands.project.installStatus.examples.default,
|
|
112
|
+
],
|
|
113
|
+
[
|
|
114
|
+
'$0 project app-install-status --json',
|
|
115
|
+
commands.project.installStatus.examples.json,
|
|
116
|
+
],
|
|
117
|
+
]);
|
|
118
|
+
return yargs;
|
|
119
|
+
}
|
|
120
|
+
const builder = makeYargsBuilder(projectInstallStatusBuilder, command, describe, {
|
|
121
|
+
useGlobalOptions: true,
|
|
122
|
+
useConfigOptions: true,
|
|
123
|
+
useAccountOptions: true,
|
|
124
|
+
useJSONOutputOptions: true,
|
|
125
|
+
});
|
|
126
|
+
const projectInstallStatusCommand = {
|
|
127
|
+
command,
|
|
128
|
+
describe,
|
|
129
|
+
handler: makeYargsHandlerWithUsageTracking('project-app-install-status', handler),
|
|
130
|
+
builder,
|
|
131
|
+
};
|
|
132
|
+
export default projectInstallStatusCommand;
|
|
@@ -19,8 +19,15 @@ import { updateHsMetaFilesWithAutoGeneratedFields } from '../../lib/projects/com
|
|
|
19
19
|
import SpinniesManager from '../../lib/ui/SpinniesManager.js';
|
|
20
20
|
const command = ['create', 'init'];
|
|
21
21
|
const describe = commands.project.create.describe;
|
|
22
|
+
const BETA_VERSIONS = [
|
|
23
|
+
PLATFORM_VERSIONS.v2026_09_BETA,
|
|
24
|
+
PLATFORM_VERSIONS.v2026_03_BETA,
|
|
25
|
+
];
|
|
22
26
|
async function handler(args) {
|
|
23
27
|
const { platformVersion, templateSource, exit, addUsageMetadata } = args;
|
|
28
|
+
if (BETA_VERSIONS.includes(platformVersion)) {
|
|
29
|
+
uiLogger.warn(commands.project.create.warnings.betaPlatformVersion(platformVersion));
|
|
30
|
+
}
|
|
24
31
|
if (templateSource && !templateSource.includes('/')) {
|
|
25
32
|
uiLogger.error(commands.project.create.errors.invalidTemplateSource);
|
|
26
33
|
return exit(EXIT_CODES.ERROR);
|
|
@@ -128,6 +135,7 @@ function projectCreateBuilder(yargs) {
|
|
|
128
135
|
PLATFORM_VERSIONS.v2025_2,
|
|
129
136
|
PLATFORM_VERSIONS.v2026_03_BETA,
|
|
130
137
|
PLATFORM_VERSIONS.v2026_03,
|
|
138
|
+
PLATFORM_VERSIONS.v2026_09_BETA,
|
|
131
139
|
],
|
|
132
140
|
default: PLATFORM_VERSIONS.v2026_03,
|
|
133
141
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { getConfigAccountById,
|
|
1
|
+
import { getConfigAccountById, getLinkedOrAllConfigAccounts, getConfigAccountEnvironment, } from '@hubspot/local-dev-lib/config';
|
|
2
|
+
import { getHsSettingsFileIfExists, getHsSettingsFilePath, } from '@hubspot/local-dev-lib/config/hsSettings';
|
|
2
3
|
import { findProjectComponents, getProjectComponentTypes, } from '../../../lib/projects/structure.js';
|
|
3
4
|
import { ComponentTypes } from '../../../types/Projects.js';
|
|
4
5
|
import { commands } from '../../../lang/en.js';
|
|
@@ -11,6 +12,7 @@ import { handleExit } from '../../../lib/process.js';
|
|
|
11
12
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
12
13
|
import { isSandbox, isDeveloperTestAccount, } from '../../../lib/accountTypes.js';
|
|
13
14
|
import { ensureProjectExists } from '../../../lib/projects/ensureProjectExists.js';
|
|
15
|
+
import { isDirectoryLinked, addAccountToLinkedSettings, } from '../../../lib/link/linkUtils.js';
|
|
14
16
|
export async function deprecatedProjectDevFlow({ args, accountId, projectConfig, projectDir, }) {
|
|
15
17
|
const { userProvidedAccount, derivedAccountId, exit } = args;
|
|
16
18
|
const env = getConfigAccountEnvironment(derivedAccountId);
|
|
@@ -32,7 +34,9 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
|
|
|
32
34
|
uiLogger.error(commands.project.dev.errors.invalidProjectComponents);
|
|
33
35
|
return exit(EXIT_CODES.SUCCESS);
|
|
34
36
|
}
|
|
35
|
-
const
|
|
37
|
+
const hsSettings = getHsSettingsFileIfExists();
|
|
38
|
+
const directoryIsLinked = isDirectoryLinked(hsSettings);
|
|
39
|
+
const accounts = getLinkedOrAllConfigAccounts();
|
|
36
40
|
if (!accounts) {
|
|
37
41
|
uiLogger.error(commands.project.dev.errors.noAccountsInConfig);
|
|
38
42
|
return exit(EXIT_CODES.ERROR);
|
|
@@ -69,6 +73,10 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
|
|
|
69
73
|
else {
|
|
70
74
|
await checkIfDefaultAccountIsSupported(accountConfig, hasPublicApps, exit);
|
|
71
75
|
}
|
|
76
|
+
if (directoryIsLinked) {
|
|
77
|
+
uiLogger.log('');
|
|
78
|
+
uiLogger.info(commands.account.subcommands.link.shared.usingLinkedAccounts(getHsSettingsFilePath()));
|
|
79
|
+
}
|
|
72
80
|
// The user is targeting an account type that we recommend developing on
|
|
73
81
|
if (!targetProjectAccountId && bypassRecommendedAccountPrompt) {
|
|
74
82
|
targetTestingAccountId = derivedAccountId;
|
|
@@ -101,6 +109,9 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
|
|
|
101
109
|
if (!accountAdded) {
|
|
102
110
|
return exit(EXIT_CODES.SUCCESS);
|
|
103
111
|
}
|
|
112
|
+
if (directoryIsLinked) {
|
|
113
|
+
addAccountToLinkedSettings(notInConfigAccount.id);
|
|
114
|
+
}
|
|
104
115
|
}
|
|
105
116
|
createNewSandbox = hasPrivateApps && createNestedAccount;
|
|
106
117
|
createNewDeveloperTestAccount = hasPublicApps && createNestedAccount;
|
|
@@ -114,6 +125,9 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
|
|
|
114
125
|
}
|
|
115
126
|
// We will be running our tests against this new sandbox account
|
|
116
127
|
targetTestingAccountId = targetProjectAccountId;
|
|
128
|
+
if (directoryIsLinked) {
|
|
129
|
+
addAccountToLinkedSettings(targetProjectAccountId);
|
|
130
|
+
}
|
|
117
131
|
}
|
|
118
132
|
if (createNewDeveloperTestAccount) {
|
|
119
133
|
try {
|
|
@@ -123,6 +137,9 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
|
|
|
123
137
|
return exit(EXIT_CODES.ERROR);
|
|
124
138
|
}
|
|
125
139
|
targetProjectAccountId = derivedAccountId;
|
|
140
|
+
if (directoryIsLinked) {
|
|
141
|
+
addAccountToLinkedSettings(targetTestingAccountId);
|
|
142
|
+
}
|
|
126
143
|
}
|
|
127
144
|
if (!targetProjectAccountId || !targetTestingAccountId) {
|
|
128
145
|
uiLogger.error(commands.project.dev.errors.noAccount(accountId));
|
|
@@ -156,6 +173,7 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
|
|
|
156
173
|
targetAccountId: targetTestingAccountId,
|
|
157
174
|
env,
|
|
158
175
|
exit,
|
|
176
|
+
port: args.port,
|
|
159
177
|
});
|
|
160
178
|
await LocalDev.start();
|
|
161
179
|
handleExit(({ isSIGHUP }) => LocalDev.stop(!isSIGHUP));
|
|
@@ -13,6 +13,7 @@ import { uiLogger } from '../../../lib/ui/logger.js';
|
|
|
13
13
|
import { logError } from '../../../lib/errorHandlers/index.js';
|
|
14
14
|
import { projectProfilePrompt } from '../../../lib/prompts/projectProfilePrompt.js';
|
|
15
15
|
import { isPromptExitError } from '../../../lib/errors/PromptExitError.js';
|
|
16
|
+
import { LOCAL_DEV_DEFAULT_PORT } from '../../../lib/constants.js';
|
|
16
17
|
const command = 'dev';
|
|
17
18
|
const describe = commands.project.dev.describe;
|
|
18
19
|
function validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV2) {
|
|
@@ -149,6 +150,11 @@ function projectDevBuilder(yargs) {
|
|
|
149
150
|
type: 'string',
|
|
150
151
|
description: commands.project.dev.options.account,
|
|
151
152
|
});
|
|
153
|
+
yargs.option('port', {
|
|
154
|
+
type: 'number',
|
|
155
|
+
description: commands.project.dev.options.port,
|
|
156
|
+
default: LOCAL_DEV_DEFAULT_PORT,
|
|
157
|
+
});
|
|
152
158
|
yargs.example([['$0 project dev', commands.project.dev.examples.default]]);
|
|
153
159
|
yargs.conflicts('profile', 'account');
|
|
154
160
|
yargs.conflicts('profile', 'testing-account');
|
|
@@ -3,7 +3,7 @@ import util from 'util';
|
|
|
3
3
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
4
4
|
import { startPortManagerServer, stopPortManagerServer, } from '@hubspot/local-dev-lib/portManager';
|
|
5
5
|
import { isTranslationError, translateForLocalDev, } from '@hubspot/project-parsing-lib/translate';
|
|
6
|
-
import { getConfigAccountEnvironment,
|
|
6
|
+
import { getConfigAccountEnvironment, getLinkedOrAllConfigAccounts, getConfigAccountById, } from '@hubspot/local-dev-lib/config';
|
|
7
7
|
import { logError } from '../../../lib/errorHandlers/index.js';
|
|
8
8
|
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
9
9
|
import { ensureProjectExists } from '../../../lib/projects/ensureProjectExists.js';
|
|
@@ -18,6 +18,8 @@ import { uiLogger } from '../../../lib/ui/logger.js';
|
|
|
18
18
|
import { commands } from '../../../lang/en.js';
|
|
19
19
|
import LocalDevWebsocketServer from '../../../lib/projects/localDev/LocalDevWebsocketServer.js';
|
|
20
20
|
import { isLocalDevRunning } from '../../../lib/projects/localDev/helpers/process.js';
|
|
21
|
+
import { getHsSettingsFileIfExists, getHsSettingsFilePath, } from '@hubspot/local-dev-lib/config/hsSettings';
|
|
22
|
+
import { isDirectoryLinked, addAccountToLinkedSettings, } from '../../../lib/link/linkUtils.js';
|
|
21
23
|
export async function unifiedProjectDevFlow({ args, targetProjectAccountId, providedTargetTestingAccountId, projectConfig, projectDir, }) {
|
|
22
24
|
const { exit } = args;
|
|
23
25
|
if (await isLocalDevRunning()) {
|
|
@@ -56,13 +58,19 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
56
58
|
uiLogger.error(commands.project.dev.errors.noAccount(targetProjectAccountId));
|
|
57
59
|
return exit(EXIT_CODES.ERROR);
|
|
58
60
|
}
|
|
59
|
-
const
|
|
61
|
+
const hsSettings = getHsSettingsFileIfExists();
|
|
62
|
+
const directoryIsLinked = isDirectoryLinked(hsSettings);
|
|
63
|
+
const accounts = getLinkedOrAllConfigAccounts();
|
|
60
64
|
const accountIsCombined = await isUnifiedAccount(targetProjectAccountConfig);
|
|
61
65
|
const targetProjectAccountIsTestAccountOrSandbox = isTestAccountOrSandbox(targetProjectAccountConfig);
|
|
62
66
|
if (!accountIsCombined) {
|
|
63
67
|
uiLogger.error(commands.project.dev.errors.accountNotCombined);
|
|
64
68
|
return exit(EXIT_CODES.ERROR);
|
|
65
69
|
}
|
|
70
|
+
if (directoryIsLinked && !providedTargetTestingAccountId) {
|
|
71
|
+
uiLogger.log('');
|
|
72
|
+
uiLogger.info(commands.account.subcommands.link.shared.usingLinkedAccounts(getHsSettingsFilePath()));
|
|
73
|
+
}
|
|
66
74
|
let targetTestingAccountId = providedTargetTestingAccountId;
|
|
67
75
|
// Temporarily removing logic to use profile account as testing account
|
|
68
76
|
// if (profileConfig) {
|
|
@@ -90,6 +98,9 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
90
98
|
if (!accountAdded) {
|
|
91
99
|
return exit(EXIT_CODES.SUCCESS);
|
|
92
100
|
}
|
|
101
|
+
if (directoryIsLinked) {
|
|
102
|
+
addAccountToLinkedSettings(devAccountPromptResponse.notInConfigAccount.id);
|
|
103
|
+
}
|
|
93
104
|
}
|
|
94
105
|
else if (devAccountPromptResponse.createNestedAccount) {
|
|
95
106
|
// Create a new developer test account and automatically add it to the CLI config
|
|
@@ -99,6 +110,9 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
99
110
|
catch {
|
|
100
111
|
return exit(EXIT_CODES.ERROR);
|
|
101
112
|
}
|
|
113
|
+
if (directoryIsLinked) {
|
|
114
|
+
addAccountToLinkedSettings(targetTestingAccountId);
|
|
115
|
+
}
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
118
|
else if (accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX) {
|
|
@@ -112,6 +126,9 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
112
126
|
catch {
|
|
113
127
|
return exit(EXIT_CODES.ERROR);
|
|
114
128
|
}
|
|
129
|
+
if (directoryIsLinked) {
|
|
130
|
+
addAccountToLinkedSettings(targetTestingAccountId);
|
|
131
|
+
}
|
|
115
132
|
}
|
|
116
133
|
}
|
|
117
134
|
else {
|
|
@@ -143,7 +160,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
143
160
|
}
|
|
144
161
|
// End setup, start local dev process
|
|
145
162
|
try {
|
|
146
|
-
await startPortManagerServer();
|
|
163
|
+
await startPortManagerServer(args.port);
|
|
147
164
|
}
|
|
148
165
|
catch (e) {
|
|
149
166
|
logError(e);
|
package/commands/project/lint.js
CHANGED
|
@@ -10,7 +10,7 @@ import { logError } from '../../lib/errorHandlers/index.js';
|
|
|
10
10
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
11
11
|
import { promptUser } from '../../lib/prompts/promptUtils.js';
|
|
12
12
|
import SpinniesManager from '../../lib/ui/SpinniesManager.js';
|
|
13
|
-
import { areAllLintPackagesInstalled, getMissingLintPackages, lintPackages, displayLintResults, hasEslintConfig, hasDeprecatedEslintConfig, getDeprecatedEslintConfigFiles, createEslintConfig, REQUIRED_PACKAGES_AND_MIN_VERSIONS, } from '../../lib/projects/uieLinting.js';
|
|
13
|
+
import { areAllLintPackagesInstalled, getMissingLintPackages, getMissingLintScripts, addLintScriptsToPackageJson, lintPackages, displayLintResults, hasEslintConfig, hasDeprecatedEslintConfig, getDeprecatedEslintConfigFiles, createEslintConfig, REQUIRED_PACKAGES_AND_MIN_VERSIONS, } from '../../lib/projects/uieLinting.js';
|
|
14
14
|
const command = 'lint';
|
|
15
15
|
const describe = commands.project.lint.help.describe;
|
|
16
16
|
async function handler(args) {
|
|
@@ -117,9 +117,10 @@ async function handler(args) {
|
|
|
117
117
|
SpinniesManager.add('lintConfigCreate', {
|
|
118
118
|
text: commands.project.lint.loading.creatingConfig,
|
|
119
119
|
});
|
|
120
|
+
const platformVersion = projectConfig.projectConfig?.platformVersion ?? null;
|
|
120
121
|
const createdConfigs = [];
|
|
121
122
|
for (const location of locationsNeedingConfig) {
|
|
122
|
-
const configPath = createEslintConfig(location);
|
|
123
|
+
const configPath = await createEslintConfig(location, platformVersion);
|
|
123
124
|
createdConfigs.push(configPath);
|
|
124
125
|
}
|
|
125
126
|
SpinniesManager.succeed('lintConfigCreate');
|
|
@@ -132,6 +133,23 @@ async function handler(args) {
|
|
|
132
133
|
return exit(EXIT_CODES.ERROR);
|
|
133
134
|
}
|
|
134
135
|
}
|
|
136
|
+
const locationsNeedingScripts = locationsReadyToLint.filter(location => getMissingLintScripts(location).length > 0);
|
|
137
|
+
if (locationsNeedingScripts.length > 0) {
|
|
138
|
+
SpinniesManager.add('lintScriptsAdd', {
|
|
139
|
+
text: commands.project.lint.loading.addingLintScripts,
|
|
140
|
+
});
|
|
141
|
+
const addedResults = [];
|
|
142
|
+
for (const location of locationsNeedingScripts) {
|
|
143
|
+
const result = addLintScriptsToPackageJson(location);
|
|
144
|
+
if (result.added.length > 0) {
|
|
145
|
+
addedResults.push(result);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
SpinniesManager.succeed('lintScriptsAdd');
|
|
149
|
+
addedResults.forEach(({ added, relativePath }) => {
|
|
150
|
+
uiLogger.success(commands.project.lint.lintScriptsAdded(added, relativePath));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
135
153
|
SpinniesManager.add('lintRun', {
|
|
136
154
|
text: commands.project.lint.loading.linting,
|
|
137
155
|
});
|
package/commands/project.js
CHANGED
|
@@ -19,6 +19,7 @@ import projectValidate from './project/validate.js';
|
|
|
19
19
|
import list from './project/list.js';
|
|
20
20
|
import info from './project/info.js';
|
|
21
21
|
import deleteProject from './project/delete.js';
|
|
22
|
+
import appInstallStatus from './project/appInstallStatus.js';
|
|
22
23
|
import { makeYargsBuilder } from '../lib/yargsUtils.js';
|
|
23
24
|
import { getProjectConfig } from '../lib/projects/config.js';
|
|
24
25
|
import { isSupportedPlatformVersion, LATEST_SUPPORTED_PLATFORM_VERSION, } from '@hubspot/project-parsing-lib/projects';
|
|
@@ -66,6 +67,7 @@ function projectBuilder(yargs) {
|
|
|
66
67
|
.command(updateDeps)
|
|
67
68
|
.command(profile)
|
|
68
69
|
.command(projectValidate)
|
|
70
|
+
.command(appInstallStatus)
|
|
69
71
|
.demandCommand(1, '');
|
|
70
72
|
return yargs;
|
|
71
73
|
}
|
package/lang/en.d.ts
CHANGED
|
@@ -129,8 +129,12 @@ export declare const commands: {
|
|
|
129
129
|
};
|
|
130
130
|
list: {
|
|
131
131
|
accounts: string;
|
|
132
|
+
allAccounts: string;
|
|
133
|
+
linkedAccounts: string;
|
|
132
134
|
defaultAccountTitle: string;
|
|
135
|
+
linkedDefaultTitle: string;
|
|
133
136
|
currentResolvedDefaultAccount: (accountId: number) => string;
|
|
137
|
+
directory: (dir: string) => string;
|
|
134
138
|
describe: string;
|
|
135
139
|
configPath: (configPath: string) => string;
|
|
136
140
|
overrideFilePathTitle: string;
|
|
@@ -177,6 +181,70 @@ export declare const commands: {
|
|
|
177
181
|
success: {
|
|
178
182
|
defaultAccountUpdated: (accountName: string) => string;
|
|
179
183
|
};
|
|
184
|
+
linked: {
|
|
185
|
+
editingLinkedDefault: (dir: string) => string;
|
|
186
|
+
alreadyDefault: (accountId: number) => string;
|
|
187
|
+
setLinkedDefault: (account: string) => string;
|
|
188
|
+
accountNotLinked: (account: string) => string;
|
|
189
|
+
promptToLink: (account: string) => string;
|
|
190
|
+
settingGlobalDefault: string;
|
|
191
|
+
nonInteractiveNotLinked: (account: string) => string;
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
link: {
|
|
195
|
+
describe: string;
|
|
196
|
+
verboseDescribe: string;
|
|
197
|
+
shared: {
|
|
198
|
+
noLinkedAccounts: string;
|
|
199
|
+
globalAccountsAvailable: (count: number) => string;
|
|
200
|
+
configurePrompt: string;
|
|
201
|
+
deprecatedConfigNotSupported: (command: string) => string;
|
|
202
|
+
writeSettingsFailed: (path: string, err: unknown) => string;
|
|
203
|
+
savedToSettings: (path: string) => string;
|
|
204
|
+
usingLinkedAccounts: (settingsPath: string) => string;
|
|
205
|
+
accountAutoLinked: (accountId: number) => string;
|
|
206
|
+
accountAutoLinkFailed: (accountId: number) => string;
|
|
207
|
+
};
|
|
208
|
+
linkingDirectory: (dir: string) => string;
|
|
209
|
+
managingLinkedAccounts: (dir: string) => string;
|
|
210
|
+
settingsInfo: (path: string) => string;
|
|
211
|
+
success: {
|
|
212
|
+
created: (path: string) => string;
|
|
213
|
+
};
|
|
214
|
+
errors: {
|
|
215
|
+
authFailed: string;
|
|
216
|
+
};
|
|
217
|
+
events: {
|
|
218
|
+
accountsLinked: (count: number) => string;
|
|
219
|
+
accountsUnlinked: (count: number) => string;
|
|
220
|
+
overrideAccountDetected: (accountId: number) => string;
|
|
221
|
+
defaultAccountSet: (accountId: number) => string;
|
|
222
|
+
defaultAccountRemoved: (isSelectionRequired: boolean) => string;
|
|
223
|
+
defaultAccountRemains: (accountId: number) => string;
|
|
224
|
+
updatedLinkedAccounts: string;
|
|
225
|
+
noAccountsLinked: string;
|
|
226
|
+
overrideFileRemoved: string;
|
|
227
|
+
invalidDefaultAccount: (accountId: number) => string;
|
|
228
|
+
};
|
|
229
|
+
prompts: {
|
|
230
|
+
howToProceed: string;
|
|
231
|
+
whatToDo: string;
|
|
232
|
+
linkExisting: string;
|
|
233
|
+
authenticateNew: string;
|
|
234
|
+
cancel: string;
|
|
235
|
+
selectDefault: string;
|
|
236
|
+
selectToLink: string;
|
|
237
|
+
selectToUnlink: string;
|
|
238
|
+
alreadyLinked: string;
|
|
239
|
+
fromHsAccount: string;
|
|
240
|
+
newlyAuthenticated: string;
|
|
241
|
+
mustSelectOne: string;
|
|
242
|
+
keepAsDefault: string;
|
|
243
|
+
};
|
|
244
|
+
};
|
|
245
|
+
unlink: {
|
|
246
|
+
describe: string;
|
|
247
|
+
verboseDescribe: string;
|
|
180
248
|
};
|
|
181
249
|
remove: {
|
|
182
250
|
describe: string;
|
|
@@ -245,6 +313,9 @@ export declare const commands: {
|
|
|
245
313
|
};
|
|
246
314
|
name: (name: string) => string;
|
|
247
315
|
scopeGroups: string;
|
|
316
|
+
linkedDefaultTitle: string;
|
|
317
|
+
settingsPath: (path: string) => string;
|
|
318
|
+
linkedDefault: (account: string) => string;
|
|
248
319
|
};
|
|
249
320
|
clean: {
|
|
250
321
|
describe: string;
|
|
@@ -1448,6 +1519,7 @@ export declare const commands: {
|
|
|
1448
1519
|
projectAccount: string;
|
|
1449
1520
|
testingAccount: string;
|
|
1450
1521
|
account: string;
|
|
1522
|
+
port: string;
|
|
1451
1523
|
};
|
|
1452
1524
|
};
|
|
1453
1525
|
create: {
|
|
@@ -1458,6 +1530,9 @@ export declare const commands: {
|
|
|
1458
1530
|
failedToFetchProjectList: string;
|
|
1459
1531
|
cannotNestProjects: (projectDir: string) => string;
|
|
1460
1532
|
};
|
|
1533
|
+
warnings: {
|
|
1534
|
+
betaPlatformVersion: (platformVersion: string) => string;
|
|
1535
|
+
};
|
|
1461
1536
|
logs: {
|
|
1462
1537
|
success: (projectName: string, projectDest: string) => string;
|
|
1463
1538
|
};
|
|
@@ -1865,6 +1940,7 @@ export declare const commands: {
|
|
|
1865
1940
|
loading: {
|
|
1866
1941
|
checking: string;
|
|
1867
1942
|
creatingConfig: string;
|
|
1943
|
+
addingLintScripts: string;
|
|
1868
1944
|
linting: string;
|
|
1869
1945
|
};
|
|
1870
1946
|
noProjectConfig: string;
|
|
@@ -1877,8 +1953,12 @@ export declare const commands: {
|
|
|
1877
1953
|
}[]) => string;
|
|
1878
1954
|
createEslintConfigPrompt: (directories: string[]) => string;
|
|
1879
1955
|
eslintConfigCreated: (configPath: string) => string;
|
|
1956
|
+
createEslintConfigRequiresV2Platform: (platformVersion?: string | null) => string;
|
|
1957
|
+
failedToFetchRemoteEslintConfig: (platformVersion: string) => string;
|
|
1880
1958
|
failedToCreateEslintConfig: (configPath: string) => string;
|
|
1881
1959
|
eslintConfigRequired: string;
|
|
1960
|
+
lintScriptsAdded: (scriptNames: string[], packageJsonPath: string) => string;
|
|
1961
|
+
failedToAddLintScripts: (packageJsonPath: string) => string;
|
|
1882
1962
|
};
|
|
1883
1963
|
updateDeps: {
|
|
1884
1964
|
help: {
|
|
@@ -2010,6 +2090,25 @@ export declare const commands: {
|
|
|
2010
2090
|
force: string;
|
|
2011
2091
|
};
|
|
2012
2092
|
};
|
|
2093
|
+
installStatus: {
|
|
2094
|
+
describe: string;
|
|
2095
|
+
examples: {
|
|
2096
|
+
default: string;
|
|
2097
|
+
json: string;
|
|
2098
|
+
};
|
|
2099
|
+
errors: {
|
|
2100
|
+
noProjectConfig: string;
|
|
2101
|
+
unsupportedPlatformVersion: (platformVersion: string) => string;
|
|
2102
|
+
failedToParseProject: string;
|
|
2103
|
+
noAppInProject: string;
|
|
2104
|
+
unsupportedAuthType: (authType: string) => string;
|
|
2105
|
+
};
|
|
2106
|
+
success: {
|
|
2107
|
+
installed: (appName: string, accountId: number) => string;
|
|
2108
|
+
installedWithOutdatedScopes: (appName: string, accountId: number) => string;
|
|
2109
|
+
};
|
|
2110
|
+
notInstalled: (appName: string, accountId: number) => string;
|
|
2111
|
+
};
|
|
2013
2112
|
};
|
|
2014
2113
|
sandbox: {
|
|
2015
2114
|
describe: string;
|
|
@@ -2978,6 +3077,9 @@ export declare const commands: {
|
|
|
2978
3077
|
};
|
|
2979
3078
|
};
|
|
2980
3079
|
export declare const lib: {
|
|
3080
|
+
linkedDirectory: {
|
|
3081
|
+
warning: (action: string, settingsPath: string) => string;
|
|
3082
|
+
};
|
|
2981
3083
|
parsing: {
|
|
2982
3084
|
unableToParseStringToNumber: string;
|
|
2983
3085
|
};
|