@hubspot/cli 7.6.0-beta.0 → 7.6.0-beta.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 (57) hide show
  1. package/bin/hs +1 -1
  2. package/commands/account/auth.js +3 -3
  3. package/commands/auth.js +23 -25
  4. package/commands/getStarted.js +55 -8
  5. package/commands/init.js +29 -31
  6. package/commands/project/cloneApp.js +4 -4
  7. package/commands/project/create.js +9 -9
  8. package/commands/project/dev/deprecatedFlow.js +4 -4
  9. package/commands/project/dev/index.js +5 -5
  10. package/commands/project/dev/unifiedFlow.js +8 -0
  11. package/commands/project/upload.d.ts +2 -2
  12. package/commands/project/upload.js +13 -2
  13. package/commands/sandbox/delete.js +5 -5
  14. package/commands/testAccount/create.d.ts +2 -2
  15. package/commands/testAccount/create.js +41 -3
  16. package/lang/en.d.ts +53 -38
  17. package/lang/en.js +50 -35
  18. package/lang/en.lyaml +2 -0
  19. package/lib/accountTypes.d.ts +1 -0
  20. package/lib/accountTypes.js +20 -9
  21. package/lib/app/migrate_legacy.js +2 -3
  22. package/lib/app/urls.d.ts +1 -1
  23. package/lib/commonOpts.d.ts +2 -0
  24. package/lib/commonOpts.js +21 -9
  25. package/lib/middleware/__test__/configMiddleware.test.js +2 -2
  26. package/lib/middleware/configMiddleware.js +10 -2
  27. package/lib/parsing.d.ts +1 -0
  28. package/lib/parsing.js +11 -0
  29. package/lib/polling.d.ts +1 -1
  30. package/lib/polling.js +11 -1
  31. package/lib/projects/add/v3AddComponent.js +4 -0
  32. package/lib/projects/create/index.d.ts +3 -2
  33. package/lib/projects/create/index.js +11 -5
  34. package/lib/projects/create/v3.d.ts +3 -3
  35. package/lib/projects/create/v3.js +2 -2
  36. package/lib/projects/localDev/AppDevModeInterface.js +1 -1
  37. package/lib/projects/localDev/LocalDevProcess.d.ts +3 -2
  38. package/lib/projects/localDev/LocalDevProcess.js +16 -12
  39. package/lib/projects/localDev/LocalDevState.d.ts +10 -5
  40. package/lib/projects/localDev/LocalDevState.js +18 -20
  41. package/lib/projects/localDev/LocalDevWatcher.js +1 -1
  42. package/lib/prompts/personalAccessKeyPrompt.js +2 -2
  43. package/lib/prompts/projectNameAndDestPrompt.d.ts +3 -0
  44. package/lib/prompts/projectNameAndDestPrompt.js +60 -0
  45. package/lib/prompts/selectProjectTemplatePrompt.d.ts +26 -0
  46. package/lib/prompts/{createProjectPrompt.js → selectProjectTemplatePrompt.js} +6 -55
  47. package/lib/ui/logger.d.ts +1 -0
  48. package/lib/ui/logger.js +1 -0
  49. package/lib/validation.d.ts +1 -1
  50. package/lib/validation.js +4 -4
  51. package/lib/yargsUtils.d.ts +1 -0
  52. package/lib/yargsUtils.js +3 -0
  53. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  54. package/package.json +3 -3
  55. package/types/LocalDev.d.ts +1 -0
  56. package/types/Yargs.d.ts +5 -1
  57. package/lib/prompts/createProjectPrompt.d.ts +0 -28
@@ -19,10 +19,10 @@ const yargsUtils_1 = require("../../lib/yargsUtils");
19
19
  const command = 'delete';
20
20
  const describe = (0, ui_1.uiBetaTag)((0, lang_1.i18n)(`commands.sandbox.subcommands.delete.describe`), false);
21
21
  async function handler(args) {
22
- const { providedAccountId, force } = args;
23
- (0, usageTracking_1.trackCommandUsage)('sandbox-delete', {}, providedAccountId);
22
+ const { userProvidedAccount, derivedAccountId, force } = args;
23
+ (0, usageTracking_1.trackCommandUsage)('sandbox-delete', {}, derivedAccountId);
24
24
  let accountPrompt;
25
- if (!providedAccountId) {
25
+ if (!userProvidedAccount) {
26
26
  if (!force) {
27
27
  accountPrompt = await (0, sandboxesPrompt_1.deleteSandboxPrompt)();
28
28
  }
@@ -40,7 +40,7 @@ async function handler(args) {
40
40
  process.exit(exitCodes_1.EXIT_CODES.ERROR);
41
41
  }
42
42
  }
43
- const sandboxAccountId = (0, config_1.getAccountId)(providedAccountId || accountPrompt.account);
43
+ const sandboxAccountId = (0, config_1.getAccountId)(userProvidedAccount || accountPrompt.account);
44
44
  if (!sandboxAccountId) {
45
45
  logger_1.logger.error((0, lang_1.i18n)(`commands.sandbox.subcommands.delete.failure.noSandboxAccountId`));
46
46
  process.exit(exitCodes_1.EXIT_CODES.ERROR);
@@ -114,7 +114,7 @@ async function handler(args) {
114
114
  : `commands.sandbox.subcommands.delete.success.delete`;
115
115
  logger_1.logger.log('');
116
116
  logger_1.logger.success((0, lang_1.i18n)(deleteKey, {
117
- account: providedAccountId || accountPrompt.account,
117
+ account: userProvidedAccount || accountPrompt.account,
118
118
  sandboxHubId: sandboxAccountId || '',
119
119
  }));
120
120
  logger_1.logger.log('');
@@ -1,5 +1,5 @@
1
- import { CommonArgs, ConfigArgs, AccountArgs, TestingArgs, YargsCommandModule, EnvironmentArgs } from '../../types/Yargs';
2
- type CreateTestAccountArgs = CommonArgs & AccountArgs & ConfigArgs & TestingArgs & EnvironmentArgs & {
1
+ import { CommonArgs, ConfigArgs, AccountArgs, TestingArgs, YargsCommandModule, EnvironmentArgs, JSONOutputArgs } from '../../types/Yargs';
2
+ type CreateTestAccountArgs = CommonArgs & AccountArgs & ConfigArgs & TestingArgs & EnvironmentArgs & JSONOutputArgs & {
3
3
  configPath?: string;
4
4
  };
5
5
  declare const createTestAccountCommand: YargsCommandModule<unknown, CreateTestAccountArgs>;
@@ -15,10 +15,13 @@ const usageTracking_1 = require("../../lib/usageTracking");
15
15
  const validation_1 = require("../../lib/validation");
16
16
  const en_1 = require("../../lang/en");
17
17
  const createDeveloperTestAccountConfigPrompt_1 = require("../../lib/prompts/createDeveloperTestAccountConfigPrompt");
18
+ const errorHandlers_1 = require("../../lib/errorHandlers");
19
+ const polling_1 = require("../../lib/polling");
20
+ const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"));
18
21
  const command = 'create';
19
22
  const describe = en_1.commands.testAccount.create.describe;
20
23
  async function handler(args) {
21
- const { derivedAccountId, configPath } = args;
24
+ const { derivedAccountId, configPath, formatOutputAsJson } = args;
22
25
  (0, usageTracking_1.trackCommandUsage)('test-account-create', {}, derivedAccountId);
23
26
  let accountConfigPath = configPath;
24
27
  let testAccountConfig;
@@ -61,14 +64,48 @@ async function handler(args) {
61
64
  else {
62
65
  testAccountConfig = await (0, createDeveloperTestAccountConfigPrompt_1.createDeveloperTestAccountConfigPrompt)();
63
66
  }
67
+ const jsonOutput = {};
68
+ let testAccountId;
69
+ SpinniesManager_1.default.init({
70
+ succeedColor: 'white',
71
+ });
72
+ SpinniesManager_1.default.add('createTestAccount', {
73
+ text: en_1.commands.testAccount.create.polling.start(testAccountConfig.accountName),
74
+ });
64
75
  try {
65
76
  const { data } = await (0, developerTestAccounts_1.createDeveloperTestAccount)(derivedAccountId, testAccountConfig);
66
- logger_1.uiLogger.success(en_1.commands.testAccount.create.success.configFileUpdated(testAccountConfig.accountName, data.id));
77
+ if (formatOutputAsJson) {
78
+ jsonOutput.accountName = data.accountName;
79
+ jsonOutput.accountId = data.id;
80
+ jsonOutput.personalAccessKey = data.personalAccessKey;
81
+ }
82
+ testAccountId = data.id;
67
83
  }
68
84
  catch (err) {
69
- logger_1.uiLogger.error(en_1.commands.testAccount.create.errors.failedToCreate);
85
+ (0, errorHandlers_1.logError)(err);
70
86
  process.exit(exitCodes_1.EXIT_CODES.ERROR);
71
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),
98
+ });
99
+ }
100
+ catch (err) {
101
+ (0, errorHandlers_1.debugError)(err);
102
+ SpinniesManager_1.default.fail('createTestAccount', {
103
+ text: en_1.commands.testAccount.create.polling.failure,
104
+ });
105
+ }
106
+ if (formatOutputAsJson) {
107
+ logger_1.uiLogger.json(jsonOutput);
108
+ }
72
109
  process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
73
110
  }
74
111
  function createTestAccountBuilder(yargs) {
@@ -90,6 +127,7 @@ const builder = (0, yargsUtils_1.makeYargsBuilder)(createTestAccountBuilder, com
90
127
  useAccountOptions: true,
91
128
  useConfigOptions: true,
92
129
  useTestingOptions: true,
130
+ useJSONOutputOptions: true,
93
131
  });
94
132
  const createTestAccountCommand = {
95
133
  command,
package/lang/en.d.ts CHANGED
@@ -28,7 +28,7 @@ export declare const commands: {
28
28
  readonly openDesignManagerPrompt: "Open Design Manager in your browser?";
29
29
  readonly openedDesignManager: "Redirected to Design Manager!";
30
30
  readonly developerOverviewBrowserOpenPrep: "We'll take you to your HubSpot account and walk you through installing and previewing your new app.";
31
- readonly openDeveloperOverviewPrompt: "Open HubSpot to go to your account?";
31
+ readonly openInstallUrl: "Open HubSpot to install your app in your account?";
32
32
  readonly openedDeveloperOverview: "HubSpot opened!";
33
33
  readonly prompts: {
34
34
  readonly selectOption: "Are you looking to build apps or CMS?";
@@ -36,17 +36,20 @@ export declare const commands: {
36
36
  readonly app: "App";
37
37
  readonly cms: "CMS";
38
38
  };
39
+ readonly installDependencies: "Would you like to install dependencies now?";
39
40
  readonly uploadProject: "Would you like to upload your project to HubSpot now?";
40
- readonly appSelected: `We'll create a new project with a sample app for you.
41
- Projects are what you can use to create apps, themes, and more at HubSpot.
42
- Usually you'll use the ${string} command, but we'll go ahead and make one now.`;
43
41
  readonly projectCreated: {
44
42
  readonly title: string;
45
- readonly description: `Upload your project to HubSpot - typically, you'll use the command ${string} for this.
46
- We'll start the process now.`;
43
+ readonly description: `Let's prepare and upload your project to HubSpot.
44
+ You can use ${string} to ${string} and ${string} to ${string} your project.`;
47
45
  };
48
46
  };
49
47
  readonly logs: {
48
+ readonly appSelected: `We'll create a new project with a sample app for you.
49
+ Projects are what you can use to create apps, themes, and more at HubSpot.
50
+ Usually you'll use the ${string} command, but we'll go ahead and make one now.`;
51
+ readonly dependenciesInstalled: "Dependencies installed successfully.";
52
+ readonly dependenciesNotInstalled: `Dependencies not installed. Remember to do this later with the command ${string} from the project directory.`;
50
53
  readonly uploadingProject: "Uploading your project to HubSpot...";
51
54
  readonly uploadSuccess: "Project uploaded successfully!";
52
55
  readonly developerOverviewLink: "Open this link to navigate to your HubSpot developer portal";
@@ -54,6 +57,7 @@ We'll start the process now.`;
54
57
  readonly errors: {
55
58
  readonly uploadFailed: "Failed to upload project to HubSpot.";
56
59
  readonly configFileNotFound: "Could not find project configuration for upload.";
60
+ readonly installDepsFailed: "Failed to install dependencies.";
57
61
  };
58
62
  };
59
63
  readonly completion: {
@@ -189,8 +193,11 @@ Global configuration replaces hubspot.config.yml, and you will be prompted to mi
189
193
  };
190
194
  };
191
195
  readonly auth: {
192
- readonly describe: (configName: string) => string;
196
+ readonly describe: "Configure authentication for your HubSpot account.";
197
+ readonly verboseDescribe: (configName: string, authMethod: string) => string;
193
198
  readonly errors: {
199
+ readonly invalidAccountIdProvided: "--account must be a number.";
200
+ readonly globalConfigFileExists: (accountAuthCommand: string) => string;
194
201
  readonly noConfigFileFound: "No config file was found. To create a new config file, use the \"hs init\" command.";
195
202
  readonly unsupportedAuthType: (type: string, supportedProtocols: string) => string;
196
203
  };
@@ -735,7 +742,8 @@ Global configuration replaces hubspot.config.yml, and you will be prompted to mi
735
742
  };
736
743
  };
737
744
  readonly init: {
738
- readonly describe: (configName: string) => string;
745
+ readonly describe: "Create a CLI config file and configure authentication for your HubSpot account.";
746
+ readonly verboseDescribe: (configName: string, command: string, authMethod: string) => string;
739
747
  readonly options: {
740
748
  readonly authType: {
741
749
  readonly describe: "Authentication mechanism";
@@ -750,14 +758,16 @@ Global configuration replaces hubspot.config.yml, and you will be prompted to mi
750
758
  };
751
759
  readonly success: {
752
760
  readonly configFileCreated: (configPath: string) => string;
753
- readonly configFileUpdated: (account: string, authType: string) => string;
761
+ readonly configFileUpdated: (authType: string, account: string | number) => string;
754
762
  };
755
763
  readonly logs: {
756
764
  readonly updateConfig: "To update an existing config file, use the \"hs auth\" command.";
757
765
  };
758
766
  readonly errors: {
767
+ readonly invalidAccountIdProvided: "--account must be a number.";
759
768
  readonly configFileExists: (configPath: string) => string;
760
769
  readonly bothConfigFilesNotAllowed: (path: string) => string;
770
+ readonly globalConfigFileExists: `You are using our new global configuration for account management, which is not compatible with this command. Please use ${string} instead.`;
761
771
  };
762
772
  };
763
773
  readonly lint: {
@@ -1796,10 +1806,12 @@ ${string}`;
1796
1806
  readonly errors: {
1797
1807
  readonly configFileNotFound: (configPath: string) => string;
1798
1808
  readonly configFileParseFailed: (configPath: string) => string;
1799
- readonly failedToCreate: "Failed to create test account";
1800
1809
  };
1801
- readonly success: {
1802
- readonly configFileUpdated: (testAccountName: string, testAccountId: number) => string;
1810
+ readonly polling: {
1811
+ readonly start: (testAccountName: string) => string;
1812
+ readonly syncing: "Test account created! Syncing account data... (may take a few minutes - you can exit and the sync will continue)";
1813
+ 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.";
1803
1815
  };
1804
1816
  readonly options: {
1805
1817
  readonly configPath: "The path to the test account config";
@@ -2426,6 +2438,12 @@ ${string}`;
2426
2438
  };
2427
2439
  };
2428
2440
  export declare const lib: {
2441
+ readonly parsing: {
2442
+ readonly unableToParseStringToNumber: "Unable to parse string to number";
2443
+ };
2444
+ readonly configMiddleWare: {
2445
+ readonly invalidAccountIdEnvironmentVariable: "Unable to parse `HUBSPOT_ACCOUNT_ID` environment variable into a number";
2446
+ };
2429
2447
  readonly process: {
2430
2448
  readonly exitDebug: (signal: string) => string;
2431
2449
  };
@@ -2595,6 +2613,9 @@ Run ${string} to upgrade to version ${string}`;
2595
2613
  readonly invalidAuthDistCombo: (authType: string, distribution: string) => string;
2596
2614
  };
2597
2615
  };
2616
+ readonly add: {
2617
+ readonly nothingAdded: "No features added.";
2618
+ };
2598
2619
  readonly validateProjectConfig: {
2599
2620
  readonly configNotFound: `Unable to locate a project configuration file. Try running again from a project directory, or run ${string} to create a new project.`;
2600
2621
  readonly configMissingFields: "The project configuration file is missing required fields.";
@@ -2770,31 +2791,18 @@ Run ${string} to upgrade to version ${string}`;
2770
2791
  };
2771
2792
  readonly commonOpts: {
2772
2793
  readonly options: {
2773
- readonly account: {
2774
- readonly describe: "HubSpot account id or name from config";
2775
- };
2776
- readonly config: {
2777
- readonly describe: "Path to a config file";
2778
- };
2779
- readonly overwrite: {
2780
- readonly describe: "Overwrite existing files";
2781
- };
2794
+ readonly account: "HubSpot account id or name from config";
2795
+ readonly config: "Path to a config file";
2796
+ readonly overwrite: "Overwrite existing files";
2782
2797
  readonly modes: {
2783
- readonly describe: {
2784
- readonly default: (modes: string) => string;
2785
- readonly read: (modes: string) => string;
2786
- readonly write: (modes: string) => string;
2787
- };
2788
- };
2789
- readonly qa: {
2790
- readonly describe: "Run command in QA mode";
2791
- };
2792
- readonly useEnv: {
2793
- readonly describe: "Use environment variable config";
2794
- };
2795
- readonly debug: {
2796
- readonly describe: "Set log level to debug";
2798
+ readonly default: (modes: string) => string;
2799
+ readonly read: (modes: string) => string;
2800
+ readonly write: (modes: string) => string;
2797
2801
  };
2802
+ readonly qa: "Run command in QA mode";
2803
+ readonly useEnv: "Use environment variable config";
2804
+ readonly jsonOutput: "Format output as JSON";
2805
+ readonly debug: "Set log level to debug";
2798
2806
  };
2799
2807
  };
2800
2808
  readonly configMigrate: {
@@ -2918,16 +2926,20 @@ Run ${string} to upgrade to version ${string}`;
2918
2926
  readonly languageRequired: "Please select API sample app's language";
2919
2927
  };
2920
2928
  };
2921
- readonly createProjectPrompt: {
2929
+ readonly projectNameAndDestPrompt: {
2922
2930
  readonly enterName: "[--name] Give your project a name: ";
2923
2931
  readonly enterDest: "[--dest] Enter the folder to create the project in:";
2924
- readonly selectTemplate: "[--template] Choose a project template: ";
2925
- readonly features: "[--features] Which features would you like your app to include?";
2926
2932
  readonly errors: {
2927
2933
  readonly nameRequired: "A project name is required";
2928
2934
  readonly destRequired: "A project dest is required";
2929
2935
  readonly invalidDest: "There is an existing project at this destination. Please provide a new path for this project.";
2930
2936
  readonly invalidCharacters: "The selected destination contains invalid characters. Please provide a new path and try again.";
2937
+ };
2938
+ };
2939
+ readonly selectProjectTemplatePrompt: {
2940
+ readonly selectTemplate: "[--template] Choose a project template: ";
2941
+ readonly features: "[--features] Which features would you like your app to include?";
2942
+ readonly errors: {
2931
2943
  readonly invalidTemplate: (template: string) => string;
2932
2944
  readonly projectTemplateRequired: "Project template is required when projectTemplates is provided";
2933
2945
  };
@@ -3032,6 +3044,9 @@ Run ${string} to upgrade to version ${string}`;
3032
3044
  };
3033
3045
  };
3034
3046
  };
3047
+ readonly polling: {
3048
+ readonly timeoutError: (timeoutMs: number) => string;
3049
+ };
3035
3050
  readonly convertFields: {
3036
3051
  readonly positionals: {
3037
3052
  readonly src: {
package/lang/en.js CHANGED
@@ -42,7 +42,7 @@ exports.commands = {
42
42
  openDesignManagerPrompt: 'Open Design Manager in your browser?',
43
43
  openedDesignManager: 'Redirected to Design Manager!',
44
44
  developerOverviewBrowserOpenPrep: "We'll take you to your HubSpot account and walk you through installing and previewing your new app.",
45
- openDeveloperOverviewPrompt: 'Open HubSpot to go to your account?',
45
+ openInstallUrl: 'Open HubSpot to install your app in your account?',
46
46
  openedDeveloperOverview: 'HubSpot opened!',
47
47
  prompts: {
48
48
  selectOption: 'Are you looking to build apps or CMS?',
@@ -50,14 +50,17 @@ exports.commands = {
50
50
  app: 'App',
51
51
  cms: 'CMS',
52
52
  },
53
+ installDependencies: 'Would you like to install dependencies now?',
53
54
  uploadProject: 'Would you like to upload your project to HubSpot now?',
54
- appSelected: `We'll create a new project with a sample app for you.\nProjects are what you can use to create apps, themes, and more at HubSpot.\nUsually you'll use the ${(0, ui_1.uiCommandReference)('hs project create')} command, but we'll go ahead and make one now.`,
55
55
  projectCreated: {
56
56
  title: chalk_1.default.bold('Next steps:'),
57
- description: `Upload your project to HubSpot - typically, you'll use the command ${(0, ui_1.uiCommandReference)('hs project upload')} for this.\nWe'll start the process now.`,
57
+ description: `Let's prepare and upload your project to HubSpot.\nYou can use ${(0, ui_1.uiCommandReference)('hs project install-deps')} to ${chalk_1.default.bold('install dependencies')} and ${(0, ui_1.uiCommandReference)('hs project upload')} to ${chalk_1.default.bold('upload')} your project.`,
58
58
  },
59
59
  },
60
60
  logs: {
61
+ appSelected: `We'll create a new project with a sample app for you.\nProjects are what you can use to create apps, themes, and more at HubSpot.\nUsually you'll use the ${(0, ui_1.uiCommandReference)('hs project create')} command, but we'll go ahead and make one now.`,
62
+ dependenciesInstalled: 'Dependencies installed successfully.',
63
+ dependenciesNotInstalled: `Dependencies not installed. Remember to do this later with the command ${(0, ui_1.uiCommandReference)('hs project install-deps')} from the project directory.`,
61
64
  uploadingProject: 'Uploading your project to HubSpot...',
62
65
  uploadSuccess: 'Project uploaded successfully!',
63
66
  developerOverviewLink: 'Open this link to navigate to your HubSpot developer portal',
@@ -65,6 +68,7 @@ exports.commands = {
65
68
  errors: {
66
69
  uploadFailed: 'Failed to upload project to HubSpot.',
67
70
  configFileNotFound: 'Could not find project configuration for upload.',
71
+ installDepsFailed: 'Failed to install dependencies.',
68
72
  },
69
73
  },
70
74
  completion: {
@@ -196,8 +200,11 @@ exports.commands = {
196
200
  },
197
201
  },
198
202
  auth: {
199
- describe: (configName) => `Configure authentication for your HubSpot account. This will update the ${configName} file that stores your account information.`,
203
+ describe: 'Configure authentication for your HubSpot account.',
204
+ verboseDescribe: (configName, authMethod) => `Configure authentication for a HubSpot account. This will update the ${configName} file that stores your account information.\n\nThe recommended authentication method is ${chalk_1.default.bold(authMethod)}, which uses an access token tied to a specific user account.`,
200
205
  errors: {
206
+ invalidAccountIdProvided: `--account must be a number.`,
207
+ globalConfigFileExists: (accountAuthCommand) => `You are using our new global configuration for account management, which is not compatible with this command. Please use ${(0, ui_1.uiCommandReference)(accountAuthCommand)} instead.`,
201
208
  noConfigFileFound: 'No config file was found. To create a new config file, use the "hs init" command.',
202
209
  unsupportedAuthType: (type, supportedProtocols) => `Unsupported auth type: ${type}. The only supported authentication protocols are ${supportedProtocols}.`,
203
210
  },
@@ -744,7 +751,8 @@ exports.commands = {
744
751
  },
745
752
  },
746
753
  init: {
747
- describe: (configName) => `Configure authentication for your HubSpot account. This will create a ${configName} file to store your account information.`,
754
+ describe: 'Create a CLI config file and configure authentication for your HubSpot account.',
755
+ verboseDescribe: (configName, command, authMethod) => `Configure authentication for a HubSpot account. This will create a ${configName} file to store your account information. To configure authentication for additional accounts, run ${command}.\n\nThe recommended authentication method is ${chalk_1.default.bold(authMethod)}, which uses an access token tied to a specific user account.`,
748
756
  options: {
749
757
  authType: {
750
758
  describe: 'Authentication mechanism',
@@ -759,14 +767,16 @@ exports.commands = {
759
767
  },
760
768
  success: {
761
769
  configFileCreated: (configPath) => `Created config file "${configPath}"`,
762
- configFileUpdated: (account, authType) => `Connected account "${account}" using "${authType}" and set it as the default account`,
770
+ configFileUpdated: (authType, account) => `Connected account "${account}" using "${authType}" and set it as the default account`,
763
771
  },
764
772
  logs: {
765
773
  updateConfig: 'To update an existing config file, use the "hs auth" command.',
766
774
  },
767
775
  errors: {
776
+ invalidAccountIdProvided: `--account must be a number.`,
768
777
  configFileExists: (configPath) => `The config file ${configPath} already exists.`,
769
778
  bothConfigFilesNotAllowed: (path) => `Unable to create config file, because there is an existing one at "${path}". To create a new config file, delete the existing one and try again.`,
779
+ globalConfigFileExists: `You are using our new global configuration for account management, which is not compatible with this command. Please use ${(0, ui_1.uiCommandReference)('hs account auth')} instead.`,
770
780
  },
771
781
  },
772
782
  lint: {
@@ -1794,10 +1804,12 @@ exports.commands = {
1794
1804
  errors: {
1795
1805
  configFileNotFound: (configPath) => `No test account config file exists at ${configPath}. Create a test account config file with the ${(0, ui_1.uiCommandReference)('hs test-account create-config')} command.`,
1796
1806
  configFileParseFailed: (configPath) => `Failed to parse test account config file at ${configPath}`,
1797
- failedToCreate: 'Failed to create test account',
1798
1807
  },
1799
- success: {
1800
- configFileUpdated: (testAccountName, testAccountId) => `Test account "${testAccountName}" successfully created with id ${testAccountId}`,
1808
+ polling: {
1809
+ start: (testAccountName) => `Creating test account "${chalk_1.default.bold(testAccountName)}"...`,
1810
+ syncing: 'Test account created! Syncing account data... (may take a few minutes - you can exit and the sync will continue)',
1811
+ 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.',
1801
1813
  },
1802
1814
  options: {
1803
1815
  configPath: 'The path to the test account config',
@@ -2424,6 +2436,12 @@ exports.commands = {
2424
2436
  },
2425
2437
  };
2426
2438
  exports.lib = {
2439
+ parsing: {
2440
+ unableToParseStringToNumber: 'Unable to parse string to number',
2441
+ },
2442
+ configMiddleWare: {
2443
+ invalidAccountIdEnvironmentVariable: 'Unable to parse `HUBSPOT_ACCOUNT_ID` environment variable into a number',
2444
+ },
2427
2445
  process: {
2428
2446
  exitDebug: (signal) => `Attempting to gracefully exit. Triggered by ${signal}`,
2429
2447
  },
@@ -2592,6 +2610,9 @@ exports.lib = {
2592
2610
  invalidAuthDistCombo: (authType, distribution) => `Invalid distribution and auth combination. Apps with distribution '${distribution}' must have auth '${authType}'`,
2593
2611
  },
2594
2612
  },
2613
+ add: {
2614
+ nothingAdded: 'No features added.',
2615
+ },
2595
2616
  validateProjectConfig: {
2596
2617
  configNotFound: `Unable to locate a project configuration file. Try running again from a project directory, or run ${(0, ui_1.uiCommandReference)('hs project create')} to create a new project.`,
2597
2618
  configMissingFields: 'The project configuration file is missing required fields.',
@@ -2765,31 +2786,18 @@ exports.lib = {
2765
2786
  },
2766
2787
  commonOpts: {
2767
2788
  options: {
2768
- account: {
2769
- describe: 'HubSpot account id or name from config',
2770
- },
2771
- config: {
2772
- describe: 'Path to a config file',
2773
- },
2774
- overwrite: {
2775
- describe: 'Overwrite existing files',
2776
- },
2789
+ account: 'HubSpot account id or name from config',
2790
+ config: 'Path to a config file',
2791
+ overwrite: 'Overwrite existing files',
2777
2792
  modes: {
2778
- describe: {
2779
- default: (modes) => `${modes}`,
2780
- read: (modes) => `Read from ${modes}`,
2781
- write: (modes) => `Write to ${modes}`,
2782
- },
2783
- },
2784
- qa: {
2785
- describe: 'Run command in QA mode',
2786
- },
2787
- useEnv: {
2788
- describe: 'Use environment variable config',
2789
- },
2790
- debug: {
2791
- describe: 'Set log level to debug',
2793
+ default: (modes) => `${modes}`,
2794
+ read: (modes) => `Read from ${modes}`,
2795
+ write: (modes) => `Write to ${modes}`,
2792
2796
  },
2797
+ qa: 'Run command in QA mode',
2798
+ useEnv: 'Use environment variable config',
2799
+ jsonOutput: 'Format output as JSON',
2800
+ debug: 'Set log level to debug',
2793
2801
  },
2794
2802
  },
2795
2803
  configMigrate: {
@@ -2913,16 +2921,20 @@ exports.lib = {
2913
2921
  languageRequired: "Please select API sample app's language",
2914
2922
  },
2915
2923
  },
2916
- createProjectPrompt: {
2924
+ projectNameAndDestPrompt: {
2917
2925
  enterName: '[--name] Give your project a name: ',
2918
2926
  enterDest: '[--dest] Enter the folder to create the project in:',
2919
- selectTemplate: '[--template] Choose a project template: ',
2920
- features: '[--features] Which features would you like your app to include?',
2921
2927
  errors: {
2922
2928
  nameRequired: 'A project name is required',
2923
2929
  destRequired: 'A project dest is required',
2924
2930
  invalidDest: 'There is an existing project at this destination. Please provide a new path for this project.',
2925
2931
  invalidCharacters: 'The selected destination contains invalid characters. Please provide a new path and try again.',
2932
+ },
2933
+ },
2934
+ selectProjectTemplatePrompt: {
2935
+ selectTemplate: '[--template] Choose a project template: ',
2936
+ features: '[--features] Which features would you like your app to include?',
2937
+ errors: {
2926
2938
  invalidTemplate: (template) => `[--template] Could not find template "${template}". Please choose an available template:`,
2927
2939
  projectTemplateRequired: 'Project template is required when projectTemplates is provided',
2928
2940
  },
@@ -3027,6 +3039,9 @@ exports.lib = {
3027
3039
  },
3028
3040
  },
3029
3041
  },
3042
+ polling: {
3043
+ timeoutError: (timeoutMs) => `Polling timed out after ${timeoutMs}ms.`,
3044
+ },
3030
3045
  convertFields: {
3031
3046
  positionals: {
3032
3047
  src: {
package/lang/en.lyaml CHANGED
@@ -1158,6 +1158,8 @@ en:
1158
1158
  describe: "Use environment variable config"
1159
1159
  debug:
1160
1160
  describe: "Set log level to debug"
1161
+ jsonOutput:
1162
+ describe: "Format output as JSON"
1161
1163
  prompts:
1162
1164
  projectDevTargetAccountPrompt:
1163
1165
  createNewSandboxOption: "<Test on a new development sandbox>"
@@ -5,4 +5,5 @@ export declare function isStandardSandbox(accountConfig: CLIAccount): boolean;
5
5
  export declare function isDevelopmentSandbox(accountConfig: CLIAccount): boolean;
6
6
  export declare function isDeveloperTestAccount(accountConfig: CLIAccount): boolean;
7
7
  export declare function isAppDeveloperAccount(accountConfig: CLIAccount): boolean;
8
+ export declare function isTestAccountOrSandbox(accountConfig: CLIAccount): boolean;
8
9
  export declare function isUnifiedAccount(account: CLIAccount): Promise<boolean>;
@@ -6,33 +6,44 @@ exports.isStandardSandbox = isStandardSandbox;
6
6
  exports.isDevelopmentSandbox = isDevelopmentSandbox;
7
7
  exports.isDeveloperTestAccount = isDeveloperTestAccount;
8
8
  exports.isAppDeveloperAccount = isAppDeveloperAccount;
9
+ exports.isTestAccountOrSandbox = isTestAccountOrSandbox;
9
10
  exports.isUnifiedAccount = isUnifiedAccount;
10
11
  const config_1 = require("@hubspot/local-dev-lib/constants/config");
11
12
  const hasFeature_1 = require("./hasFeature");
12
13
  const constants_1 = require("./constants");
13
14
  const getAccountIdentifier_1 = require("@hubspot/local-dev-lib/config/getAccountIdentifier");
14
15
  function isAccountType(accountConfig, accountType) {
15
- return (Boolean(accountConfig.accountType) &&
16
- accountConfig.accountType === accountType);
16
+ return Boolean(accountConfig.accountType && accountType.includes(accountConfig.accountType));
17
17
  }
18
18
  function isStandardAccount(accountConfig) {
19
- return isAccountType(accountConfig, config_1.HUBSPOT_ACCOUNT_TYPES.STANDARD);
19
+ return isAccountType(accountConfig, [config_1.HUBSPOT_ACCOUNT_TYPES.STANDARD]);
20
20
  }
21
21
  function isSandbox(accountConfig) {
22
- return (isAccountType(accountConfig, config_1.HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX) ||
23
- isAccountType(accountConfig, config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX));
22
+ return isAccountType(accountConfig, [
23
+ config_1.HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX,
24
+ config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX,
25
+ ]);
24
26
  }
25
27
  function isStandardSandbox(accountConfig) {
26
- return isAccountType(accountConfig, config_1.HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX);
28
+ return isAccountType(accountConfig, [config_1.HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX]);
27
29
  }
28
30
  function isDevelopmentSandbox(accountConfig) {
29
- return isAccountType(accountConfig, config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX);
31
+ return isAccountType(accountConfig, [
32
+ config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX,
33
+ ]);
30
34
  }
31
35
  function isDeveloperTestAccount(accountConfig) {
32
- return isAccountType(accountConfig, config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST);
36
+ return isAccountType(accountConfig, [config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST]);
33
37
  }
34
38
  function isAppDeveloperAccount(accountConfig) {
35
- return isAccountType(accountConfig, config_1.HUBSPOT_ACCOUNT_TYPES.APP_DEVELOPER);
39
+ return isAccountType(accountConfig, [config_1.HUBSPOT_ACCOUNT_TYPES.APP_DEVELOPER]);
40
+ }
41
+ function isTestAccountOrSandbox(accountConfig) {
42
+ return isAccountType(accountConfig, [
43
+ config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST,
44
+ config_1.HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX,
45
+ config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX,
46
+ ]);
36
47
  }
37
48
  async function isUnifiedAccount(account) {
38
49
  const accountId = (0, getAccountIdentifier_1.getAccountIdentifier)(account);
@@ -18,7 +18,7 @@ const ui_1 = require("../ui");
18
18
  const lang_1 = require("../lang");
19
19
  const accountTypes_1 = require("../accountTypes");
20
20
  const selectPublicAppForMigrationPrompt_1 = require("../prompts/selectPublicAppForMigrationPrompt");
21
- const createProjectPrompt_1 = require("../prompts/createProjectPrompt");
21
+ const projectNameAndDestPrompt_1 = require("../prompts/projectNameAndDestPrompt");
22
22
  const ensureProjectExists_1 = require("../projects/ensureProjectExists");
23
23
  const usageTracking_1 = require("../usageTracking");
24
24
  const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
@@ -58,8 +58,7 @@ async function migrateApp2023_2(derivedAccountId, options, accountConfig) {
58
58
  (0, errorHandlers_1.logError)(error, new errorHandlers_1.ApiErrorContext({ accountId: derivedAccountId }));
59
59
  return process.exit(exitCodes_1.EXIT_CODES.ERROR);
60
60
  }
61
- const createProjectPromptResponse = await (0, createProjectPrompt_1.createProjectPrompt)(options);
62
- const { name: projectName, dest: projectDest } = createProjectPromptResponse;
61
+ const { name: projectName, dest: projectDest } = await (0, projectNameAndDestPrompt_1.projectNameAndDestPrompt)(options);
63
62
  const { projectExists } = await (0, ensureProjectExists_1.ensureProjectExists)(derivedAccountId, projectName, {
64
63
  allowCreate: false,
65
64
  noLogs: true,
package/lib/app/urls.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Environment } from '@hubspot/local-dev-lib/types/Config';
2
2
  type PrivateAppInstallUrlArgs = {
3
3
  targetAccountId: number;
4
4
  env: Environment;
5
- appId: string;
5
+ appId: number;
6
6
  };
7
7
  type PublicAppInstallUrlArgs = {
8
8
  targetAccountId: number;
@@ -11,10 +11,12 @@ export declare function addCmsPublishModeOptions(yargs: Argv, { read, write }: {
11
11
  }): Argv;
12
12
  export declare function addTestingOptions(yargs: Argv): Argv;
13
13
  export declare function addUseEnvironmentOptions(yargs: Argv): Argv;
14
+ export declare function addJSONOutputOptions(yargs: Argv): Argv;
14
15
  export declare function addCustomHelpOutput(yargs: Argv, command: string | string[], describe?: string): Promise<void>;
15
16
  export declare function setLogLevel(options: Arguments<{
16
17
  debug?: boolean;
17
18
  networkDebug?: boolean;
19
+ json?: boolean;
18
20
  }>): void;
19
21
  export declare function getCommandName(argv: Arguments): string;
20
22
  export declare function getCmsPublishMode(options: Arguments<{