@hubspot/cli 7.7.19-experimental.0 → 7.7.19-experimental.2

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.
Files changed (38) hide show
  1. package/commands/app/install.d.ts +8 -0
  2. package/commands/app/install.js +127 -0
  3. package/commands/app.js +6 -1
  4. package/commands/mcp/setup.js +0 -1
  5. package/commands/mcp/start.d.ts +1 -4
  6. package/commands/mcp/start.js +3 -10
  7. package/commands/open.js +14 -12
  8. package/commands/project/dev/unifiedFlow.js +1 -1
  9. package/commands/testAccount/create.js +14 -24
  10. package/lang/en.d.ts +65 -5
  11. package/lang/en.js +65 -5
  12. package/lib/app/migrate.js +2 -6
  13. package/lib/buildAccount.d.ts +7 -1
  14. package/lib/buildAccount.js +54 -4
  15. package/lib/mcp/setup.js +3 -8
  16. package/lib/projects/create/v3.d.ts +3 -2
  17. package/lib/projects/create/v3.js +2 -2
  18. package/lib/projects/localDev/helpers.d.ts +1 -1
  19. package/lib/projects/localDev/helpers.js +2 -2
  20. package/lib/projects/structure.d.ts +2 -2
  21. package/lib/projects/upload.d.ts +2 -1
  22. package/lib/projects/upload.js +1 -0
  23. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +9 -10
  24. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +86 -47
  25. package/lib/prompts/createModulePrompt.js +1 -2
  26. package/lib/prompts/projectAddPrompt.d.ts +2 -1
  27. package/lib/prompts/projectAddPrompt.js +2 -1
  28. package/lib/prompts/promptUtils.d.ts +2 -2
  29. package/lib/prompts/promptUtils.js +161 -35
  30. package/lib/prompts/selectProjectTemplatePrompt.d.ts +2 -1
  31. package/lib/prompts/selectProjectTemplatePrompt.js +2 -1
  32. package/lib/usageTracking.d.ts +5 -5
  33. package/lib/usageTracking.js +79 -74
  34. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  35. package/mcp-server/tools/project/UploadProjectTools.js +1 -1
  36. package/mcp-server/utils/project.js +0 -3
  37. package/package.json +3 -3
  38. package/types/Prompts.d.ts +4 -2
@@ -0,0 +1,8 @@
1
+ import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, YargsCommandModule, JSONOutputArgs } from '../../types/Yargs';
2
+ type InstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
3
+ appUid?: string;
4
+ projectName?: string;
5
+ testAccountId: number;
6
+ };
7
+ declare const installAppCommand: YargsCommandModule<unknown, InstallAppArgs>;
8
+ export default installAppCommand;
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const developerTestAccounts_1 = require("@hubspot/local-dev-lib/api/developerTestAccounts");
7
+ const usageTracking_1 = require("../../lib/usageTracking");
8
+ const en_1 = require("../../lang/en");
9
+ const exitCodes_1 = require("../../lib/enums/exitCodes");
10
+ const yargsUtils_1 = require("../../lib/yargsUtils");
11
+ const constants_1 = require("../../lib/constants");
12
+ const logger_1 = require("../../lib/ui/logger");
13
+ const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"));
14
+ const errorHandlers_1 = require("../../lib/errorHandlers");
15
+ const polling_1 = require("../../lib/polling");
16
+ const config_1 = require("../../lib/projects/config");
17
+ const upload_1 = require("../../lib/projects/upload");
18
+ const structure_1 = require("../../lib/projects/structure");
19
+ const command = 'install <test-account-id>';
20
+ const describe = undefined; // commands.app.subcommands.install.describe;
21
+ async function handler(args) {
22
+ const { derivedAccountId, appUid, projectName, testAccountId, formatOutputAsJson, } = args;
23
+ (0, usageTracking_1.trackCommandUsage)('app-install', {}, derivedAccountId);
24
+ const jsonOutput = {};
25
+ let targetProjectName = projectName;
26
+ let targetAppUid = appUid;
27
+ const { projectConfig, projectDir } = await (0, config_1.getProjectConfig)();
28
+ if (!targetProjectName) {
29
+ (0, config_1.validateProjectConfig)(projectConfig, projectDir);
30
+ targetProjectName = projectConfig?.name;
31
+ }
32
+ if (!targetProjectName) {
33
+ logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.mustSpecifyProjectName);
34
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
35
+ }
36
+ let isAppOauth = true;
37
+ if (!targetAppUid) {
38
+ const intermediateRepresentation = await (0, upload_1.handleTranslate)(projectDir, projectConfig, derivedAccountId, true, undefined);
39
+ if (intermediateRepresentation) {
40
+ Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).forEach(node => {
41
+ if ((0, structure_1.isAppIRNode)(node)) {
42
+ targetAppUid = node.uid;
43
+ isAppOauth = node.config.auth.type === constants_1.APP_AUTH_TYPES.OAUTH;
44
+ }
45
+ });
46
+ }
47
+ }
48
+ if (!targetAppUid) {
49
+ logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.noAppUidFound);
50
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
51
+ }
52
+ if (!isAppOauth) {
53
+ logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.appMustBeOauth);
54
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
55
+ }
56
+ try {
57
+ const { data } = await (0, developerTestAccounts_1.installOauthAppIntoDeveloperTestAccount)(derivedAccountId, testAccountId, targetProjectName, targetAppUid);
58
+ if (data?.authCodes.length > 0) {
59
+ jsonOutput.authCode = data.authCodes[0].authCode;
60
+ }
61
+ }
62
+ catch (err) {
63
+ (0, errorHandlers_1.logError)(err);
64
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
65
+ }
66
+ SpinniesManager_1.default.init({
67
+ succeedColor: 'white',
68
+ });
69
+ SpinniesManager_1.default.add('installApp', {
70
+ text: en_1.commands.app.subcommands.install.polling.start,
71
+ });
72
+ let appInstallSucceeded = false;
73
+ try {
74
+ await (0, polling_1.poll)(() => (0, developerTestAccounts_1.fetchDeveloperTestAccountOauthAppInstallStatus)(derivedAccountId, targetProjectName, targetAppUid), {
75
+ successStates: ['SUCCESS'],
76
+ errorStates: [],
77
+ });
78
+ appInstallSucceeded = true;
79
+ }
80
+ catch (err) {
81
+ SpinniesManager_1.default.fail('installApp');
82
+ (0, errorHandlers_1.logError)(err);
83
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
84
+ }
85
+ if (!appInstallSucceeded) {
86
+ SpinniesManager_1.default.fail('installApp');
87
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
88
+ }
89
+ SpinniesManager_1.default.succeed('installApp', {
90
+ text: en_1.commands.app.subcommands.install.polling.success,
91
+ });
92
+ if (formatOutputAsJson) {
93
+ logger_1.uiLogger.json(jsonOutput);
94
+ }
95
+ process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
96
+ }
97
+ function installAppBuilder(yargs) {
98
+ yargs.positional('test-account-id', {
99
+ describe: en_1.commands.app.subcommands.install.positionals.testAccountId,
100
+ required: true,
101
+ type: 'number',
102
+ });
103
+ yargs.option('app-uid', {
104
+ describe: en_1.commands.app.subcommands.install.options.appUid,
105
+ type: 'string',
106
+ });
107
+ yargs.option('project-name', {
108
+ describe: en_1.commands.app.subcommands.install.options.projectName,
109
+ type: 'string',
110
+ });
111
+ yargs.example('install 1234567890 --app-uid=my-app-uid --project-name=my-project', en_1.commands.app.subcommands.install.example);
112
+ return yargs;
113
+ }
114
+ const builder = (0, yargsUtils_1.makeYargsBuilder)(installAppBuilder, command, en_1.commands.app.subcommands.install.describe, {
115
+ useGlobalOptions: true,
116
+ useAccountOptions: true,
117
+ useConfigOptions: true,
118
+ useEnvironmentOptions: true,
119
+ useJSONOutputOptions: true,
120
+ });
121
+ const installAppCommand = {
122
+ command,
123
+ describe,
124
+ handler,
125
+ builder,
126
+ };
127
+ exports.default = installAppCommand;
package/commands/app.js CHANGED
@@ -5,12 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const migrate_1 = __importDefault(require("./app/migrate"));
7
7
  const secret_1 = __importDefault(require("./app/secret"));
8
+ const install_1 = __importDefault(require("./app/install"));
8
9
  const yargsUtils_1 = require("../lib/yargsUtils");
9
10
  const command = ['app', 'apps'];
10
11
  // Keep the command hidden for now
11
12
  const describe = undefined;
12
13
  function appBuilder(yargs) {
13
- yargs.command(migrate_1.default).command(secret_1.default).demandCommand(1, '');
14
+ yargs
15
+ .command(migrate_1.default)
16
+ .command(secret_1.default)
17
+ .command(install_1.default)
18
+ .demandCommand(1, '');
14
19
  return yargs;
15
20
  }
16
21
  const builder = (0, yargsUtils_1.makeYargsBuilder)(appBuilder, command, describe);
@@ -37,7 +37,6 @@ function setupBuilder(yargs) {
37
37
  })
38
38
  .option('add-docs-search', {
39
39
  type: 'boolean',
40
- hidden: true,
41
40
  });
42
41
  return yargs;
43
42
  }
@@ -1,6 +1,3 @@
1
1
  import { CommonArgs, YargsCommandModule } from '../../types/Yargs';
2
- interface McpStartArgs extends CommonArgs {
3
- aiAgent: string;
4
- }
5
- declare const mcpStartCommand: YargsCommandModule<unknown, McpStartArgs>;
2
+ declare const mcpStartCommand: YargsCommandModule<unknown, CommonArgs>;
6
3
  export default mcpStartCommand;
@@ -24,9 +24,9 @@ async function handler(args) {
24
24
  process.exit(exitCodes_1.EXIT_CODES.ERROR);
25
25
  }
26
26
  (0, usageTracking_1.trackCommandUsage)('mcp-start', {}, args.derivedAccountId);
27
- await startMcpServer(args.aiAgent);
27
+ await startMcpServer();
28
28
  }
29
- async function startMcpServer(aiAgent) {
29
+ async function startMcpServer() {
30
30
  try {
31
31
  const serverPath = path_1.default.join(__dirname, '..', '..', 'mcp-server', 'server.js');
32
32
  // Check if server file exists
@@ -36,13 +36,11 @@ async function startMcpServer(aiAgent) {
36
36
  }
37
37
  logger_1.uiLogger.info(en_1.commands.mcp.start.startingServer);
38
38
  logger_1.uiLogger.info(en_1.commands.mcp.start.stopInstructions);
39
- const args = [serverPath];
40
39
  // Start the server using ts-node
41
- const child = (0, child_process_1.spawn)(`node`, args, {
40
+ const child = (0, child_process_1.spawn)('node', [serverPath], {
42
41
  stdio: 'inherit',
43
42
  env: {
44
43
  ...process.env,
45
- HUBSPOT_MCP_AI_AGENT: aiAgent || 'unknown',
46
44
  },
47
45
  });
48
46
  // Handle server process events
@@ -65,11 +63,6 @@ async function startMcpServer(aiAgent) {
65
63
  }
66
64
  }
67
65
  function startBuilder(yargs) {
68
- yargs
69
- .option('ai-agent', {
70
- type: 'string',
71
- })
72
- .demandOption('ai-agent');
73
66
  return yargs;
74
67
  }
75
68
  const builder = (0, yargsUtils_1.makeYargsBuilder)(startBuilder, command, describe, {
package/commands/open.js CHANGED
@@ -8,16 +8,18 @@ const exitCodes_1 = require("../lib/enums/exitCodes");
8
8
  const yargsUtils_1 = require("../lib/yargsUtils");
9
9
  const separator = ' => ';
10
10
  async function createListPrompt(accountId) {
11
- return (0, promptUtils_1.promptUser)([
12
- {
13
- type: 'rawlist',
14
- name: 'open',
15
- pageSize: 20,
16
- message: (0, lang_1.i18n)('commands.open.selectLink'),
17
- choices: (0, links_1.getSiteLinksAsArray)(accountId).map(l => `${l.shortcut}${separator}${l.url}`),
18
- filter: val => val.split(separator)[0],
19
- },
20
- ]);
11
+ return (0, promptUtils_1.promptUser)({
12
+ name: 'open',
13
+ type: 'rawlist',
14
+ pageSize: 20,
15
+ message: (0, lang_1.i18n)('commands.open.selectLink'),
16
+ choices: (0, links_1.getSiteLinksAsArray)(accountId)
17
+ .filter(l => !!l.url)
18
+ .map(l => ({
19
+ name: `${l.shortcut}${separator}${l.url}`,
20
+ value: l.shortcut,
21
+ })),
22
+ });
21
23
  }
22
24
  const command = 'open [shortcut]';
23
25
  const describe = (0, lang_1.i18n)('commands.open.describe');
@@ -25,8 +27,8 @@ async function handler(args) {
25
27
  const { shortcut, list, derivedAccountId } = args;
26
28
  (0, usageTracking_1.trackCommandUsage)('open', undefined, derivedAccountId);
27
29
  if (shortcut === undefined && !list) {
28
- const choice = await createListPrompt(derivedAccountId);
29
- (0, links_1.openLink)(derivedAccountId, choice.open);
30
+ const { open } = await createListPrompt(derivedAccountId);
31
+ (0, links_1.openLink)(derivedAccountId, open);
30
32
  }
31
33
  else if (list) {
32
34
  (0, links_1.logSiteLinks)(derivedAccountId);
@@ -93,7 +93,7 @@ async function unifiedProjectDevFlow({ args, targetProjectAccountId, providedTar
93
93
  }
94
94
  else if (devAccountPromptResponse.createNestedAccount) {
95
95
  // Create a new developer test account and automatically add it to the CLI config
96
- targetTestingAccountId = await (0, helpers_1.createDeveloperTestAccountForLocalDev)(targetProjectAccountId, targetProjectAccountConfig, env);
96
+ targetTestingAccountId = await (0, helpers_1.createDeveloperTestAccountForLocalDev)(targetProjectAccountId, targetProjectAccountConfig, env, true);
97
97
  }
98
98
  }
99
99
  else if (accountType === config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX) {
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fs_extra_1 = __importDefault(require("fs-extra"));
7
7
  const path_1 = __importDefault(require("path"));
8
- const developerTestAccounts_1 = require("@hubspot/local-dev-lib/api/developerTestAccounts");
9
8
  const path_2 = require("@hubspot/local-dev-lib/path");
10
9
  const yargsUtils_1 = require("../../lib/yargsUtils");
11
10
  const promptUtils_1 = require("../../lib/prompts/promptUtils");
@@ -16,8 +15,8 @@ const validation_1 = require("../../lib/validation");
16
15
  const en_1 = require("../../lang/en");
17
16
  const createDeveloperTestAccountConfigPrompt_1 = require("../../lib/prompts/createDeveloperTestAccountConfigPrompt");
18
17
  const errorHandlers_1 = require("../../lib/errorHandlers");
19
- const polling_1 = require("../../lib/polling");
20
18
  const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"));
19
+ const buildAccount_1 = require("../../lib/buildAccount");
21
20
  const command = 'create';
22
21
  const describe = en_1.commands.testAccount.create.describe;
23
22
  async function handler(args) {
@@ -73,36 +72,27 @@ async function handler(args) {
73
72
  text: en_1.commands.testAccount.create.polling.start(testAccountConfig.accountName),
74
73
  });
75
74
  try {
76
- const { data } = await (0, developerTestAccounts_1.createDeveloperTestAccount)(derivedAccountId, testAccountConfig);
75
+ const result = await (0, buildAccount_1.createDeveloperTestAccountV3)(derivedAccountId, testAccountConfig);
77
76
  if (formatOutputAsJson) {
78
- jsonOutput.accountName = data.accountName;
79
- jsonOutput.accountId = data.id;
80
- jsonOutput.personalAccessKey = data.personalAccessKey;
77
+ jsonOutput.accountName = result.accountName;
78
+ jsonOutput.accountId = result.accountId;
79
+ jsonOutput.personalAccessKey = result.personalAccessKey;
81
80
  }
82
- testAccountId = data.id;
81
+ testAccountId = result.accountId;
83
82
  }
84
83
  catch (err) {
85
- (0, errorHandlers_1.logError)(err);
86
- process.exit(exitCodes_1.EXIT_CODES.ERROR);
87
- }
88
- SpinniesManager_1.default.update('createTestAccount', {
89
- text: en_1.commands.testAccount.create.polling.syncing,
90
- });
91
- try {
92
- await (0, polling_1.poll)(() => (0, developerTestAccounts_1.fetchDeveloperTestAccountGateSyncStatus)(derivedAccountId, testAccountId), {
93
- successStates: ['SUCCESS'],
94
- errorStates: [],
95
- });
96
- SpinniesManager_1.default.succeed('createTestAccount', {
97
- text: en_1.commands.testAccount.create.polling.success(testAccountConfig.accountName, testAccountId),
84
+ SpinniesManager_1.default.fail('createTestAccount', {
85
+ text: en_1.commands.testAccount.create.polling.createFailure,
98
86
  });
99
- }
100
- catch (err) {
101
- (0, errorHandlers_1.debugError)(err);
87
+ (0, errorHandlers_1.logError)(err);
102
88
  SpinniesManager_1.default.fail('createTestAccount', {
103
- text: en_1.commands.testAccount.create.polling.failure,
89
+ text: en_1.commands.testAccount.create.polling.createFailure,
104
90
  });
91
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
105
92
  }
93
+ SpinniesManager_1.default.succeed('createTestAccount', {
94
+ text: en_1.commands.testAccount.create.polling.success(testAccountConfig.accountName, testAccountId),
95
+ });
106
96
  if (formatOutputAsJson) {
107
97
  logger_1.uiLogger.json(jsonOutput);
108
98
  }
package/lang/en.d.ts CHANGED
@@ -1502,6 +1502,28 @@ ${string}`;
1502
1502
  readonly app: {
1503
1503
  readonly describe: "Commands for managing apps.";
1504
1504
  readonly subcommands: {
1505
+ readonly install: {
1506
+ readonly describe: "Install an OAuth app into a test account.";
1507
+ readonly options: {
1508
+ readonly appUid: "The uid of the app to install";
1509
+ readonly projectName: "The name of the project that contains the app";
1510
+ };
1511
+ readonly positionals: {
1512
+ readonly testAccountId: "The id of the test account to install the app into";
1513
+ };
1514
+ readonly errors: {
1515
+ readonly mustSpecifyProjectName: `You must specify a project name. Use the ${string} flag to specify the project name or run this command from within a project directory.`;
1516
+ readonly noAppUidFound: `No app uid found. Please specify the app uid with the ${string} flag or run this command from within a project that contains an app.`;
1517
+ readonly appMustBeOauth: "This command only supports installing oauth apps. Please specify an app with oauth auth type.";
1518
+ };
1519
+ readonly polling: {
1520
+ readonly start: "Installing app...";
1521
+ readonly success: "App installed successfully";
1522
+ readonly failure: "App installation failed";
1523
+ readonly error: "Error installing app";
1524
+ };
1525
+ readonly example: "Install the app with uid my-app-uid from the project named \"my-project\" into the target account with id 1234567890";
1526
+ };
1505
1527
  readonly secret: {
1506
1528
  readonly describe: "Commands for managing secrets.";
1507
1529
  readonly subcommands: {
@@ -1811,7 +1833,7 @@ ${string}`;
1811
1833
  readonly start: (testAccountName: string) => string;
1812
1834
  readonly syncing: "Test account created! Syncing account data... (may take a few minutes - you can exit and the sync will continue)";
1813
1835
  readonly success: (testAccountName: string, testAccountId: number) => string;
1814
- readonly failure: "Failed to sync data into test account. The account may not be ready to use.";
1836
+ readonly createFailure: "Failed to create test account.";
1815
1837
  };
1816
1838
  readonly options: {
1817
1839
  readonly configPath: "The path to the test account config";
@@ -1820,7 +1842,7 @@ ${string}`;
1820
1842
  };
1821
1843
  readonly createConfig: {
1822
1844
  readonly describe: "Create a test account config file.";
1823
- readonly pathPrompt: "[--path] What is the path to the test account config?";
1845
+ readonly pathPrompt: "[--path] Enter the name of the Test Account config file: ";
1824
1846
  readonly errors: {
1825
1847
  readonly pathError: "Path is required";
1826
1848
  readonly pathFormatError: "Path must end with .json";
@@ -2763,6 +2785,12 @@ Run ${string} to upgrade to version ${string}`;
2763
2785
  readonly noLogsFound: "No logs found.";
2764
2786
  };
2765
2787
  };
2788
+ readonly buildAccount: {
2789
+ readonly createDeveloperTestAccountV3: {
2790
+ readonly syncFailure: "Failed to sync developer test account";
2791
+ readonly pakFailure: "Failed to generate personal access key for developer test account";
2792
+ };
2793
+ };
2766
2794
  readonly configOptions: {
2767
2795
  readonly enableOrDisableBooleanFieldPrompt: {
2768
2796
  readonly message: (fieldName: string) => string;
@@ -2845,9 +2873,41 @@ Run ${string} to upgrade to version ${string}`;
2845
2873
  readonly keepingCurrentDefault: (accountName: string) => string;
2846
2874
  };
2847
2875
  readonly createDeveloperTestAccountConfigPrompt: {
2848
- readonly namePrompt: "[--name] What is the name of the test account?";
2849
- readonly descriptionPrompt: "[--description] What is the description of the test account?";
2850
- readonly tiersPrompt: "[--tiers] Which product tiers should the test account have?";
2876
+ readonly namePrompt: (withFlag?: boolean) => string;
2877
+ readonly descriptionPrompt: (withFlag?: boolean) => string;
2878
+ readonly useDefaultAccountLevelsPrompt: {
2879
+ readonly message: "Would you like to create a default Test Account, or customize your own?";
2880
+ readonly default: "Default (All Hubs, ENTERPRISE)";
2881
+ readonly manual: "Customize my own";
2882
+ };
2883
+ readonly tiersPrompt: (withFlag?: boolean) => string;
2884
+ readonly tiers: {
2885
+ readonly marketing: {
2886
+ readonly free: "Marketing [FREE]";
2887
+ readonly starter: "Marketing [STARTER]";
2888
+ readonly professional: "Marketing [PROFESSIONAL]";
2889
+ };
2890
+ readonly ops: {
2891
+ readonly free: "Ops [FREE]";
2892
+ readonly starter: "Ops [STARTER]";
2893
+ readonly professional: "Ops [PROFESSIONAL]";
2894
+ };
2895
+ readonly service: {
2896
+ readonly free: "Service [FREE]";
2897
+ readonly starter: "Service [STARTER]";
2898
+ readonly professional: "Service [PROFESSIONAL]";
2899
+ };
2900
+ readonly sales: {
2901
+ readonly free: "Sales [FREE]";
2902
+ readonly starter: "Sales [STARTER]";
2903
+ readonly professional: "Sales [PROFESSIONAL]";
2904
+ };
2905
+ readonly content: {
2906
+ readonly free: "Content [FREE]";
2907
+ readonly starter: "Content [STARTER]";
2908
+ readonly professional: "Content [PROFESSIONAL]";
2909
+ };
2910
+ };
2851
2911
  readonly errors: {
2852
2912
  readonly tiersError: "Cannot have more than one tier per hub";
2853
2913
  };
package/lang/en.js CHANGED
@@ -1500,6 +1500,28 @@ exports.commands = {
1500
1500
  app: {
1501
1501
  describe: 'Commands for managing apps.',
1502
1502
  subcommands: {
1503
+ install: {
1504
+ describe: 'Install an OAuth app into a test account.',
1505
+ options: {
1506
+ appUid: 'The uid of the app to install',
1507
+ projectName: 'The name of the project that contains the app',
1508
+ },
1509
+ positionals: {
1510
+ testAccountId: 'The id of the test account to install the app into',
1511
+ },
1512
+ errors: {
1513
+ mustSpecifyProjectName: `You must specify a project name. Use the ${(0, ui_1.uiCommandReference)('--project-name')} flag to specify the project name or run this command from within a project directory.`,
1514
+ noAppUidFound: `No app uid found. Please specify the app uid with the ${(0, ui_1.uiCommandReference)('--app-uid')} flag or run this command from within a project that contains an app.`,
1515
+ appMustBeOauth: 'This command only supports installing oauth apps. Please specify an app with oauth auth type.',
1516
+ },
1517
+ polling: {
1518
+ start: 'Installing app...',
1519
+ success: 'App installed successfully',
1520
+ failure: 'App installation failed',
1521
+ error: 'Error installing app',
1522
+ },
1523
+ example: 'Install the app with uid my-app-uid from the project named "my-project" into the target account with id 1234567890',
1524
+ },
1503
1525
  secret: {
1504
1526
  describe: 'Commands for managing secrets.',
1505
1527
  subcommands: {
@@ -1809,7 +1831,7 @@ exports.commands = {
1809
1831
  start: (testAccountName) => `Creating test account "${chalk_1.default.bold(testAccountName)}"...`,
1810
1832
  syncing: 'Test account created! Syncing account data... (may take a few minutes - you can exit and the sync will continue)',
1811
1833
  success: (testAccountName, testAccountId) => `Test account "${chalk_1.default.bold(testAccountName)}" successfully created with id: ${chalk_1.default.bold(testAccountId)}`,
1812
- failure: 'Failed to sync data into test account. The account may not be ready to use.',
1834
+ createFailure: 'Failed to create test account.',
1813
1835
  },
1814
1836
  options: {
1815
1837
  configPath: 'The path to the test account config',
@@ -1818,7 +1840,7 @@ exports.commands = {
1818
1840
  },
1819
1841
  createConfig: {
1820
1842
  describe: 'Create a test account config file.',
1821
- pathPrompt: '[--path] What is the path to the test account config?',
1843
+ pathPrompt: '[--path] Enter the name of the Test Account config file: ',
1822
1844
  errors: {
1823
1845
  pathError: 'Path is required',
1824
1846
  pathFormatError: 'Path must end with .json',
@@ -2758,6 +2780,12 @@ exports.lib = {
2758
2780
  noLogsFound: 'No logs found.',
2759
2781
  },
2760
2782
  },
2783
+ buildAccount: {
2784
+ createDeveloperTestAccountV3: {
2785
+ syncFailure: 'Failed to sync developer test account',
2786
+ pakFailure: 'Failed to generate personal access key for developer test account',
2787
+ },
2788
+ },
2761
2789
  configOptions: {
2762
2790
  enableOrDisableBooleanFieldPrompt: {
2763
2791
  message: (fieldName) => `Choose to enable or disable ${fieldName}`,
@@ -2840,9 +2868,41 @@ exports.lib = {
2840
2868
  keepingCurrentDefault: (accountName) => `Account "${accountName}" will continue to be the default account`,
2841
2869
  },
2842
2870
  createDeveloperTestAccountConfigPrompt: {
2843
- namePrompt: '[--name] What is the name of the test account?',
2844
- descriptionPrompt: '[--description] What is the description of the test account?',
2845
- tiersPrompt: '[--tiers] Which product tiers should the test account have?',
2871
+ namePrompt: (withFlag = true) => `${withFlag ? '[--name] ' : ''}Enter the name of the Test Account:`,
2872
+ descriptionPrompt: (withFlag = true) => `${withFlag ? '[--description] ' : ''}Enter the description of the Test Account:`,
2873
+ useDefaultAccountLevelsPrompt: {
2874
+ message: 'Would you like to create a default Test Account, or customize your own?',
2875
+ default: 'Default (All Hubs, ENTERPRISE)',
2876
+ manual: 'Customize my own',
2877
+ },
2878
+ tiersPrompt: (withFlag = true) => `${withFlag ? '[--tiers] ' : ''}Select an option per hub to customize tiers. If left blank, default is ENTERPRISE`,
2879
+ tiers: {
2880
+ marketing: {
2881
+ free: 'Marketing [FREE]',
2882
+ starter: 'Marketing [STARTER]',
2883
+ professional: 'Marketing [PROFESSIONAL]',
2884
+ },
2885
+ ops: {
2886
+ free: 'Ops [FREE]',
2887
+ starter: 'Ops [STARTER]',
2888
+ professional: 'Ops [PROFESSIONAL]',
2889
+ },
2890
+ service: {
2891
+ free: 'Service [FREE]',
2892
+ starter: 'Service [STARTER]',
2893
+ professional: 'Service [PROFESSIONAL]',
2894
+ },
2895
+ sales: {
2896
+ free: 'Sales [FREE]',
2897
+ starter: 'Sales [STARTER]',
2898
+ professional: 'Sales [PROFESSIONAL]',
2899
+ },
2900
+ content: {
2901
+ free: 'Content [FREE]',
2902
+ starter: 'Content [STARTER]',
2903
+ professional: 'Content [PROFESSIONAL]',
2904
+ },
2905
+ },
2846
2906
  errors: {
2847
2907
  tiersError: 'Cannot have more than one tier per hub',
2848
2908
  },
@@ -25,7 +25,7 @@ const projects_1 = require("@hubspot/local-dev-lib/constants/projects");
25
25
  const transform_1 = require("@hubspot/project-parsing-lib/src/lib/transform");
26
26
  const Migration_1 = require("@hubspot/local-dev-lib/types/Migration");
27
27
  const projects_2 = require("@hubspot/local-dev-lib/api/projects");
28
- const inquirer = require('inquirer');
28
+ const prompts_1 = require("@inquirer/prompts");
29
29
  const promptUtils_1 = require("../prompts/promptUtils");
30
30
  const ui_1 = require("../ui");
31
31
  const ensureProjectExists_1 = require("../projects/ensureProjectExists");
@@ -119,11 +119,7 @@ async function promptForAppToMigrate(allApps, derivedAccountId) {
119
119
  const enabledChoices = appChoices.filter(app => !app.disabled);
120
120
  const disabledChoices = appChoices.filter(app => app.disabled);
121
121
  const { appId: selectedAppId } = await (0, promptUtils_1.listPrompt)(en_1.lib.migrate.prompt.chooseApp, {
122
- choices: [
123
- ...enabledChoices,
124
- new inquirer.Separator(),
125
- ...disabledChoices,
126
- ],
122
+ choices: [...enabledChoices, new prompts_1.Separator(), ...disabledChoices],
127
123
  });
128
124
  return selectedAppId;
129
125
  }
@@ -1,9 +1,15 @@
1
+ import { DeveloperTestAccountConfig } from '@hubspot/local-dev-lib/types/developerTestAccounts';
1
2
  import { Environment } from '@hubspot/local-dev-lib/types/Config';
2
3
  import { CLIAccount } from '@hubspot/local-dev-lib/types/Accounts';
3
4
  import { SandboxResponse } from '@hubspot/local-dev-lib/types/Sandbox';
4
5
  import { SandboxAccountType } from '../types/Sandboxes';
5
6
  export declare function saveAccountToConfig(accountId: number | undefined, accountName: string, env: Environment, personalAccessKey?: string, force?: boolean): Promise<string>;
6
- export declare function buildDeveloperTestAccount(testAccountName: string, parentAccountConfig: CLIAccount, env: Environment, portalLimit: number): Promise<number>;
7
+ export declare function createDeveloperTestAccountV3(parentAccountId: number, testAccountConfig: DeveloperTestAccountConfig): Promise<{
8
+ accountName: string;
9
+ accountId?: number;
10
+ personalAccessKey?: string;
11
+ }>;
12
+ export declare function buildDeveloperTestAccount(testAccountName: string, parentAccountConfig: CLIAccount, env: Environment, portalLimit: number, useV3?: boolean): Promise<number>;
7
13
  type SandboxAccount = SandboxResponse & {
8
14
  name: string;
9
15
  };