@hubspot/cli 8.0.11-experimental.1 → 8.0.12-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/api/migrate.js +3 -3
- package/bin/cli.js +3 -0
- package/commands/account/link.d.ts +4 -0
- package/commands/account/link.js +88 -0
- package/commands/account/unlink.d.ts +4 -0
- package/commands/account/unlink.js +69 -0
- package/commands/account.js +4 -0
- package/commands/app/migrate.js +4 -4
- package/commands/getStarted.js +2 -2
- package/commands/project/add.js +3 -3
- package/commands/project/appInstallStatus.d.ts +4 -0
- package/commands/project/appInstallStatus.js +132 -0
- package/commands/project/create.js +18 -7
- package/commands/project/delete.js +2 -2
- package/commands/project/deploy.js +4 -3
- package/commands/project/dev/index.js +5 -4
- package/commands/project/info.js +2 -2
- package/commands/project/lint.js +2 -1
- package/commands/project/migrate.js +5 -5
- package/commands/project/profile/add.js +2 -2
- package/commands/project/profile/delete.js +2 -2
- package/commands/project/upload.d.ts +2 -0
- package/commands/project/upload.js +38 -6
- package/commands/project/validate.js +2 -2
- package/commands/project/watch.js +2 -2
- package/commands/project.js +8 -3
- package/commands/testAccount/create.js +4 -4
- package/lang/en.d.ts +95 -0
- package/lang/en.js +108 -8
- package/lib/app/migrate.js +8 -0
- package/lib/doctor/Doctor.js +2 -2
- package/lib/getStartedV2Actions.js +2 -2
- package/lib/link/accountTableUtils.d.ts +10 -0
- package/lib/link/accountTableUtils.js +39 -0
- package/lib/link/index.d.ts +14 -0
- package/lib/link/index.js +154 -0
- package/lib/link/linkUtils.d.ts +4 -0
- package/lib/link/linkUtils.js +24 -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/projects/ProjectLogsManager.js +6 -3
- package/lib/projects/create/index.js +2 -2
- package/lib/projects/create/legacy.js +2 -2
- package/lib/projects/create/v2.js +2 -2
- package/lib/projects/delete.js +2 -2
- package/lib/projects/deploy.d.ts +1 -1
- package/lib/projects/deploy.js +2 -2
- package/lib/projects/preview.d.ts +7 -0
- package/lib/projects/preview.js +71 -0
- package/lib/projects/uieLinting.d.ts +8 -3
- package/lib/projects/uieLinting.js +48 -27
- package/lib/projects/upload.d.ts +1 -0
- package/lib/projects/upload.js +8 -7
- package/lib/prompts/projectsLogsPrompt.js +3 -0
- package/lib/prompts/promptUtils.js +1 -0
- package/lib/theme/cmsDevServerProcess.js +1 -1
- package/mcp-server/Tool.d.ts +15 -0
- package/mcp-server/Tool.js +53 -0
- package/mcp-server/server.js +39 -3
- package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +4 -2
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +8 -6
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +4 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +8 -6
- package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +4 -2
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -6
- package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +4 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +8 -6
- package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +4 -2
- package/mcp-server/tools/cms/HsListFunctionsTool.js +8 -6
- package/mcp-server/tools/cms/HsListTool.d.ts +4 -2
- package/mcp-server/tools/cms/HsListTool.js +8 -6
- package/mcp-server/tools/index.d.ts +3 -2
- package/mcp-server/tools/index.js +22 -22
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +6 -4
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +8 -6
- package/mcp-server/tools/project/CreateProjectTool.d.ts +6 -4
- package/mcp-server/tools/project/CreateProjectTool.js +9 -7
- package/mcp-server/tools/project/CreateTestAccountTool.d.ts +4 -2
- package/mcp-server/tools/project/CreateTestAccountTool.js +20 -8
- package/mcp-server/tools/project/DeployProjectTool.d.ts +4 -2
- package/mcp-server/tools/project/DeployProjectTool.js +4 -6
- package/mcp-server/tools/project/DocFetchTool.d.ts +4 -2
- package/mcp-server/tools/project/DocFetchTool.js +8 -6
- package/mcp-server/tools/project/DocsSearchTool.d.ts +9 -3
- package/mcp-server/tools/project/DocsSearchTool.js +32 -9
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +4 -2
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +8 -6
- package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +4 -2
- package/mcp-server/tools/project/GetApplicationInfoTool.js +8 -6
- package/mcp-server/tools/project/GetBuildLogsTool.d.ts +4 -2
- package/mcp-server/tools/project/GetBuildLogsTool.js +8 -6
- package/mcp-server/tools/project/GetBuildStatusTool.d.ts +4 -2
- package/mcp-server/tools/project/GetBuildStatusTool.js +8 -6
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -2
- package/mcp-server/tools/project/GetConfigValuesTool.js +12 -7
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +4 -2
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +4 -6
- package/mcp-server/tools/project/UploadProjectTools.d.ts +4 -2
- package/mcp-server/tools/project/UploadProjectTools.js +9 -7
- package/mcp-server/tools/project/ValidateProjectTool.d.ts +4 -2
- package/mcp-server/tools/project/ValidateProjectTool.js +8 -6
- package/mcp-server/tools/project/constants.d.ts +2 -2
- package/mcp-server/types.d.ts +0 -7
- package/mcp-server/types.js +1 -13
- package/mcp-server/utils/logger.d.ts +10 -0
- package/mcp-server/utils/logger.js +29 -0
- package/mcp-server/utils/toolUsageTracking.js +0 -2
- package/package.json +10 -10
- package/types/Link.d.ts +27 -0
- package/types/Link.js +1 -0
- package/types/Prompts.d.ts +1 -0
- package/lib/projects/platformVersion.d.ts +0 -9
- package/lib/projects/platformVersion.js +0 -39
package/lang/en.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { mapToUserFriendlyName } from '@hubspot/project-parsing-lib/transform';
|
|
3
|
-
import { PLATFORM_VERSIONS } from '@hubspot/
|
|
3
|
+
import { PLATFORM_VERSIONS } from '@hubspot/project-parsing-lib/constants';
|
|
4
4
|
import { PERSONAL_ACCESS_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
|
|
5
|
-
import { ARCHIVED_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
6
|
-
import { uiAccountDescription, uiBetaTag, uiCommandReference, uiLink,
|
|
7
|
-
import { getProjectDetailUrl, getProjectSettingsUrl,
|
|
5
|
+
import { ARCHIVED_HUBSPOT_CONFIG_YAML_FILE_NAME, DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME, GLOBAL_CONFIG_PATH, } from '@hubspot/local-dev-lib/constants/config';
|
|
6
|
+
import { indent, UI_COLORS, uiAccountDescription, uiAuthCommandReference, uiBetaTag, uiCommandReference, uiLink, } from '../lib/ui/index.js';
|
|
7
|
+
import { getLocalDevUiUrl, getProjectDetailUrl, getProjectSettingsUrl, } from '../lib/projects/urls.js';
|
|
8
8
|
import { getProductUpdatesUrl } from '../lib/links.js';
|
|
9
|
-
import { APP_DISTRIBUTION_TYPES,
|
|
9
|
+
import { APP_AUTH_TYPES, APP_DISTRIBUTION_TYPES, LEGACY_PUBLIC_APP_FILE, PROJECT_CONFIG_FILE, PROJECT_WITH_APP, } from '../lib/constants.js';
|
|
10
10
|
export const commands = {
|
|
11
11
|
generalErrors: {
|
|
12
12
|
srcIsProject: (src, command) => `"${src}" is in a project folder. Did you mean "hs project ${command}"?`,
|
|
@@ -186,6 +186,58 @@ export const commands = {
|
|
|
186
186
|
defaultAccountUpdated: (accountName) => `Default account updated to "${accountName}"`,
|
|
187
187
|
},
|
|
188
188
|
},
|
|
189
|
+
link: {
|
|
190
|
+
describe: 'Link authenticated HubSpot accounts to the current directory',
|
|
191
|
+
verboseDescribe: `Link one or more authenticated HubSpot accounts to the current directory. Linked accounts are saved in a local ${chalk.bold('.hs/settings.json')} file (added to .gitignore automatically).\n\nThis lets the CLI know which account to use when you run commands from this directory, without changing the global default. Run ${uiCommandReference('hs account current')} to see the active configuration.`,
|
|
192
|
+
shared: {
|
|
193
|
+
noLinkedAccounts: 'No HubSpot accounts are linked in this directory.',
|
|
194
|
+
globalAccountsAvailable: (count) => `You have ${chalk.cyan(count.toString())} ${count === 1 ? 'account' : 'accounts'} in your global config.`,
|
|
195
|
+
configurePrompt: `To configure this directory, run:\n${indent(1)}${uiCommandReference('hs account link')}`,
|
|
196
|
+
deprecatedConfigNotSupported: (command) => `${uiCommandReference(command)} does not support deprecated config. Run ${uiCommandReference('hs config migrate')} to migrate to global config. Then re-run ${uiCommandReference(command)}`,
|
|
197
|
+
writeSettingsFailed: (path, err) => `Failed to write to ${path}: ${err}`,
|
|
198
|
+
savedToSettings: (path) => `Saved to ${path}`,
|
|
199
|
+
},
|
|
200
|
+
linkingDirectory: (dir) => `Linking HubSpot account(s) for directory:\n${indent(1)}${dir}`,
|
|
201
|
+
managingLinkedAccounts: (dir) => `Managing linked accounts for:\n${indent(1)}${dir}`,
|
|
202
|
+
settingsInfo: (path) => `\u2139 Accounts linked here are saved in ${path}`,
|
|
203
|
+
success: {
|
|
204
|
+
created: (path) => `Linked to ${path} (created .hs and added to .gitignore).\n${indent(1)}Now when you work within this directory, the CLI will use the linked account(s).`,
|
|
205
|
+
},
|
|
206
|
+
errors: {
|
|
207
|
+
authFailed: `Authentication failed to complete`,
|
|
208
|
+
},
|
|
209
|
+
events: {
|
|
210
|
+
accountsLinked: (count) => `Linked ${count} account${count !== 1 ? 's' : ''}`,
|
|
211
|
+
accountsUnlinked: (count) => `Unlinked ${count} account${count !== 1 ? 's' : ''}`,
|
|
212
|
+
overrideAccountDetected: (accountId) => `\nCurrent default account (from .hsaccount):\n${indent(1)}${uiAccountDescription(accountId)}`,
|
|
213
|
+
defaultAccountSet: (accountId) => `Linked default account set to ${chalk.cyan(uiAccountDescription(accountId))}`,
|
|
214
|
+
defaultAccountRemoved: (isSelectionRequired) => `The linked default account was removed. ${isSelectionRequired ? 'A linked default account is required.\n' : ''}`,
|
|
215
|
+
defaultAccountRemains: (accountId) => `Linked default account remains ${chalk.cyan(uiAccountDescription(accountId))}`,
|
|
216
|
+
updatedLinkedAccounts: 'Updated linked accounts',
|
|
217
|
+
noAccountsLinked: `All accounts have been unlinked. Your global config accounts will be used.\n${indent(1)}The ${chalk.bold('.hs')} directory is no longer needed and can be safely deleted.`,
|
|
218
|
+
overrideFileRemoved: '.hsaccount file removed',
|
|
219
|
+
invalidDefaultAccount: (accountId) => `Default account ${uiAccountDescription(accountId)} is not in the linked accounts list and has been reset. Please select a new default.`,
|
|
220
|
+
},
|
|
221
|
+
prompts: {
|
|
222
|
+
howToProceed: 'How would you like to link an account?',
|
|
223
|
+
whatToDo: 'Which action would you like to perform?',
|
|
224
|
+
linkExisting: 'Link existing authenticated account(s)',
|
|
225
|
+
authenticateNew: 'Authenticate and link a new account',
|
|
226
|
+
cancel: 'Cancel',
|
|
227
|
+
selectDefault: 'Select a linked default account',
|
|
228
|
+
selectToLink: 'Select authenticated account(s) to link:',
|
|
229
|
+
selectToUnlink: 'Select account(s) to unlink',
|
|
230
|
+
alreadyLinked: '- Already linked',
|
|
231
|
+
fromHsAccount: '(from .hsaccount)',
|
|
232
|
+
newlyAuthenticated: '(just authenticated)',
|
|
233
|
+
mustSelectOne: 'You must select at least one account to link',
|
|
234
|
+
keepAsDefault: 'Keep this as the default?',
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
unlink: {
|
|
238
|
+
describe: 'Unlink HubSpot account(s) from the current directory',
|
|
239
|
+
verboseDescribe: `Remove one or more linked accounts from this directory's ${chalk.bold('.hs/settings.json')}. If the default account is removed, you will be prompted to select a new one.\n\nThis does not delete the account from the global config - it only removes the local association.`,
|
|
240
|
+
},
|
|
189
241
|
remove: {
|
|
190
242
|
describe: 'Remove an account from the config.',
|
|
191
243
|
logs: {
|
|
@@ -1321,7 +1373,7 @@ export const commands = {
|
|
|
1321
1373
|
},
|
|
1322
1374
|
},
|
|
1323
1375
|
api: {
|
|
1324
|
-
describe: 'Make an authenticated HTTP request to
|
|
1376
|
+
describe: 'Make an authenticated HTTP request to any HubSpot API endpoint that supports PAKs.',
|
|
1325
1377
|
verboseDescribe: `Make an authenticated HTTP request to any HubSpot API that supports PAKs using your CLI authentication.\n\nThis command is intended for testing and exploration of HubSpot APIs. It uses the authentication credentials configured in the CLI to make requests on your behalf.\n\nThe endpoint should be the API path, e.g. ${chalk.bold('/crm/v3/objects/contacts')}. The request will be authenticated using the account specified by ${uiCommandReference('--account')} or the default account.\n\nNote: The available endpoints depend on the scopes granted to your personal access key. If you receive a 403 error, check that your key includes the required scopes for the endpoint you are trying to reach. ${uiLink('Learn more about the HubSpot API', 'https://developers.hubspot.com/docs/api-reference/latest/overview')}`,
|
|
1326
1378
|
positionals: {
|
|
1327
1379
|
endpoint: {
|
|
@@ -1474,6 +1526,9 @@ export const commands = {
|
|
|
1474
1526
|
failedToFetchProjectList: 'Failed to fetch the list of available project templates. Please try again later.',
|
|
1475
1527
|
cannotNestProjects: (projectDir) => `A project already exists at ${projectDir}. Projects cannot be nested within other projects. Please choose a different destination and try again.`,
|
|
1476
1528
|
},
|
|
1529
|
+
warnings: {
|
|
1530
|
+
betaPlatformVersion: (platformVersion) => `Your portal must be enrolled in the beta to use platform version ${platformVersion}. If you are not enrolled in the beta, your upload will fail. ${uiLink('Enroll in the beta', getProductUpdatesUrl('286886'))}`,
|
|
1531
|
+
},
|
|
1477
1532
|
logs: {
|
|
1478
1533
|
success: (projectName, projectDest) => `Project ${chalk.bold(projectName)} was successfully created in ${projectDest}`,
|
|
1479
1534
|
},
|
|
@@ -1700,6 +1755,7 @@ export const commands = {
|
|
|
1700
1755
|
noFunctionsLinkText: 'Visit developer docs',
|
|
1701
1756
|
noFunctionsInProject: `There aren't any functions in this project\n\t- Run ${uiCommandReference('hs project logs --help')} to learn more about logs\n\t- ${uiLink('Visit developer docs', 'https://developers.hubspot.com/docs/platform/serverless-functions')} to learn more about serverless functions`,
|
|
1702
1757
|
noFunctionWithName: (name) => `No function with name "${name}"`,
|
|
1758
|
+
functionNameRequired: `A function name is required. Pass ${uiCommandReference('--function=<name>')} or run without it to select one interactively.`,
|
|
1703
1759
|
functionNotDeployed: (name) => `The function with name "${name}" is not deployed`,
|
|
1704
1760
|
projectLogsManagerNotInitialized: 'Function called on ProjectLogsManager before initialization',
|
|
1705
1761
|
noDeployedBuild: 'This project has not been deployed yet. Deploy the project first, then try again.',
|
|
@@ -1745,6 +1801,7 @@ export const commands = {
|
|
|
1745
1801
|
examples: {
|
|
1746
1802
|
default: 'Upload a project into your HubSpot account',
|
|
1747
1803
|
withProfile: 'Upload a project into your HubSpot account when using profiles',
|
|
1804
|
+
withPreview: 'Upload and preview the build on a target portal',
|
|
1748
1805
|
},
|
|
1749
1806
|
logs: {
|
|
1750
1807
|
buildSucceeded: (buildId) => `Build #${buildId} succeeded\n`,
|
|
@@ -1766,6 +1823,12 @@ export const commands = {
|
|
|
1766
1823
|
profile: {
|
|
1767
1824
|
describe: 'Profile to target for this upload',
|
|
1768
1825
|
},
|
|
1826
|
+
preview: {
|
|
1827
|
+
describe: 'Preview the build on a target portal after a successful upload',
|
|
1828
|
+
},
|
|
1829
|
+
target: {
|
|
1830
|
+
describe: 'Portal ID to preview the build on',
|
|
1831
|
+
},
|
|
1769
1832
|
},
|
|
1770
1833
|
},
|
|
1771
1834
|
watch: {
|
|
@@ -1899,6 +1962,13 @@ export const commands = {
|
|
|
1899
1962
|
},
|
|
1900
1963
|
createEslintConfigPrompt: (directories) => `ESLint configuration file not found in the following ${directories.length === 1 ? 'directory' : 'directories'}:\n${directories.map(d => ` - ${d}`).join('\n')}\n\nWould you like to set up the required ESLint configuration?`,
|
|
1901
1964
|
eslintConfigCreated: (configPath) => `ESLint configuration created at ${configPath}`,
|
|
1965
|
+
createEslintConfigRequiresV2Platform: (platformVersion) => {
|
|
1966
|
+
if (!platformVersion) {
|
|
1967
|
+
return 'Automatic ESLint configuration requires a Developer Platform project (2025.2 or later) with platformVersion set in hsproject.json. Add an eslint.config.js file manually, or set platformVersion and try again.';
|
|
1968
|
+
}
|
|
1969
|
+
return `Automatic ESLint configuration is not available for platform version ${platformVersion}. Use Developer Platform 2025.2 or later, or add eslint.config.js manually.`;
|
|
1970
|
+
},
|
|
1971
|
+
failedToFetchRemoteEslintConfig: (platformVersion) => `Could not download the ESLint config from HubSpot project components for platform version ${platformVersion}. Check your network connection and try again, or add eslint.config.js manually.`,
|
|
1902
1972
|
failedToCreateEslintConfig: (configPath) => `Failed to create ESLint configuration at ${configPath}`,
|
|
1903
1973
|
eslintConfigRequired: 'ESLint configuration is required to run the lint command. Run the command again to create the configuration.',
|
|
1904
1974
|
},
|
|
@@ -2029,6 +2099,25 @@ export const commands = {
|
|
|
2029
2099
|
force: 'skip confirmation prompt',
|
|
2030
2100
|
},
|
|
2031
2101
|
},
|
|
2102
|
+
installStatus: {
|
|
2103
|
+
describe: 'Check whether a static auth app in the current project is installed in the target account. This command must be run from within a HubSpot project directory.',
|
|
2104
|
+
examples: {
|
|
2105
|
+
default: 'Check install status for the static auth app in the current project',
|
|
2106
|
+
json: 'Output install status as JSON',
|
|
2107
|
+
},
|
|
2108
|
+
errors: {
|
|
2109
|
+
noProjectConfig: `No project config found. Run this command from within a HubSpot project directory, or use ${uiCommandReference('hs project create')} to create a new one.`,
|
|
2110
|
+
unsupportedPlatformVersion: (platformVersion) => `This command is only supported for projects on platform version 2025.2 or later (detected: ${platformVersion}).`,
|
|
2111
|
+
failedToParseProject: 'Failed to parse the project. Check your project configuration is valid and try again.',
|
|
2112
|
+
noAppInProject: 'No app was found in the local project. Install status is only available for projects that contain an app.',
|
|
2113
|
+
unsupportedAuthType: (authType) => `This command only supports static auth apps. Detected auth type: ${authType}.`,
|
|
2114
|
+
},
|
|
2115
|
+
success: {
|
|
2116
|
+
installed: (appName, accountId) => `${chalk.bold(appName)} is installed in ${uiAccountDescription(accountId)}.`,
|
|
2117
|
+
installedWithOutdatedScopes: (appName, accountId) => `${chalk.bold(appName)} is installed in ${uiAccountDescription(accountId)} with outdated scopes. Reinstall the app to grant the latest scopes.`,
|
|
2118
|
+
},
|
|
2119
|
+
notInstalled: (appName, accountId) => `${chalk.bold(appName)} is not installed in ${uiAccountDescription(accountId)}.`,
|
|
2120
|
+
},
|
|
2032
2121
|
},
|
|
2033
2122
|
sandbox: {
|
|
2034
2123
|
describe: 'Commands for managing sandboxes.',
|
|
@@ -2324,7 +2413,7 @@ export const commands = {
|
|
|
2324
2413
|
configPathPrompt: '[--config-path] Enter the path to the test account config: ',
|
|
2325
2414
|
createTestAccountFromConfigPrompt: 'How would you like to create your test account?',
|
|
2326
2415
|
createFromConfigOption: 'Create test account from config file',
|
|
2327
|
-
createFromScratchOption: '
|
|
2416
|
+
createFromScratchOption: 'Select hub tiers manually',
|
|
2328
2417
|
errors: {
|
|
2329
2418
|
configFileNotFound: (configPath) => `No test account config file exists at ${configPath}. Create a test account config file with the ${uiCommandReference('hs test-account create-config')} command.`,
|
|
2330
2419
|
configFileParseFailed: (configPath) => `Failed to parse test account config file at ${configPath}`,
|
|
@@ -3310,6 +3399,16 @@ export const lib = {
|
|
|
3310
3399
|
updatedFileDependency: (packageName, relativePath) => ` Updated dependencies.${packageName}: file:${relativePath}`,
|
|
3311
3400
|
},
|
|
3312
3401
|
},
|
|
3402
|
+
projectPreview: {
|
|
3403
|
+
triggeringPreview: (buildId, targetPortalId) => `Previewing build #${buildId} on portal ${targetPortalId}`,
|
|
3404
|
+
pollingStatus: (releaseTag, targetPortalId) => `Previewing ${releaseTag} on portal ${targetPortalId}`,
|
|
3405
|
+
succeeded: (releaseTag, targetPortalId) => `Previewed ${releaseTag} on portal ${targetPortalId}`,
|
|
3406
|
+
triggerFailed: 'Failed to trigger preview',
|
|
3407
|
+
pollFailed: 'Failed to poll preview status',
|
|
3408
|
+
timeout: 'Preview timed out after 5 minutes',
|
|
3409
|
+
warning: 'The build succeeded but the preview failed. You can manually preview this build from the project UI.',
|
|
3410
|
+
missingProjectId: 'Unable to preview: could not resolve the project ID.',
|
|
3411
|
+
},
|
|
3313
3412
|
importData: {
|
|
3314
3413
|
errors: {
|
|
3315
3414
|
incorrectAccountType: (derivedAccountId) => `The account ${uiAccountDescription(derivedAccountId)} is not a standard account, developer test account, or app developer account.`,
|
|
@@ -4056,6 +4155,7 @@ export const lib = {
|
|
|
4056
4155
|
migrate: {
|
|
4057
4156
|
componentsToBeMigrated: (components) => `${chalk.bold('The following features will be migrated:')} ${components}`,
|
|
4058
4157
|
componentsThatWillNotBeMigrated: (components) => `[NOTE] These features are not yet supported for migration but will be available later: ${components}`,
|
|
4158
|
+
legacyCrmCardMigrationDocs: () => `For more information on migrating legacy-crm-card components, follow ${uiLink('these docs', 'https://developers.hubspot.com/docs/apps/developer-platform/build-apps/migrate-an-app/migrate-legacy-crm-cards-to-app-cards')}`,
|
|
4059
4159
|
sourceContentsMoved: (newLocation) => `The contents of your old source directory have been moved to ${newLocation}, move any required files to the new source directory.`,
|
|
4060
4160
|
projectMigrationWarningTitle: (platformVersion) => `Important: Migrating to platformVersion ${platformVersion} is irreversible`,
|
|
4061
4161
|
projectMigrationWarning: (platformVersion) => uiBetaTag(`Running the ${uiCommandReference('hs project migrate')} command will permanently upgrade your project to platformVersion ${platformVersion}. This action cannot be undone. To ensure you have access to your original files, they will be copied to a new directory (archive) for safekeeping.\n\nThis command will guide you through the process, prompting you to enter the required fields and will download the new project source code into your project source directory.`, false),
|
|
@@ -4070,7 +4170,7 @@ export const lib = {
|
|
|
4070
4170
|
doesNotExist: (account) => `Project does not exist in ${uiAccountDescription(account)}. Migrations are only supported for existing projects.`,
|
|
4071
4171
|
themesAlreadyMigrated: 'This project has already been migrated to the latest platform version.',
|
|
4072
4172
|
noProjectForThemesMigration: 'Theme migrations are only supported for projects. Please try again from a project directory.',
|
|
4073
|
-
themesAndAppsNotAllowed: '
|
|
4173
|
+
themesAndAppsNotAllowed: 'Projects containing both themes and apps cannot be migrated together. To migrate, split the project into separate theme-only and app-only projects, then run migrate on each individually.',
|
|
4074
4174
|
multipleApps: 'Multiple apps found in project, this is not allowed in 2025.2',
|
|
4075
4175
|
alreadyExists: (projectName) => `A project with name ${projectName} already exists. Please choose another name.`,
|
|
4076
4176
|
failedToMigrateThemes: 'Failed to migrate project themes. Please verify that your themes are properly formatted before trying again.',
|
package/lib/app/migrate.js
CHANGED
|
@@ -124,8 +124,13 @@ export async function selectAppToMigrate(allApps, derivedAccountId, appId) {
|
|
|
124
124
|
const selectedApp = allApps.find(app => app.appId === appIdToMigrate);
|
|
125
125
|
const migratableComponents = new Set();
|
|
126
126
|
const unmigratableComponents = new Set();
|
|
127
|
+
let hasLegacyCrmCards = false;
|
|
127
128
|
selectedApp?.migrationComponents.forEach(component => {
|
|
128
129
|
const userFacingComponentType = mapToUserFacingType(component.componentType);
|
|
130
|
+
if (component.componentType === 'LEGACY_CRM_CARD' &&
|
|
131
|
+
!component.isSupported) {
|
|
132
|
+
hasLegacyCrmCards = true;
|
|
133
|
+
}
|
|
129
134
|
const shouldDisplayComponent = !AUTO_GENERATED_COMPONENT_TYPES.includes(userFacingComponentType);
|
|
130
135
|
if (shouldDisplayComponent) {
|
|
131
136
|
if (component.isSupported) {
|
|
@@ -142,6 +147,9 @@ export async function selectAppToMigrate(allApps, derivedAccountId, appId) {
|
|
|
142
147
|
if (unmigratableComponents.size !== 0) {
|
|
143
148
|
uiLogger.log(lib.migrate.componentsThatWillNotBeMigrated(`\n - ${[...unmigratableComponents].join('\n - ')}`));
|
|
144
149
|
}
|
|
150
|
+
if (hasLegacyCrmCards) {
|
|
151
|
+
uiLogger.info(lib.migrate.legacyCrmCardMigrationDocs());
|
|
152
|
+
}
|
|
145
153
|
uiLogger.log('');
|
|
146
154
|
const proceed = await confirmPrompt(lib.migrate.prompt.proceed, {
|
|
147
155
|
defaultAnswer: false,
|
package/lib/doctor/Doctor.js
CHANGED
|
@@ -26,7 +26,7 @@ import { isServerRunningAtUrl } from '../http.js';
|
|
|
26
26
|
import { WEBHOOKS_KEY, APP_KEY } from '@hubspot/project-parsing-lib/constants';
|
|
27
27
|
import { validateProjectConfig } from '../projects/config.js';
|
|
28
28
|
import { validateSourceDirectory, handleTranslate, } from '../projects/upload.js';
|
|
29
|
-
import {
|
|
29
|
+
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
30
30
|
import { validateProjectForProfile } from '../projects/projectProfiles.js';
|
|
31
31
|
import { getAllHsProfiles } from '@hubspot/project-parsing-lib/profiles';
|
|
32
32
|
const minMajorNodeVersion = 20;
|
|
@@ -534,7 +534,7 @@ export class Doctor {
|
|
|
534
534
|
if (!this.validateProjectConfigWrapper(projectConfig, projectDir)) {
|
|
535
535
|
return;
|
|
536
536
|
}
|
|
537
|
-
if (
|
|
537
|
+
if (isLegacyProject(projectConfig.platformVersion)) {
|
|
538
538
|
this.diagnosis?.addProjectSection({
|
|
539
539
|
type: 'success',
|
|
540
540
|
message: lib.doctor.projectValidation.valid,
|
|
@@ -13,7 +13,7 @@ import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
|
|
|
13
13
|
import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_CONFIG_FILE, } from '../lib/constants.js';
|
|
14
14
|
import { ProjectNestingError, ProjectConfigNotFoundError, ProjectValidationError, ProjectUploadError, ProjectBuildDeployError, } from './errors/ProjectErrors.js';
|
|
15
15
|
import { getProjectConfig, validateProjectConfig, writeProjectConfig, } from '../lib/projects/config.js';
|
|
16
|
-
import {
|
|
16
|
+
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
17
17
|
import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
|
|
18
18
|
import { handleProjectUpload } from '../lib/projects/upload.js';
|
|
19
19
|
import { validateProjectDirectory } from '../lib/prompts/projectNameAndDestPrompt.js';
|
|
@@ -109,7 +109,7 @@ export async function uploadAndDeployAction({ accountId, projectDest, }) {
|
|
|
109
109
|
uploadMessage: commands.getStarted.logs.initialUploadMessage,
|
|
110
110
|
forceCreate: true,
|
|
111
111
|
isUploadCommand: false,
|
|
112
|
-
sendIR:
|
|
112
|
+
sendIR: !isLegacyProject(projectConfig.platformVersion),
|
|
113
113
|
skipValidation: false,
|
|
114
114
|
});
|
|
115
115
|
if (uploadError) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface AccountRow {
|
|
2
|
+
name: string;
|
|
3
|
+
accountId: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function buildAccountRow(accountId: number, isDefault: boolean): AccountRow;
|
|
6
|
+
export declare function buildAccountHeader(nameColumnWidth: number): string;
|
|
7
|
+
export declare function getNameColumnWidth(rows: AccountRow[]): number;
|
|
8
|
+
export declare function sortDefaultFirst<T extends number | {
|
|
9
|
+
accountId: number;
|
|
10
|
+
}>(items: T[], defaultAccount: number | undefined): T[];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { HUBSPOT_ACCOUNT_TYPE_STRINGS } from '@hubspot/local-dev-lib/constants/config';
|
|
2
|
+
import { getConfigAccountIfExists } from '@hubspot/local-dev-lib/config';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { commands } from '../../lang/en.js';
|
|
5
|
+
import { indent } from '../ui/index.js';
|
|
6
|
+
import { INK_COLORS } from '../../ui/styles.js';
|
|
7
|
+
export function buildAccountRow(accountId, isDefault) {
|
|
8
|
+
const account = getConfigAccountIfExists(accountId);
|
|
9
|
+
let name = String(accountId);
|
|
10
|
+
if (account && account.accountType) {
|
|
11
|
+
const typeStr = HUBSPOT_ACCOUNT_TYPE_STRINGS[account.accountType];
|
|
12
|
+
name = `${account.name} [${typeStr}]`;
|
|
13
|
+
}
|
|
14
|
+
if (isDefault) {
|
|
15
|
+
name = `${name} (default)`;
|
|
16
|
+
}
|
|
17
|
+
return { name, accountId: String(accountId) };
|
|
18
|
+
}
|
|
19
|
+
export function buildAccountHeader(nameColumnWidth) {
|
|
20
|
+
const labels = commands.account.subcommands.list.labels;
|
|
21
|
+
const paddedName = chalk.bold(chalk.hex(INK_COLORS.INFO_BLUE)(labels.name.padEnd(nameColumnWidth)));
|
|
22
|
+
const accountId = chalk.bold(chalk.hex(INK_COLORS.INFO_BLUE)(labels.accountId));
|
|
23
|
+
return `${indent(1)}${paddedName} ${accountId}`;
|
|
24
|
+
}
|
|
25
|
+
export function getNameColumnWidth(rows) {
|
|
26
|
+
const labels = commands.account.subcommands.list.labels;
|
|
27
|
+
return Math.max(labels.name.length, ...rows.map(r => r.name.length));
|
|
28
|
+
}
|
|
29
|
+
export function sortDefaultFirst(items, defaultAccount) {
|
|
30
|
+
return [...items].sort((a, b) => {
|
|
31
|
+
const aId = typeof a === 'number' ? a : a.accountId;
|
|
32
|
+
const bId = typeof b === 'number' ? b : b.accountId;
|
|
33
|
+
if (aId === defaultAccount)
|
|
34
|
+
return -1;
|
|
35
|
+
if (bId === defaultAccount)
|
|
36
|
+
return 1;
|
|
37
|
+
return 0;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { HsSettingsFile } from '@hubspot/local-dev-lib/types/HsSettings';
|
|
2
|
+
import { ActionHandlerParams, ActionResult, LinkArgs } from '../../types/Link.js';
|
|
3
|
+
import { ArgumentsCamelCase } from 'yargs';
|
|
4
|
+
export declare class ActionHandlers {
|
|
5
|
+
static link({ state, context, }: ActionHandlerParams): Promise<ActionResult>;
|
|
6
|
+
static unlink({ state }: ActionHandlerParams): Promise<ActionResult>;
|
|
7
|
+
static authenticate({ state, context, args, }: ActionHandlerParams): Promise<ActionResult>;
|
|
8
|
+
static cancel(): Promise<ActionResult>;
|
|
9
|
+
}
|
|
10
|
+
export declare function handleLinkFlow({ settings, accountOverrideId, args, }: {
|
|
11
|
+
settings: HsSettingsFile;
|
|
12
|
+
accountOverrideId: number | null;
|
|
13
|
+
args: ArgumentsCamelCase<LinkArgs>;
|
|
14
|
+
}): Promise<ActionResult>;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { getAllConfigAccounts, getConfigDefaultAccountIfExists, } from '@hubspot/local-dev-lib/config';
|
|
2
|
+
import { confirmPrompt } from '../prompts/promptUtils.js';
|
|
3
|
+
import { promptForAccountsToLink, promptForAccountsToUnlink, promptForAction, promptForDefaultAccount, } from './prompts.js';
|
|
4
|
+
import { getDefaultAccountOverrideFilePath, removeDefaultAccountOverrideFile, } from '@hubspot/local-dev-lib/config/defaultAccountOverride';
|
|
5
|
+
import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
|
|
6
|
+
import { authenticateNewAccount } from '../accountAuth.js';
|
|
7
|
+
import { commands } from '../../lang/en.js';
|
|
8
|
+
import { uiLogger } from '../ui/logger.js';
|
|
9
|
+
export class ActionHandlers {
|
|
10
|
+
static async link({ state, context, }) {
|
|
11
|
+
const { eligibleAccounts, inEligibleAccounts } = context.globalAccountsList.reduce((accumulator, account) => {
|
|
12
|
+
if (state.accounts.includes(account.accountId)) {
|
|
13
|
+
accumulator.inEligibleAccounts.push(account);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
accumulator.eligibleAccounts.push(account);
|
|
17
|
+
}
|
|
18
|
+
return accumulator;
|
|
19
|
+
}, { eligibleAccounts: [], inEligibleAccounts: [] });
|
|
20
|
+
const toAdd = await promptForAccountsToLink(context, eligibleAccounts, inEligibleAccounts, state.localDefaultAccount);
|
|
21
|
+
const accounts = [...state.accounts, ...toAdd];
|
|
22
|
+
uiLogger.success(commands.account.subcommands.link.events.accountsLinked(toAdd.length));
|
|
23
|
+
const overrideFilePath = getDefaultAccountOverrideFilePath();
|
|
24
|
+
if (overrideFilePath &&
|
|
25
|
+
context.accountOverrideId &&
|
|
26
|
+
accounts.includes(context.accountOverrideId)) {
|
|
27
|
+
uiLogger.log(commands.account.subcommands.link.events.overrideAccountDetected(context.accountOverrideId));
|
|
28
|
+
uiLogger.log('');
|
|
29
|
+
const useOverride = await confirmPrompt(commands.account.subcommands.link.prompts.keepAsDefault);
|
|
30
|
+
removeDefaultAccountOverrideFile();
|
|
31
|
+
uiLogger.success(commands.account.subcommands.link.events.overrideFileRemoved);
|
|
32
|
+
if (useOverride) {
|
|
33
|
+
uiLogger.success(commands.account.subcommands.link.events.defaultAccountSet(context.accountOverrideId));
|
|
34
|
+
return {
|
|
35
|
+
status: 'success',
|
|
36
|
+
settings: {
|
|
37
|
+
accounts,
|
|
38
|
+
localDefaultAccount: context.accountOverrideId,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const localDefaultAccount = await resolveDefaultAccount({
|
|
44
|
+
accounts,
|
|
45
|
+
currentDefault: state.localDefaultAccount,
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
status: 'success',
|
|
49
|
+
settings: { accounts, localDefaultAccount },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
static async unlink({ state }) {
|
|
53
|
+
const toRemove = await promptForAccountsToUnlink(state.accounts, state.localDefaultAccount);
|
|
54
|
+
if (toRemove.length === 0) {
|
|
55
|
+
return { status: 'noop' };
|
|
56
|
+
}
|
|
57
|
+
const remainingAccounts = state.accounts.filter(account => !toRemove.includes(account));
|
|
58
|
+
const defaultWasRemoved = state.localDefaultAccount !== undefined &&
|
|
59
|
+
toRemove.includes(state.localDefaultAccount);
|
|
60
|
+
// All accounts removed
|
|
61
|
+
if (remainingAccounts.length === 0) {
|
|
62
|
+
uiLogger.success(commands.account.subcommands.link.events.noAccountsLinked);
|
|
63
|
+
return {
|
|
64
|
+
status: 'success',
|
|
65
|
+
settings: {
|
|
66
|
+
accounts: remainingAccounts,
|
|
67
|
+
localDefaultAccount: undefined,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// Default was NOT removed — accounts remain, default unchanged
|
|
72
|
+
if (!defaultWasRemoved) {
|
|
73
|
+
uiLogger.success(commands.account.subcommands.link.events.accountsUnlinked(toRemove.length));
|
|
74
|
+
uiLogger.success(commands.account.subcommands.link.events.defaultAccountRemains(state.localDefaultAccount));
|
|
75
|
+
return {
|
|
76
|
+
status: 'success',
|
|
77
|
+
settings: {
|
|
78
|
+
accounts: remainingAccounts,
|
|
79
|
+
localDefaultAccount: state.localDefaultAccount,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// Default WAS removed — need a new default
|
|
84
|
+
uiLogger.warn(commands.account.subcommands.link.events.defaultAccountRemoved(remainingAccounts.length !== 1));
|
|
85
|
+
const localDefaultAccount = await resolveDefaultAccount({
|
|
86
|
+
accounts: remainingAccounts,
|
|
87
|
+
currentDefault: undefined,
|
|
88
|
+
});
|
|
89
|
+
if (remainingAccounts.length === 1) {
|
|
90
|
+
uiLogger.success(commands.account.subcommands.link.events.updatedLinkedAccounts);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
status: 'success',
|
|
94
|
+
settings: { accounts: remainingAccounts, localDefaultAccount },
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
static async authenticate({ state, context, args, }) {
|
|
98
|
+
const updatedConfig = await authenticateNewAccount({
|
|
99
|
+
env: args.qa ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD,
|
|
100
|
+
setAsDefaultAccount: false,
|
|
101
|
+
});
|
|
102
|
+
if (!updatedConfig) {
|
|
103
|
+
return {
|
|
104
|
+
status: 'error',
|
|
105
|
+
reason: commands.account.subcommands.link.errors.authFailed,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const updatedContext = {
|
|
109
|
+
globalAccountsList: getAllConfigAccounts(),
|
|
110
|
+
globalDefaultAccount: getConfigDefaultAccountIfExists(),
|
|
111
|
+
accountOverrideId: context.accountOverrideId,
|
|
112
|
+
preselectedAccountId: updatedConfig.accountId,
|
|
113
|
+
};
|
|
114
|
+
return ActionHandlers.link({ state, context: updatedContext, args });
|
|
115
|
+
}
|
|
116
|
+
static async cancel() {
|
|
117
|
+
return {
|
|
118
|
+
status: 'noop',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export async function handleLinkFlow({ settings, accountOverrideId, args, }) {
|
|
123
|
+
const context = {
|
|
124
|
+
globalAccountsList: getAllConfigAccounts(),
|
|
125
|
+
globalDefaultAccount: getConfigDefaultAccountIfExists(),
|
|
126
|
+
accountOverrideId,
|
|
127
|
+
};
|
|
128
|
+
const accounts = settings.accounts ?? [];
|
|
129
|
+
// The default account must be one of the linked accounts. This can get
|
|
130
|
+
// out of sync if the settings file is manually edited.
|
|
131
|
+
const hasInvalidDefault = settings.localDefaultAccount !== undefined &&
|
|
132
|
+
!accounts.includes(settings.localDefaultAccount);
|
|
133
|
+
if (hasInvalidDefault) {
|
|
134
|
+
uiLogger.warn(commands.account.subcommands.link.events.invalidDefaultAccount(settings.localDefaultAccount));
|
|
135
|
+
}
|
|
136
|
+
const initialState = {
|
|
137
|
+
localDefaultAccount: hasInvalidDefault
|
|
138
|
+
? undefined
|
|
139
|
+
: settings.localDefaultAccount,
|
|
140
|
+
accounts,
|
|
141
|
+
};
|
|
142
|
+
return runAction(initialState, context, args);
|
|
143
|
+
}
|
|
144
|
+
async function runAction(state, context, args) {
|
|
145
|
+
const action = await promptForAction(state);
|
|
146
|
+
return ActionHandlers[action]({ state, context, args });
|
|
147
|
+
}
|
|
148
|
+
async function resolveDefaultAccount({ accounts, currentDefault, prompt = '', }) {
|
|
149
|
+
if (accounts.length === 1) {
|
|
150
|
+
uiLogger.success(commands.account.subcommands.link.events.defaultAccountSet(accounts[0]));
|
|
151
|
+
return accounts[0];
|
|
152
|
+
}
|
|
153
|
+
return promptForDefaultAccount(accounts, currentDefault, prompt);
|
|
154
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { HsSettingsFile } from '@hubspot/local-dev-lib/types/HsSettings';
|
|
2
|
+
export declare function isDirectoryLinked(settings: HsSettingsFile | null): settings is HsSettingsFile;
|
|
3
|
+
export declare function hasDeprecatedConfigConflict(commandArgs: (string | number)[]): boolean;
|
|
4
|
+
export declare function writeLinkedSettings(settings: HsSettingsFile, settingsPath: string): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { localConfigFileExists } from '@hubspot/local-dev-lib/config';
|
|
2
|
+
import { writeHsSettingsFile } from '@hubspot/local-dev-lib/config/hsSettings';
|
|
3
|
+
import { uiLogger } from '../ui/logger.js';
|
|
4
|
+
import { commands } from '../../lang/en.js';
|
|
5
|
+
export function isDirectoryLinked(settings) {
|
|
6
|
+
return settings !== null && settings.accounts.length > 0;
|
|
7
|
+
}
|
|
8
|
+
export function hasDeprecatedConfigConflict(commandArgs) {
|
|
9
|
+
if (localConfigFileExists()) {
|
|
10
|
+
uiLogger.error(commands.account.subcommands.link.shared.deprecatedConfigNotSupported(`hs ${commandArgs.join(' ')}`));
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
export function writeLinkedSettings(settings, settingsPath) {
|
|
16
|
+
try {
|
|
17
|
+
writeHsSettingsFile(settings);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
uiLogger.error(commands.account.subcommands.link.shared.writeSettingsFailed(settingsPath, err));
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HubSpotConfigAccount } from '@hubspot/local-dev-lib/types/Accounts';
|
|
2
|
+
import { ActionName, LinkContext } from '../../types/Link.js';
|
|
3
|
+
import { HsSettingsFile } from '@hubspot/local-dev-lib/types/HsSettings';
|
|
4
|
+
export declare function promptForAction(state: HsSettingsFile): Promise<ActionName>;
|
|
5
|
+
export declare function promptForDefaultAccount(accounts: number[], currentDefaultAccount: number | undefined, prompt?: string): Promise<number>;
|
|
6
|
+
export declare function promptForAccountsToLink(context: LinkContext, eligibleAccounts: HubSpotConfigAccount[], inEligibleAccounts: HubSpotConfigAccount[], localDefaultAccount: number | undefined): Promise<number[]>;
|
|
7
|
+
export declare function promptForAccountsToUnlink(accounts: number[], localDefaultAccount: number | undefined): Promise<number[]>;
|