@hubspot/cli 8.0.10-experimental.7 → 8.0.11-experimental.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.
Files changed (170) hide show
  1. package/bin/cli.js +2 -0
  2. package/commands/account/auth.js +12 -22
  3. package/commands/account/clean.js +5 -6
  4. package/commands/account/createOverride.js +7 -7
  5. package/commands/account/info.js +2 -1
  6. package/commands/account/list.js +3 -5
  7. package/commands/account/remove.js +2 -3
  8. package/commands/account/removeOverride.js +8 -10
  9. package/commands/account/rename.js +5 -6
  10. package/commands/account/use.js +8 -19
  11. package/commands/api.d.ts +10 -0
  12. package/commands/api.js +164 -0
  13. package/commands/app/migrate.js +8 -8
  14. package/commands/app/secret/add.js +6 -7
  15. package/commands/app/secret/delete.js +9 -10
  16. package/commands/app/secret/list.js +6 -7
  17. package/commands/app/secret/update.js +8 -9
  18. package/commands/auth.js +12 -12
  19. package/commands/cms/app/create.js +9 -5
  20. package/commands/cms/convertFields.js +8 -8
  21. package/commands/cms/delete.js +2 -3
  22. package/commands/cms/fetch.js +7 -7
  23. package/commands/cms/function/create.js +9 -5
  24. package/commands/cms/function/deploy.js +2 -3
  25. package/commands/cms/function/list.js +11 -7
  26. package/commands/cms/function/logs.js +17 -23
  27. package/commands/cms/function/server.js +2 -3
  28. package/commands/cms/getReactModule.js +7 -8
  29. package/commands/cms/lighthouseScore.js +25 -24
  30. package/commands/cms/lint.js +4 -5
  31. package/commands/cms/list.js +5 -6
  32. package/commands/cms/module/create.js +9 -5
  33. package/commands/cms/module/marketplace-validate.js +7 -8
  34. package/commands/cms/mv.js +2 -3
  35. package/commands/cms/template/create.js +10 -6
  36. package/commands/cms/theme/create.js +5 -5
  37. package/commands/cms/theme/generate-selectors.js +5 -4
  38. package/commands/cms/theme/marketplace-validate.js +8 -9
  39. package/commands/cms/theme/preview.js +16 -8
  40. package/commands/cms/upload.js +15 -12
  41. package/commands/cms/watch.js +5 -5
  42. package/commands/cms/webpack/create.js +5 -5
  43. package/commands/completion.js +3 -5
  44. package/commands/config/migrate.js +6 -7
  45. package/commands/config/set.js +5 -6
  46. package/commands/customObject/create.js +4 -5
  47. package/commands/customObject/createSchema.js +4 -5
  48. package/commands/customObject/deleteSchema.js +4 -5
  49. package/commands/customObject/fetchAllSchemas.js +2 -3
  50. package/commands/customObject/fetchSchema.js +2 -3
  51. package/commands/customObject/listSchemas.js +2 -3
  52. package/commands/customObject/updateSchema.js +4 -5
  53. package/commands/doctor.js +8 -8
  54. package/commands/feedback.js +6 -4
  55. package/commands/filemanager/fetch.js +5 -6
  56. package/commands/filemanager/upload.js +5 -5
  57. package/commands/getStarted.js +14 -16
  58. package/commands/hubdb/clear.js +5 -6
  59. package/commands/hubdb/create.js +4 -5
  60. package/commands/hubdb/delete.js +8 -9
  61. package/commands/hubdb/fetch.js +5 -6
  62. package/commands/hubdb/list.js +16 -14
  63. package/commands/init.js +14 -17
  64. package/commands/mcp/setup.js +5 -6
  65. package/commands/mcp/start.js +2 -3
  66. package/commands/open.js +4 -5
  67. package/commands/project/add.js +10 -5
  68. package/commands/project/create.js +10 -10
  69. package/commands/project/delete.d.ts +7 -0
  70. package/commands/project/delete.js +74 -0
  71. package/commands/project/deploy.js +36 -34
  72. package/commands/project/dev/deprecatedFlow.js +42 -15
  73. package/commands/project/dev/index.d.ts +3 -3
  74. package/commands/project/dev/index.js +24 -30
  75. package/commands/project/dev/unifiedFlow.js +37 -14
  76. package/commands/project/download.js +10 -11
  77. package/commands/project/info.d.ts +4 -0
  78. package/commands/project/info.js +67 -0
  79. package/commands/project/installDeps.js +9 -6
  80. package/commands/project/lint.js +11 -8
  81. package/commands/project/list.js +14 -14
  82. package/commands/project/listBuilds.js +8 -6
  83. package/commands/project/logs.js +5 -6
  84. package/commands/project/migrate.js +8 -8
  85. package/commands/project/open.js +5 -6
  86. package/commands/project/profile/add.js +12 -8
  87. package/commands/project/profile/delete.js +15 -11
  88. package/commands/project/updateDeps.js +9 -6
  89. package/commands/project/upload.js +31 -17
  90. package/commands/project/validate.js +11 -11
  91. package/commands/project/watch.js +20 -20
  92. package/commands/project.js +4 -0
  93. package/commands/sandbox/create.js +15 -15
  94. package/commands/sandbox/delete.js +13 -14
  95. package/commands/secret/addSecret.js +6 -7
  96. package/commands/secret/deleteSecret.js +5 -6
  97. package/commands/secret/listSecret.js +2 -3
  98. package/commands/secret/updateSecret.js +4 -5
  99. package/commands/testAccount/create.d.ts +1 -1
  100. package/commands/testAccount/create.js +20 -16
  101. package/commands/testAccount/createConfig.js +7 -8
  102. package/commands/testAccount/delete.js +27 -18
  103. package/commands/testAccount/importData.js +6 -7
  104. package/commands/upgrade.js +9 -10
  105. package/lang/en.d.ts +123 -5
  106. package/lang/en.js +121 -6
  107. package/lib/accountAuth.js +2 -2
  108. package/lib/buildAccount.js +3 -3
  109. package/lib/constants.d.ts +0 -1
  110. package/lib/constants.js +0 -1
  111. package/lib/doctor/Diagnosis.js +5 -5
  112. package/lib/errorHandlers/index.js +4 -3
  113. package/lib/errorHandlers/suppressError.js +4 -0
  114. package/lib/errors/PromptExitError.d.ts +4 -2
  115. package/lib/errors/PromptExitError.js +3 -0
  116. package/lib/hasFeature.js +1 -2
  117. package/lib/middleware/autoUpdateMiddleware.js +6 -3
  118. package/lib/process.d.ts +1 -1
  119. package/lib/process.js +10 -3
  120. package/lib/projects/create/v2.js +1 -2
  121. package/lib/projects/delete.d.ts +13 -0
  122. package/lib/projects/delete.js +193 -0
  123. package/lib/projects/localDev/AppDevModeInterface.js +11 -11
  124. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +3 -1
  125. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +2 -2
  126. package/lib/projects/localDev/DevSessionManager.d.ts +6 -3
  127. package/lib/projects/localDev/DevSessionManager.js +31 -19
  128. package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +3 -0
  129. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +16 -12
  130. package/lib/projects/localDev/LocalDevProcess.js +6 -5
  131. package/lib/projects/localDev/LocalDevState.d.ts +3 -2
  132. package/lib/projects/localDev/LocalDevState.js +3 -1
  133. package/lib/projects/localDev/helpers/account.d.ts +4 -3
  134. package/lib/projects/localDev/helpers/account.js +16 -19
  135. package/lib/projects/localDev/helpers/process.d.ts +1 -1
  136. package/lib/projects/localDev/helpers/process.js +4 -10
  137. package/lib/projects/localDev/helpers/project.d.ts +4 -3
  138. package/lib/projects/localDev/helpers/project.js +31 -15
  139. package/lib/projects/projectInfo.d.ts +5 -0
  140. package/lib/projects/projectInfo.js +82 -0
  141. package/lib/projects/projectProfiles.d.ts +1 -2
  142. package/lib/projects/projectProfiles.js +5 -17
  143. package/lib/projects/upload.js +19 -0
  144. package/lib/projects/workspaces.d.ts +42 -0
  145. package/lib/projects/workspaces.js +350 -0
  146. package/lib/prompts/createApiSamplePrompt.js +4 -0
  147. package/lib/prompts/projectProfilePrompt.d.ts +2 -0
  148. package/lib/prompts/projectProfilePrompt.js +46 -0
  149. package/lib/prompts/promptUtils.js +3 -2
  150. package/lib/prompts/selectHubDBTablePrompt.js +2 -2
  151. package/lib/prompts/selectPublicAppForMigrationPrompt.js +2 -2
  152. package/lib/theme/cmsDevServerProcess.d.ts +2 -0
  153. package/lib/theme/cmsDevServerProcess.js +7 -6
  154. package/lib/ui/SpinniesManager.d.ts +1 -0
  155. package/lib/ui/SpinniesManager.js +20 -6
  156. package/lib/ui/spinniesUtils.d.ts +0 -1
  157. package/lib/ui/spinniesUtils.js +6 -16
  158. package/lib/usageTracking.d.ts +3 -4
  159. package/lib/yargs/makeYargsBuilder.d.ts +13 -0
  160. package/lib/yargs/makeYargsBuilder.js +33 -0
  161. package/lib/yargs/makeYargsHandlerWithUsageTracking.d.ts +3 -0
  162. package/lib/yargs/makeYargsHandlerWithUsageTracking.js +95 -0
  163. package/lib/yargs/strictEnforceBoolean.d.ts +1 -0
  164. package/lib/yargs/strictEnforceBoolean.js +13 -0
  165. package/lib/yargsUtils.d.ts +3 -16
  166. package/lib/yargsUtils.js +3 -48
  167. package/package.json +5 -4
  168. package/types/LocalDev.d.ts +5 -0
  169. package/types/Projects.d.ts +19 -0
  170. package/types/Yargs.d.ts +18 -1
@@ -7,30 +7,29 @@ import { commands, lib } from '../../lang/en.js';
7
7
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
8
8
  import { uiFeatureHighlight, uiBetaTag } from '../../lib/ui/index.js';
9
9
  import { SANDBOX_TYPE_MAP, validateSandboxUsageLimits, } from '../../lib/sandboxes.js';
10
- import { trackCommandUsage } from '../../lib/usageTracking.js';
11
10
  import { sandboxTypePrompt } from '../../lib/prompts/sandboxesPrompt.js';
12
11
  import { promptUser } from '../../lib/prompts/promptUtils.js';
13
12
  import { logError } from '../../lib/errorHandlers/index.js';
14
13
  import { buildV2Sandbox } from '../../lib/buildAccount.js';
15
14
  import { hubspotAccountNamePrompt } from '../../lib/prompts/accountNamePrompt.js';
15
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
16
16
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
17
17
  const command = 'create';
18
18
  const describe = uiBetaTag(commands.sandbox.subcommands.create.describe, false);
19
19
  async function handler(args) {
20
- const { name, type, force, derivedAccountId } = args;
20
+ const { name, type, force, derivedAccountId, exit } = args;
21
21
  const accountConfig = getConfigAccountById(derivedAccountId);
22
22
  const env = getConfigAccountEnvironment(derivedAccountId);
23
- trackCommandUsage('sandbox-create', {}, derivedAccountId);
24
23
  // Check if account config exists
25
24
  if (!accountConfig) {
26
25
  uiLogger.error(commands.sandbox.subcommands.create.failure.noAccountConfig(derivedAccountId));
27
- process.exit(EXIT_CODES.ERROR);
26
+ return exit(EXIT_CODES.ERROR);
28
27
  }
29
28
  // Default account is not a production portal
30
29
  if (accountConfig.accountType &&
31
30
  accountConfig.accountType !== HUBSPOT_ACCOUNT_TYPES.STANDARD) {
32
31
  uiLogger.error(commands.sandbox.subcommands.create.failure.invalidAccountType(HUBSPOT_ACCOUNT_TYPE_STRINGS[HUBSPOT_ACCOUNT_TYPES[accountConfig.accountType]], accountConfig.name || ''));
33
- process.exit(EXIT_CODES.ERROR);
32
+ return exit(EXIT_CODES.ERROR);
34
33
  }
35
34
  let typePrompt;
36
35
  let namePrompt;
@@ -40,7 +39,7 @@ async function handler(args) {
40
39
  }
41
40
  else {
42
41
  uiLogger.error(commands.sandbox.subcommands.create.failure.optionMissing.type);
43
- process.exit(EXIT_CODES.ERROR);
42
+ return exit(EXIT_CODES.ERROR);
44
43
  }
45
44
  }
46
45
  const sandboxType = type
@@ -64,7 +63,7 @@ async function handler(args) {
64
63
  else {
65
64
  logError(err);
66
65
  }
67
- process.exit(EXIT_CODES.ERROR);
66
+ return exit(EXIT_CODES.ERROR);
68
67
  }
69
68
  if (!name) {
70
69
  if (!force) {
@@ -72,14 +71,15 @@ async function handler(args) {
72
71
  }
73
72
  else {
74
73
  uiLogger.error(commands.sandbox.subcommands.create.failure.optionMissing.name);
75
- process.exit(EXIT_CODES.ERROR);
74
+ return exit(EXIT_CODES.ERROR);
76
75
  }
77
76
  }
78
- const sandboxName = name || (namePrompt && namePrompt.name);
79
- if (!sandboxName) {
77
+ const maybeSandboxName = name || (namePrompt && namePrompt.name);
78
+ if (!maybeSandboxName) {
80
79
  uiLogger.error(commands.sandbox.subcommands.create.failure.optionMissing.name);
81
- process.exit(EXIT_CODES.ERROR);
80
+ return exit(EXIT_CODES.ERROR);
82
81
  }
82
+ const sandboxName = maybeSandboxName;
83
83
  let contactRecordsSyncPromptResult = false;
84
84
  if (!force) {
85
85
  const isStandardSandbox = sandboxType === HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX;
@@ -101,7 +101,7 @@ async function handler(args) {
101
101
  // Check if sandbox account config exists
102
102
  if (!sandboxAccountConfig) {
103
103
  uiLogger.error(commands.sandbox.subcommands.create.failure.noSandboxAccountConfig(result.sandbox.sandboxHubId));
104
- process.exit(EXIT_CODES.ERROR);
104
+ return exit(EXIT_CODES.ERROR);
105
105
  }
106
106
  const highlightItems = ['accountsUseCommand', 'projectCreateCommand'];
107
107
  if (sandboxType === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX) {
@@ -111,11 +111,11 @@ async function handler(args) {
111
111
  highlightItems.push('projectUploadCommand');
112
112
  }
113
113
  uiFeatureHighlight(highlightItems);
114
- process.exit(EXIT_CODES.SUCCESS);
114
+ return exit(EXIT_CODES.SUCCESS);
115
115
  }
116
116
  catch (error) {
117
117
  // Errors are logged in util functions
118
- process.exit(EXIT_CODES.ERROR);
118
+ return exit(EXIT_CODES.ERROR);
119
119
  }
120
120
  }
121
121
  function sandboxCreateBuilder(yargs) {
@@ -150,7 +150,7 @@ const builder = makeYargsBuilder(sandboxCreateBuilder, command, describe, {
150
150
  const sandboxCreateCommand = {
151
151
  command,
152
152
  describe,
153
- handler,
153
+ handler: makeYargsHandlerWithUsageTracking('sandbox-create', handler),
154
154
  builder,
155
155
  };
156
156
  export default sandboxCreateCommand;
@@ -4,7 +4,6 @@ import { deleteSandbox } from '@hubspot/local-dev-lib/api/sandboxHubs';
4
4
  import { getConfigAccountEnvironment, removeAccountFromConfig, setConfigAccountAsDefault, getAllConfigAccounts, getConfigAccountIfExists, getConfigDefaultAccountIfExists, } from '@hubspot/local-dev-lib/config';
5
5
  import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
6
6
  import { getValidEnv } from '@hubspot/local-dev-lib/environment';
7
- import { trackCommandUsage } from '../../lib/usageTracking.js';
8
7
  import { logError, debugError } from '../../lib/errorHandlers/index.js';
9
8
  import { commands } from '../../lang/en.js';
10
9
  import { deleteSandboxPrompt } from '../../lib/prompts/sandboxesPrompt.js';
@@ -12,12 +11,12 @@ import { selectAccountFromConfig } from '../../lib/prompts/accountsPrompt.js';
12
11
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
13
12
  import { promptUser } from '../../lib/prompts/promptUtils.js';
14
13
  import { uiAuthCommandReference, uiBetaTag } from '../../lib/ui/index.js';
14
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
15
15
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
16
16
  const command = 'delete';
17
17
  const describe = uiBetaTag(commands.sandbox.subcommands.delete.describe, false);
18
18
  async function handler(args) {
19
- const { userProvidedAccount, derivedAccountId, force } = args;
20
- trackCommandUsage('sandbox-delete', {}, derivedAccountId);
19
+ const { userProvidedAccount, force, exit } = args;
21
20
  let accountPrompt;
22
21
  if (!userProvidedAccount) {
23
22
  if (!force) {
@@ -27,19 +26,19 @@ async function handler(args) {
27
26
  // Account is required, throw error if force flag is present and no account is specified
28
27
  uiLogger.log('');
29
28
  uiLogger.error(commands.sandbox.subcommands.delete.failure.noAccount);
30
- process.exit(EXIT_CODES.ERROR);
29
+ return exit(EXIT_CODES.ERROR);
31
30
  }
32
31
  if (!accountPrompt) {
33
32
  uiLogger.log('');
34
33
  uiLogger.error(commands.sandbox.subcommands.delete.failure.noSandboxAccounts);
35
- process.exit(EXIT_CODES.ERROR);
34
+ return exit(EXIT_CODES.ERROR);
36
35
  }
37
36
  }
38
37
  const accountIdentifier = userProvidedAccount || accountPrompt.account;
39
38
  const sandboxAccount = getConfigAccountIfExists(accountIdentifier);
40
39
  if (!sandboxAccount) {
41
40
  uiLogger.error(commands.sandbox.subcommands.delete.failure.noSandboxAccountId);
42
- process.exit(EXIT_CODES.ERROR);
41
+ return exit(EXIT_CODES.ERROR);
43
42
  }
44
43
  const sandboxAccountId = sandboxAccount.accountId;
45
44
  const defaultAccount = getConfigDefaultAccountIfExists();
@@ -56,14 +55,14 @@ async function handler(args) {
56
55
  const parentAccountPrompt = await deleteSandboxPrompt(true);
57
56
  if (!parentAccountPrompt) {
58
57
  uiLogger.error(commands.sandbox.subcommands.delete.failure.noParentAccount);
59
- process.exit(EXIT_CODES.ERROR);
58
+ return exit(EXIT_CODES.ERROR);
60
59
  }
61
60
  const parentAccount = getConfigAccountIfExists(parentAccountPrompt.account);
62
61
  parentAccountId = parentAccount?.accountId;
63
62
  }
64
63
  else {
65
64
  uiLogger.error(commands.sandbox.subcommands.delete.failure.noParentAccount);
66
- process.exit(EXIT_CODES.ERROR);
65
+ return exit(EXIT_CODES.ERROR);
67
66
  }
68
67
  }
69
68
  }
@@ -76,7 +75,7 @@ async function handler(args) {
76
75
  uiLogger.log('');
77
76
  uiLogger.error(commands.sandbox.subcommands.delete.failure.noParentPortalAvailable(command, url));
78
77
  uiLogger.log('');
79
- process.exit(EXIT_CODES.ERROR);
78
+ return exit(EXIT_CODES.ERROR);
80
79
  }
81
80
  uiLogger.debug(commands.sandbox.subcommands.delete.debug.deleting(sandboxAccountId));
82
81
  if (isDefaultAccount) {
@@ -93,7 +92,7 @@ async function handler(args) {
93
92
  },
94
93
  ]);
95
94
  if (!confirmed) {
96
- process.exit(EXIT_CODES.SUCCESS);
95
+ return exit(EXIT_CODES.SUCCESS);
97
96
  }
98
97
  }
99
98
  await deleteSandbox(parentAccountId, sandboxAccountId);
@@ -111,7 +110,7 @@ async function handler(args) {
111
110
  // If force is specified, skip prompt and set the parent account id as the default account
112
111
  setConfigAccountAsDefault(parentAccountId);
113
112
  }
114
- process.exit(EXIT_CODES.SUCCESS);
113
+ return exit(EXIT_CODES.SUCCESS);
115
114
  }
116
115
  catch (err) {
117
116
  debugError(err);
@@ -147,12 +146,12 @@ async function handler(args) {
147
146
  // If force is specified, skip prompt and set the parent account id as the default account
148
147
  setConfigAccountAsDefault(parentAccountId);
149
148
  }
150
- process.exit(EXIT_CODES.SUCCESS);
149
+ return exit(EXIT_CODES.SUCCESS);
151
150
  }
152
151
  else {
153
152
  logError(err);
154
153
  }
155
- process.exit(EXIT_CODES.ERROR);
154
+ return exit(EXIT_CODES.ERROR);
156
155
  }
157
156
  }
158
157
  function sandboxDeleteBuilder(yargs) {
@@ -183,7 +182,7 @@ const builder = makeYargsBuilder(sandboxDeleteBuilder, command, describe, {
183
182
  const sandboxDeleteCommand = {
184
183
  command,
185
184
  describe,
186
- handler,
185
+ handler: makeYargsHandlerWithUsageTracking('sandbox-delete', handler),
187
186
  builder,
188
187
  };
189
188
  export default sandboxDeleteCommand;
@@ -1,17 +1,16 @@
1
1
  import { addSecret, fetchSecrets } from '@hubspot/local-dev-lib/api/secrets';
2
2
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
3
- import { trackCommandUsage } from '../../lib/usageTracking.js';
4
3
  import { secretValuePrompt, secretNamePrompt, } from '../../lib/prompts/secretPrompt.js';
5
4
  import { commands } from '../../lang/en.js';
6
5
  import { uiLogger } from '../../lib/ui/logger.js';
7
6
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
7
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
8
8
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
9
  const command = 'add [name]';
10
10
  const describe = commands.secret.subcommands.add.describe;
11
11
  async function handler(args) {
12
- const { name, derivedAccountId } = args;
12
+ const { name, derivedAccountId, exit } = args;
13
13
  let secretName = name;
14
- trackCommandUsage('secrets-add', {}, derivedAccountId);
15
14
  try {
16
15
  if (!secretName) {
17
16
  const { secretName: name } = await secretNamePrompt();
@@ -20,7 +19,7 @@ async function handler(args) {
20
19
  const { data: { results: secrets }, } = await fetchSecrets(derivedAccountId);
21
20
  if (secrets.includes(secretName)) {
22
21
  uiLogger.error(commands.secret.subcommands.add.errors.alreadyExists(secretName));
23
- return process.exit(EXIT_CODES.ERROR);
22
+ return exit(EXIT_CODES.ERROR);
24
23
  }
25
24
  const { secretValue } = await secretValuePrompt();
26
25
  await addSecret(derivedAccountId, secretName, secretValue);
@@ -32,9 +31,9 @@ async function handler(args) {
32
31
  request: 'add secret',
33
32
  accountId: derivedAccountId,
34
33
  }));
35
- return process.exit(EXIT_CODES.ERROR);
34
+ return exit(EXIT_CODES.ERROR);
36
35
  }
37
- process.exit(EXIT_CODES.SUCCESS);
36
+ return exit(EXIT_CODES.SUCCESS);
38
37
  }
39
38
  function addSecretBuilder(yargs) {
40
39
  yargs.positional('name', {
@@ -52,7 +51,7 @@ const builder = makeYargsBuilder(addSecretBuilder, command, describe, {
52
51
  const addSecretCommand = {
53
52
  command,
54
53
  describe,
55
- handler,
54
+ handler: makeYargsHandlerWithUsageTracking('secrets-add', handler),
56
55
  builder,
57
56
  };
58
57
  export default addSecretCommand;
@@ -3,21 +3,20 @@ import { secretListPrompt } from '../../lib/prompts/secretPrompt.js';
3
3
  import { confirmPrompt } from '../../lib/prompts/promptUtils.js';
4
4
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
5
5
  import { ApiErrorContext, logError } from '../../lib/errorHandlers/index.js';
6
- import { trackCommandUsage } from '../../lib/usageTracking.js';
7
6
  import { commands } from './../../lang/en.js';
8
7
  import { uiLogger } from '../../lib/ui/logger.js';
8
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
9
9
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
10
10
  const command = 'delete [name]';
11
11
  const describe = commands.secret.subcommands.delete.describe;
12
12
  async function handler(args) {
13
- const { name, derivedAccountId, force } = args;
13
+ const { name, derivedAccountId, force, exit } = args;
14
14
  let secretName = name;
15
- trackCommandUsage('secrets-delete', {}, derivedAccountId);
16
15
  try {
17
16
  const { data: { results: secrets }, } = await fetchSecrets(derivedAccountId);
18
17
  if (secretName && !secrets.includes(secretName)) {
19
18
  uiLogger.error(commands.secret.subcommands.delete.errors.noSecret(secretName));
20
- process.exit(EXIT_CODES.ERROR);
19
+ return exit(EXIT_CODES.ERROR);
21
20
  }
22
21
  if (!secretName) {
23
22
  const { secretToModify } = await secretListPrompt(secrets, commands.secret.subcommands.delete.selectSecret);
@@ -29,7 +28,7 @@ async function handler(args) {
29
28
  }));
30
29
  if (!confirmDelete) {
31
30
  uiLogger.success(commands.secret.subcommands.delete.deleteCanceled);
32
- process.exit(EXIT_CODES.SUCCESS);
31
+ return exit(EXIT_CODES.SUCCESS);
33
32
  }
34
33
  await deleteSecret(derivedAccountId, secretName);
35
34
  uiLogger.success(commands.secret.subcommands.delete.success.delete(secretName, derivedAccountId));
@@ -65,7 +64,7 @@ const builder = makeYargsBuilder(deleteSecretBuilder, command, describe, {
65
64
  const deleteSecretCommand = {
66
65
  command,
67
66
  describe,
68
- handler,
67
+ handler: makeYargsHandlerWithUsageTracking('secrets-delete', handler),
69
68
  builder,
70
69
  };
71
70
  export default deleteSecretCommand;
@@ -1,15 +1,14 @@
1
1
  import { fetchSecrets } from '@hubspot/local-dev-lib/api/secrets';
2
2
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
3
- import { trackCommandUsage } from '../../lib/usageTracking.js';
4
3
  import { uiAccountDescription } from '../../lib/ui/index.js';
5
4
  import { commands } from '../../lang/en.js';
6
5
  import { uiLogger } from '../../lib/ui/logger.js';
6
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
7
7
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
8
8
  const command = 'list';
9
9
  const describe = commands.secret.subcommands.list.describe;
10
10
  async function handler(args) {
11
11
  const { derivedAccountId } = args;
12
- trackCommandUsage('secrets-list', {}, derivedAccountId);
13
12
  try {
14
13
  const { data: { results }, } = await fetchSecrets(derivedAccountId);
15
14
  const groupLabel = commands.secret.subcommands.list.groupLabel(uiAccountDescription(derivedAccountId));
@@ -37,7 +36,7 @@ const builder = makeYargsBuilder(listSecretBuilder, command, describe, {
37
36
  const listSecretCommand = {
38
37
  command,
39
38
  describe,
40
- handler,
39
+ handler: makeYargsHandlerWithUsageTracking('secrets-list', handler),
41
40
  builder,
42
41
  };
43
42
  export default listSecretCommand;
@@ -1,22 +1,21 @@
1
1
  import { updateSecret, fetchSecrets } from '@hubspot/local-dev-lib/api/secrets';
2
2
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
3
3
  import { ApiErrorContext, logError } from '../../lib/errorHandlers/index.js';
4
- import { trackCommandUsage } from '../../lib/usageTracking.js';
5
4
  import { secretValuePrompt, secretListPrompt, } from '../../lib/prompts/secretPrompt.js';
6
5
  import { commands } from '../../lang/en.js';
7
6
  import { uiLogger } from '../../lib/ui/logger.js';
7
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
8
8
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
9
  const command = 'update [name]';
10
10
  const describe = commands.secret.subcommands.update.describe;
11
11
  async function handler(args) {
12
- const { name, derivedAccountId } = args;
12
+ const { name, derivedAccountId, exit } = args;
13
13
  let secretName = name;
14
- trackCommandUsage('secrets-update', {}, derivedAccountId);
15
14
  try {
16
15
  const { data: { results: secrets }, } = await fetchSecrets(derivedAccountId);
17
16
  if (secretName && !secrets.includes(secretName)) {
18
17
  uiLogger.error(commands.secret.subcommands.update.errors.noSecret(secretName));
19
- process.exit(EXIT_CODES.ERROR);
18
+ return exit(EXIT_CODES.ERROR);
20
19
  }
21
20
  if (!secretName) {
22
21
  const { secretToModify } = await secretListPrompt(secrets, commands.secret.subcommands.update.selectSecret);
@@ -51,7 +50,7 @@ const builder = makeYargsBuilder(updateSecretBuilder, command, describe, {
51
50
  const updateSecretCommand = {
52
51
  command,
53
52
  describe,
54
- handler,
53
+ handler: makeYargsHandlerWithUsageTracking('secrets-update', handler),
55
54
  builder,
56
55
  };
57
56
  export default updateSecretCommand;
@@ -1,5 +1,5 @@
1
1
  import { AccountLevel } from '@hubspot/local-dev-lib/types/developerTestAccounts.js';
2
- import { CommonArgs, ConfigArgs, AccountArgs, TestingArgs, YargsCommandModule, EnvironmentArgs, JSONOutputArgs } from '../../types/Yargs.js';
2
+ import { CommonArgs, ConfigArgs, AccountArgs, TestingArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
3
3
  type CreateTestAccountArgs = CommonArgs & AccountArgs & ConfigArgs & TestingArgs & EnvironmentArgs & JSONOutputArgs & {
4
4
  configPath?: string;
5
5
  name?: string;
@@ -3,16 +3,16 @@ import path from 'path';
3
3
  import { getValidEnv } from '@hubspot/local-dev-lib/environment';
4
4
  import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
5
5
  import { getCwd } from '@hubspot/local-dev-lib/path';
6
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
6
7
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
7
8
  import { promptUser, listPrompt } from '../../lib/prompts/promptUtils.js';
8
9
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
9
10
  import { uiLogger } from '../../lib/ui/logger.js';
10
- import { trackCommandUsage } from '../../lib/usageTracking.js';
11
11
  import { fileExists } from '../../lib/validation.js';
12
12
  import { commands } from '../../lang/en.js';
13
13
  import { createDeveloperTestAccountConfigPrompt } from '../../lib/prompts/createDeveloperTestAccountConfigPrompt.js';
14
14
  import { debugError, logError } from '../../lib/errorHandlers/index.js';
15
- import { PromptExitError } from '../../lib/errors/PromptExitError.js';
15
+ import { isPromptExitError } from '../../lib/errors/PromptExitError.js';
16
16
  import SpinniesManager from '../../lib/ui/SpinniesManager.js';
17
17
  import { createDeveloperTestAccountV2, saveAccountToConfig, } from '../../lib/buildAccount.js';
18
18
  import { ACCOUNT_LEVEL_CHOICES, ACCOUNT_LEVELS } from '../../lib/constants.js';
@@ -29,18 +29,16 @@ function hasAnyFlags(args) {
29
29
  contentLevel ||
30
30
  commerceLevel);
31
31
  }
32
- async function readConfigFile(configPath) {
32
+ function readConfigFile(configPath) {
33
33
  const absoluteConfigPath = path.resolve(getCwd(), configPath);
34
34
  if (!fileExists(absoluteConfigPath)) {
35
- uiLogger.error(commands.testAccount.create.errors.configFileNotFound(absoluteConfigPath));
36
- process.exit(EXIT_CODES.ERROR);
35
+ throw new Error(commands.testAccount.create.errors.configFileNotFound(absoluteConfigPath));
37
36
  }
38
37
  try {
39
38
  return JSON.parse(fs.readFileSync(absoluteConfigPath, 'utf8'));
40
39
  }
41
40
  catch (err) {
42
- uiLogger.error(commands.testAccount.create.errors.configFileParseFailed(absoluteConfigPath));
43
- process.exit(EXIT_CODES.ERROR);
41
+ throw new Error(commands.testAccount.create.errors.configFileParseFailed(absoluteConfigPath));
44
42
  }
45
43
  }
46
44
  async function promptForConfigPath() {
@@ -90,10 +88,16 @@ async function buildTestAccountConfig(args) {
90
88
  });
91
89
  }
92
90
  async function handler(args) {
93
- const { derivedAccountId, formatOutputAsJson } = args;
94
- trackCommandUsage('test-account-create', {}, derivedAccountId);
91
+ const { derivedAccountId, formatOutputAsJson, exit } = args;
95
92
  const env = getValidEnv(getConfigAccountEnvironment(derivedAccountId));
96
- const testAccountConfig = await buildTestAccountConfig(args);
93
+ let testAccountConfig;
94
+ try {
95
+ testAccountConfig = await buildTestAccountConfig(args);
96
+ }
97
+ catch (error) {
98
+ logError(error);
99
+ return exit(EXIT_CODES.ERROR);
100
+ }
97
101
  const resultJson = {};
98
102
  SpinniesManager.init({
99
103
  succeedColor: 'white',
@@ -112,7 +116,7 @@ async function handler(args) {
112
116
  SpinniesManager.fail('createTestAccount', {
113
117
  text: commands.testAccount.create.polling.createFailure,
114
118
  });
115
- process.exit(EXIT_CODES.ERROR);
119
+ return exit(EXIT_CODES.ERROR);
116
120
  }
117
121
  SpinniesManager.succeed('createTestAccount', {
118
122
  text: commands.testAccount.create.polling.success(testAccountConfig.accountName, resultJson.accountId, derivedAccountId),
@@ -131,15 +135,15 @@ async function handler(args) {
131
135
  }
132
136
  }
133
137
  catch (e) {
134
- if (e instanceof PromptExitError) {
135
- process.exit(e.exitCode);
138
+ if (isPromptExitError(e)) {
139
+ throw e;
136
140
  }
137
141
  debugError(e);
138
142
  uiLogger.error(commands.testAccount.create.errors.saveAccountToConfigFailure(testAccountConfig.accountName));
139
- process.exit(EXIT_CODES.ERROR);
143
+ return exit(EXIT_CODES.ERROR);
140
144
  }
141
145
  }
142
- process.exit(EXIT_CODES.SUCCESS);
146
+ return exit(EXIT_CODES.SUCCESS);
143
147
  }
144
148
  function createTestAccountBuilder(yargs) {
145
149
  yargs.option('config-path', {
@@ -226,7 +230,7 @@ const builder = makeYargsBuilder(createTestAccountBuilder, command, describe, {
226
230
  const createTestAccountCommand = {
227
231
  command,
228
232
  describe,
229
- handler,
233
+ handler: makeYargsHandlerWithUsageTracking('test-account-create', handler),
230
234
  builder,
231
235
  };
232
236
  export default createTestAccountCommand;
@@ -1,19 +1,18 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  import { getCwd } from '@hubspot/local-dev-lib/path';
4
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
4
5
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
5
6
  import { promptUser } from '../../lib/prompts/promptUtils.js';
6
7
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
7
8
  import { uiLogger } from '../../lib/ui/logger.js';
8
- import { trackCommandUsage } from '../../lib/usageTracking.js';
9
9
  import { commands } from '../../lang/en.js';
10
10
  import { createDeveloperTestAccountConfigPrompt } from '../../lib/prompts/createDeveloperTestAccountConfigPrompt.js';
11
11
  import { fileExists } from '../../lib/validation.js';
12
12
  const command = 'create-config';
13
13
  const describe = commands.testAccount.createConfig.describe;
14
14
  async function handler(args) {
15
- const { derivedAccountId, name, description, path: configPath } = args;
16
- trackCommandUsage('test-account-create-config', {}, derivedAccountId);
15
+ const { name, description, path: configPath, exit } = args;
17
16
  let accountConfigPath = configPath;
18
17
  const testAccountConfig = await createDeveloperTestAccountConfigPrompt({
19
18
  name,
@@ -43,21 +42,21 @@ async function handler(args) {
43
42
  }
44
43
  if (!accountConfigPath) {
45
44
  uiLogger.error(commands.testAccount.createConfig.errors.pathError);
46
- process.exit(EXIT_CODES.ERROR);
45
+ return exit(EXIT_CODES.ERROR);
47
46
  }
48
47
  if (fileExists(accountConfigPath)) {
49
48
  uiLogger.error(commands.testAccount.createConfig.errors.pathExistsError);
50
- process.exit(EXIT_CODES.ERROR);
49
+ return exit(EXIT_CODES.ERROR);
51
50
  }
52
51
  try {
53
52
  fs.writeFileSync(path.resolve(getCwd(), accountConfigPath), JSON.stringify(testAccountConfig, null, 2), 'utf8');
54
53
  }
55
54
  catch (err) {
56
55
  uiLogger.error(commands.testAccount.createConfig.errors.failedToCreate);
57
- process.exit(EXIT_CODES.ERROR);
56
+ return exit(EXIT_CODES.ERROR);
58
57
  }
59
58
  uiLogger.success(commands.testAccount.createConfig.success.configFileCreated(accountConfigPath));
60
- process.exit(EXIT_CODES.SUCCESS);
59
+ return exit(EXIT_CODES.SUCCESS);
61
60
  }
62
61
  function createTestAccountConfigBuilder(yargs) {
63
62
  yargs.option('name', {
@@ -86,7 +85,7 @@ const builder = makeYargsBuilder(createTestAccountConfigBuilder, command, descri
86
85
  const createTestAccountConfigCommand = {
87
86
  command,
88
87
  describe,
89
- handler,
88
+ handler: makeYargsHandlerWithUsageTracking('test-account-create-config', handler),
90
89
  builder,
91
90
  };
92
91
  export default createTestAccountConfigCommand;
@@ -1,12 +1,12 @@
1
1
  import { fetchDeveloperTestAccounts, deleteDeveloperTestAccount, } from '@hubspot/local-dev-lib/api/developerTestAccounts';
2
+ import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
2
3
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
3
4
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
4
5
  import { uiLogger } from '../../lib/ui/logger.js';
5
- import { trackCommandUsage } from '../../lib/usageTracking.js';
6
6
  import { commands } from '../../lang/en.js';
7
7
  import { removeAccountFromConfig, getConfigAccountById, getConfigAccountIfExists, setConfigAccountAsDefault, getConfigDefaultAccountIfExists, } from '@hubspot/local-dev-lib/config';
8
8
  import { promptUser } from '../../lib/prompts/promptUtils.js';
9
- import { debugError } from '../../lib/errorHandlers/index.js';
9
+ import { debugError, logError } from '../../lib/errorHandlers/index.js';
10
10
  const command = 'delete [test-account]';
11
11
  const describe = commands.testAccount.delete.describe;
12
12
  async function getAccountPromptOptions(derivedAccountId) {
@@ -25,8 +25,7 @@ async function getAccountPromptOptions(derivedAccountId) {
25
25
  async function accountToDeleteSelectionPrompt(derivedAccountId) {
26
26
  const accountData = await getAccountPromptOptions(derivedAccountId);
27
27
  if (accountData.length === 0) {
28
- uiLogger.error(commands.testAccount.delete.errors.noAccountsToDelete(derivedAccountId));
29
- process.exit(EXIT_CODES.ERROR);
28
+ throw new Error(commands.testAccount.delete.errors.noAccountsToDelete(derivedAccountId));
30
29
  }
31
30
  const { testAccountToDelete } = await promptUser([
32
31
  {
@@ -79,33 +78,35 @@ async function deleteTestAccountFromConfig(testAccountId, parentAccountName, acc
79
78
  uiLogger.error(commands.testAccount.delete.errors.failedToDeleteFromConfig(testAccountId));
80
79
  }
81
80
  }
82
- async function validateTestAccountConfigs(testAccountId) {
81
+ function validateTestAccountConfigs(testAccountId) {
83
82
  if (!testAccountId) {
84
- uiLogger.error(commands.testAccount.delete.errors.testAccountNotFound(testAccountId));
85
- process.exit(EXIT_CODES.ERROR);
83
+ throw new Error(commands.testAccount.delete.errors.testAccountNotFound(testAccountId));
86
84
  }
87
85
  const testAccountConfig = getConfigAccountById(testAccountId);
88
86
  if (!testAccountConfig) {
89
- uiLogger.error(commands.testAccount.delete.errors.testAccountNotFound(testAccountId));
90
- process.exit(EXIT_CODES.ERROR);
87
+ throw new Error(commands.testAccount.delete.errors.testAccountNotFound(testAccountId));
91
88
  }
92
89
  const parentAccountConfig = getConfigAccountById(testAccountConfig.parentAccountId);
93
90
  if (!parentAccountConfig) {
94
- uiLogger.error(commands.testAccount.delete.errors.parentAccountNotFound(testAccountId));
95
- process.exit(EXIT_CODES.ERROR);
91
+ throw new Error(commands.testAccount.delete.errors.parentAccountNotFound(testAccountId));
96
92
  }
97
93
  const parentAccountName = parentAccountConfig.name;
98
94
  return { testAccountConfig, parentAccountName };
99
95
  }
100
96
  async function handler(args) {
101
- const { derivedAccountId, testAccount, force } = args;
102
- trackCommandUsage('test-account-delete', {}, derivedAccountId);
97
+ const { derivedAccountId, testAccount, force, exit } = args;
103
98
  let testAccountIdToDelete = 0;
104
99
  // See if the account exists
105
100
  if (testAccount) {
106
101
  const account = getConfigAccountIfExists(testAccount);
107
102
  const accountId = account?.accountId || null;
108
- await validateTestAccountConfigs(accountId);
103
+ try {
104
+ validateTestAccountConfigs(accountId);
105
+ }
106
+ catch (error) {
107
+ logError(error);
108
+ return exit(EXIT_CODES.ERROR);
109
+ }
109
110
  if (accountId) {
110
111
  testAccountIdToDelete = accountId;
111
112
  }
@@ -119,10 +120,18 @@ async function handler(args) {
119
120
  catch (err) {
120
121
  debugError(err);
121
122
  uiLogger.error(commands.testAccount.delete.errors.failedToSelectAccount);
122
- process.exit(EXIT_CODES.ERROR);
123
+ return exit(EXIT_CODES.ERROR);
123
124
  }
124
125
  }
125
- const { testAccountConfig, parentAccountName } = await validateTestAccountConfigs(testAccountIdToDelete);
126
+ let testAccountConfig;
127
+ let parentAccountName;
128
+ try {
129
+ ({ testAccountConfig, parentAccountName } = validateTestAccountConfigs(testAccountIdToDelete));
130
+ }
131
+ catch (error) {
132
+ logError(error);
133
+ return exit(EXIT_CODES.ERROR);
134
+ }
126
135
  // If --force, don't prompt user; else confirm deletion
127
136
  let shouldDeleteAccount;
128
137
  if (force) {
@@ -139,7 +148,7 @@ async function handler(args) {
139
148
  else {
140
149
  uiLogger.info(commands.testAccount.delete.info.deletionCanceled);
141
150
  }
142
- process.exit(EXIT_CODES.SUCCESS);
151
+ return exit(EXIT_CODES.SUCCESS);
143
152
  }
144
153
  function deleteTestAccountBuilder(yargs) {
145
154
  yargs.positional('test-account', {
@@ -182,7 +191,7 @@ const builder = makeYargsBuilder(deleteTestAccountBuilder, command, describe, {
182
191
  const deleteTestAccountCommand = {
183
192
  command,
184
193
  describe,
185
- handler,
194
+ handler: makeYargsHandlerWithUsageTracking('test-account-delete', handler),
186
195
  builder,
187
196
  };
188
197
  export default deleteTestAccountCommand;