@hubspot/cli 7.7.35-experimental.0 → 7.8.0-beta.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 +31 -25
- package/commands/__tests__/auth.test.js +5 -0
- package/commands/__tests__/doctor.test.js +16 -16
- package/commands/__tests__/getStarted.test.js +2 -2
- package/commands/__tests__/mcp.test.js +1 -1
- package/commands/__tests__/project.test.js +2 -3
- package/commands/account/auth.js +1 -0
- package/commands/account/clean.js +18 -27
- package/commands/account/createOverride.js +13 -31
- package/commands/account/info.js +20 -31
- package/commands/account/list.js +16 -22
- package/commands/account/remove.js +12 -20
- package/commands/account/removeOverride.js +11 -21
- package/commands/account/rename.js +6 -9
- package/commands/account/use.js +12 -26
- package/commands/account.js +2 -2
- package/commands/app/__tests__/migrate.test.js +5 -6
- package/commands/app/migrate.js +13 -19
- package/commands/app/secret/add.js +2 -1
- package/commands/app/secret/delete.js +2 -1
- package/commands/app/secret/list.js +2 -1
- package/commands/app/secret/update.js +2 -1
- package/commands/app/secret.js +2 -1
- package/commands/app.js +2 -2
- package/commands/auth.d.ts +1 -0
- package/commands/auth.js +17 -7
- package/commands/cms/convertFields.js +7 -9
- package/commands/cms/getReactModule.js +9 -14
- package/commands/cms/lighthouseScore.js +33 -36
- package/commands/cms.js +2 -2
- package/commands/completion.js +3 -3
- package/commands/config/set.d.ts +1 -1
- package/commands/config/set.js +64 -37
- package/commands/config.js +2 -2
- package/commands/create.js +2 -2
- package/commands/customObject/create.js +10 -12
- package/commands/customObject/schema/create.js +9 -11
- package/commands/customObject/schema/delete.js +16 -16
- package/commands/customObject/schema/fetch-all.js +12 -11
- package/commands/customObject/schema/fetch.js +15 -15
- package/commands/customObject/schema/list.js +4 -4
- package/commands/customObject/schema/update.js +13 -13
- package/commands/customObject/schema.js +2 -2
- package/commands/customObject.js +6 -7
- package/commands/doctor.js +8 -11
- package/commands/feedback.js +8 -13
- package/commands/fetch.js +8 -8
- package/commands/filemanager/fetch.js +7 -7
- package/commands/filemanager/upload.js +15 -34
- package/commands/filemanager.js +2 -2
- package/commands/function/deploy.js +11 -29
- package/commands/function/list.js +8 -8
- package/commands/function/server.js +9 -11
- package/commands/function.d.ts +1 -1
- package/commands/function.js +2 -2
- package/commands/getStarted.d.ts +0 -2
- package/commands/getStarted.js +4 -4
- package/commands/hubdb/clear.js +7 -15
- package/commands/hubdb/create.js +9 -15
- package/commands/hubdb/delete.js +8 -15
- package/commands/hubdb/fetch.js +6 -9
- package/commands/hubdb.d.ts +1 -1
- package/commands/hubdb.js +2 -2
- package/commands/init.js +2 -3
- package/commands/lint.js +16 -16
- package/commands/list.js +8 -14
- package/commands/logs.js +14 -20
- package/commands/mcp/__tests__/setup.test.js +2 -2
- package/commands/mcp/setup.js +11 -2
- package/commands/mcp.js +3 -3
- package/commands/mv.js +6 -17
- package/commands/open.js +5 -5
- package/commands/project/__tests__/add.test.js +15 -13
- package/commands/project/__tests__/create.test.js +6 -6
- package/commands/project/__tests__/deploy.test.js +3 -7
- package/commands/project/__tests__/devUnifiedFlow.test.js +2 -4
- package/commands/project/__tests__/installDeps.test.js +8 -8
- package/commands/project/__tests__/list.test.js +31 -0
- package/commands/project/__tests__/logs.test.js +1 -4
- package/commands/project/__tests__/migrate.test.js +7 -7
- package/commands/project/__tests__/migrateApp.test.js +3 -7
- package/commands/project/__tests__/profile.test.js +1 -1
- package/commands/project/__tests__/validate.test.js +98 -0
- package/commands/project/add.d.ts +2 -2
- package/commands/project/add.js +7 -10
- package/commands/project/cloneApp.js +14 -19
- package/commands/project/create.js +3 -10
- package/commands/project/deploy.js +5 -5
- package/commands/project/dev/deprecatedFlow.js +9 -18
- package/commands/project/dev/index.js +21 -18
- package/commands/project/dev/unifiedFlow.js +14 -7
- package/commands/project/download.js +15 -16
- package/commands/project/installDeps.d.ts +2 -2
- package/commands/project/installDeps.js +9 -9
- package/commands/project/list.d.ts +4 -0
- package/commands/project/list.js +62 -0
- package/commands/project/listBuilds.js +12 -21
- package/commands/project/logs.js +21 -24
- package/commands/project/migrate.js +46 -15
- package/commands/project/migrateApp.js +10 -17
- package/commands/project/open.js +6 -14
- package/commands/project/profile/add.js +3 -3
- package/commands/project/profile/delete.js +1 -2
- package/commands/project/profile.js +2 -3
- package/commands/project/upload.js +16 -25
- package/commands/project/validate.js +7 -7
- package/commands/project/watch.js +13 -22
- package/commands/project.js +4 -3
- package/commands/sandbox/__tests__/create.test.js +5 -5
- package/commands/sandbox/create.js +22 -32
- package/commands/sandbox/delete.js +39 -64
- package/commands/sandbox.js +2 -2
- package/commands/secret/addSecret.js +7 -17
- package/commands/secret/deleteSecret.js +10 -20
- package/commands/secret/listSecret.js +8 -10
- package/commands/secret/updateSecret.js +9 -17
- package/commands/secret.js +2 -2
- package/commands/testAccount/__tests__/delete.test.js +2 -4
- package/commands/testAccount/create.js +2 -2
- package/commands/testAccount/delete.d.ts +4 -3
- package/commands/testAccount/delete.js +155 -14
- package/commands/testAccount/importData.d.ts +1 -1
- package/commands/testAccount/importData.js +1 -1
- package/commands/testAccount.js +1 -1
- package/commands/theme/preview.js +1 -4
- package/lang/en.d.ts +364 -110
- package/lang/en.js +409 -158
- package/lang/en.lyaml +4 -4
- package/lib/__tests__/buildAccount.test.js +4 -3
- package/lib/__tests__/commonOpts.test.js +1 -1
- package/lib/__tests__/dependencyManagement.test.js +1 -1
- package/lib/__tests__/developerTestAccounts.test.js +3 -3
- package/lib/__tests__/npm.test.js +1 -1
- package/lib/__tests__/oauth.test.js +4 -4
- package/lib/__tests__/process.test.js +10 -5
- package/lib/__tests__/sandboxSync.test.js +8 -8
- package/lib/__tests__/sandboxes.test.js +8 -8
- package/lib/__tests__/serverlessLogs.test.js +1 -1
- package/lib/__tests__/usageTracking.test.js +5 -5
- package/lib/__tests__/validation.test.js +2 -1
- package/lib/__tests__/yargsUtils.test.js +83 -9
- package/lib/app/__tests__/migrate.test.js +19 -56
- package/lib/app/__tests__/migrate_legacy.test.js +1 -1
- package/lib/app/migrate.d.ts +2 -8
- package/lib/app/migrate.js +6 -81
- package/lib/app/migrate_legacy.js +20 -24
- package/lib/buildAccount.d.ts +2 -2
- package/lib/buildAccount.js +32 -64
- package/lib/commonOpts.d.ts +1 -1
- package/lib/commonOpts.js +25 -22
- package/lib/configMigrate.js +88 -9
- package/lib/configOptions.js +7 -0
- package/lib/constants.d.ts +21 -1
- package/lib/constants.js +25 -1
- package/lib/dependencyManagement.js +9 -27
- package/lib/developerTestAccounts.js +9 -23
- package/lib/doctor/Diagnosis.js +11 -23
- package/lib/doctor/DiagnosticInfoBuilder.js +12 -11
- package/lib/doctor/Doctor.js +42 -90
- package/lib/doctor/__tests__/Doctor.test.js +4 -4
- package/lib/errorHandlers/index.js +12 -20
- package/lib/errorHandlers/suppressError.js +11 -18
- package/lib/lang.js +6 -5
- package/lib/links.d.ts +1 -0
- package/lib/links.js +14 -7
- package/lib/mcp/setup.js +1 -1
- package/lib/middleware/__test__/commandTargetingUtils.test.js +99 -0
- package/lib/middleware/__test__/configMiddleware.test.js +11 -11
- package/lib/middleware/__test__/yargsChecksMiddleware.test.js +6 -8
- package/lib/middleware/commandTargetingUtils.d.ts +8 -0
- package/lib/middleware/commandTargetingUtils.js +74 -0
- package/lib/middleware/configMiddleware.d.ts +1 -1
- package/lib/middleware/configMiddleware.js +21 -81
- package/lib/middleware/fireAlarmMiddleware.js +15 -5
- package/lib/middleware/gitMiddleware.js +5 -1
- package/lib/middleware/notificationsMiddleware.js +5 -11
- package/lib/middleware/yargsChecksMiddleware.js +6 -9
- package/lib/npm.js +2 -2
- package/lib/oauth.js +5 -5
- package/lib/process.js +5 -4
- package/lib/projects/__tests__/AppDevModeInterface.test.js +87 -90
- package/lib/projects/__tests__/LocalDevProcess.test.js +231 -19
- package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +89 -63
- package/lib/projects/__tests__/deploy.test.js +73 -8
- package/lib/projects/__tests__/localDevProjectHelpers.test.js +6 -2
- package/lib/projects/__tests__/platformVersion.test.js +8 -8
- package/lib/projects/__tests__/projects.test.js +12 -12
- package/lib/projects/__tests__/structure.test.js +3 -3
- package/lib/projects/__tests__/upload.test.d.ts +1 -0
- package/lib/projects/__tests__/upload.test.js +82 -0
- package/lib/projects/add/__tests__/legacyAddComponent.test.js +6 -6
- package/lib/projects/add/__tests__/v2AddComponent.test.d.ts +1 -0
- package/lib/projects/add/__tests__/{v3AddComponent.test.js → v2AddComponent.test.js} +39 -39
- package/lib/projects/add/{v3AddComponent.d.ts → v2AddComponent.d.ts} +1 -1
- package/lib/projects/add/{v3AddComponent.js → v2AddComponent.js} +5 -5
- package/lib/projects/create/__tests__/legacy.test.js +5 -5
- package/lib/projects/create/__tests__/v2.test.d.ts +1 -0
- package/lib/projects/create/__tests__/{v3.test.js → v2.test.js} +82 -7
- package/lib/projects/create/index.js +4 -4
- package/lib/projects/create/legacy.js +2 -2
- package/lib/projects/create/{v3.d.ts → v2.d.ts} +3 -3
- package/lib/projects/create/{v3.js → v2.js} +13 -11
- package/lib/projects/deploy.d.ts +1 -1
- package/lib/projects/deploy.js +2 -2
- package/lib/projects/localDev/AppDevModeInterface.d.ts +10 -1
- package/lib/projects/localDev/AppDevModeInterface.js +118 -89
- package/lib/projects/localDev/DevServerManager.d.ts +11 -29
- package/lib/projects/localDev/DevServerManager.js +19 -61
- package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +40 -0
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +120 -0
- package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
- package/lib/projects/localDev/LocalDevLogger.js +27 -6
- package/lib/projects/localDev/{LocalDevManager.js → LocalDevManager_DEPRECATED.js} +10 -11
- package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
- package/lib/projects/localDev/LocalDevProcess.js +93 -21
- package/lib/projects/localDev/LocalDevState.d.ts +12 -8
- package/lib/projects/localDev/LocalDevState.js +27 -17
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +6 -1
- package/lib/projects/localDev/LocalDevWebsocketServer.js +94 -33
- package/lib/projects/localDev/helpers/account.d.ts +1 -1
- package/lib/projects/localDev/helpers/account.js +2 -2
- package/lib/projects/localDev/helpers/project.d.ts +1 -0
- package/lib/projects/localDev/helpers/project.js +44 -4
- package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +7 -0
- package/lib/projects/localDev/localDevWebsocketServerUtils.js +19 -0
- package/lib/projects/platformVersion.d.ts +1 -1
- package/lib/projects/platformVersion.js +1 -1
- package/lib/projects/pollProjectBuildAndDeploy.js +4 -4
- package/lib/projects/structure.js +6 -6
- package/lib/projects/upload.d.ts +1 -1
- package/lib/projects/upload.js +17 -8
- package/lib/projects/urls.d.ts +0 -1
- package/lib/projects/urls.js +0 -3
- package/lib/prompts/__tests__/downloadProjectPrompt.test.js +1 -0
- package/lib/prompts/__tests__/projectAddPrompt.test.js +10 -10
- package/lib/prompts/accountNamePrompt.js +14 -19
- package/lib/prompts/accountsPrompt.js +2 -2
- package/lib/prompts/cmsFieldPrompt.js +2 -2
- package/lib/prompts/createApiSamplePrompt.js +5 -5
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +10 -1
- package/lib/prompts/createFunctionPrompt.js +14 -14
- package/lib/prompts/createModulePrompt.js +9 -9
- package/lib/prompts/createTemplatePrompt.js +2 -2
- package/lib/prompts/downloadProjectPrompt.js +5 -8
- package/lib/prompts/installAppPrompt.d.ts +1 -6
- package/lib/prompts/installAppPrompt.js +1 -6
- package/lib/prompts/personalAccessKeyPrompt.js +3 -3
- package/lib/prompts/previewPrompt.js +6 -6
- package/lib/prompts/projectAddPrompt.d.ts +2 -2
- package/lib/prompts/projectAddPrompt.js +9 -2
- package/lib/prompts/projectDevTargetAccountPrompt.js +20 -32
- package/lib/prompts/projectNamePrompt.js +4 -8
- package/lib/prompts/projectsLogsPrompt.js +2 -4
- package/lib/prompts/promptUtils.js +30 -9
- package/lib/prompts/sandboxesPrompt.js +7 -7
- package/lib/prompts/secretPrompt.js +3 -3
- package/lib/prompts/selectAppPrompt.js +3 -3
- package/lib/prompts/selectHubDBTablePrompt.js +9 -13
- package/lib/prompts/selectProjectTemplatePrompt.js +2 -0
- package/lib/prompts/selectPublicAppForMigrationPrompt.js +15 -19
- package/lib/prompts/setAsDefaultAccountPrompt.js +4 -8
- package/lib/prompts/uploadPrompt.js +5 -5
- package/lib/sandboxSync.js +24 -41
- package/lib/sandboxes.js +19 -47
- package/lib/schema.js +3 -3
- package/lib/serverlessLogs.js +11 -13
- package/lib/theme/__tests__/migrate.test.d.ts +1 -0
- package/lib/theme/__tests__/migrate.test.js +233 -0
- package/lib/theme/migrate.d.ts +13 -0
- package/lib/theme/migrate.js +90 -0
- package/lib/ui/SpinniesManager.d.ts +2 -0
- package/lib/ui/SpinniesManager.js +7 -0
- package/lib/ui/boxen.js +1 -2
- package/lib/ui/git.js +13 -10
- package/lib/ui/index.d.ts +4 -0
- package/lib/ui/index.js +47 -38
- package/lib/ui/serverlessFunctionLogs.js +9 -7
- package/lib/ui/uiMessages.d.ts +72 -0
- package/lib/ui/uiMessages.js +75 -0
- package/lib/usageTracking.js +8 -8
- package/lib/validation.js +20 -23
- package/lib/yargsUtils.d.ts +1 -1
- package/lib/yargsUtils.js +12 -5
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
- package/mcp-server/tools/index.js +4 -0
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
- package/mcp-server/tools/project/DocsSearchTool.js +5 -5
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +23 -0
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +68 -0
- package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +11 -0
- package/mcp-server/tools/project/GetApplicationInfoTool.js +49 -0
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +12 -6
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +2 -2
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +12 -10
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +169 -0
- package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +115 -0
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -7
- package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
- package/mcp-server/utils/cliConfig.d.ts +1 -0
- package/mcp-server/utils/cliConfig.js +12 -0
- package/mcp-server/utils/toolUsageTracking.js +2 -2
- package/package.json +8 -7
- package/types/LocalDev.d.ts +19 -3
- package/ui/index.js +1 -1
- package/lib/middleware/__test__/utils.test.js +0 -51
- package/lib/middleware/utils.d.ts +0 -8
- package/lib/middleware/utils.js +0 -14
- package/lib/projects/localDev/DevServerManagerV2.d.ts +0 -22
- package/lib/projects/localDev/DevServerManagerV2.js +0 -81
- /package/{lib/middleware/__test__/utils.test.d.ts → commands/project/__tests__/list.test.d.ts} +0 -0
- /package/{lib/projects/add/__tests__/v3AddComponent.test.d.ts → commands/project/__tests__/validate.test.d.ts} +0 -0
- /package/lib/{projects/create/__tests__/v3.test.d.ts → middleware/__test__/commandTargetingUtils.test.d.ts} +0 -0
- /package/lib/projects/localDev/{LocalDevManager.d.ts → LocalDevManager_DEPRECATED.d.ts} +0 -0
package/lang/en.lyaml
CHANGED
|
@@ -2,7 +2,7 @@ en:
|
|
|
2
2
|
commands:
|
|
3
3
|
generalErrors:
|
|
4
4
|
updateNotify:
|
|
5
|
-
notifyTitle: "
|
|
5
|
+
notifyTitle: "CLI update available"
|
|
6
6
|
cmsUpdateNotification: "{{#bold}}The CMS CLI is now the HubSpot CLI{{/bold}}\n\nTo upgrade, uninstall {{#bold}}{{ packageName }}{{/bold}}\nand then run {{ updateCommand }}"
|
|
7
7
|
cliUpdateNotification: "HubSpot CLI version {{#cyan}}{{#bold}}{currentVersion}{{/bold}}{{/cyan}} is outdated.\nRun {{ updateCommand }} to upgrade to version {{#cyan}}{{#bold}}{latestVersion}{{/bold}}{{/cyan}}"
|
|
8
8
|
srcIsProject: "\"{{ src }}\" is in a project folder. Did you mean \"hs project {{command}}\"?"
|
|
@@ -801,7 +801,7 @@ en:
|
|
|
801
801
|
uploadFailed: "Failed to upload file \"{{ filePath }}\" to \"{{ remotePath }}\""
|
|
802
802
|
deleteFileFailed: "Failed to delete file \"{{ remotePath }}\""
|
|
803
803
|
deleteFolderFailed: "Failed to delete folder \"{{ remotePath }}\""
|
|
804
|
-
|
|
804
|
+
v2ApiError: "{{ command }} is not supported for platform version '{{ platformVersion}}', use {{ newCommand }} instead to develop locally. {{ linkToDocs }}"
|
|
805
805
|
download:
|
|
806
806
|
describe: "Download your project files from HubSpot."
|
|
807
807
|
examples:
|
|
@@ -1162,7 +1162,7 @@ en:
|
|
|
1162
1162
|
createNewSandboxOption: "<Test on a new development sandbox>"
|
|
1163
1163
|
createNewDeveloperTestAccountOption: "<Test on a new developer test account>"
|
|
1164
1164
|
chooseDefaultAccountOption: "<{{#bold}}\U00002757{{/bold}} Test on this production account {{#bold}}\U00002757{{/bold}}>"
|
|
1165
|
-
promptMessage: "
|
|
1165
|
+
promptMessage: "Choose a {{ accountType }} under {{ accountIdentifier }} to test with:"
|
|
1166
1166
|
sandboxLimit: "Your account reached the limit of {{ limit }} development sandboxes"
|
|
1167
1167
|
sandboxLimitWithSuggestion: "Your account reached the limit of {{ limit }} development sandboxes. Run {{ authCommand }} to add an existing one to the config."
|
|
1168
1168
|
developerTestAccountLimit: "Your account reached the limit of {{ limit }} developer test accounts."
|
|
@@ -1348,7 +1348,7 @@ en:
|
|
|
1348
1348
|
succeed: "Created {{#bold}}{{ accountName }} [standard sandbox] ({{ accountId }}){{/bold}}."
|
|
1349
1349
|
failure:
|
|
1350
1350
|
invalidUser: "Couldn't create {{#bold}}{{ accountName }}{{/bold}} because your account has been removed from {{#bold}}{{ parentAccountName }}{{/bold}} or your permission set doesn't allow you to create the sandbox. To update your permissions, contact a super admin in {{#bold}}{{ parentAccountName }}{{/bold}}."
|
|
1351
|
-
403Gating: "
|
|
1351
|
+
403Gating: "We couldn't create {{#bold}}{{ accountName }}{{/bold}} because {{#bold}}{{ parentAccountName }}{{/bold}} is a developer account and does not have access to development sandboxes. To gain access to developer sandboxes, you can convert your account: https://developers.hubspot.com/docs/getting-started/convert-your-account-into-a-developer-crm-account"
|
|
1352
1352
|
usageLimitsFetch: "Unable to fetch sandbox usage limits. Please try again."
|
|
1353
1353
|
generic: "An error occurred while creating a new sandbox. Please try again."
|
|
1354
1354
|
limit:
|
|
@@ -10,7 +10,8 @@ vi.mock('@hubspot/local-dev-lib/personalAccessKey');
|
|
|
10
10
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
11
11
|
vi.mock('@hubspot/local-dev-lib/api/developerTestAccounts');
|
|
12
12
|
vi.mock('@hubspot/local-dev-lib/api/sandboxHubs');
|
|
13
|
-
vi.mock('
|
|
13
|
+
vi.mock('../ui/logger.js');
|
|
14
|
+
vi.mock('../errorHandlers/index.js');
|
|
14
15
|
vi.mock('../prompts/personalAccessKeyPrompt');
|
|
15
16
|
vi.mock('../prompts/accountNamePrompt');
|
|
16
17
|
vi.mock('../ui/SpinniesManager', () => ({
|
|
@@ -101,7 +102,7 @@ describe('lib/buildAccount', () => {
|
|
|
101
102
|
expect(result).toBe('test-account-with-new-name');
|
|
102
103
|
});
|
|
103
104
|
});
|
|
104
|
-
describe('
|
|
105
|
+
describe('createDeveloperTestAccountV2()', () => {
|
|
105
106
|
const parentAccountId = 123456;
|
|
106
107
|
const mockDeveoperTestAccountConfig = {
|
|
107
108
|
accountName: 'Developer Test Account',
|
|
@@ -119,7 +120,7 @@ describe('lib/buildAccount', () => {
|
|
|
119
120
|
});
|
|
120
121
|
});
|
|
121
122
|
it('should create a developer test account successfully', async () => {
|
|
122
|
-
const result = await buildAccount.
|
|
123
|
+
const result = await buildAccount.createDeveloperTestAccountV2(parentAccountId, mockDeveoperTestAccountConfig);
|
|
123
124
|
expect(result).toEqual({
|
|
124
125
|
accountName: mockDeveoperTestAccountConfig.accountName,
|
|
125
126
|
accountId: 123456,
|
|
@@ -12,7 +12,7 @@ function buildArguments(args) {
|
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
15
|
-
vi.mock('
|
|
15
|
+
vi.mock('../../ui/logger.js');
|
|
16
16
|
describe('lib/commonOpts', () => {
|
|
17
17
|
describe('getCmsPublishMode()', () => {
|
|
18
18
|
const accounts = {
|
|
@@ -6,7 +6,7 @@ import { getProjectConfig } from '../projects/config.js';
|
|
|
6
6
|
import SpinniesManager from '../ui/SpinniesManager.js';
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
vi.mock('../projects/config');
|
|
9
|
-
vi.mock('
|
|
9
|
+
vi.mock('../../ui/logger.js');
|
|
10
10
|
vi.mock('@hubspot/local-dev-lib/fs');
|
|
11
11
|
vi.mock('fs');
|
|
12
12
|
vi.mock('../ui/SpinniesManager', () => ({
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { getAccountId, getConfigAccounts } from '@hubspot/local-dev-lib/config';
|
|
2
|
-
import {
|
|
2
|
+
import { uiLogger } from '../ui/logger.js';
|
|
3
3
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
4
4
|
import { fetchDeveloperTestAccounts } from '@hubspot/local-dev-lib/api/developerTestAccounts';
|
|
5
5
|
import { mockHubSpotHttpError } from '../testUtils.js';
|
|
6
6
|
import * as errorHandlers from '../errorHandlers/index.js';
|
|
7
7
|
import { getHasDevTestAccounts, handleDeveloperTestAccountCreateError, validateDevTestAccountUsageLimits, } from '../developerTestAccounts.js';
|
|
8
8
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
9
|
-
vi.mock('
|
|
9
|
+
vi.mock('../ui/logger.js');
|
|
10
10
|
vi.mock('@hubspot/local-dev-lib/api/developerTestAccounts');
|
|
11
11
|
vi.mock('../errorHandlers');
|
|
12
12
|
const mockedGetAccountId = getAccountId;
|
|
@@ -101,7 +101,7 @@ describe('lib/developerTestAccounts', () => {
|
|
|
101
101
|
let loggerErrorSpy;
|
|
102
102
|
let logErrorSpy;
|
|
103
103
|
beforeEach(() => {
|
|
104
|
-
loggerErrorSpy = vi.spyOn(
|
|
104
|
+
loggerErrorSpy = vi.spyOn(uiLogger, 'error');
|
|
105
105
|
logErrorSpy = vi.spyOn(errorHandlers, 'logError');
|
|
106
106
|
});
|
|
107
107
|
afterEach(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import util from 'util';
|
|
2
2
|
import { isGloballyInstalled, getLatestCliVersion, DEFAULT_PACKAGE_MANAGER, } from '../npm.js';
|
|
3
3
|
import pkg from '../../package.json' with { type: 'json' };
|
|
4
|
-
vi.mock('
|
|
4
|
+
vi.mock('../../ui/logger.js');
|
|
5
5
|
vi.mock('../ui/SpinniesManager');
|
|
6
6
|
describe('lib/npm', () => {
|
|
7
7
|
let execMock;
|
|
@@ -3,7 +3,7 @@ import open from 'open';
|
|
|
3
3
|
import { OAuth2Manager } from '@hubspot/local-dev-lib/models/OAuth2Manager';
|
|
4
4
|
import { getAccountConfig } from '@hubspot/local-dev-lib/config';
|
|
5
5
|
import { addOauthToAccountConfig } from '@hubspot/local-dev-lib/oauth';
|
|
6
|
-
import {
|
|
6
|
+
import { uiLogger } from '../ui/logger.js';
|
|
7
7
|
import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
|
|
8
8
|
import { DEFAULT_OAUTH_SCOPES } from '@hubspot/local-dev-lib/constants/auth';
|
|
9
9
|
import { authenticateWithOauth } from '../oauth.js';
|
|
@@ -12,7 +12,7 @@ vi.mock('open');
|
|
|
12
12
|
vi.mock('@hubspot/local-dev-lib/models/OAuth2Manager');
|
|
13
13
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
14
14
|
vi.mock('@hubspot/local-dev-lib/oauth');
|
|
15
|
-
vi.mock('
|
|
15
|
+
vi.mock('../ui/logger.js');
|
|
16
16
|
const mockedExpress = express;
|
|
17
17
|
const mockedOAuth2Manager = OAuth2Manager;
|
|
18
18
|
const mockedGetAccountConfig = getAccountConfig;
|
|
@@ -59,7 +59,7 @@ describe('lib/oauth', () => {
|
|
|
59
59
|
env: ENVIRONMENTS.PROD,
|
|
60
60
|
});
|
|
61
61
|
// Verify logger was called
|
|
62
|
-
expect(
|
|
62
|
+
expect(uiLogger.log).toHaveBeenCalledWith('Authorizing');
|
|
63
63
|
// Verify OAuth tokens were added to config
|
|
64
64
|
expect(addOauthToAccountConfig).toHaveBeenCalledWith(mockOAuth2Manager);
|
|
65
65
|
});
|
|
@@ -75,7 +75,7 @@ describe('lib/oauth', () => {
|
|
|
75
75
|
throw new Error('exit');
|
|
76
76
|
});
|
|
77
77
|
await expect(authenticateWithOauth(invalidConfig)).rejects.toThrow('exit');
|
|
78
|
-
expect(
|
|
78
|
+
expect(uiLogger.error).toHaveBeenCalled();
|
|
79
79
|
expect(exitSpy).toHaveBeenCalled();
|
|
80
80
|
exitSpy.mockRestore();
|
|
81
81
|
});
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import readline from 'readline';
|
|
2
|
-
import {
|
|
2
|
+
import { uiLogger } from '../ui/logger.js';
|
|
3
|
+
import { setLogLevel, LOG_LEVEL } from '@hubspot/local-dev-lib/logger';
|
|
3
4
|
import { handleExit, handleKeypress, TERMINATION_SIGNALS } from '../process.js';
|
|
4
5
|
vi.mock('readline');
|
|
5
|
-
vi.mock('
|
|
6
|
+
vi.mock('../ui/logger.js');
|
|
7
|
+
vi.mock('@hubspot/local-dev-lib/logger', async () => {
|
|
8
|
+
const logger = await vi.importActual('@hubspot/local-dev-lib/logger');
|
|
9
|
+
return { ...logger, setLogLevel: vi.fn() };
|
|
10
|
+
});
|
|
6
11
|
const mockedReadline = readline;
|
|
7
|
-
const
|
|
12
|
+
const mockedUiLogger = uiLogger;
|
|
8
13
|
const mockedSetLogLevel = setLogLevel;
|
|
9
14
|
const processRemoveListenerSpy = vi.spyOn(process, 'removeAllListeners');
|
|
10
15
|
const processOnSpy = vi.spyOn(process, 'on');
|
|
@@ -26,7 +31,7 @@ describe('lib/process', () => {
|
|
|
26
31
|
sighupCallback();
|
|
27
32
|
expect(mockedSetLogLevel).toHaveBeenCalledWith(LOG_LEVEL.NONE);
|
|
28
33
|
expect(mockCallback).toHaveBeenCalledWith({ isSIGHUP: true });
|
|
29
|
-
expect(
|
|
34
|
+
expect(mockedUiLogger.debug).toHaveBeenCalledWith(expect.stringContaining('SIGHUP'));
|
|
30
35
|
});
|
|
31
36
|
it('should handle non-SIGHUP signals correctly', async () => {
|
|
32
37
|
handleExit(mockCallback);
|
|
@@ -36,7 +41,7 @@ describe('lib/process', () => {
|
|
|
36
41
|
sigintCallback();
|
|
37
42
|
expect(mockedSetLogLevel).not.toHaveBeenCalled();
|
|
38
43
|
expect(mockCallback).toHaveBeenCalledWith({ isSIGHUP: false });
|
|
39
|
-
expect(
|
|
44
|
+
expect(mockedUiLogger.debug).toHaveBeenCalledWith(expect.stringContaining('SIGINT'));
|
|
40
45
|
});
|
|
41
46
|
it('should prevent duplicate exit handling', async () => {
|
|
42
47
|
handleExit(mockCallback);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { uiLogger } from '../ui/logger.js';
|
|
2
2
|
import { initiateSync } from '@hubspot/local-dev-lib/api/sandboxSync';
|
|
3
3
|
import { getAccountId } from '@hubspot/local-dev-lib/config';
|
|
4
4
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
@@ -6,12 +6,12 @@ import { mockHubSpotHttpError } from '../testUtils.js';
|
|
|
6
6
|
import { getAvailableSyncTypes } from '../sandboxes.js';
|
|
7
7
|
import { syncSandbox } from '../sandboxSync.js';
|
|
8
8
|
import SpinniesManager from '../ui/SpinniesManager.js';
|
|
9
|
-
vi.mock('
|
|
9
|
+
vi.mock('../ui/logger.js');
|
|
10
10
|
vi.mock('@hubspot/local-dev-lib/api/sandboxSync');
|
|
11
11
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
12
12
|
vi.mock('../sandboxes');
|
|
13
13
|
vi.mock('../ui/SpinniesManager');
|
|
14
|
-
const
|
|
14
|
+
const mockedUiLogger = uiLogger;
|
|
15
15
|
const mockedInitiateSync = initiateSync;
|
|
16
16
|
const mockedGetAccountId = getAccountId;
|
|
17
17
|
const mockedGetAvailableSyncTypes = getAvailableSyncTypes;
|
|
@@ -73,7 +73,7 @@ describe('lib/sandboxSync', () => {
|
|
|
73
73
|
mockedInitiateSync.mockRejectedValue(error);
|
|
74
74
|
await expect(syncSandbox(mockChildAccount, mockParentAccount, mockEnv, mockSyncTasks)).rejects.toEqual(error);
|
|
75
75
|
expect(mockedSpinniesFail).toHaveBeenCalled();
|
|
76
|
-
expect(
|
|
76
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/Couldn't run the sync because there's another sync in progress/));
|
|
77
77
|
});
|
|
78
78
|
it('handles invalid user error', async () => {
|
|
79
79
|
const error = mockHubSpotHttpError('', {
|
|
@@ -86,7 +86,7 @@ describe('lib/sandboxSync', () => {
|
|
|
86
86
|
mockedInitiateSync.mockRejectedValue(error);
|
|
87
87
|
await expect(syncSandbox(mockChildAccount, mockParentAccount, mockEnv, mockSyncTasks)).rejects.toEqual(error);
|
|
88
88
|
expect(mockedSpinniesFail).toHaveBeenCalled();
|
|
89
|
-
expect(
|
|
89
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/because your account has been removed from/));
|
|
90
90
|
});
|
|
91
91
|
it('handles not super admin error', async () => {
|
|
92
92
|
const error = mockHubSpotHttpError('', {
|
|
@@ -99,7 +99,7 @@ describe('lib/sandboxSync', () => {
|
|
|
99
99
|
mockedInitiateSync.mockRejectedValue(error);
|
|
100
100
|
await expect(syncSandbox(mockChildAccount, mockParentAccount, mockEnv, mockSyncTasks)).rejects.toEqual(error);
|
|
101
101
|
expect(mockedSpinniesFail).toHaveBeenCalled();
|
|
102
|
-
expect(
|
|
102
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/Couldn't run the sync because you are not a super admin in/));
|
|
103
103
|
});
|
|
104
104
|
it('handles sandbox not found error', async () => {
|
|
105
105
|
const error = mockHubSpotHttpError('', {
|
|
@@ -112,12 +112,12 @@ describe('lib/sandboxSync', () => {
|
|
|
112
112
|
mockedInitiateSync.mockRejectedValue(error);
|
|
113
113
|
await expect(syncSandbox(mockChildAccount, mockParentAccount, mockEnv, mockSyncTasks)).rejects.toEqual(error);
|
|
114
114
|
expect(mockedSpinniesFail).toHaveBeenCalled();
|
|
115
|
-
expect(
|
|
115
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/may have been deleted through the UI/));
|
|
116
116
|
});
|
|
117
117
|
it('displays slim info message when specified', async () => {
|
|
118
118
|
mockedInitiateSync.mockResolvedValue({ status: 'SUCCESS' });
|
|
119
119
|
await syncSandbox(mockChildAccount, mockParentAccount, mockEnv, mockSyncTasks, true);
|
|
120
|
-
expect(
|
|
120
|
+
expect(mockedUiLogger.info).not.toHaveBeenCalled();
|
|
121
121
|
expect(mockedSpinniesSucceed).toHaveBeenCalledWith('sandboxSync', expect.objectContaining({
|
|
122
122
|
text: expect.stringMatching(/Initiated sync of object definitions from production to /),
|
|
123
123
|
}));
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { uiLogger } from '../ui/logger.js';
|
|
2
2
|
import { getSandboxUsageLimits } from '@hubspot/local-dev-lib/api/sandboxHubs';
|
|
3
3
|
import { fetchTypes } from '@hubspot/local-dev-lib/api/sandboxSync';
|
|
4
4
|
import { getAccountId, getConfigAccounts } from '@hubspot/local-dev-lib/config';
|
|
5
5
|
import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
|
|
6
6
|
import { mockHubSpotHttpError } from '../testUtils.js';
|
|
7
7
|
import { getSandboxTypeAsString, getHasSandboxesByType, getAvailableSyncTypes, validateSandboxUsageLimits, handleSandboxCreateError, } from '../sandboxes.js';
|
|
8
|
-
vi.mock('
|
|
8
|
+
vi.mock('../ui/logger.js');
|
|
9
9
|
vi.mock('@hubspot/local-dev-lib/api/sandboxHubs');
|
|
10
10
|
vi.mock('@hubspot/local-dev-lib/api/sandboxSync');
|
|
11
11
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
@@ -13,7 +13,7 @@ const mockedGetAccountId = getAccountId;
|
|
|
13
13
|
const mockedGetSandboxUsageLimits = getSandboxUsageLimits;
|
|
14
14
|
const mockedFetchTypes = fetchTypes;
|
|
15
15
|
const mockedGetConfigAccounts = getConfigAccounts;
|
|
16
|
-
const
|
|
16
|
+
const mockedUiLogger = uiLogger;
|
|
17
17
|
describe('lib/sandboxes', () => {
|
|
18
18
|
describe('getSandboxTypeAsString()', () => {
|
|
19
19
|
it('returns "development" for development sandbox type', () => {
|
|
@@ -101,7 +101,7 @@ describe('lib/sandboxes', () => {
|
|
|
101
101
|
usage: { DEVELOPER: { available: 0, limit: 1 } },
|
|
102
102
|
},
|
|
103
103
|
});
|
|
104
|
-
await expect(validateSandboxUsageLimits(mockAccount, HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX, 'qa')).rejects.toThrow(/reached the limit of 1
|
|
104
|
+
await expect(validateSandboxUsageLimits(mockAccount, HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX, 'qa')).rejects.toThrow(/reached the limit of 1 developer sandboxes/);
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
107
|
describe('handleSandboxCreateError()', () => {
|
|
@@ -117,8 +117,8 @@ describe('lib/sandboxes', () => {
|
|
|
117
117
|
},
|
|
118
118
|
});
|
|
119
119
|
expect(() => handleSandboxCreateError(error, mockEnv, mockName, mockAccountId)).toThrow(error);
|
|
120
|
-
expect(
|
|
121
|
-
expect(
|
|
120
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/The personal access key you provided doesn't include sandbox permissions/));
|
|
121
|
+
expect(mockedUiLogger.info).toHaveBeenCalledWith(expect.stringMatching(/To update CLI permissions for/));
|
|
122
122
|
});
|
|
123
123
|
it('handles user access not allowed error', () => {
|
|
124
124
|
const error = mockHubSpotHttpError('user access not allowed error', {
|
|
@@ -129,7 +129,7 @@ describe('lib/sandboxes', () => {
|
|
|
129
129
|
},
|
|
130
130
|
});
|
|
131
131
|
expect(() => handleSandboxCreateError(error, mockEnv, mockName, mockAccountId)).toThrow(error);
|
|
132
|
-
expect(
|
|
132
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/your permission set doesn't allow you to create the sandbox/));
|
|
133
133
|
});
|
|
134
134
|
it('handles 403 gating error', () => {
|
|
135
135
|
const error = mockHubSpotHttpError('403 gating error', {
|
|
@@ -140,7 +140,7 @@ describe('lib/sandboxes', () => {
|
|
|
140
140
|
},
|
|
141
141
|
});
|
|
142
142
|
expect(() => handleSandboxCreateError(error, mockEnv, mockName, mockAccountId)).toThrow(error);
|
|
143
|
-
expect(
|
|
143
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(expect.stringMatching(/does not have access to development sandboxes/));
|
|
144
144
|
});
|
|
145
145
|
});
|
|
146
146
|
});
|
|
@@ -2,7 +2,7 @@ import mockStdIn from 'mock-stdin';
|
|
|
2
2
|
import { outputLogs } from '../ui/serverlessFunctionLogs.js';
|
|
3
3
|
import { tailLogs } from '../serverlessLogs.js';
|
|
4
4
|
vi.mock('../ui/serverlessFunctionLogs');
|
|
5
|
-
vi.mock('
|
|
5
|
+
vi.mock('../../ui/logger.js');
|
|
6
6
|
vi.mock('../ui/SpinniesManager', () => ({
|
|
7
7
|
default: {
|
|
8
8
|
init: vi.fn(),
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { trackUsage } from '@hubspot/local-dev-lib/trackUsage';
|
|
2
2
|
import { isTrackingAllowed, getAccountConfig, } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { API_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
|
|
4
|
-
import {
|
|
4
|
+
import { uiLogger } from '../ui/logger.js';
|
|
5
5
|
import { trackCommandUsage, trackHelpUsage, trackConvertFieldsUsage, trackAuthAction, trackCommandMetadataUsage, } from '../usageTracking.js';
|
|
6
6
|
import packageJson from '../../package.json' with { type: 'json' };
|
|
7
7
|
const version = packageJson.version;
|
|
8
8
|
vi.mock('@hubspot/local-dev-lib/trackUsage');
|
|
9
9
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
10
|
-
vi.mock('
|
|
10
|
+
vi.mock('../ui/logger.js');
|
|
11
11
|
const mockedTrackUsage = trackUsage;
|
|
12
12
|
const mockedIsTrackingAllowed = isTrackingAllowed;
|
|
13
13
|
const mockedGetAccountConfig = getAccountConfig;
|
|
14
|
-
const
|
|
14
|
+
const mockedUiLogger = uiLogger;
|
|
15
15
|
describe('lib/usageTracking', () => {
|
|
16
16
|
const mockPlatform = 'darwin';
|
|
17
17
|
const mockNodeVersion = 'v16.14.0';
|
|
@@ -53,7 +53,7 @@ describe('lib/usageTracking', () => {
|
|
|
53
53
|
throw error;
|
|
54
54
|
});
|
|
55
55
|
await trackCommandUsage(mockCommand);
|
|
56
|
-
expect(
|
|
56
|
+
expect(mockedUiLogger.debug).toHaveBeenCalledWith(expect.stringContaining(error.message));
|
|
57
57
|
});
|
|
58
58
|
});
|
|
59
59
|
describe('trackHelpUsage()', () => {
|
|
@@ -76,7 +76,7 @@ describe('lib/usageTracking', () => {
|
|
|
76
76
|
});
|
|
77
77
|
it('should track main help usage without command', async () => {
|
|
78
78
|
await trackHelpUsage('');
|
|
79
|
-
expect(
|
|
79
|
+
expect(mockedUiLogger.debug).toHaveBeenCalledWith(expect.stringContaining('main command'));
|
|
80
80
|
});
|
|
81
81
|
});
|
|
82
82
|
describe('trackConvertFieldsUsage()', () => {
|
|
@@ -3,7 +3,8 @@ import { getOauthManager } from '@hubspot/local-dev-lib/oauth';
|
|
|
3
3
|
import { accessTokenForPersonalAccessKey } from '@hubspot/local-dev-lib/personalAccessKey';
|
|
4
4
|
import { validateAccount } from '../validation.js';
|
|
5
5
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
6
|
-
vi.mock('
|
|
6
|
+
vi.mock('../../lib/ui/logger.js');
|
|
7
|
+
vi.mock('../errorHandlers/index.js');
|
|
7
8
|
vi.mock('@hubspot/local-dev-lib/oauth');
|
|
8
9
|
vi.mock('@hubspot/local-dev-lib/personalAccessKey');
|
|
9
10
|
vi.mock('../commonOpts');
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
import { hasFlag, makeYargsBuilder,
|
|
1
|
+
import { hasFlag, makeYargsBuilder, strictEnforceBoolean, } from '../yargsUtils.js';
|
|
2
2
|
import * as commonOpts from '../commonOpts.js';
|
|
3
3
|
vi.mock('../commonOpts');
|
|
4
|
+
vi.mock('../../lang/en.js', () => ({
|
|
5
|
+
commands: {
|
|
6
|
+
config: {
|
|
7
|
+
subcommands: {
|
|
8
|
+
set: {
|
|
9
|
+
errors: {
|
|
10
|
+
invalidBoolean: (option, value) => `Invalid boolean value "${value}" for --${option}. Valid values are: true, false`,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
4
17
|
const argvWithFlag = ['hs', 'command', '--test'];
|
|
5
18
|
const argvWithoutFlag = ['hs', 'command'];
|
|
6
19
|
describe('lib/yargsUtils', () => {
|
|
@@ -36,15 +49,76 @@ describe('lib/yargsUtils', () => {
|
|
|
36
49
|
expect(commonOpts.addCustomHelpOutput).toHaveBeenCalled();
|
|
37
50
|
});
|
|
38
51
|
});
|
|
39
|
-
describe('
|
|
40
|
-
it('should
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
describe('strictEnforceBoolean()', () => {
|
|
53
|
+
it('should validate valid boolean values (true/false, case-insensitive)', () => {
|
|
54
|
+
const validArgs = [
|
|
55
|
+
['hs', 'config', 'set', '--allow-usage-tracking=true'],
|
|
56
|
+
['hs', 'config', 'set', '--allow-usage-tracking=false'],
|
|
57
|
+
['hs', 'config', 'set', '--allow-usage-tracking=TRUE'],
|
|
58
|
+
['hs', 'config', 'set', '--allow-usage-tracking=False'],
|
|
59
|
+
];
|
|
60
|
+
validArgs.forEach(args => {
|
|
61
|
+
expect(() => strictEnforceBoolean(args, ['allow-usage-tracking'])).not.toThrow();
|
|
62
|
+
expect(strictEnforceBoolean(args, ['allow-usage-tracking'])).toBe(true);
|
|
47
63
|
});
|
|
48
64
|
});
|
|
65
|
+
it('should reject invalid boolean values with descriptive error messages', () => {
|
|
66
|
+
const invalidCases = [
|
|
67
|
+
{
|
|
68
|
+
args: ['hs', 'config', 'set', '--allow-usage-tracking=yes'],
|
|
69
|
+
value: 'yes',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
args: ['hs', 'config', 'set', '--allow-usage-tracking=1'],
|
|
73
|
+
value: '1',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
args: ['hs', 'config', 'set', '--auto-open-browser=maybe'],
|
|
77
|
+
value: 'maybe',
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
invalidCases.forEach(({ args, value }) => {
|
|
81
|
+
const option = args[3].split('=')[0].replace('--', '');
|
|
82
|
+
expect(() => strictEnforceBoolean(args, [option])).toThrow(`Invalid boolean value "${value}" for --${option}. Valid values are: true, false`);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
it('should support multiple config values in a single command', () => {
|
|
86
|
+
const args = [
|
|
87
|
+
'hs',
|
|
88
|
+
'config',
|
|
89
|
+
'set',
|
|
90
|
+
'--allow-usage-tracking=true',
|
|
91
|
+
'--auto-open-browser=false',
|
|
92
|
+
'--allow-auto-updates=true',
|
|
93
|
+
'--http-timeout=5000',
|
|
94
|
+
'--default-cms-publish-mode=draft',
|
|
95
|
+
];
|
|
96
|
+
const booleanOptions = [
|
|
97
|
+
'allow-usage-tracking',
|
|
98
|
+
'auto-open-browser',
|
|
99
|
+
'allow-auto-updates',
|
|
100
|
+
];
|
|
101
|
+
expect(() => strictEnforceBoolean(args, booleanOptions)).not.toThrow();
|
|
102
|
+
expect(strictEnforceBoolean(args, booleanOptions)).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
it('should error when one of multiple values is invalid', () => {
|
|
105
|
+
const args = [
|
|
106
|
+
'hs',
|
|
107
|
+
'config',
|
|
108
|
+
'set',
|
|
109
|
+
'--allow-usage-tracking=true',
|
|
110
|
+
'--auto-open-browser=invalid',
|
|
111
|
+
'--http-timeout=5000',
|
|
112
|
+
];
|
|
113
|
+
const booleanOptions = ['allow-usage-tracking', 'auto-open-browser'];
|
|
114
|
+
expect(() => strictEnforceBoolean(args, booleanOptions)).toThrow('Invalid boolean value "invalid" for --auto-open-browser. Valid values are: true, false');
|
|
115
|
+
});
|
|
116
|
+
it('should maintain backwards compatability', () => {
|
|
117
|
+
expect(() => strictEnforceBoolean(['hs', 'config', 'set', '--allow-usage-tracking=true'], ['allow-usage-tracking'])).not.toThrow();
|
|
118
|
+
// No values provided (interactive mode)
|
|
119
|
+
expect(() => strictEnforceBoolean(['hs', 'config', 'set'], ['allow-usage-tracking'])).not.toThrow();
|
|
120
|
+
// Flag without equals sign (succeed with true)
|
|
121
|
+
expect(() => strictEnforceBoolean(['hs', 'config', 'set', '--allow-usage-tracking'], ['allow-usage-tracking'])).not.toThrow();
|
|
122
|
+
});
|
|
49
123
|
});
|
|
50
124
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { uiLogger } from '../../ui/logger.js';
|
|
2
2
|
import { getCwd, sanitizeFileName } from '@hubspot/local-dev-lib/path';
|
|
3
3
|
import { extractZipArchive } from '@hubspot/local-dev-lib/archive';
|
|
4
|
-
import { validateUid
|
|
4
|
+
import { validateUid } from '@hubspot/project-parsing-lib';
|
|
5
5
|
import { UNMIGRATABLE_REASONS } from '@hubspot/local-dev-lib/constants/projects';
|
|
6
6
|
import { MIGRATION_STATUS } from '@hubspot/local-dev-lib/types/Migration';
|
|
7
7
|
import { downloadProject } from '@hubspot/local-dev-lib/api/projects';
|
|
@@ -12,8 +12,8 @@ import { poll } from '../../polling.js';
|
|
|
12
12
|
import { CLI_UNMIGRATABLE_REASONS, continueAppMigration, initializeAppMigration, listAppsForMigration, } from '../../../api/migrate.js';
|
|
13
13
|
import { lib } from '../../../lang/en.js';
|
|
14
14
|
import { hasUnfiedAppsAccess } from '../../hasFeature.js';
|
|
15
|
-
import { getUnmigratableReason, generateFilterAppsByProjectNameFunction, buildErrorMessageFromMigrationStatus, fetchMigrationApps, promptForAppToMigrate, selectAppToMigrate, handleMigrationSetup,
|
|
16
|
-
vi.mock('
|
|
15
|
+
import { getUnmigratableReason, generateFilterAppsByProjectNameFunction, buildErrorMessageFromMigrationStatus, fetchMigrationApps, promptForAppToMigrate, selectAppToMigrate, handleMigrationSetup, beginAppMigration, pollMigrationStatus, finalizeAppMigration, downloadProjectFiles, migrateApp2025_2, logInvalidAccountError, validateMigrationApps, } from '../migrate.js';
|
|
16
|
+
vi.mock('../../ui/logger.js');
|
|
17
17
|
vi.mock('@hubspot/local-dev-lib/path');
|
|
18
18
|
vi.mock('@hubspot/local-dev-lib/archive');
|
|
19
19
|
vi.mock('@hubspot/project-parsing-lib');
|
|
@@ -28,7 +28,7 @@ vi.mock('../../../api/migrate');
|
|
|
28
28
|
vi.mock('../../hasFeature');
|
|
29
29
|
vi.mock('../../projects/urls');
|
|
30
30
|
vi.mock('fs');
|
|
31
|
-
const
|
|
31
|
+
const mockedUiLogger = uiLogger;
|
|
32
32
|
const mockedGetCwd = getCwd;
|
|
33
33
|
const mockedSanitizeFileName = sanitizeFileName;
|
|
34
34
|
const mockedExtractZipArchive = extractZipArchive;
|
|
@@ -40,7 +40,6 @@ const mockedListPrompt = listPrompt;
|
|
|
40
40
|
const mockedEnsureProjectExists = ensureProjectExists;
|
|
41
41
|
const mockedPoll = poll;
|
|
42
42
|
const mockedListAppsForMigration = listAppsForMigration;
|
|
43
|
-
const mockedGetProjectThemeDetails = getProjectThemeDetails;
|
|
44
43
|
const mockedInitializeAppMigration = initializeAppMigration;
|
|
45
44
|
const mockedContinueAppMigration = continueAppMigration;
|
|
46
45
|
const mockedHasUnfiedAppsAccess = hasUnfiedAppsAccess;
|
|
@@ -205,58 +204,31 @@ describe('lib/app/migrate', () => {
|
|
|
205
204
|
expect(result.migratableApps[0].projectName).toBe(PROJECT_NAME);
|
|
206
205
|
});
|
|
207
206
|
});
|
|
208
|
-
describe('
|
|
209
|
-
it('should return false when no projectConfig is provided', async () => {
|
|
210
|
-
const result = await getHasMigratableThemes();
|
|
211
|
-
expect(result).toEqual({
|
|
212
|
-
hasMigratableThemes: false,
|
|
213
|
-
migratableThemesCount: 0,
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
it('should return true when there are migratable themes', async () => {
|
|
217
|
-
mockedGetProjectThemeDetails.mockResolvedValue({
|
|
218
|
-
legacyThemeDetails: [
|
|
219
|
-
{
|
|
220
|
-
configFilepath: 'src/theme.json',
|
|
221
|
-
themePath: 'src/theme',
|
|
222
|
-
themeConfig: {
|
|
223
|
-
secret_names: ['my-secret'],
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
],
|
|
227
|
-
legacyReactThemeDetails: [],
|
|
228
|
-
});
|
|
229
|
-
const projectConfig = createLoadedProjectConfig(PROJECT_NAME);
|
|
230
|
-
const result = await getHasMigratableThemes(projectConfig);
|
|
231
|
-
expect(result).toEqual({
|
|
232
|
-
hasMigratableThemes: true,
|
|
233
|
-
migratableThemesCount: 1,
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
describe('validateMigrationAppsAndThemes', () => {
|
|
207
|
+
describe('validateMigrationApps', () => {
|
|
238
208
|
const mockMigratableApp1 = createMockMigratableApp(1, 'App 1', PROJECT_NAME);
|
|
239
209
|
const mockMigratableApp2 = createMockMigratableApp(2, 'App 2', PROJECT_NAME);
|
|
240
210
|
it('should throw an error when multiple apps are found for a project', async () => {
|
|
241
211
|
const projectConfig = createLoadedProjectConfig(PROJECT_NAME);
|
|
242
|
-
await expect(
|
|
212
|
+
await expect(validateMigrationApps(APP_ID, ACCOUNT_ID, {
|
|
243
213
|
migratableApps: [mockMigratableApp1, mockMigratableApp2],
|
|
244
214
|
unmigratableApps: [],
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
it('should throw an error when cms themes are found for a project', async () => {
|
|
248
|
-
const projectConfig = createLoadedProjectConfig(PROJECT_NAME);
|
|
249
|
-
await expect(validateMigrationAppsAndThemes(APP_ID, ACCOUNT_ID, { migratableApps: [mockMigratableApp1], unmigratableApps: [] }, true, projectConfig)).rejects.toThrow(lib.migrate.errors.project.themesAndAppsNotAllowed);
|
|
215
|
+
}, projectConfig)).rejects.toThrow(lib.migrate.errors.project.multipleApps);
|
|
250
216
|
});
|
|
251
217
|
it('should throw an error when no apps are found for a project', async () => {
|
|
252
218
|
const projectConfig = createLoadedProjectConfig(PROJECT_NAME);
|
|
253
|
-
await expect(
|
|
219
|
+
await expect(validateMigrationApps(APP_ID, ACCOUNT_ID, { migratableApps: [], unmigratableApps: [] }, projectConfig)).rejects.toThrow(lib.migrate.errors.noAppsForProject(PROJECT_NAME));
|
|
254
220
|
});
|
|
255
221
|
it('should throw an error when no migratable apps are found', async () => {
|
|
256
|
-
await expect(
|
|
222
|
+
await expect(validateMigrationApps(APP_ID, ACCOUNT_ID, {
|
|
223
|
+
migratableApps: [],
|
|
224
|
+
unmigratableApps: mockUnmigratableApps,
|
|
225
|
+
})).rejects.toThrow(/No apps in account/);
|
|
257
226
|
});
|
|
258
227
|
it('should throw an error when appId is provided but not found', async () => {
|
|
259
|
-
await expect(
|
|
228
|
+
await expect(validateMigrationApps(APP_ID, ACCOUNT_ID, {
|
|
229
|
+
migratableApps: [],
|
|
230
|
+
unmigratableApps: [],
|
|
231
|
+
})).rejects.toThrow(/No apps in account/);
|
|
260
232
|
});
|
|
261
233
|
});
|
|
262
234
|
describe('promptForAppToMigrate', () => {
|
|
@@ -330,10 +302,6 @@ describe('lib/app/migrate', () => {
|
|
|
330
302
|
unmigratableApps: [],
|
|
331
303
|
},
|
|
332
304
|
});
|
|
333
|
-
mockedGetProjectThemeDetails.mockResolvedValue({
|
|
334
|
-
legacyThemeDetails: [],
|
|
335
|
-
legacyReactThemeDetails: [],
|
|
336
|
-
});
|
|
337
305
|
mockedListPrompt.mockResolvedValue({ appId: 1 });
|
|
338
306
|
mockedConfirmPrompt.mockResolvedValue(true);
|
|
339
307
|
mockedEnsureProjectExists.mockResolvedValue({ projectExists: false });
|
|
@@ -352,16 +320,11 @@ describe('lib/app/migrate', () => {
|
|
|
352
320
|
unmigratableApps: [],
|
|
353
321
|
},
|
|
354
322
|
});
|
|
355
|
-
mockedGetProjectThemeDetails.mockResolvedValueOnce({
|
|
356
|
-
legacyThemeDetails: [],
|
|
357
|
-
legacyReactThemeDetails: [],
|
|
358
|
-
});
|
|
359
323
|
const result = await handleMigrationSetup(ACCOUNT_ID, defaultOptions, projectConfig);
|
|
360
324
|
expect(result).toEqual({
|
|
361
325
|
appIdToMigrate: 1,
|
|
362
326
|
projectName: PROJECT_NAME,
|
|
363
327
|
projectDest: MOCK_PROJECT_DIR,
|
|
364
|
-
isThemesMigration: false,
|
|
365
328
|
});
|
|
366
329
|
});
|
|
367
330
|
it('should prompt for project name when not provided', async () => {
|
|
@@ -528,8 +491,8 @@ describe('lib/app/migrate', () => {
|
|
|
528
491
|
describe('logInvalidAccountError', () => {
|
|
529
492
|
it('should log the invalid account error message', () => {
|
|
530
493
|
logInvalidAccountError();
|
|
531
|
-
expect(
|
|
532
|
-
expect(
|
|
494
|
+
expect(mockedUiLogger.error).toHaveBeenCalledWith(lib.migrate.errors.invalidAccountTypeTitle);
|
|
495
|
+
expect(mockedUiLogger.log).toHaveBeenCalledWith(expect.stringContaining('Only public apps created in a developer account can be converted to a project component'));
|
|
533
496
|
});
|
|
534
497
|
});
|
|
535
498
|
});
|