@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.
- package/commands/mcp/__tests__/start.test.js +1 -8
- package/commands/mcp/start.js +1 -0
- package/lang/en.d.ts +0 -7
- package/lang/en.js +1 -8
- package/lib/getStartedV2Actions.d.ts +0 -13
- package/lib/getStartedV2Actions.js +0 -53
- package/lib/mcp/__tests__/setup.test.js +0 -15
- package/lib/mcp/setup.d.ts +0 -1
- package/lib/mcp/setup.js +34 -105
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +1 -1
- package/mcp-server/tools/cms/HsCreateModuleTool.js +1 -1
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +1 -1
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +1 -1
- package/mcp-server/tools/cms/HsListFunctionsTool.js +1 -1
- package/mcp-server/tools/cms/HsListTool.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +2 -1
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +2 -2
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +2 -2
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +2 -2
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +2 -2
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +2 -2
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +1 -1
- package/mcp-server/tools/project/CreateProjectTool.js +1 -1
- package/mcp-server/tools/project/CreateTestAccountTool.js +1 -1
- package/mcp-server/tools/project/DeployProjectTool.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.js +1 -1
- package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
- package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +2 -2
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +2 -2
- package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +2 -2
- package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +2 -2
- package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +2 -10
- package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +2 -2
- package/mcp-server/utils/__tests__/command.test.js +3 -233
- package/mcp-server/utils/__tests__/project.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/project.test.js +140 -0
- package/mcp-server/utils/command.d.ts +0 -5
- package/mcp-server/utils/command.js +0 -24
- package/mcp-server/utils/project.d.ts +5 -0
- package/mcp-server/utils/project.js +18 -0
- package/package.json +8 -2
- package/ui/components/getStarted/GetStartedFlow.js +2 -79
- package/ui/components/getStarted/reducer.d.ts +0 -20
- package/ui/components/getStarted/reducer.js +0 -36
- package/ui/components/getStarted/screens/ProjectSetupScreen.js +1 -2
- package/ui/lib/constants.d.ts +0 -1
- package/ui/lib/constants.js +0 -1
- package/ui/components/getStarted/screens/InstallationScreen.d.ts +0 -7
- 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,
|
|
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 && (
|
|
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
|
}
|
package/ui/lib/constants.d.ts
CHANGED
package/ui/lib/constants.js
CHANGED
|
@@ -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
|
-
}
|