@hubspot/cli 8.1.0 → 8.2.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.
- package/commands/cms/__tests__/watch.test.js +0 -8
- package/commands/cms/function/logs.js +1 -0
- package/commands/cms/theme/preview.js +9 -64
- package/commands/cms/watch.d.ts +0 -1
- package/commands/cms/watch.js +2 -8
- package/commands/feedback.js +1 -1
- package/commands/mcp/__tests__/start.test.js +8 -1
- package/commands/mcp/setup.js +1 -9
- package/commands/mcp/start.js +0 -1
- package/commands/project/__tests__/create.test.js +1 -1
- package/commands/project/create.js +2 -2
- package/commands/project/watch.js +15 -2
- package/lang/en.d.ts +17 -6
- package/lang/en.js +18 -7
- package/lib/__tests__/commandSuggestion.test.js +2 -0
- package/lib/__tests__/serverlessLogs.test.js +79 -64
- package/lib/commandSuggestion.js +1 -7
- package/lib/constants.d.ts +1 -1
- package/lib/constants.js +1 -1
- package/lib/generateSelectors.js +1 -2
- package/lib/getStartedV2Actions.d.ts +13 -0
- package/lib/getStartedV2Actions.js +53 -0
- package/lib/mcp/__tests__/setup.test.js +357 -28
- package/lib/mcp/setup.d.ts +1 -0
- package/lib/mcp/setup.js +77 -30
- package/lib/projects/create/__tests__/legacy.test.js +6 -24
- package/lib/projects/create/index.js +1 -4
- package/lib/projects/create/legacy.js +3 -8
- package/lib/projects/create/v2.js +1 -9
- package/lib/projects/ensureProjectExists.js +1 -2
- package/lib/projects/pollProjectBuildAndDeploy.js +90 -85
- package/lib/projects/upload.d.ts +1 -0
- package/lib/projects/upload.js +37 -46
- package/lib/projects/watch.d.ts +2 -1
- package/lib/projects/watch.js +32 -24
- package/lib/serverlessLogs.js +50 -44
- package/lib/theme/cmsDevServerProcess.d.ts +12 -0
- package/lib/theme/cmsDevServerProcess.js +148 -0
- package/lib/theme/cmsDevServerRunner.d.ts +14 -0
- package/lib/theme/cmsDevServerRunner.js +90 -0
- package/lib/usageTracking.js +8 -5
- 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 +1 -2
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +1 -2
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +1 -2
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +1 -2
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +1 -2
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +1 -2
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +20 -3
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +7 -11
- package/mcp-server/tools/project/CreateProjectTool.d.ts +24 -4
- package/mcp-server/tools/project/CreateProjectTool.js +6 -11
- package/mcp-server/tools/project/CreateTestAccountTool.js +1 -1
- package/mcp-server/tools/project/DeployProjectTool.js +1 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +5 -8
- package/mcp-server/tools/project/GetBuildLogsTool.d.ts +2 -2
- package/mcp-server/tools/project/GetBuildLogsTool.js +6 -7
- package/mcp-server/tools/project/GetBuildStatusTool.d.ts +1 -1
- package/mcp-server/tools/project/GetBuildStatusTool.js +3 -4
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +6 -1
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -6
- 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 +1 -2
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -2
- package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +1 -2
- package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +1 -2
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +0 -32
- package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +10 -2
- package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +2 -2
- package/mcp-server/tools/project/constants.d.ts +12 -1
- package/mcp-server/tools/project/constants.js +12 -16
- package/mcp-server/utils/__tests__/command.test.js +233 -3
- package/mcp-server/utils/__tests__/feedbackTracking.test.js +9 -64
- package/mcp-server/utils/command.d.ts +5 -0
- package/mcp-server/utils/command.js +24 -0
- package/mcp-server/utils/feedbackTracking.js +2 -17
- package/package.json +4 -5
- package/ui/components/getStarted/GetStartedFlow.js +79 -2
- package/ui/components/getStarted/reducer.d.ts +20 -0
- package/ui/components/getStarted/reducer.js +36 -0
- package/ui/components/getStarted/screens/InstallationScreen.d.ts +7 -0
- package/ui/components/getStarted/screens/InstallationScreen.js +16 -0
- package/ui/components/getStarted/screens/ProjectSetupScreen.js +2 -1
- package/ui/lib/constants.d.ts +1 -0
- package/ui/lib/constants.js +1 -0
- package/mcp-server/utils/__tests__/project.test.d.ts +0 -1
- package/mcp-server/utils/__tests__/project.test.js +0 -140
- package/mcp-server/utils/project.d.ts +0 -5
- package/mcp-server/utils/project.js +0 -18
|
@@ -17,6 +17,13 @@ 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,
|
|
20
27
|
};
|
|
21
28
|
case 'SET_ERROR':
|
|
22
29
|
return { ...state, error: action.payload };
|
|
@@ -66,6 +73,35 @@ export function flowReducer(state, action) {
|
|
|
66
73
|
statuses: { ...state.statuses, upload: ACTION_STATUSES.ERROR },
|
|
67
74
|
error: action.payload,
|
|
68
75
|
};
|
|
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
|
+
};
|
|
69
105
|
default:
|
|
70
106
|
return state;
|
|
71
107
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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 {};
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
}
|
|
@@ -35,5 +35,6 @@ 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 && (_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 })
|
|
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) })] }))] }) }));
|
|
39
40
|
}
|
package/ui/lib/constants.d.ts
CHANGED
package/ui/lib/constants.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { runCommandInDir } from '../project.js';
|
|
2
|
-
import { execAsync } from '../command.js';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
vi.mock('../command', () => ({
|
|
6
|
-
execAsync: vi.fn(),
|
|
7
|
-
addFlag: vi.fn((command, flagName, value) => {
|
|
8
|
-
if (Array.isArray(value)) {
|
|
9
|
-
return `${command} --${flagName} ${value.map(item => `"${item}"`).join(' ')}`;
|
|
10
|
-
}
|
|
11
|
-
return `${command} --${flagName} "${value}"`;
|
|
12
|
-
}),
|
|
13
|
-
}));
|
|
14
|
-
vi.mock('fs');
|
|
15
|
-
vi.mock('path');
|
|
16
|
-
const mockExecAsync = execAsync;
|
|
17
|
-
const mockExistsSync = fs.existsSync;
|
|
18
|
-
const mockMkdirSync = fs.mkdirSync;
|
|
19
|
-
const mockResolve = path.resolve;
|
|
20
|
-
describe('mcp-server/utils/project', () => {
|
|
21
|
-
describe('runCommandInDir', () => {
|
|
22
|
-
const mockDirectory = '/test/directory';
|
|
23
|
-
const mockCommand = 'npm install';
|
|
24
|
-
const mockResolvedPath = '/resolved/test/directory';
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
mockResolve.mockReturnValue(mockResolvedPath);
|
|
27
|
-
});
|
|
28
|
-
it('should run command in existing directory', async () => {
|
|
29
|
-
const expectedResult = {
|
|
30
|
-
stdout: 'command output',
|
|
31
|
-
stderr: '',
|
|
32
|
-
};
|
|
33
|
-
mockExistsSync.mockReturnValue(true);
|
|
34
|
-
mockExecAsync.mockResolvedValue(expectedResult);
|
|
35
|
-
const result = await runCommandInDir(mockDirectory, mockCommand);
|
|
36
|
-
expect(mockExistsSync).toHaveBeenCalledWith(mockDirectory);
|
|
37
|
-
expect(mockMkdirSync).not.toHaveBeenCalled();
|
|
38
|
-
expect(mockResolve).toHaveBeenCalledWith(mockDirectory);
|
|
39
|
-
expect(mockExecAsync).toHaveBeenCalledWith(mockCommand, expect.objectContaining({
|
|
40
|
-
cwd: mockResolvedPath,
|
|
41
|
-
env: expect.any(Object),
|
|
42
|
-
}));
|
|
43
|
-
expect(result).toEqual(expectedResult);
|
|
44
|
-
});
|
|
45
|
-
it('should create directory if it does not exist', async () => {
|
|
46
|
-
const expectedResult = {
|
|
47
|
-
stdout: 'command output',
|
|
48
|
-
stderr: '',
|
|
49
|
-
};
|
|
50
|
-
mockExistsSync.mockReturnValue(false);
|
|
51
|
-
mockExecAsync.mockResolvedValue(expectedResult);
|
|
52
|
-
const result = await runCommandInDir(mockDirectory, mockCommand);
|
|
53
|
-
expect(mockExistsSync).toHaveBeenCalledWith(mockDirectory);
|
|
54
|
-
expect(mockMkdirSync).toHaveBeenCalledWith(mockDirectory);
|
|
55
|
-
expect(mockResolve).toHaveBeenCalledWith(mockDirectory);
|
|
56
|
-
expect(mockExecAsync).toHaveBeenCalledWith(mockCommand, expect.objectContaining({
|
|
57
|
-
cwd: mockResolvedPath,
|
|
58
|
-
env: expect.any(Object),
|
|
59
|
-
}));
|
|
60
|
-
expect(result).toEqual(expectedResult);
|
|
61
|
-
});
|
|
62
|
-
it('should propagate execAsync errors', async () => {
|
|
63
|
-
const error = new Error('Command failed');
|
|
64
|
-
mockExistsSync.mockReturnValue(true);
|
|
65
|
-
mockExecAsync.mockRejectedValue(error);
|
|
66
|
-
await expect(runCommandInDir(mockDirectory, mockCommand)).rejects.toThrow('Command failed');
|
|
67
|
-
expect(mockExecAsync).toHaveBeenCalledWith(mockCommand, expect.objectContaining({
|
|
68
|
-
cwd: mockResolvedPath,
|
|
69
|
-
env: expect.any(Object),
|
|
70
|
-
}));
|
|
71
|
-
});
|
|
72
|
-
it('should handle stderr in results', async () => {
|
|
73
|
-
const expectedResult = {
|
|
74
|
-
stdout: 'some output',
|
|
75
|
-
stderr: 'warning message',
|
|
76
|
-
};
|
|
77
|
-
mockExistsSync.mockReturnValue(true);
|
|
78
|
-
mockExecAsync.mockResolvedValue(expectedResult);
|
|
79
|
-
const result = await runCommandInDir(mockDirectory, mockCommand);
|
|
80
|
-
expect(result.stdout).toBe('some output');
|
|
81
|
-
expect(result.stderr).toBe('warning message');
|
|
82
|
-
});
|
|
83
|
-
it('should add --disable-usage-tracking flag to hs commands', async () => {
|
|
84
|
-
const hsCommand = 'hs project upload';
|
|
85
|
-
const expectedResult = {
|
|
86
|
-
stdout: 'success',
|
|
87
|
-
stderr: '',
|
|
88
|
-
};
|
|
89
|
-
mockExistsSync.mockReturnValue(true);
|
|
90
|
-
mockExecAsync.mockResolvedValue(expectedResult);
|
|
91
|
-
await runCommandInDir(mockDirectory, hsCommand);
|
|
92
|
-
expect(mockExecAsync).toHaveBeenCalledWith('hs project upload --disable-usage-tracking "true"', expect.objectContaining({
|
|
93
|
-
cwd: mockResolvedPath,
|
|
94
|
-
env: expect.any(Object),
|
|
95
|
-
}));
|
|
96
|
-
});
|
|
97
|
-
it('should not add --disable-usage-tracking flag to non-hs commands', async () => {
|
|
98
|
-
const nonHsCommand = 'npm install';
|
|
99
|
-
const expectedResult = {
|
|
100
|
-
stdout: 'success',
|
|
101
|
-
stderr: '',
|
|
102
|
-
};
|
|
103
|
-
mockExistsSync.mockReturnValue(true);
|
|
104
|
-
mockExecAsync.mockResolvedValue(expectedResult);
|
|
105
|
-
await runCommandInDir(mockDirectory, nonHsCommand);
|
|
106
|
-
expect(mockExecAsync).toHaveBeenCalledWith('npm install', expect.objectContaining({
|
|
107
|
-
cwd: mockResolvedPath,
|
|
108
|
-
env: expect.any(Object),
|
|
109
|
-
}));
|
|
110
|
-
});
|
|
111
|
-
it('should add --disable-usage-tracking flag to hs commands with existing flags', async () => {
|
|
112
|
-
const hsCommand = 'hs project upload --profile prod';
|
|
113
|
-
const expectedResult = {
|
|
114
|
-
stdout: 'success',
|
|
115
|
-
stderr: '',
|
|
116
|
-
};
|
|
117
|
-
mockExistsSync.mockReturnValue(true);
|
|
118
|
-
mockExecAsync.mockResolvedValue(expectedResult);
|
|
119
|
-
await runCommandInDir(mockDirectory, hsCommand);
|
|
120
|
-
expect(mockExecAsync).toHaveBeenCalledWith('hs project upload --profile prod --disable-usage-tracking "true"', expect.objectContaining({
|
|
121
|
-
cwd: mockResolvedPath,
|
|
122
|
-
env: expect.any(Object),
|
|
123
|
-
}));
|
|
124
|
-
});
|
|
125
|
-
it('should handle hs commands that start with whitespace', async () => {
|
|
126
|
-
const hsCommand = 'hs init';
|
|
127
|
-
const expectedResult = {
|
|
128
|
-
stdout: 'success',
|
|
129
|
-
stderr: '',
|
|
130
|
-
};
|
|
131
|
-
mockExistsSync.mockReturnValue(true);
|
|
132
|
-
mockExecAsync.mockResolvedValue(expectedResult);
|
|
133
|
-
await runCommandInDir(mockDirectory, hsCommand);
|
|
134
|
-
expect(mockExecAsync).toHaveBeenCalledWith('hs init --disable-usage-tracking "true"', expect.objectContaining({
|
|
135
|
-
cwd: mockResolvedPath,
|
|
136
|
-
env: expect.any(Object),
|
|
137
|
-
}));
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { addFlag, execAsync } from './command.js';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
export async function runCommandInDir(directory, command) {
|
|
5
|
-
if (!fs.existsSync(directory)) {
|
|
6
|
-
fs.mkdirSync(directory);
|
|
7
|
-
}
|
|
8
|
-
let finalCommand = command;
|
|
9
|
-
if (command.startsWith('hs ')) {
|
|
10
|
-
finalCommand = addFlag(finalCommand, 'disable-usage-tracking', true);
|
|
11
|
-
}
|
|
12
|
-
return execAsync(finalCommand, {
|
|
13
|
-
cwd: path.resolve(directory),
|
|
14
|
-
env: {
|
|
15
|
-
...process.env,
|
|
16
|
-
},
|
|
17
|
-
});
|
|
18
|
-
}
|