@hubspot/cli 8.0.8-experimental.0 → 8.0.8-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 (49) hide show
  1. package/commands/mcp/__tests__/start.test.js +1 -8
  2. package/commands/mcp/start.js +1 -0
  3. package/lang/en.d.ts +0 -7
  4. package/lang/en.js +1 -8
  5. package/lib/getStartedV2Actions.d.ts +0 -13
  6. package/lib/getStartedV2Actions.js +0 -53
  7. package/lib/mcp/__tests__/setup.test.js +0 -15
  8. package/lib/mcp/setup.d.ts +0 -1
  9. package/lib/mcp/setup.js +34 -105
  10. package/mcp-server/tools/cms/HsCreateFunctionTool.js +1 -1
  11. package/mcp-server/tools/cms/HsCreateModuleTool.js +1 -1
  12. package/mcp-server/tools/cms/HsCreateTemplateTool.js +1 -1
  13. package/mcp-server/tools/cms/HsFunctionLogsTool.js +1 -1
  14. package/mcp-server/tools/cms/HsListFunctionsTool.js +1 -1
  15. package/mcp-server/tools/cms/HsListTool.js +1 -1
  16. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +2 -1
  17. package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +2 -2
  18. package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +2 -2
  19. package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +2 -2
  20. package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +2 -2
  21. package/mcp-server/tools/cms/__tests__/HsListTool.test.js +2 -2
  22. package/mcp-server/tools/project/AddFeatureToProjectTool.js +1 -1
  23. package/mcp-server/tools/project/CreateProjectTool.js +1 -1
  24. package/mcp-server/tools/project/CreateTestAccountTool.js +1 -1
  25. package/mcp-server/tools/project/DeployProjectTool.js +1 -1
  26. package/mcp-server/tools/project/UploadProjectTools.js +1 -1
  27. package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
  28. package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +2 -2
  29. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +2 -2
  30. package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +2 -2
  31. package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +2 -2
  32. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +2 -10
  33. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +2 -2
  34. package/mcp-server/utils/__tests__/command.test.js +3 -233
  35. package/mcp-server/utils/__tests__/project.test.d.ts +1 -0
  36. package/mcp-server/utils/__tests__/project.test.js +140 -0
  37. package/mcp-server/utils/command.d.ts +0 -5
  38. package/mcp-server/utils/command.js +0 -24
  39. package/mcp-server/utils/project.d.ts +5 -0
  40. package/mcp-server/utils/project.js +18 -0
  41. package/package.json +8 -2
  42. package/ui/components/getStarted/GetStartedFlow.js +2 -79
  43. package/ui/components/getStarted/reducer.d.ts +0 -20
  44. package/ui/components/getStarted/reducer.js +0 -36
  45. package/ui/components/getStarted/screens/ProjectSetupScreen.js +1 -2
  46. package/ui/lib/constants.d.ts +0 -1
  47. package/ui/lib/constants.js +0 -1
  48. package/ui/components/getStarted/screens/InstallationScreen.d.ts +0 -7
  49. package/ui/components/getStarted/screens/InstallationScreen.js +0 -16
@@ -1,15 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { sanitizeFileName, untildify } from '@hubspot/local-dev-lib/path';
3
3
  import { useApp, useFocus, useInput } from 'ink';
4
- import open from 'open';
5
4
  import { useCallback, useEffect, useReducer } from 'react';
6
5
  import { commands } from '../../../lang/en.js';
7
- import { createProjectAction, pollAppInstallation, trackGetStartedUsage, uploadAndDeployAction, } from '../../../lib/getStartedV2Actions.js';
8
- import { validateProjectDirectory } from '../../../lib/prompts/projectNameAndDestPrompt.js';
6
+ import { createProjectAction, trackGetStartedUsage, uploadAndDeployAction, } from '../../../lib/getStartedV2Actions.js';
9
7
  import { uiAccountDescription } from '../../../lib/ui/index.js';
10
8
  import { ACTION_STATUSES, GET_STARTED_FLOW_STEPS, } from '../../lib/constants.js';
11
9
  import { flowReducer } from './reducer.js';
12
- import { InstallationScreen } from './screens/InstallationScreen.js';
13
10
  import { ProjectSetupScreen } from './screens/ProjectSetupScreen.js';
14
11
  import { UploadScreen } from './screens/UploadScreen.js';
15
12
  import { getProject } from './selectors.js';
@@ -47,7 +44,6 @@ export function GetStartedFlow({ derivedAccountId, initialName, initialDest, })
47
44
  statuses: {
48
45
  create: initialName ? ACTION_STATUSES.RUNNING : ACTION_STATUSES.IDLE,
49
46
  upload: ACTION_STATUSES.IDLE,
50
- installApp: ACTION_STATUSES.IDLE,
51
47
  },
52
48
  });
53
49
  const [state, dispatch] = useReducer(flowReducer, getInitialState());
@@ -72,16 +68,6 @@ export function GetStartedFlow({ derivedAccountId, initialName, initialDest, })
72
68
  dispatch({ type: 'SET_STEP', payload: GET_STARTED_FLOW_STEPS.DEST_INPUT });
73
69
  }, []);
74
70
  const handleDestSubmit = useCallback(async () => {
75
- const validationResult = validateProjectDirectory(project.destination);
76
- if (validationResult !== true) {
77
- dispatch({
78
- type: 'SET_DEST_ERROR',
79
- payload: typeof validationResult === 'string'
80
- ? validationResult
81
- : commands.getStarted.v2.unknownError,
82
- });
83
- return;
84
- }
85
71
  dispatch({ type: 'SET_STEP', payload: GET_STARTED_FLOW_STEPS.CREATING });
86
72
  try {
87
73
  await createProjectAction({
@@ -122,57 +108,6 @@ export function GetStartedFlow({ derivedAccountId, initialName, initialDest, })
122
108
  dispatch({ type: 'UPLOAD_ERROR', payload: errorMessage });
123
109
  }
124
110
  }, [derivedAccountId, project.destination]);
125
- const handlePollInstallation = useCallback(async () => {
126
- const uploadApp = project.uploadResult?.app;
127
- const projectId = project.uploadResult?.projectId;
128
- if (!projectId || !uploadApp?.uid) {
129
- dispatch({
130
- type: 'INSTALL_APP_ERROR',
131
- payload: commands.getStarted.v2.unknownError,
132
- });
133
- return;
134
- }
135
- try {
136
- await pollAppInstallation({
137
- accountId: derivedAccountId,
138
- projectId,
139
- appUid: uploadApp.uid,
140
- requiredScopes: uploadApp.config?.auth?.requiredScopes,
141
- optionalScopes: uploadApp.config?.auth?.optionalScopes,
142
- onTimeout: () => {
143
- dispatch({ type: 'SET_POLLING_TIMED_OUT', payload: true });
144
- },
145
- });
146
- dispatch({ type: 'INSTALL_APP_DONE' });
147
- }
148
- catch (error) {
149
- dispatch({
150
- type: 'INSTALL_APP_ERROR',
151
- payload: error instanceof Error
152
- ? error.message
153
- : commands.getStarted.v2.unknownError,
154
- });
155
- }
156
- }, [project.uploadResult, derivedAccountId]);
157
- const handleBrowserOpen = useCallback(async (shouldOpen) => {
158
- await trackGetStartedUsage({
159
- step: 'open-install-page',
160
- type: shouldOpen ? 'opened' : 'declined',
161
- }, derivedAccountId);
162
- if (shouldOpen && project.uploadResult?.installUrl) {
163
- try {
164
- await open(project.uploadResult.installUrl, { url: true });
165
- }
166
- catch (error) {
167
- dispatch({
168
- type: 'SET_BROWSER_FAILED_URL',
169
- payload: project.uploadResult.installUrl,
170
- });
171
- }
172
- }
173
- dispatch({ type: 'START_INSTALL_APP' });
174
- await handlePollInstallation();
175
- }, [project.uploadResult, derivedAccountId, handlePollInstallation]);
176
111
  const handleNameChange = useCallback((value) => {
177
112
  dispatch({ type: 'SET_PROJECT_NAME', payload: value });
178
113
  }, []);
@@ -181,8 +116,7 @@ export function GetStartedFlow({ derivedAccountId, initialName, initialDest, })
181
116
  }, []);
182
117
  useInput((_, key) => {
183
118
  const hasError = state.statuses.create === ACTION_STATUSES.ERROR ||
184
- state.statuses.upload === ACTION_STATUSES.ERROR ||
185
- state.statuses.installApp === ACTION_STATUSES.ERROR;
119
+ state.statuses.upload === ACTION_STATUSES.ERROR;
186
120
  if (hasError) {
187
121
  exit();
188
122
  return;
@@ -192,22 +126,11 @@ export function GetStartedFlow({ derivedAccountId, initialName, initialDest, })
192
126
  if (state.step === GET_STARTED_FLOW_STEPS.COMPLETE) {
193
127
  handleUploadStart();
194
128
  }
195
- else if (state.step === GET_STARTED_FLOW_STEPS.OPEN_APP_PROMPT) {
196
- handleBrowserOpen(true);
197
- }
198
- else if (state.step === GET_STARTED_FLOW_STEPS.INSTALLING_APP &&
199
- state.statuses.installApp === ACTION_STATUSES.DONE) {
200
- // Ready for card setup - will be handled in PR3
201
- exit();
202
- }
203
129
  });
204
130
  if (state.step === GET_STARTED_FLOW_STEPS.UPLOADING ||
205
131
  state.step === GET_STARTED_FLOW_STEPS.OPEN_APP_PROMPT) {
206
132
  return _jsx(UploadScreen, { state: state, accountName: accountName });
207
133
  }
208
- if (state.step === GET_STARTED_FLOW_STEPS.INSTALLING_APP) {
209
- return _jsx(InstallationScreen, { state: state, accountName: accountName });
210
- }
211
134
  // Show project setup screen for initial flow
212
135
  return (_jsx(ProjectSetupScreen, { state: state, onSelectOption: handleSelect, onNameChange: handleNameChange, onNameSubmit: handleNameSubmit, onDestChange: handleDestChange, onDestSubmit: handleDestSubmit }));
213
136
  }
@@ -14,7 +14,6 @@ export type AppState = {
14
14
  export type ActionStatuses = {
15
15
  create: ActionStatus;
16
16
  upload: ActionStatus;
17
- installApp: ActionStatus;
18
17
  };
19
18
  export type FlowState = {
20
19
  step: FlowStep;
@@ -22,9 +21,6 @@ export type FlowState = {
22
21
  app: AppState;
23
22
  statuses: ActionStatuses;
24
23
  error?: string;
25
- destError?: string;
26
- browserFailedUrl?: string;
27
- pollingTimedOut?: boolean;
28
24
  };
29
25
  type FlowAction = {
30
26
  type: 'SET_STEP';
@@ -41,9 +37,6 @@ type FlowAction = {
41
37
  } | {
42
38
  type: 'SET_ERROR';
43
39
  payload: string;
44
- } | {
45
- type: 'SET_DEST_ERROR';
46
- payload: string;
47
40
  } | {
48
41
  type: 'CLEAR_ERROR';
49
42
  } | {
@@ -61,19 +54,6 @@ type FlowAction = {
61
54
  } | {
62
55
  type: 'UPLOAD_ERROR';
63
56
  payload: string;
64
- } | {
65
- type: 'START_INSTALL_APP';
66
- } | {
67
- type: 'INSTALL_APP_DONE';
68
- } | {
69
- type: 'INSTALL_APP_ERROR';
70
- payload: string;
71
- } | {
72
- type: 'SET_BROWSER_FAILED_URL';
73
- payload: string;
74
- } | {
75
- type: 'SET_POLLING_TIMED_OUT';
76
- payload: boolean;
77
57
  };
78
58
  export declare function flowReducer(state: FlowState, action: FlowAction): FlowState;
79
59
  export {};
@@ -17,13 +17,6 @@ export function flowReducer(state, action) {
17
17
  return {
18
18
  ...state,
19
19
  project: { ...state.project, destination: action.payload },
20
- destError: undefined,
21
- };
22
- case 'SET_DEST_ERROR':
23
- return {
24
- ...state,
25
- step: GET_STARTED_FLOW_STEPS.DEST_INPUT,
26
- destError: action.payload,
27
20
  };
28
21
  case 'SET_ERROR':
29
22
  return { ...state, error: action.payload };
@@ -73,35 +66,6 @@ export function flowReducer(state, action) {
73
66
  statuses: { ...state.statuses, upload: ACTION_STATUSES.ERROR },
74
67
  error: action.payload,
75
68
  };
76
- case 'START_INSTALL_APP':
77
- return {
78
- ...state,
79
- step: GET_STARTED_FLOW_STEPS.INSTALLING_APP,
80
- statuses: { ...state.statuses, installApp: ACTION_STATUSES.RUNNING },
81
- error: undefined,
82
- pollingTimedOut: false,
83
- };
84
- case 'INSTALL_APP_DONE':
85
- return {
86
- ...state,
87
- statuses: { ...state.statuses, installApp: ACTION_STATUSES.DONE },
88
- };
89
- case 'INSTALL_APP_ERROR':
90
- return {
91
- ...state,
92
- statuses: { ...state.statuses, installApp: ACTION_STATUSES.ERROR },
93
- error: action.payload,
94
- };
95
- case 'SET_BROWSER_FAILED_URL':
96
- return {
97
- ...state,
98
- browserFailedUrl: action.payload,
99
- };
100
- case 'SET_POLLING_TIMED_OUT':
101
- return {
102
- ...state,
103
- pollingTimedOut: action.payload,
104
- };
105
69
  default:
106
70
  return state;
107
71
  }
@@ -35,6 +35,5 @@ export function ProjectSetupScreen({ state, onSelectOption, onNameChange, onName
35
35
  return (_jsx(BoxWithTitle, { flexGrow: 1, title: "hs get-started", borderColor: INK_COLORS.HUBSPOT_ORANGE, titleBackgroundColor: INK_COLORS.HUBSPOT_ORANGE, children: _jsxs(Box, { flexDirection: "column", rowGap: 1, children: [_jsx(Text, { bold: true, children: titleText }), state.step === GET_STARTED_FLOW_STEPS.SELECT ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: overviewText }), _jsx(Text, { children: projectsText }), _jsxs(Box, { flexDirection: "row", flexWrap: "wrap", columnGap: 1, children: [_jsx(Text, { color: INK_COLORS.HUBSPOT_TEAL, children: "?" }), _jsx(Text, { children: selectPrompt })] }), _jsx(SelectInput, { items: GET_STARTED_FLOW_OPTIONS, onSelect: onSelectOption })] })) : (_jsxs(Box, { flexDirection: "row", flexWrap: "wrap", columnGap: 1, children: [_jsx(Text, { color: INK_COLORS.HUBSPOT_TEAL, children: "?" }), _jsx(Text, { children: `${selectPrompt}` }), _jsx(Text, { color: INK_COLORS.INFO_BLUE, children: state.app.selectedLabel })] })), _jsxs(ActionSection, { status: state.statuses.create, statusText: runningProjectCreateText, errorMessage: state.statuses.create === ACTION_STATUSES.ERROR
36
36
  ? `${state.error}\n\n${commands.getStarted.v2.pressKeyToExit}`
37
37
  : undefined, children: [state.step !== GET_STARTED_FLOW_STEPS.SELECT && (_jsx(InputField, { flag: "name", prompt: "Enter your project name", value: project.name, isEditing: state.step === GET_STARTED_FLOW_STEPS.NAME_INPUT, onChange: onNameChange, onSubmit: onNameSubmit })), state.step !== GET_STARTED_FLOW_STEPS.SELECT &&
38
- state.step !== GET_STARTED_FLOW_STEPS.NAME_INPUT && (_jsxs(_Fragment, { children: [_jsx(InputField, { flag: "dest", prompt: "Choose where to create the project", value: project.destination, isEditing: state.step === GET_STARTED_FLOW_STEPS.DEST_INPUT, onChange: onDestChange, onSubmit: onDestSubmit }), state.destError &&
39
- state.step === GET_STARTED_FLOW_STEPS.DEST_INPUT && (_jsx(Text, { color: INK_COLORS.ALERT_RED, children: state.destError }))] }))] }), state.step === GET_STARTED_FLOW_STEPS.COMPLETE && (_jsxs(Box, { flexDirection: "row", flexWrap: "wrap", columnGap: 1, children: [_jsx(Text, { color: INK_COLORS.HUBSPOT_TEAL, children: "?" }), _jsx(Text, { children: commands.getStarted.v2.pressEnterToContinueDeploy(state.app.selectedLabel) })] }))] }) }));
38
+ state.step !== GET_STARTED_FLOW_STEPS.NAME_INPUT && (_jsx(InputField, { flag: "dest", prompt: "Choose where to create the project", value: project.destination, isEditing: state.step === GET_STARTED_FLOW_STEPS.DEST_INPUT, onChange: onDestChange, onSubmit: onDestSubmit }))] }), state.step === GET_STARTED_FLOW_STEPS.COMPLETE && (_jsxs(Box, { flexDirection: "row", flexWrap: "wrap", columnGap: 1, children: [_jsx(Text, { color: INK_COLORS.HUBSPOT_TEAL, children: "?" }), _jsx(Text, { children: commands.getStarted.v2.pressEnterToContinueDeploy(state.app.selectedLabel) })] }))] }) }));
40
39
  }
@@ -12,6 +12,5 @@ export declare const GET_STARTED_FLOW_STEPS: {
12
12
  readonly INSTALLING: "installing";
13
13
  readonly UPLOADING: "uploading";
14
14
  readonly OPEN_APP_PROMPT: "open-app-prompt";
15
- readonly INSTALLING_APP: "installing-app";
16
15
  readonly COMPLETE: "complete";
17
16
  };
@@ -12,6 +12,5 @@ export const GET_STARTED_FLOW_STEPS = {
12
12
  INSTALLING: 'installing',
13
13
  UPLOADING: 'uploading',
14
14
  OPEN_APP_PROMPT: 'open-app-prompt',
15
- INSTALLING_APP: 'installing-app',
16
15
  COMPLETE: 'complete',
17
16
  };
@@ -1,7 +0,0 @@
1
- import { FlowState } from '../reducer.js';
2
- type InstallationScreenProps = {
3
- state: FlowState;
4
- accountName: string;
5
- };
6
- export declare function InstallationScreen({ state, accountName, }: InstallationScreenProps): import("react/jsx-runtime").JSX.Element;
7
- export {};
@@ -1,16 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { commands } from '../../../../lang/en.js';
4
- import { ActionSection } from '../../ActionSection.js';
5
- import { BoxWithTitle } from '../../BoxWithTitle.js';
6
- import { INK_COLORS } from '../../../styles.js';
7
- import { getProject } from '../selectors.js';
8
- import { ACTION_STATUSES, GET_STARTED_FLOW_STEPS, } from '../../../lib/constants.js';
9
- export function InstallationScreen({ state, accountName, }) {
10
- const project = getProject(state);
11
- const titleText = commands.getStarted.v2.startTitle;
12
- // If we get to the installation screen, the app is uploaded and we have the name
13
- const appName = project.uploadResult?.app?.config.name;
14
- return (_jsx(BoxWithTitle, { flexGrow: 1, title: "hs get-started", borderColor: INK_COLORS.HUBSPOT_ORANGE, titleBackgroundColor: INK_COLORS.HUBSPOT_ORANGE, children: _jsxs(Box, { flexDirection: "column", rowGap: 1, children: [_jsx(Text, { bold: true, children: titleText }), _jsx(Text, { children: commands.getStarted.v2.installInstructions }), _jsx(ActionSection, { status: state.statuses.installApp, statusText: commands.getStarted.v2.installingApp(appName, accountName) }), state.browserFailedUrl && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Text, { color: INK_COLORS.WARNING_YELLOW, children: commands.getStarted.v2.browserFailedToOpen(state.browserFailedUrl) }) })), state.pollingTimedOut && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Text, { color: INK_COLORS.WARNING_YELLOW, children: commands.getStarted.v2.pollingTimeout(2) }) })), state.step === GET_STARTED_FLOW_STEPS.INSTALLING_APP &&
15
- state.statuses.installApp === ACTION_STATUSES.DONE && (_jsx(Text, { children: commands.getStarted.v2.pressEnterToContinueSetup }))] }) }));
16
- }