@hubspot/cli 7.7.20-experimental.0 → 7.7.21-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 (62) hide show
  1. package/bin/cli.js +6 -2
  2. package/commands/__tests__/getStarted.test.js +0 -10
  3. package/commands/app/__tests__/install.test.d.ts +1 -0
  4. package/commands/app/__tests__/install.test.js +52 -0
  5. package/commands/app/install.d.ts +8 -0
  6. package/commands/app/install.js +127 -0
  7. package/commands/app.js +6 -1
  8. package/commands/getStarted.js +12 -27
  9. package/commands/mcp/setup.js +1 -0
  10. package/commands/mcp/start.d.ts +4 -1
  11. package/commands/mcp/start.js +8 -3
  12. package/commands/project/__tests__/deploy.test.js +27 -25
  13. package/commands/project/__tests__/devUnifiedFlow.test.js +20 -16
  14. package/commands/project/create.js +1 -1
  15. package/commands/project/deploy.d.ts +3 -2
  16. package/commands/project/deploy.js +61 -55
  17. package/commands/project/dev/unifiedFlow.js +7 -6
  18. package/commands/testAccount/__tests__/createConfig.test.js +0 -3
  19. package/commands/testAccount/create.js +14 -24
  20. package/commands/testAccount/createConfig.d.ts +0 -2
  21. package/commands/testAccount/createConfig.js +7 -8
  22. package/lang/en.d.ts +61 -23
  23. package/lang/en.js +62 -24
  24. package/lang/en.lyaml +0 -26
  25. package/lib/__tests__/buildAccount.test.js +30 -2
  26. package/lib/__tests__/usageTracking.test.js +8 -14
  27. package/lib/buildAccount.d.ts +7 -1
  28. package/lib/buildAccount.js +54 -4
  29. package/lib/mcp/setup.js +8 -3
  30. package/lib/projects/add/legacyAddComponent.js +1 -1
  31. package/lib/projects/add/v3AddComponent.js +1 -1
  32. package/lib/projects/localDev/DevServerManager.js +0 -2
  33. package/lib/projects/localDev/DevServerManagerV2.js +0 -2
  34. package/lib/projects/localDev/helpers.d.ts +1 -1
  35. package/lib/projects/localDev/helpers.js +2 -2
  36. package/lib/projects/structure.d.ts +2 -2
  37. package/lib/projects/upload.d.ts +2 -1
  38. package/lib/projects/upload.js +2 -1
  39. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +11 -10
  40. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +73 -31
  41. package/lib/prompts/promptUtils.js +66 -56
  42. package/lib/ui/index.js +1 -1
  43. package/lib/usageTracking.d.ts +11 -0
  44. package/lib/usageTracking.js +67 -73
  45. package/mcp-server/tools/project/AddFeatureToProject.js +4 -1
  46. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  47. package/mcp-server/tools/project/CreateProjectTool.js +4 -1
  48. package/mcp-server/tools/project/DeployProject.js +4 -1
  49. package/mcp-server/tools/project/GuidedWalkthroughTool.js +4 -1
  50. package/mcp-server/tools/project/UploadProjectTools.js +4 -1
  51. package/mcp-server/tools/project/ValidateProjectTool.js +4 -1
  52. package/mcp-server/tools/project/__tests__/AddFeatureToProject.test.js +1 -0
  53. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -0
  54. package/mcp-server/tools/project/__tests__/DeployProject.test.js +1 -0
  55. package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -0
  56. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -0
  57. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -0
  58. package/mcp-server/utils/__tests__/project.test.js +9 -6
  59. package/mcp-server/utils/project.js +3 -0
  60. package/mcp-server/utils/toolUsageTracking.d.ts +1 -0
  61. package/mcp-server/utils/toolUsageTracking.js +25 -0
  62. package/package.json +4 -4
@@ -1,17 +1,18 @@
1
- import { DeveloperTestAccountConfig } from '@hubspot/local-dev-lib/types/developerTestAccounts';
1
+ import { AccountLevel, DeveloperTestAccountConfig } from '@hubspot/local-dev-lib/types/developerTestAccounts';
2
2
  declare const hubs: {
3
- readonly MARKETING: "marketingLevel";
4
- readonly OPS: "opsLevel";
5
- readonly SERVICE: "serviceLevel";
6
- readonly SALES: "salesLevel";
7
- readonly CONTENT: "contentLevel";
3
+ MARKETING: string;
4
+ OPS: string;
5
+ SERVICE: string;
6
+ SALES: string;
7
+ CONTENT: string;
8
8
  };
9
9
  type HubName = keyof typeof hubs;
10
- type HubTier = 'STARTER' | 'PROFESSIONAL' | 'ENTERPRISE';
11
- export type HubConfig = `${HubName}:${HubTier}`;
10
+ export type HubConfig = {
11
+ hub: HubName;
12
+ tier: AccountLevel;
13
+ };
12
14
  export declare function createDeveloperTestAccountConfigPrompt(args?: {
13
15
  name?: string;
14
16
  description?: string;
15
- tiers?: HubConfig[];
16
- }): Promise<DeveloperTestAccountConfig>;
17
+ }, supportFlags?: boolean): Promise<DeveloperTestAccountConfig>;
17
18
  export {};
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createDeveloperTestAccountConfigPrompt = createDeveloperTestAccountConfigPrompt;
4
+ const prompts_1 = require("@inquirer/prompts");
4
5
  const en_1 = require("../../lang/en");
5
6
  const promptUtils_1 = require("./promptUtils");
6
- const prompts_1 = require("@inquirer/prompts");
7
7
  const hubs = {
8
8
  MARKETING: 'marketingLevel',
9
9
  OPS: 'opsLevel',
@@ -11,63 +11,108 @@ const hubs = {
11
11
  SALES: 'salesLevel',
12
12
  CONTENT: 'contentLevel',
13
13
  };
14
+ const AccountTiers = {
15
+ FREE: 'FREE',
16
+ STARTER: 'STARTER',
17
+ PROFESSIONAL: 'PROFESSIONAL',
18
+ ENTERPRISE: 'ENTERPRISE',
19
+ };
20
+ const makeHubTiers = (hubKey) => {
21
+ const hubTypeKey = hubKey.toLowerCase();
22
+ const hubName = en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.hubTypes[hubTypeKey];
23
+ return [
24
+ {
25
+ name: `${hubName} [${AccountTiers.FREE}]`,
26
+ value: { hub: hubKey, tier: AccountTiers.FREE },
27
+ },
28
+ {
29
+ name: `${hubName} [${AccountTiers.STARTER}]`,
30
+ value: { hub: hubKey, tier: AccountTiers.STARTER },
31
+ },
32
+ {
33
+ name: `${hubName} [${AccountTiers.PROFESSIONAL}]`,
34
+ value: { hub: hubKey, tier: AccountTiers.PROFESSIONAL },
35
+ },
36
+ {
37
+ name: `${hubName} [${AccountTiers.ENTERPRISE}]`,
38
+ value: { hub: hubKey, tier: AccountTiers.ENTERPRISE },
39
+ },
40
+ ];
41
+ };
14
42
  const TEST_ACCOUNT_TIERS = [
15
- { name: 'Marketing STARTER', value: 'MARKETING:STARTER' },
16
- {
17
- name: 'Marketing PROFESSIONAL',
18
- value: 'MARKETING:PROFESSIONAL',
19
- },
20
- { name: 'Marketing ENTERPRISE', value: 'MARKETING:ENTERPRISE' },
43
+ ...makeHubTiers('MARKETING'),
21
44
  new prompts_1.Separator(),
22
- { name: 'Ops STARTER', value: 'OPS:STARTER' },
23
- { name: 'Ops PROFESSIONAL', value: 'OPS:PROFESSIONAL' },
24
- { name: 'Ops ENTERPRISE', value: 'OPS:ENTERPRISE' },
45
+ ...makeHubTiers('OPS'),
25
46
  new prompts_1.Separator(),
26
- { name: 'Service STARTER', value: 'SERVICE:STARTER' },
27
- { name: 'Service PROFESSIONAL', value: 'SERVICE:PROFESSIONAL' },
28
- { name: 'Service ENTERPRISE', value: 'SERVICE:ENTERPRISE' },
47
+ ...makeHubTiers('SERVICE'),
29
48
  new prompts_1.Separator(),
30
- { name: 'Sales STARTER', value: 'SALES:STARTER' },
31
- { name: 'Sales PROFESSIONAL', value: 'SALES:PROFESSIONAL' },
32
- { name: 'Sales ENTERPRISE', value: 'SALES:ENTERPRISE' },
49
+ ...makeHubTiers('SALES'),
33
50
  new prompts_1.Separator(),
34
- { name: 'Content STARTER', value: 'CONTENT:STARTER' },
35
- { name: 'Content PROFESSIONAL', value: 'CONTENT:PROFESSIONAL' },
36
- { name: 'Content ENTERPRISE', value: 'CONTENT:ENTERPRISE' },
51
+ ...makeHubTiers('CONTENT'),
37
52
  new prompts_1.Separator(),
38
53
  ];
39
- async function createDeveloperTestAccountConfigPrompt(args = {}) {
40
- const { name, description, tiers } = args;
54
+ async function createDeveloperTestAccountConfigPrompt(args = {}, supportFlags = true) {
55
+ const { name, description } = args;
41
56
  let accountName = name;
42
57
  let accountDescription = description;
43
- let accountLevelsArray = tiers;
58
+ let accountLevelsArray = [];
44
59
  if (!accountName) {
45
60
  const namePromptResult = await (0, promptUtils_1.promptUser)({
46
61
  name: 'accountName',
47
- message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.namePrompt,
62
+ message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.namePrompt(supportFlags),
48
63
  type: 'input',
64
+ validate: value => {
65
+ if (!value) {
66
+ return en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.errors
67
+ .nameRequired;
68
+ }
69
+ return true;
70
+ },
49
71
  });
50
72
  accountName = namePromptResult.accountName;
51
73
  }
52
74
  if (!accountDescription) {
53
75
  const descriptionPromptResult = await (0, promptUtils_1.promptUser)({
54
76
  name: 'description',
55
- message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.descriptionPrompt,
77
+ message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.descriptionPrompt(supportFlags),
56
78
  type: 'input',
57
79
  });
58
80
  accountDescription = descriptionPromptResult.description;
59
81
  }
60
- if (!accountLevelsArray) {
82
+ const useDefaultAccountLevelsPromptResult = await (0, promptUtils_1.promptUser)({
83
+ name: 'useDefaultAccountLevels',
84
+ message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt
85
+ .useDefaultAccountLevelsPrompt.message,
86
+ type: 'list',
87
+ choices: [
88
+ {
89
+ name: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt
90
+ .useDefaultAccountLevelsPrompt.default,
91
+ value: 'default',
92
+ },
93
+ {
94
+ name: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt
95
+ .useDefaultAccountLevelsPrompt.manual,
96
+ value: 'manual',
97
+ },
98
+ ],
99
+ });
100
+ if (useDefaultAccountLevelsPromptResult.useDefaultAccountLevels === 'manual') {
61
101
  const accountLevelsPromptResult = await (0, promptUtils_1.promptUser)({
62
102
  name: 'testAccountLevels',
63
103
  message: en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.tiersPrompt,
64
104
  type: 'checkbox',
105
+ pageSize: 13,
65
106
  choices: TEST_ACCOUNT_TIERS,
66
107
  validate: choices => {
67
- if (choices?.length > 1) {
108
+ if (choices?.length < Object.keys(hubs).length) {
109
+ return en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.errors
110
+ .allHubsRequired;
111
+ }
112
+ else {
68
113
  const hubMap = {};
69
114
  for (const choice of choices) {
70
- const hub = choice.split(':')[0];
115
+ const { hub } = choice.value;
71
116
  if (hubMap[hub]) {
72
117
  return en_1.lib.prompts.createDeveloperTestAccountConfigPrompt.errors
73
118
  .tiersError;
@@ -80,11 +125,8 @@ async function createDeveloperTestAccountConfigPrompt(args = {}) {
80
125
  });
81
126
  accountLevelsArray = accountLevelsPromptResult.testAccountLevels;
82
127
  }
83
- if (!accountLevelsArray) {
84
- accountLevelsArray = [];
85
- }
86
128
  const accountLevels = accountLevelsArray.reduce((acc, level) => {
87
- const [hubName, hubTier] = level.split(':');
129
+ const { hub: hubName, tier: hubTier } = level;
88
130
  const hubLevel = hubs[hubName];
89
131
  acc[hubLevel] = hubTier;
90
132
  return acc;
@@ -6,7 +6,11 @@ exports.confirmPrompt = confirmPrompt;
6
6
  exports.listPrompt = listPrompt;
7
7
  exports.inputPrompt = inputPrompt;
8
8
  const prompts_1 = require("@inquirer/prompts");
9
+ const exitCodes_1 = require("../enums/exitCodes");
9
10
  exports.Separator = new prompts_1.Separator();
11
+ function isUserCancellationError(error) {
12
+ return error instanceof Error && error.name === 'ExitPromptError';
13
+ }
10
14
  function mapPromptChoicesToChoices(choices) {
11
15
  return (choices?.map(choice => {
12
16
  if (typeof choice === 'string') {
@@ -23,68 +27,74 @@ function mapPromptChoicesToChoices(choices) {
23
27
  };
24
28
  }) || []);
25
29
  }
26
- function handleArrayConfig(config) {
27
- return (async () => {
28
- const result = {};
29
- for (const prompt of config) {
30
- if (prompt.when !== undefined) {
31
- const shouldPrompt = typeof prompt.when === 'function'
32
- ? prompt.when()
33
- : (prompt.when ?? true);
34
- if (!shouldPrompt) {
35
- continue;
36
- }
37
- }
38
- if (typeof prompt.message === 'function') {
39
- prompt.message = prompt.message(result);
30
+ async function handleArrayConfig(config) {
31
+ const result = {};
32
+ for (const prompt of config) {
33
+ if (prompt.when !== undefined) {
34
+ const shouldPrompt = typeof prompt.when === 'function'
35
+ ? prompt.when()
36
+ : (prompt.when ?? true);
37
+ if (!shouldPrompt) {
38
+ continue;
40
39
  }
41
- // Pass the accumulated results to each prompt
42
- const promptWithAnswers = {
43
- ...prompt,
44
- default: typeof prompt.default === 'function'
45
- ? (answers) => {
46
- const mergedAnswers = { ...answers, ...result };
47
- return prompt.default(mergedAnswers);
48
- }
49
- : prompt.default,
50
- };
51
- const response = await promptUser(promptWithAnswers);
52
- Object.assign(result, response);
53
40
  }
54
- return result;
55
- })();
56
- }
57
- function promptUser(config) {
58
- if (Array.isArray(config)) {
59
- return handleArrayConfig(config);
41
+ if (typeof prompt.message === 'function') {
42
+ prompt.message = prompt.message(result);
43
+ }
44
+ // Pass the accumulated results to each prompt
45
+ const promptWithAnswers = {
46
+ ...prompt,
47
+ default: typeof prompt.default === 'function'
48
+ ? (answers) => {
49
+ const mergedAnswers = { ...answers, ...result };
50
+ return prompt.default(mergedAnswers);
51
+ }
52
+ : prompt.default,
53
+ };
54
+ const response = await promptUser(promptWithAnswers);
55
+ Object.assign(result, response);
60
56
  }
61
- else {
62
- if (config.when !== undefined) {
63
- const shouldPrompt = typeof config.when === 'function'
64
- ? config.when()
65
- : (config.when ?? true);
66
- if (!shouldPrompt) {
67
- return Promise.resolve({});
57
+ return result;
58
+ }
59
+ async function promptUser(config) {
60
+ try {
61
+ if (Array.isArray(config)) {
62
+ return await handleArrayConfig(config);
63
+ }
64
+ else {
65
+ if (config.when !== undefined) {
66
+ const shouldPrompt = typeof config.when === 'function'
67
+ ? config.when()
68
+ : (config.when ?? true);
69
+ if (!shouldPrompt) {
70
+ return Promise.resolve({});
71
+ }
68
72
  }
69
73
  }
74
+ switch (config.type) {
75
+ case 'list':
76
+ return await handleSelectPrompt(config);
77
+ case 'input':
78
+ return await handleInputPrompt(config);
79
+ case 'confirm':
80
+ return await handleConfirmPrompt(config);
81
+ case 'checkbox':
82
+ return await handleCheckboxPrompt(config);
83
+ case 'password':
84
+ return await handlePasswordPrompt(config);
85
+ case 'number':
86
+ return await handleNumberPrompt(config);
87
+ case 'rawlist':
88
+ return await handleRawListPrompt(config);
89
+ default:
90
+ return await handleInputPrompt(config);
91
+ }
70
92
  }
71
- switch (config.type) {
72
- case 'list':
73
- return handleSelectPrompt(config);
74
- case 'input':
75
- return handleInputPrompt(config);
76
- case 'confirm':
77
- return handleConfirmPrompt(config);
78
- case 'checkbox':
79
- return handleCheckboxPrompt(config);
80
- case 'password':
81
- return handlePasswordPrompt(config);
82
- case 'number':
83
- return handleNumberPrompt(config);
84
- case 'rawlist':
85
- return handleRawListPrompt(config);
86
- default:
87
- return handleInputPrompt(config);
93
+ catch (error) {
94
+ if (isUserCancellationError(error)) {
95
+ process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
96
+ }
97
+ throw error;
88
98
  }
89
99
  }
90
100
  function handleRawListPrompt(config) {
package/lib/ui/index.js CHANGED
@@ -59,7 +59,7 @@ function uiAccountDescription(accountId, bold = true) {
59
59
  const account = (0, config_1.getAccountConfig)(accountId || undefined);
60
60
  let message;
61
61
  if (account && account.accountType) {
62
- message = `${account.name} [${HUBSPOT_ACCOUNT_TYPE_STRINGS[account.accountType]}] (${accountId})`;
62
+ message = `${account.name ? `${account.name} ` : ''}[${HUBSPOT_ACCOUNT_TYPE_STRINGS[account.accountType]}] (${accountId})`;
63
63
  }
64
64
  else {
65
65
  message = accountId ? accountId.toString() : '';
@@ -13,6 +13,17 @@ type Meta = {
13
13
  file?: boolean;
14
14
  successful?: boolean;
15
15
  };
16
+ export declare const EventClass: {
17
+ USAGE: string;
18
+ INTERACTION: string;
19
+ VIEW: string;
20
+ ACTIVATION: string;
21
+ };
22
+ export declare function getNodeVersionData(): {
23
+ nodeVersion: string;
24
+ nodeMajorVersion: string;
25
+ };
26
+ export declare function getPlatform(): string;
16
27
  export declare function trackCommandUsage(command: string, meta?: Meta, accountId?: number): Promise<void>;
17
28
  export declare function trackHelpUsage(command: string): Promise<void>;
18
29
  export declare function trackConvertFieldsUsage(command: string): Promise<void>;
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventClass = void 0;
4
+ exports.getNodeVersionData = getNodeVersionData;
5
+ exports.getPlatform = getPlatform;
3
6
  exports.trackCommandUsage = trackCommandUsage;
4
7
  exports.trackHelpUsage = trackHelpUsage;
5
8
  exports.trackConvertFieldsUsage = trackConvertFieldsUsage;
@@ -11,7 +14,7 @@ const auth_1 = require("@hubspot/local-dev-lib/constants/auth");
11
14
  const logger_1 = require("@hubspot/local-dev-lib/logger");
12
15
  const package_json_1 = require("../package.json");
13
16
  const errorHandlers_1 = require("./errorHandlers");
14
- const EventClass = {
17
+ exports.EventClass = {
15
18
  USAGE: 'USAGE',
16
19
  INTERACTION: 'INTERACTION',
17
20
  VIEW: 'VIEW',
@@ -46,86 +49,45 @@ async function trackCommandUsage(command, meta = {}, accountId) {
46
49
  ? accountConfig.authType
47
50
  : auth_1.API_KEY_AUTH_METHOD.value;
48
51
  }
49
- setImmediate(async () => {
50
- const usageTrackingEvent = {
51
- action: 'cli-command',
52
- os: getPlatform(),
53
- ...getNodeVersionData(),
54
- version: package_json_1.version,
55
- command,
56
- authType,
57
- ...meta,
58
- };
59
- try {
60
- await (0, trackUsage_1.trackUsage)('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
61
- logger_1.logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
62
- }
63
- catch (e) {
64
- (0, errorHandlers_1.debugError)(e);
65
- }
52
+ return trackCliInteraction({
53
+ action: 'cli-command',
54
+ command,
55
+ authType,
56
+ ...meta,
57
+ accountId,
66
58
  });
67
59
  }
68
60
  async function trackHelpUsage(command) {
69
61
  if (!(0, config_1.isTrackingAllowed)()) {
70
62
  return;
71
63
  }
72
- try {
73
- if (command) {
74
- logger_1.logger.debug('Tracking help usage of "%s" sub-command', command);
75
- }
76
- else {
77
- logger_1.logger.debug('Tracking help usage of main command');
78
- }
79
- await (0, trackUsage_1.trackUsage)('cli-interaction', EventClass.INTERACTION, {
80
- action: 'cli-help',
81
- os: getPlatform(),
82
- ...getNodeVersionData(),
83
- version: package_json_1.version,
84
- command,
85
- });
64
+ if (command) {
65
+ logger_1.logger.debug('Tracking help usage of "%s" sub-command', command);
86
66
  }
87
- catch (e) {
88
- (0, errorHandlers_1.debugError)(e);
67
+ else {
68
+ logger_1.logger.debug('Tracking help usage of main command');
89
69
  }
70
+ return trackCliInteraction({
71
+ action: 'cli-help',
72
+ command,
73
+ });
90
74
  }
91
75
  async function trackConvertFieldsUsage(command) {
92
- if (!(0, config_1.isTrackingAllowed)()) {
93
- return;
94
- }
95
- try {
96
- logger_1.logger.debug('Attempting to track usage of "%s" command', command);
97
- await (0, trackUsage_1.trackUsage)('cli-interaction', EventClass.INTERACTION, {
98
- action: 'cli-process-fields',
99
- os: getPlatform(),
100
- ...getNodeVersionData(),
101
- version: package_json_1.version,
102
- command,
103
- });
104
- }
105
- catch (e) {
106
- (0, errorHandlers_1.debugError)(e);
107
- }
76
+ return trackCliInteraction({
77
+ action: 'cli-process-fields',
78
+ command,
79
+ });
108
80
  }
109
81
  async function trackAuthAction(command, authType, step, accountId) {
110
- if (!(0, config_1.isTrackingAllowed)()) {
111
- return;
112
- }
113
- const usageTrackingEvent = {
82
+ return trackCliInteraction({
114
83
  action: 'cli-auth',
115
- os: getPlatform(),
116
- ...getNodeVersionData(),
117
- version: package_json_1.version,
118
84
  command,
119
85
  authType,
120
- step,
121
- };
122
- try {
123
- await (0, trackUsage_1.trackUsage)('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
124
- logger_1.logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
125
- }
126
- catch (e) {
127
- (0, errorHandlers_1.debugError)(e);
128
- }
86
+ accountId,
87
+ meta: {
88
+ step,
89
+ },
90
+ });
129
91
  }
130
92
  async function trackCommandMetadataUsage(command, meta = {}, accountId) {
131
93
  if (!(0, config_1.isTrackingAllowed)()) {
@@ -140,9 +102,21 @@ async function trackCommandMetadataUsage(command, meta = {}, accountId) {
140
102
  ? accountConfig.authType
141
103
  : auth_1.API_KEY_AUTH_METHOD.value;
142
104
  }
143
- setImmediate(async () => {
105
+ return trackCliInteraction({
106
+ action: 'cli-command-metadata',
107
+ command,
108
+ authType,
109
+ accountId,
110
+ meta,
111
+ });
112
+ }
113
+ async function trackCliInteraction({ action, accountId, command, authType, meta = {}, }) {
114
+ try {
115
+ if (!(0, config_1.isTrackingAllowed)()) {
116
+ return;
117
+ }
144
118
  const usageTrackingEvent = {
145
- action: 'cli-command-metadata',
119
+ action,
146
120
  os: getPlatform(),
147
121
  ...getNodeVersionData(),
148
122
  version: package_json_1.version,
@@ -150,12 +124,32 @@ async function trackCommandMetadataUsage(command, meta = {}, accountId) {
150
124
  authType,
151
125
  ...meta,
152
126
  };
127
+ if (process.env.HUBSPOT_MCP_AI_AGENT) {
128
+ try {
129
+ await (0, trackUsage_1.trackUsage)('cli-interaction', exports.EventClass.INTERACTION, {
130
+ ...usageTrackingEvent,
131
+ action: 'cli-mcp-server',
132
+ type: process.env.HUBSPOT_MCP_AI_AGENT,
133
+ }, accountId);
134
+ logger_1.logger.debug('Sent AI usage tracking command event: %o', {
135
+ ...usageTrackingEvent,
136
+ action: 'cli-mcp-server',
137
+ type: process.env.HUBSPOT_MCP_AI_AGENT,
138
+ });
139
+ }
140
+ catch (error) {
141
+ (0, errorHandlers_1.debugError)(error);
142
+ }
143
+ }
153
144
  try {
154
- await (0, trackUsage_1.trackUsage)('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
155
- logger_1.logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
145
+ return (0, trackUsage_1.trackUsage)('cli-interaction', exports.EventClass.INTERACTION, usageTrackingEvent, accountId);
156
146
  }
157
- catch (e) {
158
- (0, errorHandlers_1.debugError)(e);
147
+ catch (error) {
148
+ (0, errorHandlers_1.debugError)(error);
159
149
  }
160
- });
150
+ logger_1.logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
151
+ }
152
+ catch (e) {
153
+ (0, errorHandlers_1.debugError)(e);
154
+ }
161
155
  }
@@ -8,6 +8,7 @@ const command_1 = require("../../utils/command");
8
8
  const constants_2 = require("./constants");
9
9
  const project_1 = require("../../utils/project");
10
10
  const content_1 = require("../../utils/content");
11
+ const toolUsageTracking_1 = require("../../utils/toolUsageTracking");
11
12
  const inputSchema = {
12
13
  absoluteProjectPath: constants_2.absoluteProjectPath,
13
14
  addApp: zod_1.z
@@ -40,12 +41,14 @@ const inputSchema = {
40
41
  const inputSchemaZodObject = zod_1.z.object({
41
42
  ...inputSchema,
42
43
  });
44
+ const toolName = 'add-feature-to-hubspot-project';
43
45
  class AddFeatureToProject extends types_1.Tool {
44
46
  constructor(mcpServer) {
45
47
  super(mcpServer);
46
48
  }
47
49
  async handler({ absoluteProjectPath, distribution, auth, features, addApp, }) {
48
50
  try {
51
+ await (0, toolUsageTracking_1.trackToolUsage)(toolName);
49
52
  let command = `hs project add`;
50
53
  const content = [];
51
54
  if (distribution) {
@@ -75,7 +78,7 @@ class AddFeatureToProject extends types_1.Tool {
75
78
  }
76
79
  }
77
80
  register() {
78
- return this.mcpServer.registerTool('add-feature-to-hubspot-project', {
81
+ return this.mcpServer.registerTool(toolName, {
79
82
  title: 'Add feature to HubSpot Project',
80
83
  description: 'Adds a feature to an existing HubSpot project',
81
84
  inputSchema,
@@ -13,16 +13,16 @@ declare const inputSchemaZodObject: z.ZodObject<{
13
13
  projectBase: "app" | "empty";
14
14
  absoluteCurrentWorkingDirectory: string;
15
15
  destination: string;
16
- auth?: "oauth" | "static" | undefined;
17
16
  name?: string | undefined;
17
+ auth?: "oauth" | "static" | undefined;
18
18
  distribution?: "marketplace" | "private" | undefined;
19
19
  features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
20
20
  }, {
21
21
  projectBase: "app" | "empty";
22
22
  absoluteCurrentWorkingDirectory: string;
23
23
  destination: string;
24
- auth?: "oauth" | "static" | undefined;
25
24
  name?: string | undefined;
25
+ auth?: "oauth" | "static" | undefined;
26
26
  distribution?: "marketplace" | "private" | undefined;
27
27
  features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
28
28
  }>;
@@ -9,6 +9,7 @@ const v3_1 = require("../../../lib/projects/create/v3");
9
9
  const constants_2 = require("./constants");
10
10
  const project_1 = require("../../utils/project");
11
11
  const content_1 = require("../../utils/content");
12
+ const toolUsageTracking_1 = require("../../utils/toolUsageTracking");
12
13
  const inputSchema = {
13
14
  absoluteCurrentWorkingDirectory: constants_2.absoluteCurrentWorkingDirectory,
14
15
  name: zod_1.z
@@ -47,11 +48,13 @@ const inputSchema = {
47
48
  };
48
49
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
49
50
  const inputSchemaZodObject = zod_1.z.object({ ...inputSchema });
51
+ const toolName = 'create-hubspot-project';
50
52
  class CreateProjectTool extends types_1.Tool {
51
53
  constructor(mcpServer) {
52
54
  super(mcpServer);
53
55
  }
54
56
  async handler({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }) {
57
+ await (0, toolUsageTracking_1.trackToolUsage)(toolName);
55
58
  let command = (0, command_1.addFlag)('hs project create', 'platform-version', '2025.2');
56
59
  const content = [];
57
60
  if (name) {
@@ -94,7 +97,7 @@ class CreateProjectTool extends types_1.Tool {
94
97
  }
95
98
  }
96
99
  register() {
97
- return this.mcpServer.registerTool('create-hubspot-project', {
100
+ return this.mcpServer.registerTool(toolName, {
98
101
  title: 'Create HubSpot Project',
99
102
  description: 'Creates a HubSpot project with the provided name and outputs it in the provided destination',
100
103
  inputSchema,
@@ -7,6 +7,7 @@ const command_1 = require("../../utils/command");
7
7
  const constants_1 = require("./constants");
8
8
  const project_1 = require("../../utils/project");
9
9
  const content_1 = require("../../utils/content");
10
+ const toolUsageTracking_1 = require("../../utils/toolUsageTracking");
10
11
  const inputSchema = {
11
12
  absoluteProjectPath: constants_1.absoluteProjectPath,
12
13
  buildNumber: zod_1.z
@@ -17,11 +18,13 @@ const inputSchema = {
17
18
  const inputSchemaZodObject = zod_1.z.object({
18
19
  ...inputSchema,
19
20
  });
21
+ const toolName = 'deploy-hubspot-project';
20
22
  class DeployProject extends types_1.Tool {
21
23
  constructor(mcpServer) {
22
24
  super(mcpServer);
23
25
  }
24
26
  async handler({ absoluteProjectPath, buildNumber, }) {
27
+ await (0, toolUsageTracking_1.trackToolUsage)(toolName);
25
28
  let command = `hs project deploy`;
26
29
  const content = [];
27
30
  if (!buildNumber) {
@@ -40,7 +43,7 @@ class DeployProject extends types_1.Tool {
40
43
  return (0, content_1.formatTextContents)(stdout, stderr);
41
44
  }
42
45
  register() {
43
- return this.mcpServer.registerTool('deploy-hubspot-project', {
46
+ return this.mcpServer.registerTool(toolName, {
44
47
  title: 'Deploy a build of HubSpot Project',
45
48
  description: 'Takes a build number and a project name and deploys that build of the project. DO NOT run this tool unless the user specifies they would like to deploy the project.',
46
49
  inputSchema,