@hubspot/cli 7.7.21-experimental.0 → 7.7.22-experimental.0

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 (75) hide show
  1. package/bin/cli.js +6 -2
  2. package/commands/__tests__/getStarted.test.js +0 -10
  3. package/commands/create/api-sample.d.ts +1 -1
  4. package/commands/create/app.d.ts +1 -1
  5. package/commands/create/function.d.ts +1 -1
  6. package/commands/create/index.d.ts +1 -1
  7. package/commands/create/module.d.ts +1 -1
  8. package/commands/create/react-app.d.ts +1 -1
  9. package/commands/create/template.d.ts +1 -1
  10. package/commands/create/vue-app.d.ts +1 -1
  11. package/commands/create/webpack-serverless.d.ts +1 -1
  12. package/commands/create/website-theme.d.ts +1 -1
  13. package/commands/create.d.ts +1 -1
  14. package/commands/getStarted.js +12 -27
  15. package/commands/mcp/setup.js +1 -0
  16. package/commands/mcp/start.d.ts +4 -1
  17. package/commands/mcp/start.js +8 -3
  18. package/commands/project/__tests__/deploy.test.js +28 -26
  19. package/commands/project/__tests__/devUnifiedFlow.test.js +19 -16
  20. package/commands/project/create.js +2 -2
  21. package/commands/project/deploy.d.ts +3 -2
  22. package/commands/project/deploy.js +63 -54
  23. package/commands/project/dev/unifiedFlow.js +7 -6
  24. package/commands/testAccount/__tests__/createConfig.test.js +0 -3
  25. package/commands/testAccount/create.js +12 -25
  26. package/commands/testAccount/createConfig.d.ts +0 -2
  27. package/commands/testAccount/createConfig.js +8 -9
  28. package/lang/en.d.ts +40 -23
  29. package/lang/en.js +41 -24
  30. package/lang/en.lyaml +0 -26
  31. package/lib/__tests__/buildAccount.test.js +31 -3
  32. package/lib/__tests__/usageTracking.test.js +8 -14
  33. package/lib/buildAccount.d.ts +8 -2
  34. package/lib/buildAccount.js +54 -5
  35. package/lib/mcp/setup.js +26 -5
  36. package/lib/projects/add/legacyAddComponent.js +2 -2
  37. package/lib/projects/add/v3AddComponent.js +2 -2
  38. package/lib/projects/localDev/DevServerManager.js +0 -2
  39. package/lib/projects/localDev/DevServerManagerV2.js +0 -2
  40. package/lib/projects/localDev/helpers.d.ts +1 -1
  41. package/lib/projects/localDev/helpers.js +2 -2
  42. package/lib/projects/upload.js +1 -1
  43. package/lib/prompts/createApiSamplePrompt.d.ts +1 -1
  44. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +11 -10
  45. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +73 -31
  46. package/lib/prompts/promptUtils.js +66 -56
  47. package/lib/prompts/sandboxesPrompt.d.ts +1 -1
  48. package/lib/sandboxSync.d.ts +1 -1
  49. package/lib/sandboxes.d.ts +1 -1
  50. package/lib/schema.js +5 -1
  51. package/lib/ui/index.js +1 -1
  52. package/lib/usageTracking.d.ts +11 -0
  53. package/lib/usageTracking.js +66 -75
  54. package/mcp-server/tools/project/AddFeatureToProject.js +4 -1
  55. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  56. package/mcp-server/tools/project/CreateProjectTool.js +4 -1
  57. package/mcp-server/tools/project/DeployProject.js +4 -1
  58. package/mcp-server/tools/project/GuidedWalkthroughTool.js +4 -1
  59. package/mcp-server/tools/project/UploadProjectTools.js +4 -1
  60. package/mcp-server/tools/project/ValidateProjectTool.js +4 -1
  61. package/mcp-server/tools/project/__tests__/AddFeatureToProject.test.js +1 -0
  62. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -0
  63. package/mcp-server/tools/project/__tests__/DeployProject.test.js +1 -0
  64. package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -0
  65. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -0
  66. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -0
  67. package/mcp-server/utils/__tests__/project.test.js +9 -6
  68. package/mcp-server/utils/project.js +3 -0
  69. package/mcp-server/utils/toolUsageTracking.d.ts +1 -0
  70. package/mcp-server/utils/toolUsageTracking.js +22 -0
  71. package/package.json +4 -4
  72. /package/types/{cms.d.ts → Cms.d.ts} +0 -0
  73. /package/types/{cms.js → Cms.js} +0 -0
  74. /package/types/{sandboxes.d.ts → Sandboxes.d.ts} +0 -0
  75. /package/types/{sandboxes.js → Sandboxes.js} +0 -0
@@ -1,17 +1,18 @@
1
- import { DeveloperTestAccountConfig } from '@hubspot/local-dev-lib/types/developerTestAccounts.js';
1
+ import { AccountLevel, DeveloperTestAccountConfig } from '@hubspot/local-dev-lib/types/developerTestAccounts.js';
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,6 +1,6 @@
1
+ import { Separator } from '@inquirer/prompts';
1
2
  import { lib } from '../../lang/en.js';
2
3
  import { promptUser } from './promptUtils.js';
3
- import { Separator } from '@inquirer/prompts';
4
4
  const hubs = {
5
5
  MARKETING: 'marketingLevel',
6
6
  OPS: 'opsLevel',
@@ -8,63 +8,108 @@ const hubs = {
8
8
  SALES: 'salesLevel',
9
9
  CONTENT: 'contentLevel',
10
10
  };
11
+ const AccountTiers = {
12
+ FREE: 'FREE',
13
+ STARTER: 'STARTER',
14
+ PROFESSIONAL: 'PROFESSIONAL',
15
+ ENTERPRISE: 'ENTERPRISE',
16
+ };
17
+ const makeHubTiers = (hubKey) => {
18
+ const hubTypeKey = hubKey.toLowerCase();
19
+ const hubName = lib.prompts.createDeveloperTestAccountConfigPrompt.hubTypes[hubTypeKey];
20
+ return [
21
+ {
22
+ name: `${hubName} [${AccountTiers.FREE}]`,
23
+ value: { hub: hubKey, tier: AccountTiers.FREE },
24
+ },
25
+ {
26
+ name: `${hubName} [${AccountTiers.STARTER}]`,
27
+ value: { hub: hubKey, tier: AccountTiers.STARTER },
28
+ },
29
+ {
30
+ name: `${hubName} [${AccountTiers.PROFESSIONAL}]`,
31
+ value: { hub: hubKey, tier: AccountTiers.PROFESSIONAL },
32
+ },
33
+ {
34
+ name: `${hubName} [${AccountTiers.ENTERPRISE}]`,
35
+ value: { hub: hubKey, tier: AccountTiers.ENTERPRISE },
36
+ },
37
+ ];
38
+ };
11
39
  const TEST_ACCOUNT_TIERS = [
12
- { name: 'Marketing STARTER', value: 'MARKETING:STARTER' },
13
- {
14
- name: 'Marketing PROFESSIONAL',
15
- value: 'MARKETING:PROFESSIONAL',
16
- },
17
- { name: 'Marketing ENTERPRISE', value: 'MARKETING:ENTERPRISE' },
40
+ ...makeHubTiers('MARKETING'),
18
41
  new Separator(),
19
- { name: 'Ops STARTER', value: 'OPS:STARTER' },
20
- { name: 'Ops PROFESSIONAL', value: 'OPS:PROFESSIONAL' },
21
- { name: 'Ops ENTERPRISE', value: 'OPS:ENTERPRISE' },
42
+ ...makeHubTiers('OPS'),
22
43
  new Separator(),
23
- { name: 'Service STARTER', value: 'SERVICE:STARTER' },
24
- { name: 'Service PROFESSIONAL', value: 'SERVICE:PROFESSIONAL' },
25
- { name: 'Service ENTERPRISE', value: 'SERVICE:ENTERPRISE' },
44
+ ...makeHubTiers('SERVICE'),
26
45
  new Separator(),
27
- { name: 'Sales STARTER', value: 'SALES:STARTER' },
28
- { name: 'Sales PROFESSIONAL', value: 'SALES:PROFESSIONAL' },
29
- { name: 'Sales ENTERPRISE', value: 'SALES:ENTERPRISE' },
46
+ ...makeHubTiers('SALES'),
30
47
  new Separator(),
31
- { name: 'Content STARTER', value: 'CONTENT:STARTER' },
32
- { name: 'Content PROFESSIONAL', value: 'CONTENT:PROFESSIONAL' },
33
- { name: 'Content ENTERPRISE', value: 'CONTENT:ENTERPRISE' },
48
+ ...makeHubTiers('CONTENT'),
34
49
  new Separator(),
35
50
  ];
36
- export async function createDeveloperTestAccountConfigPrompt(args = {}) {
37
- const { name, description, tiers } = args;
51
+ export async function createDeveloperTestAccountConfigPrompt(args = {}, supportFlags = true) {
52
+ const { name, description } = args;
38
53
  let accountName = name;
39
54
  let accountDescription = description;
40
- let accountLevelsArray = tiers;
55
+ let accountLevelsArray = [];
41
56
  if (!accountName) {
42
57
  const namePromptResult = await promptUser({
43
58
  name: 'accountName',
44
- message: lib.prompts.createDeveloperTestAccountConfigPrompt.namePrompt,
59
+ message: lib.prompts.createDeveloperTestAccountConfigPrompt.namePrompt(supportFlags),
45
60
  type: 'input',
61
+ validate: value => {
62
+ if (!value) {
63
+ return lib.prompts.createDeveloperTestAccountConfigPrompt.errors
64
+ .nameRequired;
65
+ }
66
+ return true;
67
+ },
46
68
  });
47
69
  accountName = namePromptResult.accountName;
48
70
  }
49
71
  if (!accountDescription) {
50
72
  const descriptionPromptResult = await promptUser({
51
73
  name: 'description',
52
- message: lib.prompts.createDeveloperTestAccountConfigPrompt.descriptionPrompt,
74
+ message: lib.prompts.createDeveloperTestAccountConfigPrompt.descriptionPrompt(supportFlags),
53
75
  type: 'input',
54
76
  });
55
77
  accountDescription = descriptionPromptResult.description;
56
78
  }
57
- if (!accountLevelsArray) {
79
+ const useDefaultAccountLevelsPromptResult = await promptUser({
80
+ name: 'useDefaultAccountLevels',
81
+ message: lib.prompts.createDeveloperTestAccountConfigPrompt
82
+ .useDefaultAccountLevelsPrompt.message,
83
+ type: 'list',
84
+ choices: [
85
+ {
86
+ name: lib.prompts.createDeveloperTestAccountConfigPrompt
87
+ .useDefaultAccountLevelsPrompt.default,
88
+ value: 'default',
89
+ },
90
+ {
91
+ name: lib.prompts.createDeveloperTestAccountConfigPrompt
92
+ .useDefaultAccountLevelsPrompt.manual,
93
+ value: 'manual',
94
+ },
95
+ ],
96
+ });
97
+ if (useDefaultAccountLevelsPromptResult.useDefaultAccountLevels === 'manual') {
58
98
  const accountLevelsPromptResult = await promptUser({
59
99
  name: 'testAccountLevels',
60
100
  message: lib.prompts.createDeveloperTestAccountConfigPrompt.tiersPrompt,
61
101
  type: 'checkbox',
102
+ pageSize: 13,
62
103
  choices: TEST_ACCOUNT_TIERS,
63
104
  validate: choices => {
64
- if (choices?.length > 1) {
105
+ if (choices?.length < Object.keys(hubs).length) {
106
+ return lib.prompts.createDeveloperTestAccountConfigPrompt.errors
107
+ .allHubsRequired;
108
+ }
109
+ else {
65
110
  const hubMap = {};
66
111
  for (const choice of choices) {
67
- const hub = choice.split(':')[0];
112
+ const { hub } = choice.value;
68
113
  if (hubMap[hub]) {
69
114
  return lib.prompts.createDeveloperTestAccountConfigPrompt.errors
70
115
  .tiersError;
@@ -77,11 +122,8 @@ export async function createDeveloperTestAccountConfigPrompt(args = {}) {
77
122
  });
78
123
  accountLevelsArray = accountLevelsPromptResult.testAccountLevels;
79
124
  }
80
- if (!accountLevelsArray) {
81
- accountLevelsArray = [];
82
- }
83
125
  const accountLevels = accountLevelsArray.reduce((acc, level) => {
84
- const [hubName, hubTier] = level.split(':');
126
+ const { hub: hubName, tier: hubTier } = level;
85
127
  const hubLevel = hubs[hubName];
86
128
  acc[hubLevel] = hubTier;
87
129
  return acc;
@@ -1,5 +1,9 @@
1
1
  import { confirm, Separator as _Separator, select, input, checkbox, password, number, } from '@inquirer/prompts';
2
+ import { EXIT_CODES } from '../enums/exitCodes.js';
2
3
  export const Separator = new _Separator();
4
+ function isUserCancellationError(error) {
5
+ return error instanceof Error && error.name === 'ExitPromptError';
6
+ }
3
7
  function mapPromptChoicesToChoices(choices) {
4
8
  return (choices?.map(choice => {
5
9
  if (typeof choice === 'string') {
@@ -16,68 +20,74 @@ function mapPromptChoicesToChoices(choices) {
16
20
  };
17
21
  }) || []);
18
22
  }
19
- function handleArrayConfig(config) {
20
- return (async () => {
21
- const result = {};
22
- for (const prompt of config) {
23
- if (prompt.when !== undefined) {
24
- const shouldPrompt = typeof prompt.when === 'function'
25
- ? prompt.when()
26
- : (prompt.when ?? true);
27
- if (!shouldPrompt) {
28
- continue;
29
- }
30
- }
31
- if (typeof prompt.message === 'function') {
32
- prompt.message = prompt.message(result);
23
+ async function handleArrayConfig(config) {
24
+ const result = {};
25
+ for (const prompt of config) {
26
+ if (prompt.when !== undefined) {
27
+ const shouldPrompt = typeof prompt.when === 'function'
28
+ ? prompt.when()
29
+ : (prompt.when ?? true);
30
+ if (!shouldPrompt) {
31
+ continue;
33
32
  }
34
- // Pass the accumulated results to each prompt
35
- const promptWithAnswers = {
36
- ...prompt,
37
- default: typeof prompt.default === 'function'
38
- ? (answers) => {
39
- const mergedAnswers = { ...answers, ...result };
40
- return prompt.default(mergedAnswers);
41
- }
42
- : prompt.default,
43
- };
44
- const response = await promptUser(promptWithAnswers);
45
- Object.assign(result, response);
46
33
  }
47
- return result;
48
- })();
49
- }
50
- export function promptUser(config) {
51
- if (Array.isArray(config)) {
52
- return handleArrayConfig(config);
34
+ if (typeof prompt.message === 'function') {
35
+ prompt.message = prompt.message(result);
36
+ }
37
+ // Pass the accumulated results to each prompt
38
+ const promptWithAnswers = {
39
+ ...prompt,
40
+ default: typeof prompt.default === 'function'
41
+ ? (answers) => {
42
+ const mergedAnswers = { ...answers, ...result };
43
+ return prompt.default(mergedAnswers);
44
+ }
45
+ : prompt.default,
46
+ };
47
+ const response = await promptUser(promptWithAnswers);
48
+ Object.assign(result, response);
53
49
  }
54
- else {
55
- if (config.when !== undefined) {
56
- const shouldPrompt = typeof config.when === 'function'
57
- ? config.when()
58
- : (config.when ?? true);
59
- if (!shouldPrompt) {
60
- return Promise.resolve({});
50
+ return result;
51
+ }
52
+ export async function promptUser(config) {
53
+ try {
54
+ if (Array.isArray(config)) {
55
+ return await handleArrayConfig(config);
56
+ }
57
+ else {
58
+ if (config.when !== undefined) {
59
+ const shouldPrompt = typeof config.when === 'function'
60
+ ? config.when()
61
+ : (config.when ?? true);
62
+ if (!shouldPrompt) {
63
+ return Promise.resolve({});
64
+ }
61
65
  }
62
66
  }
67
+ switch (config.type) {
68
+ case 'list':
69
+ return await handleSelectPrompt(config);
70
+ case 'input':
71
+ return await handleInputPrompt(config);
72
+ case 'confirm':
73
+ return await handleConfirmPrompt(config);
74
+ case 'checkbox':
75
+ return await handleCheckboxPrompt(config);
76
+ case 'password':
77
+ return await handlePasswordPrompt(config);
78
+ case 'number':
79
+ return await handleNumberPrompt(config);
80
+ case 'rawlist':
81
+ return await handleRawListPrompt(config);
82
+ default:
83
+ return await handleInputPrompt(config);
84
+ }
63
85
  }
64
- switch (config.type) {
65
- case 'list':
66
- return handleSelectPrompt(config);
67
- case 'input':
68
- return handleInputPrompt(config);
69
- case 'confirm':
70
- return handleConfirmPrompt(config);
71
- case 'checkbox':
72
- return handleCheckboxPrompt(config);
73
- case 'password':
74
- return handlePasswordPrompt(config);
75
- case 'number':
76
- return handleNumberPrompt(config);
77
- case 'rawlist':
78
- return handleRawListPrompt(config);
79
- default:
80
- return handleInputPrompt(config);
86
+ catch (error) {
87
+ if (isUserCancellationError(error)) {
88
+ process.exit(EXIT_CODES.SUCCESS);
89
+ }
90
+ throw error;
81
91
  }
82
92
  }
83
93
  function handleRawListPrompt(config) {
@@ -1,4 +1,4 @@
1
- import { SandboxAccountType } from '../../types/sandboxes.js';
1
+ import { SandboxAccountType } from '../../types/Sandboxes.js';
2
2
  type SandboxTypePromptResponse = {
3
3
  type: SandboxAccountType;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import { CLIAccount } from '@hubspot/local-dev-lib/types/Accounts';
2
2
  import { Environment } from '@hubspot/local-dev-lib/types/Config';
3
- import { SandboxSyncTask } from '../types/sandboxes.js';
3
+ import { SandboxSyncTask } from '../types/Sandboxes.js';
4
4
  export declare function syncSandbox(accountConfig: CLIAccount, parentAccountConfig: CLIAccount, env: Environment, syncTasks: Array<SandboxSyncTask>, slimInfoMessage?: boolean): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import { AccountType, CLIAccount } from '@hubspot/local-dev-lib/types/Accounts';
2
2
  import { Environment } from '@hubspot/local-dev-lib/types/Config';
3
- import { SandboxSyncTask, SandboxAccountType } from '../types/sandboxes.js';
3
+ import { SandboxSyncTask, SandboxAccountType } from '../types/Sandboxes.js';
4
4
  export declare const SYNC_TYPES: {
5
5
  readonly OBJECT_RECORDS: "object-records";
6
6
  };
package/lib/schema.js CHANGED
@@ -6,6 +6,10 @@ export function logSchemas(schemas) {
6
6
  const data = schemas
7
7
  .map(r => [r.labels.singular, r.name, r.objectTypeId || ''])
8
8
  .sort((a, b) => (a[1] > b[1] ? 1 : -1));
9
+ if (data.length === 0) {
10
+ logger.log('No Schemas were found');
11
+ return;
12
+ }
9
13
  data.unshift([
10
14
  chalk.bold('Label'),
11
15
  chalk.bold('Name'),
@@ -15,7 +19,7 @@ export function logSchemas(schemas) {
15
19
  singleLine: true,
16
20
  border: getBorderCharacters('honeywell'),
17
21
  };
18
- logger.log(data.length ? table(data, tableConfig) : 'No Schemas were found');
22
+ logger.log(table(data, tableConfig));
19
23
  }
20
24
  export async function listSchemas(accountId) {
21
25
  const { data } = await fetchObjectSchemas(accountId);
package/lib/ui/index.js CHANGED
@@ -41,7 +41,7 @@ export function uiAccountDescription(accountId, bold = true) {
41
41
  const account = getAccountConfig(accountId || undefined);
42
42
  let message;
43
43
  if (account && account.accountType) {
44
- message = `${account.name} [${HUBSPOT_ACCOUNT_TYPE_STRINGS[account.accountType]}] (${accountId})`;
44
+ message = `${account.name ? `${account.name} ` : ''}[${HUBSPOT_ACCOUNT_TYPE_STRINGS[account.accountType]}] (${accountId})`;
45
45
  }
46
46
  else {
47
47
  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>;
@@ -5,19 +5,19 @@ import { logger } from '@hubspot/local-dev-lib/logger';
5
5
  import packageJson from '../package.json' with { type: 'json' };
6
6
  const version = packageJson.version;
7
7
  import { debugError } from './errorHandlers/index.js';
8
- const EventClass = {
8
+ export const EventClass = {
9
9
  USAGE: 'USAGE',
10
10
  INTERACTION: 'INTERACTION',
11
11
  VIEW: 'VIEW',
12
12
  ACTIVATION: 'ACTIVATION',
13
13
  };
14
- function getNodeVersionData() {
14
+ export function getNodeVersionData() {
15
15
  return {
16
16
  nodeVersion: process.version,
17
17
  nodeMajorVersion: (process.version || '').split('.')[0],
18
18
  };
19
19
  }
20
- function getPlatform() {
20
+ export function getPlatform() {
21
21
  switch (process.platform) {
22
22
  case 'darwin':
23
23
  return 'macos';
@@ -40,86 +40,45 @@ export async function trackCommandUsage(command, meta = {}, accountId) {
40
40
  ? accountConfig.authType
41
41
  : API_KEY_AUTH_METHOD.value;
42
42
  }
43
- setImmediate(async () => {
44
- const usageTrackingEvent = {
45
- action: 'cli-command',
46
- os: getPlatform(),
47
- ...getNodeVersionData(),
48
- version,
49
- command,
50
- authType,
51
- ...meta,
52
- };
53
- try {
54
- await trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
55
- logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
56
- }
57
- catch (e) {
58
- debugError(e);
59
- }
43
+ return trackCliInteraction({
44
+ action: 'cli-command',
45
+ command,
46
+ authType,
47
+ ...meta,
48
+ accountId,
60
49
  });
61
50
  }
62
51
  export async function trackHelpUsage(command) {
63
52
  if (!isTrackingAllowed()) {
64
53
  return;
65
54
  }
66
- try {
67
- if (command) {
68
- logger.debug('Tracking help usage of "%s" sub-command', command);
69
- }
70
- else {
71
- logger.debug('Tracking help usage of main command');
72
- }
73
- await trackUsage('cli-interaction', EventClass.INTERACTION, {
74
- action: 'cli-help',
75
- os: getPlatform(),
76
- ...getNodeVersionData(),
77
- version,
78
- command,
79
- });
55
+ if (command) {
56
+ logger.debug('Tracking help usage of "%s" sub-command', command);
80
57
  }
81
- catch (e) {
82
- debugError(e);
58
+ else {
59
+ logger.debug('Tracking help usage of main command');
83
60
  }
61
+ return trackCliInteraction({
62
+ action: 'cli-help',
63
+ command,
64
+ });
84
65
  }
85
66
  export async function trackConvertFieldsUsage(command) {
86
- if (!isTrackingAllowed()) {
87
- return;
88
- }
89
- try {
90
- logger.debug('Attempting to track usage of "%s" command', command);
91
- await trackUsage('cli-interaction', EventClass.INTERACTION, {
92
- action: 'cli-process-fields',
93
- os: getPlatform(),
94
- ...getNodeVersionData(),
95
- version,
96
- command,
97
- });
98
- }
99
- catch (e) {
100
- debugError(e);
101
- }
67
+ return trackCliInteraction({
68
+ action: 'cli-process-fields',
69
+ command,
70
+ });
102
71
  }
103
72
  export async function trackAuthAction(command, authType, step, accountId) {
104
- if (!isTrackingAllowed()) {
105
- return;
106
- }
107
- const usageTrackingEvent = {
73
+ return trackCliInteraction({
108
74
  action: 'cli-auth',
109
- os: getPlatform(),
110
- ...getNodeVersionData(),
111
- version,
112
75
  command,
113
76
  authType,
114
- step,
115
- };
116
- try {
117
- await trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
118
- logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
119
- }
120
- catch (e) {
121
- debugError(e);
122
- }
77
+ accountId,
78
+ meta: {
79
+ step,
80
+ },
81
+ });
123
82
  }
124
83
  export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
125
84
  if (!isTrackingAllowed()) {
@@ -134,9 +93,21 @@ export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
134
93
  ? accountConfig.authType
135
94
  : API_KEY_AUTH_METHOD.value;
136
95
  }
137
- setImmediate(async () => {
96
+ return trackCliInteraction({
97
+ action: 'cli-command-metadata',
98
+ command,
99
+ authType,
100
+ accountId,
101
+ meta,
102
+ });
103
+ }
104
+ async function trackCliInteraction({ action, accountId, command, authType, meta = {}, }) {
105
+ try {
106
+ if (!isTrackingAllowed()) {
107
+ return;
108
+ }
138
109
  const usageTrackingEvent = {
139
- action: 'cli-command-metadata',
110
+ action,
140
111
  os: getPlatform(),
141
112
  ...getNodeVersionData(),
142
113
  version,
@@ -144,12 +115,32 @@ export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
144
115
  authType,
145
116
  ...meta,
146
117
  };
118
+ if (process.env.HUBSPOT_MCP_AI_AGENT) {
119
+ try {
120
+ await trackUsage('cli-interaction', EventClass.INTERACTION, {
121
+ ...usageTrackingEvent,
122
+ action: 'cli-mcp-server',
123
+ type: process.env.HUBSPOT_MCP_AI_AGENT,
124
+ }, accountId);
125
+ logger.debug('Sent AI usage tracking command event: %o', {
126
+ ...usageTrackingEvent,
127
+ action: 'cli-mcp-server',
128
+ type: process.env.HUBSPOT_MCP_AI_AGENT,
129
+ });
130
+ }
131
+ catch (error) {
132
+ debugError(error);
133
+ }
134
+ }
147
135
  try {
148
- await trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
149
- logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
136
+ return trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
150
137
  }
151
- catch (e) {
152
- debugError(e);
138
+ catch (error) {
139
+ debugError(error);
153
140
  }
154
- });
141
+ logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
142
+ }
143
+ catch (e) {
144
+ debugError(e);
145
+ }
155
146
  }
@@ -5,6 +5,7 @@ import { addFlag } from '../../utils/command.js';
5
5
  import { absoluteProjectPath } from './constants.js';
6
6
  import { runCommandInDir } from '../../utils/project.js';
7
7
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
8
+ import { trackToolUsage } from '../../utils/toolUsageTracking.js';
8
9
  const inputSchema = {
9
10
  absoluteProjectPath,
10
11
  addApp: z
@@ -37,12 +38,14 @@ const inputSchema = {
37
38
  const inputSchemaZodObject = z.object({
38
39
  ...inputSchema,
39
40
  });
41
+ const toolName = 'add-feature-to-hubspot-project';
40
42
  export class AddFeatureToProject extends Tool {
41
43
  constructor(mcpServer) {
42
44
  super(mcpServer);
43
45
  }
44
46
  async handler({ absoluteProjectPath, distribution, auth, features, addApp, }) {
45
47
  try {
48
+ await trackToolUsage(toolName);
46
49
  let command = `hs project add`;
47
50
  const content = [];
48
51
  if (distribution) {
@@ -72,7 +75,7 @@ export class AddFeatureToProject extends Tool {
72
75
  }
73
76
  }
74
77
  register() {
75
- return this.mcpServer.registerTool('add-feature-to-hubspot-project', {
78
+ return this.mcpServer.registerTool(toolName, {
76
79
  title: 'Add feature to HubSpot Project',
77
80
  description: 'Adds a feature to an existing HubSpot project',
78
81
  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
  }>;