@hubspot/cli 8.1.2-experimental.1 → 8.1.2-experimental.3
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/module/create.js +0 -5
- package/commands/project/appInstallStatus.d.ts +2 -2
- package/commands/project/appInstallStatus.js +1 -0
- package/commands/project/info.d.ts +2 -2
- package/commands/project/info.js +1 -0
- package/lang/en.d.ts +3 -0
- package/lang/en.js +3 -0
- package/lib/projects/uieLinting.d.ts +2 -0
- package/lib/projects/uieLinting.js +15 -0
- package/lib/projects/upload.js +9 -0
- package/lib/projects/validateLintConfigOnUpload.d.ts +9 -0
- package/lib/projects/validateLintConfigOnUpload.js +45 -0
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +2 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +5 -7
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +2 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +3 -2
- package/mcp-server/tools/cms/HsListFunctionsTool.js +3 -2
- package/mcp-server/tools/cms/HsListTool.js +2 -2
- package/package.json +1 -1
|
@@ -73,11 +73,6 @@ 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
|
-
});
|
|
81
76
|
return yargs;
|
|
82
77
|
}
|
|
83
78
|
const builder = makeYargsBuilder(moduleCreateBuilder, command, describe, {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AccountArgs, CommonArgs, ConfigArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
-
type ProjectInstallStatusArgs = CommonArgs & ConfigArgs & AccountArgs & JSONOutputArgs;
|
|
1
|
+
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
+
type ProjectInstallStatusArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
|
|
3
3
|
declare const projectInstallStatusCommand: YargsCommandModule<unknown, ProjectInstallStatusArgs>;
|
|
4
4
|
export default projectInstallStatusCommand;
|
|
@@ -121,6 +121,7 @@ const builder = makeYargsBuilder(projectInstallStatusBuilder, command, describe,
|
|
|
121
121
|
useGlobalOptions: true,
|
|
122
122
|
useConfigOptions: true,
|
|
123
123
|
useAccountOptions: true,
|
|
124
|
+
useEnvironmentOptions: true,
|
|
124
125
|
useJSONOutputOptions: true,
|
|
125
126
|
});
|
|
126
127
|
const projectInstallStatusCommand = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AccountArgs, CommonArgs, ConfigArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
-
type ProjectInfoArgs = CommonArgs & ConfigArgs & AccountArgs & JSONOutputArgs;
|
|
1
|
+
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
+
type ProjectInfoArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
|
|
3
3
|
declare const projectInfoCommand: YargsCommandModule<unknown, ProjectInfoArgs>;
|
|
4
4
|
export default projectInfoCommand;
|
package/commands/project/info.js
CHANGED
|
@@ -56,6 +56,7 @@ const builder = makeYargsBuilder(projectInfoBuilder, command, verboseDescribe, {
|
|
|
56
56
|
useGlobalOptions: true,
|
|
57
57
|
useConfigOptions: true,
|
|
58
58
|
useAccountOptions: true,
|
|
59
|
+
useEnvironmentOptions: true,
|
|
59
60
|
useJSONOutputOptions: true,
|
|
60
61
|
});
|
|
61
62
|
const projectInfoCommand = {
|
package/lang/en.d.ts
CHANGED
|
@@ -3406,6 +3406,9 @@ export declare const lib: {
|
|
|
3406
3406
|
updatingPackageJsonWorkspaces: (packageJsonPath: string) => string;
|
|
3407
3407
|
updatedWorkspaces: (workspaces: string) => string;
|
|
3408
3408
|
updatedFileDependency: (packageName: string, relativePath: string) => string;
|
|
3409
|
+
lintPackagesNotConfigured: (packageRoot: string) => string;
|
|
3410
|
+
lintConfigNotFound: (packageRoot: string) => string;
|
|
3411
|
+
lintHubSpotRulesNotActive: (packageRoot: string) => string;
|
|
3409
3412
|
npmAuditClean: (packageRoot: string) => string;
|
|
3410
3413
|
npmAuditIssues: (packageRoot: string, details: string) => string;
|
|
3411
3414
|
npmAuditNpmUnavailable: (packageRoot: string) => string;
|
package/lang/en.js
CHANGED
|
@@ -3432,6 +3432,9 @@ export const lib = {
|
|
|
3432
3432
|
updatingPackageJsonWorkspaces: (packageJsonPath) => `Updating package.json workspaces in archive: ${packageJsonPath}`,
|
|
3433
3433
|
updatedWorkspaces: (workspaces) => ` Updated workspaces: ${workspaces}`,
|
|
3434
3434
|
updatedFileDependency: (packageName, relativePath) => ` Updated dependencies.${packageName}: file:${relativePath}`,
|
|
3435
|
+
lintPackagesNotConfigured: (packageRoot) => `Project lint: lint packages not installed for ${chalk.bold(packageRoot)}. Run ${uiCommandReference('hs project lint')} to install them.`,
|
|
3436
|
+
lintConfigNotFound: (packageRoot) => `Project lint: ESLint configuration not found for ${chalk.bold(packageRoot)}. Run ${uiCommandReference('hs project lint')} to create an ESLint config.`,
|
|
3437
|
+
lintHubSpotRulesNotActive: (packageRoot) => `Project lint: HubSpot ESLint rules not active for ${chalk.bold(packageRoot)}. Configure ${chalk.bold('@hubspot/eslint-config-ui-extensions')} — see ${uiLink('setup instructions', 'https://www.npmjs.com/package/@hubspot/eslint-config-ui-extensions')}.`,
|
|
3435
3438
|
npmAuditClean: (packageRoot) => `npm audit: No npm dependency issues found for ${chalk.bold(packageRoot)}`,
|
|
3436
3439
|
npmAuditIssues: (packageRoot, details) => `npm audit: security issues found for ${chalk.bold(packageRoot)}: ${details}`,
|
|
3437
3440
|
npmAuditNpmUnavailable: (packageRoot) => `npm audit: skipped for ${chalk.bold(packageRoot)} (npm not available in PATH)`,
|
|
@@ -23,6 +23,8 @@ export declare function hasEslintConfig(directory: string): boolean;
|
|
|
23
23
|
export declare function hasDeprecatedEslintConfig(directory: string): boolean;
|
|
24
24
|
export declare function getDeprecatedEslintConfigFiles(directory: string): string[];
|
|
25
25
|
export declare function createEslintConfig(directory: string, platformVersion?: string | null): Promise<string>;
|
|
26
|
+
export declare const HUBSPOT_UI_EXTENSIONS_RULE_PREFIX = "@hubspot/ui-extensions/";
|
|
27
|
+
export declare function isHubSpotEslintConfigActive(directory: string): Promise<boolean>;
|
|
26
28
|
export declare function lintPackagesInDirectory(directory: string, projectDir?: string): Promise<{
|
|
27
29
|
success: boolean;
|
|
28
30
|
output: string;
|
|
@@ -163,6 +163,21 @@ export async function createEslintConfig(directory, platformVersion) {
|
|
|
163
163
|
throw error;
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
+
export const HUBSPOT_UI_EXTENSIONS_RULE_PREFIX = '@hubspot/ui-extensions/';
|
|
167
|
+
export async function isHubSpotEslintConfigActive(directory) {
|
|
168
|
+
const exec = util.promisify(execAsync);
|
|
169
|
+
try {
|
|
170
|
+
const { stdout } = await exec('npx eslint --print-config ./Component.tsx', {
|
|
171
|
+
cwd: directory,
|
|
172
|
+
});
|
|
173
|
+
const config = JSON.parse(stdout);
|
|
174
|
+
const rules = config.rules ?? {};
|
|
175
|
+
return Object.keys(rules).some(rule => rule.startsWith(HUBSPOT_UI_EXTENSIONS_RULE_PREFIX));
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
166
181
|
export async function lintPackagesInDirectory(directory, projectDir) {
|
|
167
182
|
const displayPath = projectDir
|
|
168
183
|
? path.relative(projectDir, directory)
|
package/lib/projects/upload.js
CHANGED
|
@@ -18,6 +18,7 @@ import { walk } from '@hubspot/local-dev-lib/fs';
|
|
|
18
18
|
import { LEGACY_CONFIG_FILES } from '../constants.js';
|
|
19
19
|
import { archiveWorkspacesAndDependencies, getPackageJsonPathsToUpdate, getLockfilePathsToUpdate, } from './workspaces.js';
|
|
20
20
|
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
21
|
+
import { validateLintConfigOnUpload } from './validateLintConfigOnUpload.js';
|
|
21
22
|
import { runNpmAuditsBeforeProjectUpload } from './npmAuditOnUpload.js';
|
|
22
23
|
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
|
|
23
24
|
const accountIdentifier = uiAccountDescription(accountId) || `${accountId}`;
|
|
@@ -61,6 +62,14 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
|
|
|
61
62
|
workspaceMappings = await collectWorkspaceDirectories(parsedPackageJsons);
|
|
62
63
|
fileDependencyMappings = await collectFileDependencies(parsedPackageJsons);
|
|
63
64
|
}
|
|
65
|
+
if (isUploadCommand && !skipValidation) {
|
|
66
|
+
await validateLintConfigOnUpload({
|
|
67
|
+
srcDir,
|
|
68
|
+
projectDir,
|
|
69
|
+
parsedPackageJsons,
|
|
70
|
+
isLegacyPlatform: isLegacyProject(projectConfig.platformVersion),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
64
73
|
if (isUploadCommand && !skipNpmAudit) {
|
|
65
74
|
await runNpmAuditsBeforeProjectUpload({
|
|
66
75
|
srcDir,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ParsedPackageJson } from '@hubspot/project-parsing-lib/workspaces';
|
|
2
|
+
type ValidateLintConfigOnUploadArgs = {
|
|
3
|
+
srcDir: string;
|
|
4
|
+
projectDir: string;
|
|
5
|
+
parsedPackageJsons: ParsedPackageJson[];
|
|
6
|
+
isLegacyPlatform: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare function validateLintConfigOnUpload({ srcDir, projectDir, parsedPackageJsons, isLegacyPlatform, }: ValidateLintConfigOnUploadArgs): Promise<void>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { lib } from '../../lang/en.js';
|
|
3
|
+
import { uiLogger } from '../ui/logger.js';
|
|
4
|
+
import { areAllLintPackagesInstalled, hasEslintConfig, isHubSpotEslintConfigActive, } from './uieLinting.js';
|
|
5
|
+
export async function validateLintConfigOnUpload({ srcDir, projectDir, parsedPackageJsons, isLegacyPlatform, }) {
|
|
6
|
+
const lintRoots = new Set();
|
|
7
|
+
if (isLegacyPlatform) {
|
|
8
|
+
lintRoots.add(srcDir);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
for (const { dir } of parsedPackageJsons) {
|
|
12
|
+
lintRoots.add(dir);
|
|
13
|
+
}
|
|
14
|
+
if (lintRoots.size === 0) {
|
|
15
|
+
lintRoots.add(srcDir);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
let hasAnyOutput = false;
|
|
19
|
+
for (const lintRoot of lintRoots) {
|
|
20
|
+
const relativeRoot = path.relative(projectDir, lintRoot) || '.';
|
|
21
|
+
let warnMessage;
|
|
22
|
+
if (!areAllLintPackagesInstalled(lintRoot)) {
|
|
23
|
+
warnMessage =
|
|
24
|
+
lib.projectUpload.handleProjectUpload.lintPackagesNotConfigured(relativeRoot);
|
|
25
|
+
}
|
|
26
|
+
else if (!hasEslintConfig(lintRoot)) {
|
|
27
|
+
warnMessage =
|
|
28
|
+
lib.projectUpload.handleProjectUpload.lintConfigNotFound(relativeRoot);
|
|
29
|
+
}
|
|
30
|
+
else if (!(await isHubSpotEslintConfigActive(lintRoot))) {
|
|
31
|
+
warnMessage =
|
|
32
|
+
lib.projectUpload.handleProjectUpload.lintHubSpotRulesNotActive(relativeRoot);
|
|
33
|
+
}
|
|
34
|
+
if (warnMessage) {
|
|
35
|
+
if (!hasAnyOutput) {
|
|
36
|
+
uiLogger.log('');
|
|
37
|
+
hasAnyOutput = true;
|
|
38
|
+
}
|
|
39
|
+
uiLogger.warn(warnMessage);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (hasAnyOutput) {
|
|
43
|
+
uiLogger.log('');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -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 create function';
|
|
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 create function 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,8 +1,9 @@
|
|
|
1
1
|
import { Tool } from '../../Tool.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { runCommandInDir } from '../../utils/command.js';
|
|
5
|
+
import { formatTextContents, formatTextContent } from '../../utils/content.js';
|
|
6
|
+
import { addFlag } from '../../utils/command.js';
|
|
6
7
|
import { CONTENT_TYPES } from '../../../types/Cms.js';
|
|
7
8
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
8
9
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
@@ -74,7 +75,7 @@ export class HsCreateModuleTool extends Tool {
|
|
|
74
75
|
};
|
|
75
76
|
}
|
|
76
77
|
// Build the command
|
|
77
|
-
let command = 'hs
|
|
78
|
+
let command = 'hs create module';
|
|
78
79
|
if (userSuppliedName) {
|
|
79
80
|
command += ` "${userSuppliedName}"`;
|
|
80
81
|
}
|
|
@@ -100,9 +101,6 @@ export class HsCreateModuleTool extends Tool {
|
|
|
100
101
|
if (availableForNewContent !== undefined) {
|
|
101
102
|
command = addFlag(command, 'available-for-new-content', availableForNewContent);
|
|
102
103
|
}
|
|
103
|
-
else {
|
|
104
|
-
command = addFlag(command, 'available-for-new-content', true);
|
|
105
|
-
}
|
|
106
104
|
try {
|
|
107
105
|
const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
|
|
108
106
|
return formatTextContents(stdout, stderr);
|
|
@@ -118,7 +116,7 @@ export class HsCreateModuleTool extends Tool {
|
|
|
118
116
|
register() {
|
|
119
117
|
return this.mcpServer.registerTool(toolName, {
|
|
120
118
|
title: 'Create HubSpot CMS Module',
|
|
121
|
-
description: 'Creates a new HubSpot CMS module using the hs
|
|
119
|
+
description: 'Creates a new HubSpot CMS module using the hs create module 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.',
|
|
122
120
|
inputSchema,
|
|
123
121
|
annotations: {
|
|
124
122
|
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 create template';
|
|
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 create template 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,7 +1,8 @@
|
|
|
1
1
|
import { Tool } from '../../Tool.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { addFlag
|
|
3
|
+
import { addFlag } from '../../utils/command.js';
|
|
4
4
|
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
5
|
+
import { runCommandInDir } from '../../utils/command.js';
|
|
5
6
|
import { formatTextContents } from '../../utils/content.js';
|
|
6
7
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
7
8
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
@@ -37,7 +38,7 @@ export class HsFunctionLogsTool extends Tool {
|
|
|
37
38
|
const normalizedEndpoint = endpoint.startsWith('/')
|
|
38
39
|
? endpoint.slice(1)
|
|
39
40
|
: endpoint;
|
|
40
|
-
let command = `hs
|
|
41
|
+
let command = `hs logs ${normalizedEndpoint}`;
|
|
41
42
|
if (latest) {
|
|
42
43
|
command = addFlag(command, 'latest', latest);
|
|
43
44
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Tool } from '../../Tool.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { addFlag
|
|
3
|
+
import { addFlag } from '../../utils/command.js';
|
|
4
4
|
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
5
|
+
import { runCommandInDir } from '../../utils/command.js';
|
|
5
6
|
import { formatTextContents } from '../../utils/content.js';
|
|
6
7
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
7
8
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
@@ -25,7 +26,7 @@ export class HsListFunctionsTool extends Tool {
|
|
|
25
26
|
}
|
|
26
27
|
async handler({ account, json, absoluteCurrentWorkingDirectory, }) {
|
|
27
28
|
setupHubSpotConfig(absoluteCurrentWorkingDirectory);
|
|
28
|
-
let command = 'hs
|
|
29
|
+
let command = 'hs function list';
|
|
29
30
|
if (json) {
|
|
30
31
|
command += ' --json';
|
|
31
32
|
}
|
|
@@ -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
|
|
29
|
+
let command = 'hs 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
|
|
49
|
+
text: `Error executing hs list command: ${getErrorMessage(error)}`,
|
|
50
50
|
},
|
|
51
51
|
],
|
|
52
52
|
};
|
package/package.json
CHANGED