@hubspot/cli 8.1.2-experimental.3 → 8.1.4-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.
- package/commands/account/link.js +1 -3
- package/commands/account/unlink.js +1 -3
- package/commands/cms/module/create.js +6 -0
- package/commands/project/lint.js +3 -3
- package/commands/project/release/create.d.ts +7 -0
- package/commands/project/release/create.js +159 -0
- package/commands/project/release/info.d.ts +6 -0
- package/commands/project/release/info.js +147 -0
- package/commands/project/release/list.d.ts +6 -0
- package/commands/project/release/list.js +111 -0
- package/commands/project/release.d.ts +3 -0
- package/commands/project/release.js +20 -0
- package/commands/project/upload.js +9 -0
- package/commands/project.js +2 -0
- package/lang/en.d.ts +61 -0
- package/lang/en.js +61 -0
- package/lib/commonOpts.js +0 -1
- package/lib/projects/uieLinting.d.ts +2 -0
- package/lib/projects/uieLinting.js +25 -1
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +2 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +4 -5
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +2 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +2 -3
- package/mcp-server/tools/cms/HsListFunctionsTool.js +2 -3
- package/mcp-server/tools/cms/HsListTool.js +2 -2
- package/mcp-server/utils/command.js +3 -1
- package/mcp-server/utils/config.js +1 -0
- package/package.json +3 -3
package/commands/account/link.js
CHANGED
|
@@ -15,9 +15,7 @@ import { commands } from '../../lang/en.js';
|
|
|
15
15
|
import { debugError } from '../../lib/errorHandlers/index.js';
|
|
16
16
|
import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
|
|
17
17
|
const command = 'link';
|
|
18
|
-
|
|
19
|
-
// const describe = commands.account.subcommands.link.describe;
|
|
20
|
-
const describe = undefined;
|
|
18
|
+
const describe = commands.account.subcommands.link.describe;
|
|
21
19
|
async function handler(args) {
|
|
22
20
|
const { exit } = args;
|
|
23
21
|
if (hasDeprecatedConfigConflict(args._)) {
|
|
@@ -11,9 +11,7 @@ import { commands } from '../../lang/en.js';
|
|
|
11
11
|
import { DEFAULT_HS_SETTINGS_PATH } from '@hubspot/local-dev-lib/constants/config';
|
|
12
12
|
import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
|
|
13
13
|
const command = 'unlink';
|
|
14
|
-
|
|
15
|
-
// const describe = commands.account.subcommands.link.describe;
|
|
16
|
-
const describe = undefined;
|
|
14
|
+
const describe = commands.account.subcommands.unlink.describe;
|
|
17
15
|
async function handler(args) {
|
|
18
16
|
const { exit } = args;
|
|
19
17
|
if (hasDeprecatedConfigConflict(args._)) {
|
|
@@ -73,6 +73,12 @@ function moduleCreateBuilder(yargs) {
|
|
|
73
73
|
type: 'boolean',
|
|
74
74
|
default: false,
|
|
75
75
|
});
|
|
76
|
+
yargs.option('available-for-new-content', {
|
|
77
|
+
describe: commands.cms.subcommands.module.subcommands.create.options
|
|
78
|
+
.availableForNewContent,
|
|
79
|
+
type: 'boolean',
|
|
80
|
+
default: true,
|
|
81
|
+
});
|
|
76
82
|
return yargs;
|
|
77
83
|
}
|
|
78
84
|
const builder = makeYargsBuilder(moduleCreateBuilder, command, describe, {
|
package/commands/project/lint.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import {
|
|
2
|
+
import { installPackages } from '../../lib/dependencyManagement.js';
|
|
3
3
|
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
4
4
|
import { isPromptExitError } from '../../lib/errors/PromptExitError.js';
|
|
5
5
|
import { getProjectConfig } from '../../lib/projects/config.js';
|
|
@@ -10,7 +10,7 @@ import { logError } from '../../lib/errorHandlers/index.js';
|
|
|
10
10
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
11
11
|
import { promptUser } from '../../lib/prompts/promptUtils.js';
|
|
12
12
|
import SpinniesManager from '../../lib/ui/SpinniesManager.js';
|
|
13
|
-
import { areAllLintPackagesInstalled,
|
|
13
|
+
import { addLintScriptsToPackageJson, areAllLintPackagesInstalled, createEslintConfig, displayLintResults, getDeprecatedEslintConfigFiles, getMissingLintPackages, getMissingLintScripts, getUieLintablePackageJsonLocations, hasDeprecatedEslintConfig, hasEslintConfig, lintPackages, REQUIRED_PACKAGES_AND_MIN_VERSIONS, } from '../../lib/projects/uieLinting.js';
|
|
14
14
|
import { clearPackageJsonCache } from '../../lib/npm/packageJson.js';
|
|
15
15
|
const command = 'lint';
|
|
16
16
|
const describe = commands.project.lint.help.describe;
|
|
@@ -26,7 +26,7 @@ async function handler(args) {
|
|
|
26
26
|
SpinniesManager.add('lintCheck', {
|
|
27
27
|
text: commands.project.lint.loading.checking,
|
|
28
28
|
});
|
|
29
|
-
const lintLocations = await
|
|
29
|
+
const lintLocations = await getUieLintablePackageJsonLocations(projectConfig);
|
|
30
30
|
const locationsReadyToLint = [];
|
|
31
31
|
const locationsNeedingPackages = new Map();
|
|
32
32
|
for (const lintLocation of lintLocations) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../../types/Yargs.js';
|
|
2
|
+
export type ProjectReleaseCreateArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
3
|
+
build?: number;
|
|
4
|
+
force: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare const projectReleaseCreateCommand: YargsCommandModule<unknown, ProjectReleaseCreateArgs>;
|
|
7
|
+
export default projectReleaseCreateCommand;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { fetchProject, getBuildStatus, } from '@hubspot/local-dev-lib/api/projects';
|
|
2
|
+
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
3
|
+
import { logError, ApiErrorContext } from '../../../lib/errorHandlers/index.js';
|
|
4
|
+
import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
|
|
5
|
+
import { confirmPrompt } from '../../../lib/prompts/promptUtils.js';
|
|
6
|
+
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
7
|
+
import { uiLogger } from '../../../lib/ui/logger.js';
|
|
8
|
+
import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
|
|
9
|
+
import { commands } from '../../../lang/en.js';
|
|
10
|
+
import { makeWrappedYargsHandler } from '../../../lib/yargs/makeWrappedYargsHandler.js';
|
|
11
|
+
import { createRelease } from '../../../api/releases.js';
|
|
12
|
+
const command = 'create';
|
|
13
|
+
// const describe = commands.project.release.create.describe;
|
|
14
|
+
const describe = undefined;
|
|
15
|
+
// const verboseDescribe = commands.project.release.create.verboseDescribe;
|
|
16
|
+
const verboseDescribe = undefined;
|
|
17
|
+
async function resolveBuildId(accountId, projectName, buildOption) {
|
|
18
|
+
const { data: { deployedBuildId }, } = await fetchProject(accountId, projectName);
|
|
19
|
+
if (buildOption) {
|
|
20
|
+
return buildOption;
|
|
21
|
+
}
|
|
22
|
+
if (!deployedBuildId) {
|
|
23
|
+
throw new Error(commands.project.release.create.errors.noDeployedBuild);
|
|
24
|
+
}
|
|
25
|
+
return deployedBuildId;
|
|
26
|
+
}
|
|
27
|
+
async function validateBuild(accountId, projectName, buildId) {
|
|
28
|
+
try {
|
|
29
|
+
await getBuildStatus(accountId, projectName, buildId);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
if (isHubSpotHttpError(e) && e.status === 404) {
|
|
33
|
+
uiLogger.error(commands.project.release.create.errors.buildNotFound(buildId, projectName));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
logError(e, new ApiErrorContext({
|
|
37
|
+
accountId,
|
|
38
|
+
request: 'project release create',
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function executeRelease(accountId, projectName, buildId, formatOutputAsJson) {
|
|
45
|
+
try {
|
|
46
|
+
const { data: release } = await createRelease(accountId, projectName, buildId);
|
|
47
|
+
if (formatOutputAsJson) {
|
|
48
|
+
uiLogger.json(release);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
uiLogger.success(commands.project.release.create.success(release.releaseTag, release.buildId));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
if (isHubSpotHttpError(e) && e.status === 422) {
|
|
56
|
+
uiLogger.error(commands.project.release.create.errors.buildNotDeployed(buildId));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
logError(e, new ApiErrorContext({
|
|
60
|
+
accountId,
|
|
61
|
+
request: 'project release create',
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
throw e;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function handler(args) {
|
|
68
|
+
const { exit, derivedAccountId, build: buildOption, json: formatOutputAsJson, force, } = args;
|
|
69
|
+
const { projectConfig, projectDir } = await getProjectConfig();
|
|
70
|
+
try {
|
|
71
|
+
validateProjectConfig(projectConfig, projectDir);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logError(error);
|
|
75
|
+
return exit(EXIT_CODES.ERROR);
|
|
76
|
+
}
|
|
77
|
+
const projectName = projectConfig.name;
|
|
78
|
+
let buildId;
|
|
79
|
+
try {
|
|
80
|
+
buildId = await resolveBuildId(derivedAccountId, projectName, buildOption);
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
if (isHubSpotHttpError(e) && e.status === 404) {
|
|
84
|
+
uiLogger.error(commands.project.release.create.errors.projectNotFound(derivedAccountId, projectName));
|
|
85
|
+
}
|
|
86
|
+
else if (!(e instanceof Error) || !e.message) {
|
|
87
|
+
logError(e, new ApiErrorContext({
|
|
88
|
+
accountId: derivedAccountId,
|
|
89
|
+
request: 'project release create',
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
uiLogger.error(e.message);
|
|
94
|
+
}
|
|
95
|
+
return exit(EXIT_CODES.ERROR);
|
|
96
|
+
}
|
|
97
|
+
if (buildOption) {
|
|
98
|
+
try {
|
|
99
|
+
await validateBuild(derivedAccountId, projectName, buildId);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return exit(EXIT_CODES.ERROR);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!formatOutputAsJson && !force) {
|
|
106
|
+
const confirmed = await confirmPrompt(commands.project.release.create.confirmPrompt(projectName, buildId));
|
|
107
|
+
if (!confirmed) {
|
|
108
|
+
uiLogger.log(commands.project.release.create.cancelled);
|
|
109
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
await executeRelease(derivedAccountId, projectName, buildId, !!formatOutputAsJson);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return exit(EXIT_CODES.ERROR);
|
|
117
|
+
}
|
|
118
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
119
|
+
}
|
|
120
|
+
function projectReleaseCreateBuilder(yargs) {
|
|
121
|
+
yargs.options({
|
|
122
|
+
build: {
|
|
123
|
+
alias: ['build-id'],
|
|
124
|
+
describe: commands.project.release.create.options.build,
|
|
125
|
+
type: 'number',
|
|
126
|
+
},
|
|
127
|
+
force: {
|
|
128
|
+
alias: ['f'],
|
|
129
|
+
describe: commands.project.release.create.options.force,
|
|
130
|
+
default: false,
|
|
131
|
+
type: 'boolean',
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
yargs.example([
|
|
135
|
+
[
|
|
136
|
+
'$0 project release create',
|
|
137
|
+
commands.project.release.create.examples.default,
|
|
138
|
+
],
|
|
139
|
+
[
|
|
140
|
+
'$0 project release create --build=5',
|
|
141
|
+
commands.project.release.create.examples.withBuild,
|
|
142
|
+
],
|
|
143
|
+
]);
|
|
144
|
+
return yargs;
|
|
145
|
+
}
|
|
146
|
+
const builder = makeYargsBuilder(projectReleaseCreateBuilder, command, verboseDescribe, {
|
|
147
|
+
useGlobalOptions: true,
|
|
148
|
+
useConfigOptions: true,
|
|
149
|
+
useAccountOptions: true,
|
|
150
|
+
useEnvironmentOptions: true,
|
|
151
|
+
useJSONOutputOptions: true,
|
|
152
|
+
});
|
|
153
|
+
const projectReleaseCreateCommand = {
|
|
154
|
+
command,
|
|
155
|
+
describe,
|
|
156
|
+
builder,
|
|
157
|
+
handler: makeWrappedYargsHandler('project-release-create', handler),
|
|
158
|
+
};
|
|
159
|
+
export default projectReleaseCreateCommand;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../../types/Yargs.js';
|
|
2
|
+
export type ProjectReleaseInfoArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
3
|
+
tag?: string;
|
|
4
|
+
};
|
|
5
|
+
declare const projectReleaseInfoCommand: YargsCommandModule<unknown, ProjectReleaseInfoArgs>;
|
|
6
|
+
export default projectReleaseInfoCommand;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { getReleaseInfo, listReleases } from '../../../api/releases.js';
|
|
2
|
+
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
3
|
+
import { logError, ApiErrorContext } from '../../../lib/errorHandlers/index.js';
|
|
4
|
+
import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
|
|
5
|
+
import { listPrompt } from '../../../lib/prompts/promptUtils.js';
|
|
6
|
+
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
7
|
+
import { uiLogger } from '../../../lib/ui/logger.js';
|
|
8
|
+
import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
|
|
9
|
+
import { commands } from '../../../lang/en.js';
|
|
10
|
+
import { renderTable } from '../../../ui/render.js';
|
|
11
|
+
import { makeWrappedYargsHandler } from '../../../lib/yargs/makeWrappedYargsHandler.js';
|
|
12
|
+
import { isPromptExitError } from '../../../lib/errors/PromptExitError.js';
|
|
13
|
+
import { mapToUserFacingType } from '@hubspot/project-parsing-lib/transform';
|
|
14
|
+
import { AUTO_GENERATED_COMPONENT_TYPES } from '@hubspot/project-parsing-lib/constants';
|
|
15
|
+
const command = 'info';
|
|
16
|
+
// const describe = commands.project.release.info.describe;
|
|
17
|
+
const describe = undefined;
|
|
18
|
+
// const verboseDescribe = commands.project.release.info.verboseDescribe;
|
|
19
|
+
const verboseDescribe = undefined;
|
|
20
|
+
function normalizeTag(rawTag) {
|
|
21
|
+
return rawTag.startsWith('v') ? rawTag : `v${rawTag}`;
|
|
22
|
+
}
|
|
23
|
+
async function selectReleasePrompt(accountId, projectName) {
|
|
24
|
+
const { data: { results, paging }, } = await listReleases(accountId, projectName);
|
|
25
|
+
if (results.length === 0) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (paging?.next?.after) {
|
|
29
|
+
uiLogger.info(commands.project.release.info.moreReleasesHint);
|
|
30
|
+
}
|
|
31
|
+
return listPrompt(commands.project.release.info.selectRelease(projectName), {
|
|
32
|
+
choices: results.map(release => ({
|
|
33
|
+
name: `${release.releaseTag} (build #${release.buildId}, ${new Date(release.createdAt).toLocaleString()})`,
|
|
34
|
+
value: release.releaseTag,
|
|
35
|
+
})),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function handler(args) {
|
|
39
|
+
const { derivedAccountId, tag: rawTag, json: formatOutputAsJson, exit, } = args;
|
|
40
|
+
const { projectConfig, projectDir } = await getProjectConfig();
|
|
41
|
+
try {
|
|
42
|
+
validateProjectConfig(projectConfig, projectDir);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
logError(error);
|
|
46
|
+
return exit(EXIT_CODES.ERROR);
|
|
47
|
+
}
|
|
48
|
+
const projectName = projectConfig.name;
|
|
49
|
+
let tag;
|
|
50
|
+
if (rawTag) {
|
|
51
|
+
tag = normalizeTag(rawTag);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
try {
|
|
55
|
+
const selected = await selectReleasePrompt(derivedAccountId, projectName);
|
|
56
|
+
if (!selected) {
|
|
57
|
+
uiLogger.error(commands.project.release.info.errors.noReleases);
|
|
58
|
+
return exit(EXIT_CODES.ERROR);
|
|
59
|
+
}
|
|
60
|
+
tag = selected;
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
if (isPromptExitError(e)) {
|
|
64
|
+
throw e;
|
|
65
|
+
}
|
|
66
|
+
logError(e);
|
|
67
|
+
return exit(EXIT_CODES.ERROR);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const { data: release } = await getReleaseInfo(derivedAccountId, projectName, tag);
|
|
72
|
+
if (formatOutputAsJson) {
|
|
73
|
+
uiLogger.json(release);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
uiLogger.log(commands.project.release.info.releaseDetails(release.releaseTag, projectName));
|
|
77
|
+
renderTable(['Release', 'Build', 'Created'], [
|
|
78
|
+
[
|
|
79
|
+
release.releaseTag,
|
|
80
|
+
`#${release.buildId}`,
|
|
81
|
+
new Date(release.createdAt).toLocaleString(),
|
|
82
|
+
],
|
|
83
|
+
]);
|
|
84
|
+
const visibleComponents = (release.components ?? []).filter(component => !AUTO_GENERATED_COMPONENT_TYPES.includes(component.buildType));
|
|
85
|
+
if (visibleComponents.length > 0) {
|
|
86
|
+
uiLogger.log('');
|
|
87
|
+
uiLogger.log(commands.project.release.info.components);
|
|
88
|
+
const componentRows = visibleComponents.map(component => [
|
|
89
|
+
mapToUserFacingType(component.buildType),
|
|
90
|
+
component.buildName ?? '',
|
|
91
|
+
component.rootPath ?? '',
|
|
92
|
+
]);
|
|
93
|
+
renderTable(['Type', 'Name', 'Path'], componentRows);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
uiLogger.log('');
|
|
97
|
+
uiLogger.log(commands.project.release.info.noComponents);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
if (isHubSpotHttpError(e) && e.status === 404) {
|
|
103
|
+
uiLogger.error(commands.project.release.info.errors.releaseNotFound(tag, projectName));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
logError(e, new ApiErrorContext({
|
|
107
|
+
accountId: derivedAccountId,
|
|
108
|
+
request: 'project release info',
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
return exit(EXIT_CODES.ERROR);
|
|
112
|
+
}
|
|
113
|
+
return exit(EXIT_CODES.SUCCESS);
|
|
114
|
+
}
|
|
115
|
+
function projectReleaseInfoBuilder(yargs) {
|
|
116
|
+
yargs.options({
|
|
117
|
+
tag: {
|
|
118
|
+
describe: commands.project.release.info.options.tag,
|
|
119
|
+
type: 'string',
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
yargs.example([
|
|
123
|
+
[
|
|
124
|
+
'$0 project release info --tag=v1.0.0',
|
|
125
|
+
commands.project.release.info.examples.default,
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
'$0 project release info --tag=v1.0.0 --json',
|
|
129
|
+
commands.project.release.info.examples.json,
|
|
130
|
+
],
|
|
131
|
+
]);
|
|
132
|
+
return yargs;
|
|
133
|
+
}
|
|
134
|
+
const builder = makeYargsBuilder(projectReleaseInfoBuilder, command, verboseDescribe, {
|
|
135
|
+
useGlobalOptions: true,
|
|
136
|
+
useConfigOptions: true,
|
|
137
|
+
useAccountOptions: true,
|
|
138
|
+
useEnvironmentOptions: true,
|
|
139
|
+
useJSONOutputOptions: true,
|
|
140
|
+
});
|
|
141
|
+
const projectReleaseInfoCommand = {
|
|
142
|
+
command,
|
|
143
|
+
describe,
|
|
144
|
+
builder,
|
|
145
|
+
handler: makeWrappedYargsHandler('project-release-info', handler),
|
|
146
|
+
};
|
|
147
|
+
export default projectReleaseInfoCommand;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../../types/Yargs.js';
|
|
2
|
+
export type ProjectReleaseListArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
3
|
+
limit?: number;
|
|
4
|
+
};
|
|
5
|
+
declare const projectReleaseListCommand: YargsCommandModule<unknown, ProjectReleaseListArgs>;
|
|
6
|
+
export default projectReleaseListCommand;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { listReleases } from '../../../api/releases.js';
|
|
2
|
+
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
3
|
+
import { isPromptExitError } from '../../../lib/errors/PromptExitError.js';
|
|
4
|
+
import { logError, ApiErrorContext } from '../../../lib/errorHandlers/index.js';
|
|
5
|
+
import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
|
|
6
|
+
import { promptUser } from '../../../lib/prompts/promptUtils.js';
|
|
7
|
+
import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
8
|
+
import { uiLogger } from '../../../lib/ui/logger.js';
|
|
9
|
+
import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
|
|
10
|
+
import { commands } from '../../../lang/en.js';
|
|
11
|
+
import { renderTable } from '../../../ui/render.js';
|
|
12
|
+
import { makeWrappedYargsHandler } from '../../../lib/yargs/makeWrappedYargsHandler.js';
|
|
13
|
+
const command = 'list';
|
|
14
|
+
// const describe = commands.project.release.list.describe;
|
|
15
|
+
const describe = undefined;
|
|
16
|
+
// const verboseDescribe = commands.project.release.list.verboseDescribe;
|
|
17
|
+
const verboseDescribe = undefined;
|
|
18
|
+
async function fetchAndDisplayReleases(accountId, projectName, options) {
|
|
19
|
+
const { data: { results, paging }, } = await listReleases(accountId, projectName, options);
|
|
20
|
+
uiLogger.log(commands.project.release.list.showingReleases(results.length, projectName));
|
|
21
|
+
if (results.length === 0) {
|
|
22
|
+
uiLogger.log(commands.project.release.list.noReleases);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const rows = results.map(release => [
|
|
26
|
+
release.releaseTag,
|
|
27
|
+
`#${release.buildId}`,
|
|
28
|
+
new Date(release.createdAt).toLocaleString(),
|
|
29
|
+
]);
|
|
30
|
+
renderTable(['Release', 'Build', 'Created'], rows);
|
|
31
|
+
}
|
|
32
|
+
if (paging?.next?.after) {
|
|
33
|
+
await promptUser({
|
|
34
|
+
name: 'more',
|
|
35
|
+
message: commands.project.release.list.continueOrExitPrompt,
|
|
36
|
+
});
|
|
37
|
+
await fetchAndDisplayReleases(accountId, projectName, {
|
|
38
|
+
limit: options.limit,
|
|
39
|
+
after: paging.next.after,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function handler(args) {
|
|
44
|
+
const { derivedAccountId, limit, json: formatOutputAsJson } = args;
|
|
45
|
+
const { projectConfig, projectDir } = await getProjectConfig();
|
|
46
|
+
try {
|
|
47
|
+
validateProjectConfig(projectConfig, projectDir);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
logError(error);
|
|
51
|
+
process.exit(EXIT_CODES.ERROR);
|
|
52
|
+
}
|
|
53
|
+
const projectName = projectConfig.name;
|
|
54
|
+
try {
|
|
55
|
+
if (formatOutputAsJson) {
|
|
56
|
+
const { data } = await listReleases(derivedAccountId, projectName, {
|
|
57
|
+
limit,
|
|
58
|
+
});
|
|
59
|
+
uiLogger.json(data);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
await fetchAndDisplayReleases(derivedAccountId, projectName, { limit });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
if (isPromptExitError(e)) {
|
|
67
|
+
throw e;
|
|
68
|
+
}
|
|
69
|
+
if (isHubSpotHttpError(e) && e.status === 404) {
|
|
70
|
+
uiLogger.error(commands.project.release.list.errors.projectNotFound(derivedAccountId, projectName));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
logError(e, new ApiErrorContext({
|
|
74
|
+
accountId: derivedAccountId,
|
|
75
|
+
request: 'project release list',
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
process.exit(EXIT_CODES.ERROR);
|
|
79
|
+
}
|
|
80
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
81
|
+
}
|
|
82
|
+
function projectReleaseListBuilder(yargs) {
|
|
83
|
+
yargs.options({
|
|
84
|
+
limit: {
|
|
85
|
+
describe: commands.project.release.list.options.limit,
|
|
86
|
+
type: 'number',
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
yargs.example([
|
|
90
|
+
['$0 project release list', commands.project.release.list.examples.default],
|
|
91
|
+
[
|
|
92
|
+
'$0 project release list --limit=5',
|
|
93
|
+
commands.project.release.list.examples.withLimit,
|
|
94
|
+
],
|
|
95
|
+
]);
|
|
96
|
+
return yargs;
|
|
97
|
+
}
|
|
98
|
+
const builder = makeYargsBuilder(projectReleaseListBuilder, command, verboseDescribe, {
|
|
99
|
+
useGlobalOptions: true,
|
|
100
|
+
useConfigOptions: true,
|
|
101
|
+
useAccountOptions: true,
|
|
102
|
+
useEnvironmentOptions: true,
|
|
103
|
+
useJSONOutputOptions: true,
|
|
104
|
+
});
|
|
105
|
+
const projectReleaseListCommand = {
|
|
106
|
+
command,
|
|
107
|
+
describe,
|
|
108
|
+
builder,
|
|
109
|
+
handler: makeWrappedYargsHandler('project-release-list', handler),
|
|
110
|
+
};
|
|
111
|
+
export default projectReleaseListCommand;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import create from './release/create.js';
|
|
2
|
+
import info from './release/info.js';
|
|
3
|
+
import list from './release/list.js';
|
|
4
|
+
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
5
|
+
// import { commands } from '../../lang/en.js';
|
|
6
|
+
const command = 'release';
|
|
7
|
+
// const describe = commands.project.release.describe;
|
|
8
|
+
const describe = undefined;
|
|
9
|
+
function projectReleaseBuilder(yargs) {
|
|
10
|
+
yargs.command(create).command(info).command(list).demandCommand(1, '');
|
|
11
|
+
return yargs;
|
|
12
|
+
}
|
|
13
|
+
const builder = makeYargsBuilder(projectReleaseBuilder, command, describe);
|
|
14
|
+
const projectReleaseCommand = {
|
|
15
|
+
command,
|
|
16
|
+
describe,
|
|
17
|
+
builder,
|
|
18
|
+
handler: () => { },
|
|
19
|
+
};
|
|
20
|
+
export default projectReleaseCommand;
|
|
@@ -124,6 +124,15 @@ async function handler(args) {
|
|
|
124
124
|
jsonOutput.deployId = result.deployResult.deployId;
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
+
if (result && !result.succeeded) {
|
|
128
|
+
if (formatOutputAsJson) {
|
|
129
|
+
uiLogger.json(jsonOutput);
|
|
130
|
+
}
|
|
131
|
+
return exit(EXIT_CODES.ERROR);
|
|
132
|
+
}
|
|
133
|
+
if (!result && !uploadError) {
|
|
134
|
+
return exit(EXIT_CODES.ERROR);
|
|
135
|
+
}
|
|
127
136
|
}
|
|
128
137
|
catch (e) {
|
|
129
138
|
logError(e, new ApiErrorContext({
|
package/commands/project.js
CHANGED
|
@@ -15,6 +15,7 @@ import installDeps from './project/installDeps.js';
|
|
|
15
15
|
import lint from './project/lint.js';
|
|
16
16
|
import updateDeps from './project/updateDeps.js';
|
|
17
17
|
import profile from './project/profile.js';
|
|
18
|
+
import release from './project/release.js';
|
|
18
19
|
import projectValidate from './project/validate.js';
|
|
19
20
|
import list from './project/list.js';
|
|
20
21
|
import info from './project/info.js';
|
|
@@ -66,6 +67,7 @@ function projectBuilder(yargs) {
|
|
|
66
67
|
.command(lint)
|
|
67
68
|
.command(updateDeps)
|
|
68
69
|
.command(profile)
|
|
70
|
+
.command(release)
|
|
69
71
|
.command(projectValidate)
|
|
70
72
|
.command(appInstallStatus)
|
|
71
73
|
.demandCommand(1, '');
|
package/lang/en.d.ts
CHANGED
|
@@ -1729,6 +1729,67 @@ export declare const commands: {
|
|
|
1729
1729
|
deployLatestBuild: string;
|
|
1730
1730
|
};
|
|
1731
1731
|
};
|
|
1732
|
+
release: {
|
|
1733
|
+
describe: string;
|
|
1734
|
+
create: {
|
|
1735
|
+
describe: string;
|
|
1736
|
+
verboseDescribe: string;
|
|
1737
|
+
confirmPrompt: (projectName: string, buildId: number) => string;
|
|
1738
|
+
success: (releaseTag: string, buildId: number) => string;
|
|
1739
|
+
cancelled: string;
|
|
1740
|
+
errors: {
|
|
1741
|
+
projectNotFound: (accountId: number, projectName: string) => string;
|
|
1742
|
+
noDeployedBuild: string;
|
|
1743
|
+
buildNotFound: (buildId: number, projectName: string) => string;
|
|
1744
|
+
buildNotDeployed: (buildId: number) => string;
|
|
1745
|
+
};
|
|
1746
|
+
options: {
|
|
1747
|
+
build: string;
|
|
1748
|
+
force: string;
|
|
1749
|
+
};
|
|
1750
|
+
examples: {
|
|
1751
|
+
default: string;
|
|
1752
|
+
withBuild: string;
|
|
1753
|
+
};
|
|
1754
|
+
};
|
|
1755
|
+
list: {
|
|
1756
|
+
describe: string;
|
|
1757
|
+
verboseDescribe: string;
|
|
1758
|
+
noReleases: string;
|
|
1759
|
+
showingReleases: (count: number, projectName: string) => string;
|
|
1760
|
+
continueOrExitPrompt: string;
|
|
1761
|
+
errors: {
|
|
1762
|
+
projectNotFound: (accountId: number, projectName: string) => string;
|
|
1763
|
+
};
|
|
1764
|
+
options: {
|
|
1765
|
+
limit: string;
|
|
1766
|
+
};
|
|
1767
|
+
examples: {
|
|
1768
|
+
default: string;
|
|
1769
|
+
withLimit: string;
|
|
1770
|
+
};
|
|
1771
|
+
};
|
|
1772
|
+
info: {
|
|
1773
|
+
describe: string;
|
|
1774
|
+
verboseDescribe: string;
|
|
1775
|
+
releaseDetails: (releaseTag: string, projectName: string) => string;
|
|
1776
|
+
components: string;
|
|
1777
|
+
noComponents: string;
|
|
1778
|
+
moreReleasesHint: string;
|
|
1779
|
+
selectRelease: (projectName: string) => string;
|
|
1780
|
+
errors: {
|
|
1781
|
+
releaseNotFound: (releaseTag: string, projectName: string) => string;
|
|
1782
|
+
noReleases: string;
|
|
1783
|
+
};
|
|
1784
|
+
options: {
|
|
1785
|
+
tag: string;
|
|
1786
|
+
};
|
|
1787
|
+
examples: {
|
|
1788
|
+
default: string;
|
|
1789
|
+
json: string;
|
|
1790
|
+
};
|
|
1791
|
+
};
|
|
1792
|
+
};
|
|
1732
1793
|
listBuilds: {
|
|
1733
1794
|
describe: string;
|
|
1734
1795
|
continueOrExitPrompt: string;
|
package/lang/en.js
CHANGED
|
@@ -1746,6 +1746,67 @@ export const commands = {
|
|
|
1746
1746
|
deployLatestBuild: 'Deploy the latest build of the current project',
|
|
1747
1747
|
},
|
|
1748
1748
|
},
|
|
1749
|
+
release: {
|
|
1750
|
+
describe: 'Manage project releases.',
|
|
1751
|
+
create: {
|
|
1752
|
+
describe: 'Create a release for a project build.',
|
|
1753
|
+
verboseDescribe: `Create a release for a project build\n\nReleases mark a deployed build with an auto-generated semantic version tag (e.g. v1.0.0). The build must have been successfully deployed before it can be released.\n\nBy default, the latest deployed build is used. Use ${uiCommandReference('--build')} to specify a different build ID.`,
|
|
1754
|
+
confirmPrompt: (projectName, buildId) => `Create a release for project ${chalk.bold(projectName)} using build ${chalk.bold(String(buildId))}?`,
|
|
1755
|
+
success: (releaseTag, buildId) => `Release ${chalk.bold(releaseTag)} created for build ${chalk.bold(String(buildId))}.`,
|
|
1756
|
+
cancelled: 'Release creation cancelled.',
|
|
1757
|
+
errors: {
|
|
1758
|
+
projectNotFound: (accountId, projectName) => `The project ${chalk.bold(projectName)} does not exist in account ${uiAccountDescription(accountId)}. Run ${uiCommandReference('hs project upload')} to upload your project files to HubSpot.`,
|
|
1759
|
+
noDeployedBuild: `No deployed build found for this project. Run ${uiCommandReference('hs project deploy')} first.`,
|
|
1760
|
+
buildNotFound: (buildId, projectName) => `Build ${chalk.bold(String(buildId))} was not found for project ${chalk.bold(projectName)}. Run ${uiCommandReference('hs project list-builds')} to view existing builds or ${uiCommandReference('hs project deploy')} to deploy a build first.`,
|
|
1761
|
+
buildNotDeployed: (buildId) => `Build ${chalk.bold(String(buildId))} has not been deployed. Run ${uiCommandReference('hs project deploy')} first.`,
|
|
1762
|
+
},
|
|
1763
|
+
options: {
|
|
1764
|
+
build: 'Build ID to release. Defaults to the latest deployed build.',
|
|
1765
|
+
force: 'Skip confirmation prompt.',
|
|
1766
|
+
},
|
|
1767
|
+
examples: {
|
|
1768
|
+
default: 'Create a release for the latest deployed build',
|
|
1769
|
+
withBuild: 'Create a release for a specific build',
|
|
1770
|
+
},
|
|
1771
|
+
},
|
|
1772
|
+
list: {
|
|
1773
|
+
describe: 'List releases for the current project.',
|
|
1774
|
+
verboseDescribe: `List releases for the current project\n\nDisplays all releases in sorted order, newest first. Includes the version tag, build ID, and creation date. Use ${uiCommandReference('--limit')} to control how many results are shown.`,
|
|
1775
|
+
noReleases: 'No releases found for this project.',
|
|
1776
|
+
showingReleases: (count, projectName) => `Showing ${count} release${count === 1 ? '' : 's'} for ${chalk.bold(projectName)}:`,
|
|
1777
|
+
continueOrExitPrompt: 'Press <enter> to load more, or ctrl+c to exit',
|
|
1778
|
+
errors: {
|
|
1779
|
+
projectNotFound: (accountId, projectName) => `The project ${chalk.bold(projectName)} does not exist in account ${uiAccountDescription(accountId)}. Run ${uiCommandReference('hs project upload')} to upload your project files to HubSpot.`,
|
|
1780
|
+
},
|
|
1781
|
+
options: {
|
|
1782
|
+
limit: 'Number of releases to show',
|
|
1783
|
+
},
|
|
1784
|
+
examples: {
|
|
1785
|
+
default: 'List releases for the current project',
|
|
1786
|
+
withLimit: 'Show only the 5 most recent releases',
|
|
1787
|
+
},
|
|
1788
|
+
},
|
|
1789
|
+
info: {
|
|
1790
|
+
describe: 'Show details about a specific release.',
|
|
1791
|
+
verboseDescribe: `Show details about a specific release\n\nDisplays the release tag, build ID, creation date, and list of components included in the release. Use ${uiCommandReference('--json')} for machine-readable output.`,
|
|
1792
|
+
releaseDetails: (releaseTag, projectName) => `Release ${chalk.bold(releaseTag)} for ${chalk.bold(projectName)}:`,
|
|
1793
|
+
components: 'Components:',
|
|
1794
|
+
noComponents: 'No components found for this release.',
|
|
1795
|
+
moreReleasesHint: `Not all releases are shown. Use ${uiCommandReference('--tag')} to look up an older release directly.`,
|
|
1796
|
+
selectRelease: (projectName) => `Select a release for ${chalk.bold(projectName)}`,
|
|
1797
|
+
errors: {
|
|
1798
|
+
releaseNotFound: (releaseTag, projectName) => `Release ${chalk.bold(releaseTag)} was not found for project ${chalk.bold(projectName)}. Verify the project has been uploaded and the release tag exists. Run ${uiCommandReference('hs project release list')} to view existing releases.`,
|
|
1799
|
+
noReleases: 'No releases found for this project.',
|
|
1800
|
+
},
|
|
1801
|
+
options: {
|
|
1802
|
+
tag: 'Release tag to look up (e.g. v1.0.0)',
|
|
1803
|
+
},
|
|
1804
|
+
examples: {
|
|
1805
|
+
default: 'Show details about a specific release',
|
|
1806
|
+
json: 'Output release details as JSON',
|
|
1807
|
+
},
|
|
1808
|
+
},
|
|
1809
|
+
},
|
|
1749
1810
|
listBuilds: {
|
|
1750
1811
|
describe: "List the project's builds.",
|
|
1751
1812
|
continueOrExitPrompt: 'Press <enter> to load more, or ctrl+c to exit',
|
package/lib/commonOpts.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LoadedProjectConfig } from './config.js';
|
|
1
2
|
export declare const REQUIRED_PACKAGES_AND_MIN_VERSIONS: {
|
|
2
3
|
readonly eslint: "9.0.0";
|
|
3
4
|
readonly '@eslint/js': "9.0.0";
|
|
@@ -23,6 +24,7 @@ export declare function hasEslintConfig(directory: string): boolean;
|
|
|
23
24
|
export declare function hasDeprecatedEslintConfig(directory: string): boolean;
|
|
24
25
|
export declare function getDeprecatedEslintConfigFiles(directory: string): string[];
|
|
25
26
|
export declare function createEslintConfig(directory: string, platformVersion?: string | null): Promise<string>;
|
|
27
|
+
export declare function getUieLintablePackageJsonLocations(projectConfig: LoadedProjectConfig): Promise<string[]>;
|
|
26
28
|
export declare const HUBSPOT_UI_EXTENSIONS_RULE_PREFIX = "@hubspot/ui-extensions/";
|
|
27
29
|
export declare function isHubSpotEslintConfigActive(directory: string): Promise<boolean>;
|
|
28
30
|
export declare function lintPackagesInDirectory(directory: string, projectDir?: string): Promise<{
|
|
@@ -10,7 +10,8 @@ import { uiLogger } from '../ui/logger.js';
|
|
|
10
10
|
import { clearPackageJsonCache, safeGetPackageJsonCached, } from '../npm/packageJson.js';
|
|
11
11
|
import { debugError } from '../errorHandlers/index.js';
|
|
12
12
|
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
13
|
-
import {
|
|
13
|
+
import { DEFAULT_PROJECT_TEMPLATE_BRANCH, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, } from '../constants.js';
|
|
14
|
+
import { CARDS_KEY, Components, PAGES_KEY, SETTINGS_KEY, } from '@hubspot/project-parsing-lib/constants';
|
|
14
15
|
export const REQUIRED_PACKAGES_AND_MIN_VERSIONS = {
|
|
15
16
|
eslint: '9.0.0',
|
|
16
17
|
'@eslint/js': '9.0.0',
|
|
@@ -40,6 +41,11 @@ const DEPRECATED_ESLINT_CONFIG_FILES = [
|
|
|
40
41
|
'.eslintrc.json',
|
|
41
42
|
'.eslintrc',
|
|
42
43
|
];
|
|
44
|
+
const UIE_COMPONENTS = [
|
|
45
|
+
Components[CARDS_KEY],
|
|
46
|
+
Components[SETTINGS_KEY],
|
|
47
|
+
Components[PAGES_KEY],
|
|
48
|
+
];
|
|
43
49
|
export const LINT_SCRIPTS = {
|
|
44
50
|
lint: 'eslint .',
|
|
45
51
|
'lint:fix': 'eslint . --fix',
|
|
@@ -163,7 +169,24 @@ export async function createEslintConfig(directory, platformVersion) {
|
|
|
163
169
|
throw error;
|
|
164
170
|
}
|
|
165
171
|
}
|
|
172
|
+
export async function getUieLintablePackageJsonLocations(projectConfig) {
|
|
173
|
+
if (!projectConfig.projectDir || !projectConfig.projectConfig?.srcDir) {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
const srcDirAbsolute = path.resolve(projectConfig.projectDir, projectConfig.projectConfig.srcDir);
|
|
177
|
+
const uiePackageDirPrefixes = UIE_COMPONENTS.map(component => path.join(srcDirAbsolute, component.parentComponent
|
|
178
|
+
? Components[component.parentComponent].dir
|
|
179
|
+
: '', component.dir));
|
|
180
|
+
const allLocations = await getProjectPackageJsonLocations(projectConfig.projectDir);
|
|
181
|
+
return allLocations.filter(location => {
|
|
182
|
+
const resolvedLocation = path.resolve(location);
|
|
183
|
+
return uiePackageDirPrefixes.some(prefix => resolvedLocation.startsWith(prefix));
|
|
184
|
+
});
|
|
185
|
+
}
|
|
166
186
|
export const HUBSPOT_UI_EXTENSIONS_RULE_PREFIX = '@hubspot/ui-extensions/';
|
|
187
|
+
function getEnvironmentWithoutNpmConfig() {
|
|
188
|
+
return Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.toLowerCase().startsWith('npm_config_')));
|
|
189
|
+
}
|
|
167
190
|
export async function isHubSpotEslintConfigActive(directory) {
|
|
168
191
|
const exec = util.promisify(execAsync);
|
|
169
192
|
try {
|
|
@@ -188,6 +211,7 @@ export async function lintPackagesInDirectory(directory, projectDir) {
|
|
|
188
211
|
const { stdout, stderr } = await exec(lintCommand, {
|
|
189
212
|
cwd: directory,
|
|
190
213
|
maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large outputs
|
|
214
|
+
env: getEnvironmentWithoutNpmConfig(),
|
|
191
215
|
});
|
|
192
216
|
let output = `\n${displayPath}:\n`;
|
|
193
217
|
if (stdout && stdout.trim()) {
|
|
@@ -59,7 +59,7 @@ export class HsCreateFunctionTool extends Tool {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
// Build the command
|
|
62
|
-
let command = 'hs
|
|
62
|
+
let command = 'hs cms function create';
|
|
63
63
|
if (dest) {
|
|
64
64
|
command += ` "${dest}"`;
|
|
65
65
|
}
|
|
@@ -94,7 +94,7 @@ export class HsCreateFunctionTool extends Tool {
|
|
|
94
94
|
register() {
|
|
95
95
|
return this.mcpServer.registerTool(toolName, {
|
|
96
96
|
title: 'Create HubSpot CMS Serverless Function',
|
|
97
|
-
description: `Creates a new HubSpot CMS serverless function using the hs
|
|
97
|
+
description: `Creates a new HubSpot CMS serverless function using the hs cms function create command. Functions can be created non-interactively by specifying functionsFolder, filename, and endpointPath. Supports all HTTP methods (${HTTP_METHODS.join(', ')}).`,
|
|
98
98
|
inputSchema,
|
|
99
99
|
annotations: {
|
|
100
100
|
readOnlyHint: false,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Tool } from '../../Tool.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
4
|
-
import { runCommandInDir } from '../../utils/command.js';
|
|
5
|
-
import {
|
|
6
|
-
import { addFlag } from '../../utils/command.js';
|
|
4
|
+
import { addFlag, runCommandInDir } from '../../utils/command.js';
|
|
5
|
+
import { formatTextContent, formatTextContents } from '../../utils/content.js';
|
|
7
6
|
import { CONTENT_TYPES } from '../../../types/Cms.js';
|
|
8
7
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
9
8
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
@@ -75,7 +74,7 @@ export class HsCreateModuleTool extends Tool {
|
|
|
75
74
|
};
|
|
76
75
|
}
|
|
77
76
|
// Build the command
|
|
78
|
-
let command = 'hs
|
|
77
|
+
let command = 'hs cms module create';
|
|
79
78
|
if (userSuppliedName) {
|
|
80
79
|
command += ` "${userSuppliedName}"`;
|
|
81
80
|
}
|
|
@@ -116,7 +115,7 @@ export class HsCreateModuleTool extends Tool {
|
|
|
116
115
|
register() {
|
|
117
116
|
return this.mcpServer.registerTool(toolName, {
|
|
118
117
|
title: 'Create HubSpot CMS Module',
|
|
119
|
-
description: 'Creates a new HubSpot CMS module using the hs
|
|
118
|
+
description: 'Creates a new HubSpot CMS module using the hs cms module create command. Modules can be created non-interactively by specifying moduleLabel and other module options. You can create either HubL or React modules by setting the reactType parameter.',
|
|
120
119
|
inputSchema,
|
|
121
120
|
annotations: {
|
|
122
121
|
readOnlyHint: false,
|
|
@@ -47,7 +47,7 @@ export class HsCreateTemplateTool extends Tool {
|
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
// Build the command
|
|
50
|
-
let command = 'hs
|
|
50
|
+
let command = 'hs cms template create';
|
|
51
51
|
if (userSuppliedName) {
|
|
52
52
|
command += ` "${userSuppliedName}"`;
|
|
53
53
|
}
|
|
@@ -73,7 +73,7 @@ export class HsCreateTemplateTool extends Tool {
|
|
|
73
73
|
register() {
|
|
74
74
|
return this.mcpServer.registerTool(toolName, {
|
|
75
75
|
title: 'Create HubSpot CMS Template',
|
|
76
|
-
description: `Creates a new HubSpot CMS template using the hs
|
|
76
|
+
description: `Creates a new HubSpot CMS template using the hs cms template create command. Templates can be created non-interactively by specifying templateType. Supports all template types including: ${TEMPLATE_TYPES.join(', ')}.`,
|
|
77
77
|
inputSchema,
|
|
78
78
|
annotations: {
|
|
79
79
|
readOnlyHint: false,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Tool } from '../../Tool.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { addFlag } from '../../utils/command.js';
|
|
3
|
+
import { addFlag, runCommandInDir } from '../../utils/command.js';
|
|
4
4
|
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
5
|
-
import { runCommandInDir } from '../../utils/command.js';
|
|
6
5
|
import { formatTextContents } from '../../utils/content.js';
|
|
7
6
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
8
7
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
@@ -38,7 +37,7 @@ export class HsFunctionLogsTool extends Tool {
|
|
|
38
37
|
const normalizedEndpoint = endpoint.startsWith('/')
|
|
39
38
|
? endpoint.slice(1)
|
|
40
39
|
: endpoint;
|
|
41
|
-
let command = `hs logs ${normalizedEndpoint}`;
|
|
40
|
+
let command = `hs cms function logs ${normalizedEndpoint}`;
|
|
42
41
|
if (latest) {
|
|
43
42
|
command = addFlag(command, 'latest', latest);
|
|
44
43
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Tool } from '../../Tool.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { addFlag } from '../../utils/command.js';
|
|
3
|
+
import { addFlag, runCommandInDir } from '../../utils/command.js';
|
|
4
4
|
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
5
|
-
import { runCommandInDir } from '../../utils/command.js';
|
|
6
5
|
import { formatTextContents } from '../../utils/content.js';
|
|
7
6
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
8
7
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
@@ -26,7 +25,7 @@ export class HsListFunctionsTool extends Tool {
|
|
|
26
25
|
}
|
|
27
26
|
async handler({ account, json, absoluteCurrentWorkingDirectory, }) {
|
|
28
27
|
setupHubSpotConfig(absoluteCurrentWorkingDirectory);
|
|
29
|
-
let command = 'hs function list';
|
|
28
|
+
let command = 'hs cms function list';
|
|
30
29
|
if (json) {
|
|
31
30
|
command += ' --json';
|
|
32
31
|
}
|
|
@@ -26,7 +26,7 @@ export class HsListTool extends Tool {
|
|
|
26
26
|
}
|
|
27
27
|
async handler({ path, account, absoluteCurrentWorkingDirectory, }) {
|
|
28
28
|
setupHubSpotConfig(absoluteCurrentWorkingDirectory);
|
|
29
|
-
let command = 'hs list';
|
|
29
|
+
let command = 'hs cms list';
|
|
30
30
|
if (path) {
|
|
31
31
|
command += ` ${path}`;
|
|
32
32
|
}
|
|
@@ -46,7 +46,7 @@ export class HsListTool extends Tool {
|
|
|
46
46
|
content: [
|
|
47
47
|
{
|
|
48
48
|
type: 'text',
|
|
49
|
-
text: `Error executing hs list command: ${getErrorMessage(error)}`,
|
|
49
|
+
text: `Error executing hs cms list command: ${getErrorMessage(error)}`,
|
|
50
50
|
},
|
|
51
51
|
],
|
|
52
52
|
};
|
|
@@ -24,10 +24,12 @@ export async function runCommandInDir(directory, command) {
|
|
|
24
24
|
}
|
|
25
25
|
finalCommand = addFlag(finalCommand, 'disable-usage-tracking', true);
|
|
26
26
|
}
|
|
27
|
+
const resolvedDir = path.resolve(directory);
|
|
27
28
|
return execAsync(finalCommand, {
|
|
28
|
-
cwd:
|
|
29
|
+
cwd: resolvedDir,
|
|
29
30
|
env: {
|
|
30
31
|
...process.env,
|
|
32
|
+
INIT_CWD: resolvedDir,
|
|
31
33
|
},
|
|
32
34
|
});
|
|
33
35
|
}
|
|
@@ -3,6 +3,7 @@ export function setupHubSpotConfig(absoluteCurrentWorkingDirectory) {
|
|
|
3
3
|
if (!absoluteCurrentWorkingDirectory) {
|
|
4
4
|
return;
|
|
5
5
|
}
|
|
6
|
+
process.env.INIT_CWD = absoluteCurrentWorkingDirectory;
|
|
6
7
|
const configPath = getLocalConfigFilePathIfExists(absoluteCurrentWorkingDirectory);
|
|
7
8
|
if (configPath) {
|
|
8
9
|
process.env.HUBSPOT_CONFIG_PATH = configPath;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "8.1.
|
|
3
|
+
"version": "8.1.4-experimental.0",
|
|
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",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"!**/__tests__/**"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@hubspot/local-dev-lib": "5.7.
|
|
13
|
+
"@hubspot/local-dev-lib": "5.7.1",
|
|
14
14
|
"@hubspot/project-parsing-lib": "0.16.0",
|
|
15
15
|
"@hubspot/serverless-dev-runtime": "7.0.7",
|
|
16
16
|
"@hubspot/ui-extensions-dev-server": "2.0.7",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"table": "6.9.0",
|
|
38
38
|
"tmp": "0.2.4",
|
|
39
39
|
"update-notifier": "7.3.1",
|
|
40
|
-
"ws": "
|
|
40
|
+
"ws": "8.20.0",
|
|
41
41
|
"yargs": "17.7.2",
|
|
42
42
|
"yargs-parser": "21.1.1"
|
|
43
43
|
},
|