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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/commands/app/install.d.ts +8 -0
  2. package/commands/app/install.js +127 -0
  3. package/commands/app.js +6 -1
  4. package/commands/mcp/setup.js +0 -1
  5. package/commands/mcp/start.d.ts +1 -4
  6. package/commands/mcp/start.js +3 -10
  7. package/commands/open.js +14 -12
  8. package/commands/project/dev/unifiedFlow.js +1 -1
  9. package/commands/testAccount/create.js +14 -24
  10. package/lang/en.d.ts +65 -5
  11. package/lang/en.js +65 -5
  12. package/lib/app/migrate.js +2 -6
  13. package/lib/buildAccount.d.ts +7 -1
  14. package/lib/buildAccount.js +54 -4
  15. package/lib/mcp/setup.js +3 -8
  16. package/lib/projects/create/v3.d.ts +3 -2
  17. package/lib/projects/create/v3.js +2 -2
  18. package/lib/projects/localDev/helpers.d.ts +1 -1
  19. package/lib/projects/localDev/helpers.js +2 -2
  20. package/lib/projects/structure.d.ts +2 -2
  21. package/lib/projects/upload.d.ts +2 -1
  22. package/lib/projects/upload.js +1 -0
  23. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +9 -10
  24. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +86 -47
  25. package/lib/prompts/createModulePrompt.js +1 -2
  26. package/lib/prompts/projectAddPrompt.d.ts +2 -1
  27. package/lib/prompts/projectAddPrompt.js +2 -1
  28. package/lib/prompts/promptUtils.d.ts +2 -2
  29. package/lib/prompts/promptUtils.js +161 -35
  30. package/lib/prompts/selectProjectTemplatePrompt.d.ts +2 -1
  31. package/lib/prompts/selectProjectTemplatePrompt.js +2 -1
  32. package/lib/usageTracking.d.ts +5 -5
  33. package/lib/usageTracking.js +79 -74
  34. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  35. package/mcp-server/tools/project/UploadProjectTools.js +1 -1
  36. package/mcp-server/utils/project.js +0 -3
  37. package/package.json +3 -3
  38. package/types/Prompts.d.ts +4 -2
@@ -5,49 +5,175 @@ exports.promptUser = promptUser;
5
5
  exports.confirmPrompt = confirmPrompt;
6
6
  exports.listPrompt = listPrompt;
7
7
  exports.inputPrompt = inputPrompt;
8
- const inquirer = require('inquirer');
9
- const promptModule = inquirer.createPromptModule();
10
- exports.Separator = new inquirer.Separator();
8
+ const prompts_1 = require("@inquirer/prompts");
9
+ exports.Separator = new prompts_1.Separator();
10
+ function mapPromptChoicesToChoices(choices) {
11
+ return (choices?.map(choice => {
12
+ if (typeof choice === 'string') {
13
+ return { value: choice, name: choice };
14
+ }
15
+ else if (choice instanceof prompts_1.Separator) {
16
+ return choice;
17
+ }
18
+ return {
19
+ value: choice.value,
20
+ name: choice.name,
21
+ disabled: choice.disabled,
22
+ checked: choice.checked,
23
+ };
24
+ }) || []);
25
+ }
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);
40
+ }
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
+ }
54
+ return result;
55
+ })();
56
+ }
11
57
  function promptUser(config) {
12
- return promptModule(config);
58
+ if (Array.isArray(config)) {
59
+ return handleArrayConfig(config);
60
+ }
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({});
68
+ }
69
+ }
70
+ }
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);
88
+ }
89
+ }
90
+ function handleRawListPrompt(config) {
91
+ const choices = mapPromptChoicesToChoices(config.choices);
92
+ choices.map((choice, index) => {
93
+ if (!(choice instanceof prompts_1.Separator)) {
94
+ choice.name = `${index + 1}) ${choice.name}`;
95
+ }
96
+ });
97
+ return (0, prompts_1.select)({
98
+ message: config.message,
99
+ choices: choices,
100
+ pageSize: config.pageSize,
101
+ default: config.default,
102
+ }).then(resp => ({ [config.name]: resp }));
103
+ }
104
+ function handleNumberPrompt(config) {
105
+ return (0, prompts_1.number)({
106
+ message: config.message,
107
+ default: config.default,
108
+ validate: config.validate,
109
+ }).then(resp => ({ [config.name]: resp }));
110
+ }
111
+ function handlePasswordPrompt(config) {
112
+ return (0, prompts_1.password)({
113
+ message: config.message,
114
+ mask: '*',
115
+ validate: config.validate,
116
+ }).then(resp => ({ [config.name]: resp }));
117
+ }
118
+ function handleCheckboxPrompt(config) {
119
+ const choices = mapPromptChoicesToChoices(config.choices);
120
+ return (0, prompts_1.checkbox)({
121
+ message: config.message,
122
+ choices: choices,
123
+ pageSize: config.pageSize,
124
+ validate: config.validate,
125
+ }).then(resp => ({ [config.name]: resp }));
126
+ }
127
+ function handleConfirmPrompt(config) {
128
+ return confirmPrompt(config.message, {
129
+ defaultAnswer: config.default,
130
+ }).then(resp => ({ [config.name]: resp }));
131
+ }
132
+ function handleInputPrompt(config) {
133
+ return (0, prompts_1.input)({
134
+ message: config.message,
135
+ default: config.default,
136
+ validate: config.validate,
137
+ transformer: config.transformer,
138
+ }).then(resp => ({ [config.name]: resp }));
139
+ }
140
+ function handleSelectPrompt(config) {
141
+ const choices = mapPromptChoicesToChoices(config.choices);
142
+ return (0, prompts_1.select)({
143
+ message: config.message,
144
+ choices: choices,
145
+ default: config.default,
146
+ pageSize: config.pageSize,
147
+ }).then(resp => ({ [config.name]: resp }));
13
148
  }
14
149
  async function confirmPrompt(message, options = {}) {
15
- const { defaultAnswer = true, when } = options;
16
- const { choice } = await promptUser([
17
- {
18
- name: 'choice',
19
- type: 'confirm',
20
- message,
21
- default: defaultAnswer,
22
- when,
23
- },
24
- ]);
150
+ const { defaultAnswer = true } = options;
151
+ const choice = await (0, prompts_1.confirm)({
152
+ message,
153
+ default: defaultAnswer,
154
+ });
25
155
  return choice;
26
156
  }
27
157
  async function listPrompt(message, { choices, when, defaultAnswer, validate, }) {
28
- const { choice } = await promptUser([
29
- {
30
- name: 'choice',
31
- type: 'list',
32
- message,
33
- choices,
34
- when,
35
- default: defaultAnswer,
36
- validate,
37
- },
38
- ]);
158
+ const { choice } = await promptUser({
159
+ name: 'choice',
160
+ type: 'list',
161
+ message,
162
+ choices,
163
+ when,
164
+ default: defaultAnswer,
165
+ validate,
166
+ });
39
167
  return choice;
40
168
  }
41
169
  async function inputPrompt(message, { when, validate, defaultAnswer, } = {}) {
42
- const { input } = await promptUser([
43
- {
44
- name: 'input',
45
- type: 'input',
46
- default: defaultAnswer,
47
- message,
48
- when,
49
- validate,
50
- },
51
- ]);
170
+ const { input } = await promptUser({
171
+ name: 'input',
172
+ type: 'input',
173
+ default: defaultAnswer,
174
+ message,
175
+ when,
176
+ validate,
177
+ });
52
178
  return input;
53
179
  }
@@ -1,3 +1,4 @@
1
+ import { Separator } from '@inquirer/prompts';
1
2
  import { ComponentTemplate, ComponentTemplateChoice, ProjectTemplate } from '../../types/Projects';
2
3
  export type SelectProjectTemplatePromptResponse = {
3
4
  projectTemplate?: ProjectTemplate;
@@ -22,5 +23,5 @@ export type PromptOptionsArg = {
22
23
  features?: string[];
23
24
  };
24
25
  export declare function selectProjectTemplatePrompt(promptOptions: PromptOptionsArg, projectTemplates?: ProjectTemplate[], componentTemplates?: undefined): Promise<SelectProjectTemplatePromptResponseProjectTemplate>;
25
- export declare function selectProjectTemplatePrompt(promptOptions: PromptOptionsArg, projectTemplates?: undefined, componentTemplates?: ComponentTemplateChoice[]): Promise<SelectProjectTemplatePromptResponseComponentTemplates>;
26
+ export declare function selectProjectTemplatePrompt(promptOptions: PromptOptionsArg, projectTemplates?: undefined, componentTemplates?: (ComponentTemplateChoice | Separator)[]): Promise<SelectProjectTemplatePromptResponseComponentTemplates>;
26
27
  export {};
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.selectProjectTemplatePrompt = selectProjectTemplatePrompt;
4
+ const prompts_1 = require("@inquirer/prompts");
4
5
  const promptUtils_1 = require("./promptUtils");
5
6
  const en_1 = require("../../lang/en");
6
7
  function findTemplateByNameOrLabel(projectTemplates, templateNameOrLabel) {
@@ -12,7 +13,7 @@ async function selectProjectTemplatePrompt(promptOptions, projectTemplates, comp
12
13
  const selectedComponents = [];
13
14
  if (createProjectFromComponents && promptOptions.features) {
14
15
  componentTemplates.forEach(template => {
15
- if (!template.value) {
16
+ if (template instanceof prompts_1.Separator || !template.value) {
16
17
  return;
17
18
  }
18
19
  if (promptOptions.features?.includes(template.value.type)) {
@@ -13,9 +13,9 @@ type Meta = {
13
13
  file?: boolean;
14
14
  successful?: boolean;
15
15
  };
16
- export declare function trackCommandUsage(command: string, meta?: Meta, accountId?: number): void;
17
- export declare function trackHelpUsage(command: string): void;
18
- export declare function trackConvertFieldsUsage(command: string): void;
19
- export declare function trackAuthAction(command: string, authType: string, step: string, accountId?: number): void;
20
- export declare function trackCommandMetadataUsage(command: string, meta?: Meta, accountId?: number): void;
16
+ export declare function trackCommandUsage(command: string, meta?: Meta, accountId?: number): Promise<void>;
17
+ export declare function trackHelpUsage(command: string): Promise<void>;
18
+ export declare function trackConvertFieldsUsage(command: string): Promise<void>;
19
+ export declare function trackAuthAction(command: string, authType: string, step: string, accountId?: number): Promise<void>;
20
+ export declare function trackCommandMetadataUsage(command: string, meta?: Meta, accountId?: number): Promise<void>;
21
21
  export {};
@@ -33,7 +33,7 @@ function getPlatform() {
33
33
  return process.platform;
34
34
  }
35
35
  }
36
- function trackCommandUsage(command, meta = {}, accountId) {
36
+ async function trackCommandUsage(command, meta = {}, accountId) {
37
37
  if (!(0, config_1.isTrackingAllowed)()) {
38
38
  return;
39
39
  }
@@ -46,47 +46,88 @@ function trackCommandUsage(command, meta = {}, accountId) {
46
46
  ? accountConfig.authType
47
47
  : auth_1.API_KEY_AUTH_METHOD.value;
48
48
  }
49
- trackCliInteraction({
50
- action: 'cli-command',
51
- command,
52
- authType,
53
- ...meta,
54
- accountId,
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
+ }
55
66
  });
56
67
  }
57
- function trackHelpUsage(command) {
68
+ async function trackHelpUsage(command) {
58
69
  if (!(0, config_1.isTrackingAllowed)()) {
59
70
  return;
60
71
  }
61
- if (command) {
62
- logger_1.logger.debug('Tracking help usage of "%s" sub-command', command);
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
+ });
63
86
  }
64
- else {
65
- logger_1.logger.debug('Tracking help usage of main command');
87
+ catch (e) {
88
+ (0, errorHandlers_1.debugError)(e);
66
89
  }
67
- trackCliInteraction({
68
- action: 'cli-help',
69
- command,
70
- });
71
90
  }
72
- function trackConvertFieldsUsage(command) {
73
- trackCliInteraction({
74
- action: 'cli-process-fields',
75
- command,
76
- });
91
+ 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
+ }
77
108
  }
78
- function trackAuthAction(command, authType, step, accountId) {
79
- trackCliInteraction({
109
+ async function trackAuthAction(command, authType, step, accountId) {
110
+ if (!(0, config_1.isTrackingAllowed)()) {
111
+ return;
112
+ }
113
+ const usageTrackingEvent = {
80
114
  action: 'cli-auth',
115
+ os: getPlatform(),
116
+ ...getNodeVersionData(),
117
+ version: package_json_1.version,
81
118
  command,
82
119
  authType,
83
- accountId,
84
- meta: {
85
- step,
86
- },
87
- });
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
+ }
88
129
  }
89
- function trackCommandMetadataUsage(command, meta = {}, accountId) {
130
+ async function trackCommandMetadataUsage(command, meta = {}, accountId) {
90
131
  if (!(0, config_1.isTrackingAllowed)()) {
91
132
  return;
92
133
  }
@@ -99,21 +140,9 @@ function trackCommandMetadataUsage(command, meta = {}, accountId) {
99
140
  ? accountConfig.authType
100
141
  : auth_1.API_KEY_AUTH_METHOD.value;
101
142
  }
102
- trackCliInteraction({
103
- action: 'cli-command-metadata',
104
- command,
105
- authType,
106
- accountId,
107
- meta,
108
- });
109
- }
110
- function trackCliInteraction({ action, accountId, command, authType, meta = {}, }) {
111
- try {
112
- if (!(0, config_1.isTrackingAllowed)()) {
113
- return;
114
- }
143
+ setImmediate(async () => {
115
144
  const usageTrackingEvent = {
116
- action,
145
+ action: 'cli-command-metadata',
117
146
  os: getPlatform(),
118
147
  ...getNodeVersionData(),
119
148
  version: package_json_1.version,
@@ -121,36 +150,12 @@ function trackCliInteraction({ action, accountId, command, authType, meta = {},
121
150
  authType,
122
151
  ...meta,
123
152
  };
124
- if (process.env.HUBSPOT_MCP_AI_AGENT) {
125
- setImmediate(async () => {
126
- try {
127
- await (0, trackUsage_1.trackUsage)('cli-interaction', EventClass.INTERACTION, {
128
- ...usageTrackingEvent,
129
- action: 'cli-mcp-server',
130
- type: process.env.HUBSPOT_MCP_AI_AGENT,
131
- }, accountId);
132
- logger_1.logger.debug('Sent AI usage tracking command event: %o', {
133
- ...usageTrackingEvent,
134
- action: 'cli-mcp-server',
135
- type: process.env.HUBSPOT_MCP_AI_AGENT,
136
- });
137
- }
138
- catch (error) {
139
- (0, errorHandlers_1.debugError)(error);
140
- }
141
- });
153
+ 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);
142
156
  }
143
- setImmediate(async () => {
144
- try {
145
- await (0, trackUsage_1.trackUsage)('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
146
- }
147
- catch (error) {
148
- (0, errorHandlers_1.debugError)(error);
149
- }
150
- });
151
- logger_1.logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
152
- }
153
- catch (e) {
154
- (0, errorHandlers_1.debugError)(e);
155
- }
157
+ catch (e) {
158
+ (0, errorHandlers_1.debugError)(e);
159
+ }
160
+ });
156
161
  }
@@ -14,17 +14,17 @@ declare const inputSchemaZodObject: z.ZodObject<{
14
14
  absoluteCurrentWorkingDirectory: string;
15
15
  destination: string;
16
16
  auth?: "oauth" | "static" | undefined;
17
+ name?: string | undefined;
17
18
  distribution?: "marketplace" | "private" | undefined;
18
19
  features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
19
- name?: string | undefined;
20
20
  }, {
21
21
  projectBase: "app" | "empty";
22
22
  absoluteCurrentWorkingDirectory: string;
23
23
  destination: string;
24
24
  auth?: "oauth" | "static" | undefined;
25
+ name?: string | undefined;
25
26
  distribution?: "marketplace" | "private" | undefined;
26
27
  features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
27
- name?: string | undefined;
28
28
  }>;
29
29
  export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
30
30
  export declare class CreateProjectTool extends Tool<CreateProjectInputSchema> {
@@ -21,7 +21,7 @@ class UploadProjectTools extends types_1.Tool {
21
21
  super(mcpServer);
22
22
  }
23
23
  async handler({ absoluteProjectPath, }) {
24
- const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, `hs project upload --force-create --debug`);
24
+ const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, `hs project upload --force-create`);
25
25
  return (0, content_1.formatTextContents)(stdout, stderr);
26
26
  }
27
27
  register() {
@@ -13,8 +13,5 @@ async function runCommandInDir(directory, command) {
13
13
  }
14
14
  return (0, command_1.execAsync)(command, {
15
15
  cwd: path_1.default.resolve(directory),
16
- env: {
17
- ...process.env,
18
- },
19
16
  });
20
17
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "7.7.19-experimental.0",
3
+ "version": "7.7.19-experimental.2",
4
4
  "description": "The official CLI for developing on HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": "https://github.com/HubSpot/hubspot-cli",
7
7
  "dependencies": {
8
- "@hubspot/local-dev-lib": "3.12.0",
8
+ "@hubspot/local-dev-lib": "3.13.1",
9
9
  "@hubspot/project-parsing-lib": "0.5.1",
10
10
  "@hubspot/serverless-dev-runtime": "7.0.6",
11
11
  "@hubspot/theme-preview-dev-server": "0.0.10",
@@ -19,7 +19,7 @@
19
19
  "express": "4.21.2",
20
20
  "findup-sync": "4.0.0",
21
21
  "fs-extra": "8.1.0",
22
- "inquirer": "8.2.0",
22
+ "inquirer": "12.7.0",
23
23
  "js-yaml": "4.1.0",
24
24
  "moment": "2.30.1",
25
25
  "open": "7.4.2",
@@ -1,3 +1,4 @@
1
+ import { Separator } from '@inquirer/prompts';
1
2
  export type GenericPromptResponse = {
2
3
  [key: string]: any;
3
4
  };
@@ -6,9 +7,10 @@ export type PromptChoices<T = any> = Array<string | {
6
7
  name: string;
7
8
  value?: T;
8
9
  disabled?: string | boolean;
9
- }>;
10
+ checked?: boolean;
11
+ } | Separator>;
10
12
  export type PromptWhen = boolean | (() => boolean);
11
- type PromptOperand = string | number | boolean | string[] | boolean[] | null;
13
+ export type PromptOperand = string | number | boolean | string[] | boolean[] | null;
12
14
  export type PromptConfig<T extends GenericPromptResponse> = {
13
15
  name: keyof T;
14
16
  type?: PromptType;