@hubspot/cli 7.6.0-beta.11 → 7.6.0-beta.13
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/app/__tests__/migrate.test.js +1 -0
- package/commands/getStarted.js +7 -20
- package/commands/mcp/setup.d.ts +0 -1
- package/commands/mcp/setup.js +11 -11
- package/commands/project/__tests__/add.test.js +64 -0
- package/commands/project/__tests__/create.test.js +57 -0
- package/commands/project/__tests__/deploy.test.js +3 -2
- package/commands/project/add.d.ts +1 -1
- package/commands/project/add.js +3 -5
- package/commands/project/create.js +7 -2
- package/commands/project/deploy.js +9 -61
- package/commands/project/dev/index.js +1 -1
- package/commands/project/dev/unifiedFlow.js +4 -1
- package/commands/project/migrate.js +26 -7
- package/commands/project/upload.js +2 -2
- package/commands/project/validate.js +1 -1
- package/commands/project/watch.js +2 -2
- package/lang/en.d.ts +20 -5
- package/lang/en.js +38 -22
- package/lang/en.lyaml +12 -12
- package/lib/__tests__/hasFeature.test.js +145 -7
- package/lib/__tests__/importData.test.js +1 -1
- package/lib/app/__tests__/migrate.test.js +14 -51
- package/lib/app/migrate.d.ts +2 -8
- package/lib/app/migrate.js +5 -73
- package/lib/constants.d.ts +4 -0
- package/lib/constants.js +4 -0
- package/lib/errorHandlers/index.d.ts +4 -0
- package/lib/errorHandlers/index.js +1 -1
- package/lib/hasFeature.js +6 -0
- package/lib/importData.js +1 -1
- package/lib/links.d.ts +1 -0
- package/lib/links.js +10 -3
- package/lib/mcp/setup.d.ts +0 -2
- package/lib/mcp/setup.js +4 -29
- package/lib/projects/__tests__/AppDevModeInterface.test.js +71 -44
- package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
- package/lib/projects/__tests__/components.test.js +164 -7
- package/lib/projects/__tests__/deploy.test.js +164 -0
- package/lib/projects/__tests__/platformVersion.test.d.ts +1 -0
- package/lib/projects/__tests__/{buildAndDeploy.test.js → platformVersion.test.js} +2 -2
- package/lib/projects/add/__tests__/legacyAddComponent.test.js +49 -6
- package/lib/projects/add/__tests__/v3AddComponent.test.js +142 -8
- package/lib/projects/add/legacyAddComponent.d.ts +1 -1
- package/lib/projects/add/legacyAddComponent.js +5 -1
- package/lib/projects/add/v3AddComponent.d.ts +2 -1
- package/lib/projects/add/v3AddComponent.js +22 -5
- package/lib/projects/components.d.ts +1 -0
- package/lib/projects/components.js +27 -1
- package/lib/projects/create/__tests__/v3.test.js +97 -9
- package/lib/projects/create/index.js +2 -2
- package/lib/projects/create/legacy.js +1 -1
- package/lib/projects/create/v3.d.ts +2 -2
- package/lib/projects/create/v3.js +35 -12
- package/lib/projects/deploy.d.ts +13 -0
- package/lib/projects/deploy.js +63 -0
- package/lib/projects/localDev/AppDevModeInterface.d.ts +5 -3
- package/lib/projects/localDev/AppDevModeInterface.js +110 -47
- package/lib/projects/localDev/DevServerManagerV2.js +1 -0
- package/lib/projects/localDev/LocalDevProcess.js +3 -1
- package/lib/projects/localDev/LocalDevState.d.ts +5 -2
- package/lib/projects/localDev/LocalDevState.js +9 -1
- package/lib/projects/localDev/helpers/project.d.ts +2 -2
- package/lib/projects/localDev/helpers/project.js +6 -8
- package/lib/projects/platformVersion.d.ts +1 -0
- package/lib/projects/platformVersion.js +10 -0
- package/lib/projects/{buildAndDeploy.d.ts → pollProjectBuildAndDeploy.d.ts} +0 -1
- package/lib/projects/{buildAndDeploy.js → pollProjectBuildAndDeploy.js} +0 -10
- package/lib/projects/upload.js +1 -1
- package/lib/projects/urls.d.ts +1 -0
- package/lib/projects/urls.js +3 -0
- package/lib/prompts/__tests__/projectAddPrompt.test.d.ts +1 -0
- package/lib/prompts/__tests__/projectAddPrompt.test.js +143 -0
- package/lib/prompts/__tests__/selectProjectTemplatePrompt.test.d.ts +1 -0
- package/lib/prompts/__tests__/selectProjectTemplatePrompt.test.js +160 -0
- package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +1 -0
- package/lib/prompts/importDataFilePathPrompt.js +4 -2
- package/lib/prompts/installAppPrompt.d.ts +6 -1
- package/lib/prompts/installAppPrompt.js +6 -1
- package/lib/prompts/projectAddPrompt.js +1 -1
- package/lib/prompts/promptUtils.d.ts +5 -0
- package/lib/prompts/promptUtils.js +9 -0
- package/lib/prompts/selectProjectTemplatePrompt.js +1 -1
- package/lib/theme/__tests__/migrate.test.d.ts +1 -0
- package/lib/theme/__tests__/migrate.test.js +233 -0
- package/lib/theme/migrate.d.ts +13 -0
- package/lib/theme/migrate.js +90 -0
- package/lib/ui/index.js +3 -6
- package/lib/usageTracking.js +2 -2
- package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +32 -0
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +96 -0
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +38 -0
- package/mcp-server/tools/cms/HsCreateModuleTool.js +118 -0
- package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +26 -0
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +75 -0
- package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +32 -0
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +76 -0
- package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +23 -0
- package/mcp-server/tools/cms/HsListFunctionsTool.js +58 -0
- package/mcp-server/tools/cms/HsListTool.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +251 -0
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +224 -0
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +206 -0
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +183 -0
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +120 -0
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +1 -1
- package/mcp-server/tools/index.js +13 -1
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +3 -3
- package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/CreateProjectTool.js +5 -5
- package/mcp-server/tools/project/DeployProjectTool.js +1 -1
- package/mcp-server/tools/project/DocFetchTool.js +2 -2
- package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
- package/mcp-server/tools/project/DocsSearchTool.js +7 -7
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +14 -8
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.js +2 -2
- package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
- package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +2 -2
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +14 -12
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +9 -8
- package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -1
- package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/constants.d.ts +1 -1
- package/mcp-server/tools/project/constants.js +14 -6
- package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
- package/mcp-server/utils/cliConfig.d.ts +1 -0
- package/mcp-server/utils/cliConfig.js +12 -0
- package/package.json +4 -3
- package/types/LocalDev.d.ts +2 -1
- package/types/Projects.d.ts +1 -0
- package/ui/components/BoxWithTitle.d.ts +8 -0
- package/ui/components/BoxWithTitle.js +9 -0
- package/ui/components/HorizontalSelectPrompt.d.ts +8 -0
- package/ui/components/HorizontalSelectPrompt.js +30 -0
- package/ui/components/StatusMessageBoxes.d.ts +12 -0
- package/ui/components/StatusMessageBoxes.js +31 -0
- package/ui/lib/ui-testing-utils.d.ts +9 -0
- package/ui/lib/ui-testing-utils.js +47 -0
- package/ui/lib/useTerminalSize.d.ts +13 -0
- package/ui/lib/useTerminalSize.js +31 -0
- package/ui/styles.d.ts +18 -0
- package/ui/styles.js +18 -0
- package/ui/views/UiSandbox.d.ts +5 -0
- package/ui/views/UiSandbox.js +25 -0
- /package/lib/projects/__tests__/{buildAndDeploy.test.d.ts → deploy.test.d.ts} +0 -0
|
@@ -10,6 +10,7 @@ vi.mock('@hubspot/local-dev-lib/config');
|
|
|
10
10
|
vi.mock('@hubspot/local-dev-lib/logger');
|
|
11
11
|
vi.mock('../../../lib/app/migrate');
|
|
12
12
|
vi.mock('../../../lib/app/migrate_legacy');
|
|
13
|
+
vi.mock('../../../lib/projects/config.js');
|
|
13
14
|
const mockYargs = yargs;
|
|
14
15
|
const mockedGetAccountConfig = getAccountConfig;
|
|
15
16
|
const mockedMigrateApp2023_2 = migrateApp2023_2;
|
package/commands/getStarted.js
CHANGED
|
@@ -16,7 +16,8 @@ import { handleProjectUpload } from '../lib/projects/upload.js';
|
|
|
16
16
|
import { PROJECT_CONFIG_FILE, GET_STARTED_OPTIONS, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, } from '../lib/constants.js';
|
|
17
17
|
import { writeProjectConfig, getProjectConfig, validateProjectConfig, } from '../lib/projects/config.js';
|
|
18
18
|
import { getProjectPackageJsonLocations, installPackages, } from '../lib/dependencyManagement.js';
|
|
19
|
-
import { pollProjectBuildAndDeploy
|
|
19
|
+
import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
|
|
20
|
+
import { useV3Api } from '../lib/projects/platformVersion.js';
|
|
20
21
|
import { openLink } from '../lib/links.js';
|
|
21
22
|
import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
|
|
22
23
|
import { getEnv } from '@hubspot/local-dev-lib/config';
|
|
@@ -28,10 +29,10 @@ async function handler(args) {
|
|
|
28
29
|
const { derivedAccountId } = args;
|
|
29
30
|
const env = getEnv(derivedAccountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD;
|
|
30
31
|
await trackCommandUsage('get-started', {}, derivedAccountId);
|
|
31
|
-
|
|
32
|
-
const templateSource = 'robrown-hubspot/hubspot-project-components-ua-app-objects-beta';
|
|
32
|
+
const accountName = uiAccountDescription(derivedAccountId);
|
|
33
33
|
uiInfoSection(commands.getStarted.startTitle, () => {
|
|
34
34
|
uiLogger.log(commands.getStarted.startDescription);
|
|
35
|
+
uiLogger.log(commands.getStarted.guideOverview(accountName));
|
|
35
36
|
});
|
|
36
37
|
const { default: selectedOption } = await promptUser([
|
|
37
38
|
{
|
|
@@ -80,16 +81,7 @@ async function handler(args) {
|
|
|
80
81
|
else {
|
|
81
82
|
uiLogger.log(' ');
|
|
82
83
|
uiLogger.log(commands.getStarted.logs.appSelected);
|
|
83
|
-
// 1. Fetch project templates
|
|
84
|
-
let latestRepoReleaseTag;
|
|
85
84
|
const { dest, name } = await projectNameAndDestPrompt(args);
|
|
86
|
-
// Specific template for get-started command
|
|
87
|
-
const projectTemplate = {
|
|
88
|
-
name: 'private-app-get-started-template',
|
|
89
|
-
label: 'CRM getting started project with private apps',
|
|
90
|
-
path: 'projects/private-app-get-started-template',
|
|
91
|
-
};
|
|
92
|
-
// 3. Create the project files
|
|
93
85
|
const projectDest = path.resolve(getCwd(), dest);
|
|
94
86
|
const { projectConfig: existingProjectConfig, projectDir: existingProjectDir, } = await getProjectConfig(projectDest);
|
|
95
87
|
if (existingProjectConfig &&
|
|
@@ -104,13 +96,10 @@ async function handler(args) {
|
|
|
104
96
|
uiLogger.error(commands.project.create.errors.cannotNestProjects(existingProjectDir));
|
|
105
97
|
process.exit(EXIT_CODES.ERROR);
|
|
106
98
|
}
|
|
107
|
-
const repo = templateSource || HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
|
|
108
99
|
// 4. Clone the project template from GitHub
|
|
109
|
-
// This is temporary until we have the UA template in the main repo
|
|
110
100
|
try {
|
|
111
|
-
await cloneGithubRepo(
|
|
112
|
-
sourceDir:
|
|
113
|
-
tag: latestRepoReleaseTag,
|
|
101
|
+
await cloneGithubRepo(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, projectDest, {
|
|
102
|
+
sourceDir: '2025.2/private-app-get-started-template',
|
|
114
103
|
hideLogs: true,
|
|
115
104
|
});
|
|
116
105
|
await trackCommandMetadataUsage('get-started', {
|
|
@@ -163,7 +152,6 @@ async function handler(args) {
|
|
|
163
152
|
uiLogger.log(' ');
|
|
164
153
|
}
|
|
165
154
|
// 6. Ask user if they want to upload the project
|
|
166
|
-
const accountName = uiAccountDescription(derivedAccountId);
|
|
167
155
|
const { shouldUpload } = await promptUser([
|
|
168
156
|
{
|
|
169
157
|
type: 'confirm',
|
|
@@ -192,12 +180,11 @@ async function handler(args) {
|
|
|
192
180
|
process.exit(EXIT_CODES.ERROR);
|
|
193
181
|
}
|
|
194
182
|
validateProjectConfig(newProjectConfig, newProjectDir);
|
|
195
|
-
const targetAccountId = derivedAccountId;
|
|
196
183
|
uiLogger.log(' ');
|
|
197
184
|
uiLogger.log(commands.getStarted.logs.uploadingProject);
|
|
198
185
|
uiLogger.log(' ');
|
|
199
186
|
const { result, uploadError } = await handleProjectUpload({
|
|
200
|
-
accountId:
|
|
187
|
+
accountId: derivedAccountId,
|
|
201
188
|
projectConfig: newProjectConfig,
|
|
202
189
|
projectDir: newProjectDir,
|
|
203
190
|
callbackFunc: pollProjectBuildAndDeploy,
|
package/commands/mcp/setup.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CommonArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
2
|
interface MCPSetupArgs extends CommonArgs {
|
|
3
3
|
client?: string[];
|
|
4
|
-
addDocsSearch?: boolean;
|
|
5
4
|
}
|
|
6
5
|
declare const mcpSetupCommand: YargsCommandModule<unknown, MCPSetupArgs>;
|
|
7
6
|
export default mcpSetupCommand;
|
package/commands/mcp/setup.js
CHANGED
|
@@ -2,11 +2,19 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
|
2
2
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
3
3
|
import { commands } from '../../lang/en.js';
|
|
4
4
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
5
|
-
import { addMcpServerToConfig,
|
|
5
|
+
import { addMcpServerToConfig, supportedTools } from '../../lib/mcp/setup.js';
|
|
6
6
|
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
7
|
+
import { hasFeature } from '../../lib/hasFeature.js';
|
|
8
|
+
import { FEATURES } from '../../lib/constants.js';
|
|
7
9
|
const command = ['setup', 'update'];
|
|
8
10
|
const describe = undefined; // Leave hidden for now
|
|
9
11
|
async function handler(args) {
|
|
12
|
+
const { derivedAccountId } = args;
|
|
13
|
+
const hasMcpAccess = await hasFeature(derivedAccountId, FEATURES.MCP_ACCESS);
|
|
14
|
+
if (!hasMcpAccess) {
|
|
15
|
+
uiLogger.error(commands.mcp.setup.errors.needsMcpAccess(derivedAccountId));
|
|
16
|
+
process.exit(EXIT_CODES.ERROR);
|
|
17
|
+
}
|
|
10
18
|
try {
|
|
11
19
|
await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
12
20
|
}
|
|
@@ -16,10 +24,7 @@ async function handler(args) {
|
|
|
16
24
|
}
|
|
17
25
|
trackCommandUsage('mcp-setup', {}, args.derivedAccountId);
|
|
18
26
|
try {
|
|
19
|
-
|
|
20
|
-
if (args.addDocsSearch) {
|
|
21
|
-
await addMintlifyMcpServer(derivedTargets);
|
|
22
|
-
}
|
|
27
|
+
await addMcpServerToConfig(args.client);
|
|
23
28
|
}
|
|
24
29
|
catch (e) {
|
|
25
30
|
process.exit(EXIT_CODES.ERROR);
|
|
@@ -27,15 +32,10 @@ async function handler(args) {
|
|
|
27
32
|
process.exit(EXIT_CODES.SUCCESS);
|
|
28
33
|
}
|
|
29
34
|
function setupBuilder(yargs) {
|
|
30
|
-
yargs
|
|
31
|
-
.option('client', {
|
|
35
|
+
yargs.option('client', {
|
|
32
36
|
describe: commands.mcp.setup.args.client,
|
|
33
37
|
type: 'array',
|
|
34
38
|
choices: [...supportedTools.map(tool => tool.value)],
|
|
35
|
-
})
|
|
36
|
-
.option('add-docs-search', {
|
|
37
|
-
type: 'boolean',
|
|
38
|
-
hidden: true,
|
|
39
39
|
});
|
|
40
40
|
return yargs;
|
|
41
41
|
}
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import yargs from 'yargs';
|
|
2
2
|
import projectAddCommand from '../add.js';
|
|
3
3
|
import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, } from '../../../lib/constants.js';
|
|
4
|
+
import { v3AddComponent } from '../../../lib/projects/add/v3AddComponent.js';
|
|
5
|
+
import { legacyAddComponent } from '../../../lib/projects/add/legacyAddComponent.js';
|
|
6
|
+
import { getProjectConfig } from '../../../lib/projects/config.js';
|
|
7
|
+
import { useV3Api } from '../../../lib/projects/platformVersion.js';
|
|
8
|
+
import { trackCommandUsage } from '../../../lib/usageTracking.js';
|
|
4
9
|
vi.mock('../../../lib/commonOpts');
|
|
10
|
+
vi.mock('../../../lib/projects/add/v3AddComponent');
|
|
11
|
+
vi.mock('../../../lib/projects/add/legacyAddComponent');
|
|
12
|
+
vi.mock('../../../lib/projects/config');
|
|
13
|
+
vi.mock('../../../lib/projects/platformVersion');
|
|
14
|
+
vi.mock('../../../lib/usageTracking');
|
|
15
|
+
const mockedV3AddComponent = vi.mocked(v3AddComponent);
|
|
16
|
+
const mockedLegacyAddComponent = vi.mocked(legacyAddComponent);
|
|
17
|
+
const mockedGetProjectConfig = vi.mocked(getProjectConfig);
|
|
18
|
+
const mockedUseV3Api = vi.mocked(useV3Api);
|
|
19
|
+
const mockedTrackCommandUsage = vi.mocked(trackCommandUsage);
|
|
5
20
|
describe('commands/project/add', () => {
|
|
6
21
|
const yargsMock = yargs;
|
|
7
22
|
describe('command', () => {
|
|
@@ -40,4 +55,53 @@ describe('commands/project/add', () => {
|
|
|
40
55
|
});
|
|
41
56
|
});
|
|
42
57
|
});
|
|
58
|
+
describe('handler', () => {
|
|
59
|
+
const mockProjectConfig = {
|
|
60
|
+
name: 'test-project',
|
|
61
|
+
srcDir: 'src',
|
|
62
|
+
platformVersion: 'v3',
|
|
63
|
+
};
|
|
64
|
+
const mockProjectDir = '/path/to/project';
|
|
65
|
+
const mockArgs = {
|
|
66
|
+
derivedAccountId: 123,
|
|
67
|
+
name: 'test-component',
|
|
68
|
+
type: 'module',
|
|
69
|
+
};
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
mockedGetProjectConfig.mockResolvedValue({
|
|
72
|
+
projectConfig: mockProjectConfig,
|
|
73
|
+
projectDir: mockProjectDir,
|
|
74
|
+
});
|
|
75
|
+
mockedTrackCommandUsage.mockResolvedValue();
|
|
76
|
+
mockedV3AddComponent.mockResolvedValue();
|
|
77
|
+
mockedLegacyAddComponent.mockResolvedValue();
|
|
78
|
+
vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
79
|
+
throw new Error('process.exit called');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
it('should call v3AddComponent with accountId for v3 projects', async () => {
|
|
83
|
+
mockedUseV3Api.mockReturnValue(true);
|
|
84
|
+
await expect(projectAddCommand.handler(mockArgs)).rejects.toThrow('process.exit called');
|
|
85
|
+
expect(mockedV3AddComponent).toHaveBeenCalledWith(mockArgs, mockProjectDir, mockProjectConfig, 123);
|
|
86
|
+
expect(mockedLegacyAddComponent).not.toHaveBeenCalled();
|
|
87
|
+
});
|
|
88
|
+
it('should call legacyAddComponent for non-v3 projects', async () => {
|
|
89
|
+
mockedUseV3Api.mockReturnValue(false);
|
|
90
|
+
await expect(projectAddCommand.handler(mockArgs)).rejects.toThrow('process.exit called');
|
|
91
|
+
expect(mockedLegacyAddComponent).toHaveBeenCalledWith(mockArgs, mockProjectDir, mockProjectConfig, 123);
|
|
92
|
+
expect(mockedV3AddComponent).not.toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
it('should exit with error when project config is not found', async () => {
|
|
95
|
+
mockedGetProjectConfig.mockResolvedValue({
|
|
96
|
+
projectConfig: null,
|
|
97
|
+
projectDir: null,
|
|
98
|
+
});
|
|
99
|
+
const mockExit = vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
100
|
+
throw new Error('process.exit called');
|
|
101
|
+
});
|
|
102
|
+
await expect(projectAddCommand.handler(mockArgs)).rejects.toThrow('process.exit called');
|
|
103
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
104
|
+
mockExit.mockRestore();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
43
107
|
});
|
|
@@ -27,14 +27,71 @@ describe('commands/project/create', () => {
|
|
|
27
27
|
it('should define project creation options', () => {
|
|
28
28
|
const optionsSpy = vi.spyOn(yargsMock, 'options');
|
|
29
29
|
const exampleSpy = vi.spyOn(yargsMock, 'example');
|
|
30
|
+
const conflictsSpy = vi.spyOn(yargsMock, 'conflicts');
|
|
30
31
|
projectCreateCommand.builder(yargsMock);
|
|
31
32
|
expect(optionsSpy).toHaveBeenCalledWith(expect.objectContaining({
|
|
32
33
|
name: expect.any(Object),
|
|
33
34
|
dest: expect.any(Object),
|
|
34
35
|
template: expect.any(Object),
|
|
35
36
|
'template-source': expect.any(Object),
|
|
37
|
+
'platform-version': expect.any(Object),
|
|
38
|
+
'project-base': expect.any(Object),
|
|
39
|
+
distribution: expect.any(Object),
|
|
40
|
+
auth: expect.any(Object),
|
|
41
|
+
features: expect.any(Object),
|
|
36
42
|
}));
|
|
43
|
+
expect(conflictsSpy).toHaveBeenCalledWith('template', 'features');
|
|
37
44
|
expect(exampleSpy).toHaveBeenCalled();
|
|
38
45
|
});
|
|
46
|
+
it('should define platform version option with correct choices', () => {
|
|
47
|
+
const optionsSpy = vi.spyOn(yargsMock, 'options');
|
|
48
|
+
projectCreateCommand.builder(yargsMock);
|
|
49
|
+
const optionsCall = optionsSpy.mock.calls[0][0];
|
|
50
|
+
expect(optionsCall['platform-version']).toEqual(expect.objectContaining({
|
|
51
|
+
hidden: true,
|
|
52
|
+
type: 'string',
|
|
53
|
+
choices: ['2023.2', '2025.1', '2025.2'],
|
|
54
|
+
default: '2023.2',
|
|
55
|
+
}));
|
|
56
|
+
});
|
|
57
|
+
it('should define project base option with correct choices', () => {
|
|
58
|
+
const optionsSpy = vi.spyOn(yargsMock, 'options');
|
|
59
|
+
projectCreateCommand.builder(yargsMock);
|
|
60
|
+
const optionsCall = optionsSpy.mock.calls[0][0];
|
|
61
|
+
expect(optionsCall['project-base']).toEqual(expect.objectContaining({
|
|
62
|
+
hidden: true,
|
|
63
|
+
type: 'string',
|
|
64
|
+
choices: ['empty', 'app'],
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
it('should define distribution option with correct choices', () => {
|
|
68
|
+
const optionsSpy = vi.spyOn(yargsMock, 'options');
|
|
69
|
+
projectCreateCommand.builder(yargsMock);
|
|
70
|
+
const optionsCall = optionsSpy.mock.calls[0][0];
|
|
71
|
+
expect(optionsCall.distribution).toEqual(expect.objectContaining({
|
|
72
|
+
hidden: true,
|
|
73
|
+
type: 'string',
|
|
74
|
+
choices: ['private', 'marketplace'],
|
|
75
|
+
}));
|
|
76
|
+
});
|
|
77
|
+
it('should define auth option with correct choices', () => {
|
|
78
|
+
const optionsSpy = vi.spyOn(yargsMock, 'options');
|
|
79
|
+
projectCreateCommand.builder(yargsMock);
|
|
80
|
+
const optionsCall = optionsSpy.mock.calls[0][0];
|
|
81
|
+
expect(optionsCall.auth).toEqual(expect.objectContaining({
|
|
82
|
+
hidden: true,
|
|
83
|
+
type: 'string',
|
|
84
|
+
choices: ['oauth', 'static'],
|
|
85
|
+
}));
|
|
86
|
+
});
|
|
87
|
+
it('should define features option as array', () => {
|
|
88
|
+
const optionsSpy = vi.spyOn(yargsMock, 'options');
|
|
89
|
+
projectCreateCommand.builder(yargsMock);
|
|
90
|
+
const optionsCall = optionsSpy.mock.calls[0][0];
|
|
91
|
+
expect(optionsCall.features).toEqual(expect.objectContaining({
|
|
92
|
+
hidden: true,
|
|
93
|
+
type: 'array',
|
|
94
|
+
}));
|
|
95
|
+
});
|
|
39
96
|
});
|
|
40
97
|
});
|
|
@@ -8,7 +8,7 @@ import * as ui from '../../../lib/ui/index.js';
|
|
|
8
8
|
import { addAccountOptions, addConfigOptions, addJSONOutputOptions, addUseEnvironmentOptions, } from '../../../lib/commonOpts.js';
|
|
9
9
|
import * as projectUtils from '../../../lib/projects/config.js';
|
|
10
10
|
import * as projectUrlUtils from '../../../lib/projects/urls.js';
|
|
11
|
-
import { pollDeployStatus } from '../../../lib/projects/
|
|
11
|
+
import { pollDeployStatus } from '../../../lib/projects/pollProjectBuildAndDeploy.js';
|
|
12
12
|
import * as projectNamePrompt from '../../../lib/prompts/projectNamePrompt.js';
|
|
13
13
|
import * as promptUtils from '../../../lib/prompts/promptUtils.js';
|
|
14
14
|
import { trackCommandUsage } from '../../../lib/usageTracking.js';
|
|
@@ -23,7 +23,8 @@ vi.mock('../../../lib/commonOpts');
|
|
|
23
23
|
vi.mock('../../../lib/validation');
|
|
24
24
|
vi.mock('../../../lib/projects/config');
|
|
25
25
|
vi.mock('../../../lib/projects/urls');
|
|
26
|
-
vi.mock('../../../lib/projects/
|
|
26
|
+
vi.mock('../../../lib/projects/pollProjectBuildAndDeploy');
|
|
27
|
+
vi.mock('../../../lib/projects/platformVersion');
|
|
27
28
|
vi.mock('../../../lib/prompts/projectNamePrompt');
|
|
28
29
|
vi.mock('../../../lib/prompts/promptUtils');
|
|
29
30
|
vi.mock('../../../lib/usageTracking');
|
package/commands/project/add.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { logError } from '../../lib/errorHandlers/index.js';
|
|
2
|
-
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
3
2
|
import { getProjectConfig } from '../../lib/projects/config.js';
|
|
4
3
|
import { uiBetaTag } from '../../lib/ui/index.js';
|
|
5
4
|
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
6
5
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
7
6
|
import { commands } from '../../lang/en.js';
|
|
8
|
-
import { useV3Api } from '../../lib/projects/
|
|
7
|
+
import { useV3Api } from '../../lib/projects/platformVersion.js';
|
|
9
8
|
import { legacyAddComponent } from '../../lib/projects/add/legacyAddComponent.js';
|
|
10
9
|
import { v3AddComponent } from '../../lib/projects/add/v3AddComponent.js';
|
|
11
10
|
import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, } from '../../lib/constants.js';
|
|
@@ -15,7 +14,6 @@ const describe = uiBetaTag(commands.project.add.describe, false);
|
|
|
15
14
|
async function handler(args) {
|
|
16
15
|
try {
|
|
17
16
|
const { derivedAccountId } = args;
|
|
18
|
-
trackCommandUsage('project-add', undefined, derivedAccountId);
|
|
19
17
|
const { projectConfig, projectDir } = await getProjectConfig();
|
|
20
18
|
if (!projectDir || !projectConfig) {
|
|
21
19
|
uiLogger.error(commands.project.add.error.locationInProject);
|
|
@@ -23,10 +21,10 @@ async function handler(args) {
|
|
|
23
21
|
}
|
|
24
22
|
const isV3ProjectCreate = useV3Api(projectConfig.platformVersion);
|
|
25
23
|
if (isV3ProjectCreate) {
|
|
26
|
-
await v3AddComponent(args, projectDir, projectConfig);
|
|
24
|
+
await v3AddComponent(args, projectDir, projectConfig, derivedAccountId);
|
|
27
25
|
}
|
|
28
26
|
else {
|
|
29
|
-
await legacyAddComponent(args, projectDir, projectConfig);
|
|
27
|
+
await legacyAddComponent(args, projectDir, projectConfig, derivedAccountId);
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
30
|
catch (e) {
|
|
@@ -16,6 +16,8 @@ import { PLATFORM_VERSIONS } from '@hubspot/local-dev-lib/constants/projects';
|
|
|
16
16
|
import { commands } from '../../lang/en.js';
|
|
17
17
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
18
18
|
import { handleProjectCreationFlow, } from '../../lib/projects/create/index.js';
|
|
19
|
+
import { getProjectMetadata, } from '@hubspot/project-parsing-lib/src/lib/project.js';
|
|
20
|
+
import { updateHsMetaFilesWithAutoGeneratedFields } from '../../lib/projects/components.js';
|
|
19
21
|
const command = ['create', 'init'];
|
|
20
22
|
const describe = uiBetaTag(commands.project.create.describe, false);
|
|
21
23
|
const { v2023_2, v2025_1, v2025_2 } = PLATFORM_VERSIONS;
|
|
@@ -39,7 +41,7 @@ async function handler(args) {
|
|
|
39
41
|
type: selectProjectTemplatePromptResponse.projectTemplate?.name ||
|
|
40
42
|
(selectProjectTemplatePromptResponse.componentTemplates || [])
|
|
41
43
|
// @ts-expect-error
|
|
42
|
-
.map((item) => item.
|
|
44
|
+
.map((item) => item.type)
|
|
43
45
|
.join(','),
|
|
44
46
|
}, derivedAccountId);
|
|
45
47
|
const projectDest = path.resolve(getCwd(), projectNameAndDestPromptResponse.dest);
|
|
@@ -73,10 +75,13 @@ async function handler(args) {
|
|
|
73
75
|
}
|
|
74
76
|
const projectConfigPath = path.join(projectDest, PROJECT_CONFIG_FILE);
|
|
75
77
|
const parsedConfigFile = JSON.parse(fs.readFileSync(projectConfigPath).toString());
|
|
78
|
+
const projectName = projectNameAndDestPromptResponse.name;
|
|
76
79
|
writeProjectConfig(projectConfigPath, {
|
|
77
80
|
...parsedConfigFile,
|
|
78
|
-
name:
|
|
81
|
+
name: projectName,
|
|
79
82
|
});
|
|
83
|
+
const projectMetadata = await getProjectMetadata(path.join(projectDest, parsedConfigFile.srcDir));
|
|
84
|
+
updateHsMetaFilesWithAutoGeneratedFields(projectName, projectMetadata.hsMetaFiles);
|
|
80
85
|
// If the template is 'no-template', we need to manually create a src directory
|
|
81
86
|
if (selectProjectTemplatePromptResponse.projectTemplate?.name ===
|
|
82
87
|
EMPTY_PROJECT_TEMPLATE_NAME ||
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fetchProject } from '@hubspot/local-dev-lib/api/projects';
|
|
2
2
|
import { getAccountConfig } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
4
|
-
import { useV3Api } from '../../lib/projects/
|
|
4
|
+
import { useV3Api } from '../../lib/projects/platformVersion.js';
|
|
5
5
|
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
6
6
|
import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
|
|
7
7
|
import { getProjectConfig } from '../../lib/projects/config.js';
|
|
8
|
-
import { pollDeployStatus } from '../../lib/projects/buildAndDeploy.js';
|
|
9
8
|
import { projectNamePrompt } from '../../lib/prompts/projectNamePrompt.js';
|
|
10
9
|
import { promptUser } from '../../lib/prompts/promptUtils.js';
|
|
11
10
|
import { uiBetaTag, uiLine } from '../../lib/ui/index.js';
|
|
@@ -13,54 +12,11 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
|
13
12
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
14
13
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|
|
15
14
|
import { loadProfile, logProfileFooter, logProfileHeader, exitIfUsingProfiles, } from '../../lib/projectProfiles.js';
|
|
16
|
-
import {
|
|
15
|
+
import { PROJECT_DEPLOY_TEXT } from '../../lib/constants.js';
|
|
17
16
|
import { commands } from '../../lang/en.js';
|
|
17
|
+
import { handleProjectDeploy, validateBuildIdForDeploy, logDeployErrors, } from '../../lib/projects/deploy.js';
|
|
18
18
|
const command = 'deploy';
|
|
19
19
|
const describe = uiBetaTag(commands.project.deploy.describe, false);
|
|
20
|
-
function validateBuildId(buildId, deployedBuildId, latestBuildId, projectName, accountId) {
|
|
21
|
-
if (Number(buildId) > latestBuildId) {
|
|
22
|
-
return commands.project.deploy.errors.buildIdDoesNotExist(accountId, buildId, projectName);
|
|
23
|
-
}
|
|
24
|
-
if (Number(buildId) === deployedBuildId) {
|
|
25
|
-
return commands.project.deploy.errors.buildAlreadyDeployed(accountId, buildId, projectName);
|
|
26
|
-
}
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
function logDeployErrors(errorData) {
|
|
30
|
-
uiLogger.error(errorData.message);
|
|
31
|
-
errorData.errors.forEach(err => {
|
|
32
|
-
// This is how the pre-deploy check manifests itself in < 2025.2 projects
|
|
33
|
-
if (err.subCategory === PROJECT_ERROR_TYPES.DEPLOY_CONTAINS_REMOVALS) {
|
|
34
|
-
uiLogger.log(commands.project.deploy.errors.deployContainsRemovals(err.context.COMPONENT_NAME));
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
uiLogger.log(err.message);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
function handleBlockedDeploy(deployResp) {
|
|
42
|
-
const deployCanBeForced = deployResp.issues.every(issue => issue.blockingMessages.every(message => message.isWarning));
|
|
43
|
-
uiLogger.log('');
|
|
44
|
-
if (deployCanBeForced) {
|
|
45
|
-
uiLogger.warn(commands.project.deploy.errors.deployWarningsHeader);
|
|
46
|
-
uiLogger.log('');
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
uiLogger.error(commands.project.deploy.errors.deployBlockedHeader);
|
|
50
|
-
uiLogger.log('');
|
|
51
|
-
}
|
|
52
|
-
deployResp.issues.forEach(issue => {
|
|
53
|
-
if (issue.blockingMessages.length > 0) {
|
|
54
|
-
issue.blockingMessages.forEach(message => {
|
|
55
|
-
uiLogger.log(commands.project.deploy.errors.deployIssueComponentWarning(issue.uid, issue.componentTypeName, message.message));
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
uiLogger.log(commands.project.deploy.errors.deployIssueComponentGeneric(issue.uid, issue.componentTypeName));
|
|
60
|
-
}
|
|
61
|
-
uiLogger.log('');
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
20
|
async function handler(args) {
|
|
65
21
|
const { derivedAccountId, project: projectOption, buildId: buildIdOption, force: forceOption, deployLatestBuild: deployLatestBuildOption, json: formatOutputAsJson, } = args;
|
|
66
22
|
const accountConfig = getAccountConfig(derivedAccountId);
|
|
@@ -105,7 +61,7 @@ async function handler(args) {
|
|
|
105
61
|
return process.exit(EXIT_CODES.ERROR);
|
|
106
62
|
}
|
|
107
63
|
if (buildIdToDeploy) {
|
|
108
|
-
const validationResult =
|
|
64
|
+
const validationResult = validateBuildIdForDeploy(buildIdToDeploy, deployedBuildId, latestBuild.buildId, projectName, targetAccountId);
|
|
109
65
|
if (validationResult !== true) {
|
|
110
66
|
uiLogger.error(validationResult.toString());
|
|
111
67
|
return process.exit(EXIT_CODES.ERROR);
|
|
@@ -122,7 +78,7 @@ async function handler(args) {
|
|
|
122
78
|
default: latestBuild.buildId === deployedBuildId
|
|
123
79
|
? undefined
|
|
124
80
|
: latestBuild.buildId,
|
|
125
|
-
validate: buildId =>
|
|
81
|
+
validate: buildId => validateBuildIdForDeploy(buildId, deployedBuildId, latestBuild.buildId, projectName, targetAccountId),
|
|
126
82
|
});
|
|
127
83
|
buildIdToDeploy = deployBuildIdPromptResponse.buildId;
|
|
128
84
|
}
|
|
@@ -131,21 +87,13 @@ async function handler(args) {
|
|
|
131
87
|
uiLogger.error(commands.project.deploy.errors.noBuildId);
|
|
132
88
|
return process.exit(EXIT_CODES.ERROR);
|
|
133
89
|
}
|
|
134
|
-
const
|
|
135
|
-
if (!
|
|
136
|
-
if (deployResp?.buildResultType === 'DEPLOY_BLOCKED') {
|
|
137
|
-
handleBlockedDeploy(deployResp);
|
|
138
|
-
process.exit(EXIT_CODES.ERROR);
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
uiLogger.error(commands.project.deploy.errors.deploy);
|
|
142
|
-
}
|
|
90
|
+
const deployResult = await handleProjectDeploy(targetAccountId, projectName, buildIdToDeploy, useV3Api(projectConfig?.platformVersion), forceOption);
|
|
91
|
+
if (!deployResult) {
|
|
143
92
|
return process.exit(EXIT_CODES.ERROR);
|
|
144
93
|
}
|
|
145
94
|
else if (formatOutputAsJson) {
|
|
146
|
-
jsonOutput.deployId =
|
|
95
|
+
jsonOutput.deployId = deployResult.deployId;
|
|
147
96
|
}
|
|
148
|
-
const deployResult = await pollDeployStatus(targetAccountId, projectName, Number(deployResp.id), buildIdToDeploy);
|
|
149
97
|
if (deployResult.status === PROJECT_DEPLOY_TEXT.STATES.SUCCESS) {
|
|
150
98
|
deploySuccess = true;
|
|
151
99
|
}
|
|
@@ -5,7 +5,7 @@ import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
|
|
|
5
5
|
import { uiBetaTag, uiLine } from '../../../lib/ui/index.js';
|
|
6
6
|
import { deprecatedProjectDevFlow } from './deprecatedFlow.js';
|
|
7
7
|
import { unifiedProjectDevFlow } from './unifiedFlow.js';
|
|
8
|
-
import { useV3Api } from '../../../lib/projects/
|
|
8
|
+
import { useV3Api } from '../../../lib/projects/platformVersion.js';
|
|
9
9
|
import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
|
|
10
10
|
import { loadProfile, exitIfUsingProfiles, } from '../../../lib/projectProfiles.js';
|
|
11
11
|
import { commands } from '../../../lang/en.js';
|
|
@@ -22,6 +22,7 @@ import LocalDevWebsocketServer from '../../../lib/projects/localDev/LocalDevWebs
|
|
|
22
22
|
export async function unifiedProjectDevFlow({ args, targetProjectAccountId, providedTargetTestingAccountId, projectConfig, projectDir, }) {
|
|
23
23
|
const env = getValidEnv(getEnv(targetProjectAccountId));
|
|
24
24
|
let projectNodes;
|
|
25
|
+
let projectProfileData;
|
|
25
26
|
// Get IR
|
|
26
27
|
try {
|
|
27
28
|
const intermediateRepresentation = await translateForLocalDev({
|
|
@@ -30,6 +31,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
30
31
|
accountId: targetProjectAccountId,
|
|
31
32
|
}, { profile: args.profile });
|
|
32
33
|
projectNodes = intermediateRepresentation.intermediateNodesIndexedByUid;
|
|
34
|
+
projectProfileData = intermediateRepresentation.profileData;
|
|
33
35
|
uiLogger.debug(util.inspect(projectNodes, false, null, true));
|
|
34
36
|
}
|
|
35
37
|
catch (e) {
|
|
@@ -107,7 +109,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
107
109
|
let project = uploadedProject;
|
|
108
110
|
SpinniesManager.init();
|
|
109
111
|
if (projectExists && project) {
|
|
110
|
-
await compareLocalProjectToDeployed(projectConfig, targetProjectAccountId, project.deployedBuild?.buildId, projectNodes);
|
|
112
|
+
await compareLocalProjectToDeployed(projectConfig, targetProjectAccountId, project.deployedBuild?.buildId, projectNodes, args.profile);
|
|
111
113
|
}
|
|
112
114
|
else {
|
|
113
115
|
project = await createNewProjectForLocalDev(projectConfig, targetProjectAccountId, false, false);
|
|
@@ -116,6 +118,7 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
|
|
|
116
118
|
// End setup, start local dev process
|
|
117
119
|
const localDevProcess = new LocalDevProcess({
|
|
118
120
|
initialProjectNodes: projectNodes,
|
|
121
|
+
initialProjectProfileData: projectProfileData,
|
|
119
122
|
debug: args.debug,
|
|
120
123
|
profile: args.profile,
|
|
121
124
|
targetProjectAccountId,
|
|
@@ -8,6 +8,9 @@ import { uiCommandReference } from '../../lib/ui/index.js';
|
|
|
8
8
|
import { commands, lib } from '../../lang/en.js';
|
|
9
9
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
10
10
|
import { logInBox } from '../../lib/ui/boxen.js';
|
|
11
|
+
import { getHasMigratableThemes, migrateThemes2025_2, } from '../../lib/theme/migrate.js';
|
|
12
|
+
import { hasFeature } from '../../lib/hasFeature.js';
|
|
13
|
+
import { FEATURES } from '../../lib/constants.js';
|
|
11
14
|
const { v2025_2 } = PLATFORM_VERSIONS;
|
|
12
15
|
const command = 'migrate';
|
|
13
16
|
const describe = undefined; // commands.project.migrate.describe
|
|
@@ -26,13 +29,29 @@ async function handler(args) {
|
|
|
26
29
|
}
|
|
27
30
|
const { derivedAccountId } = args;
|
|
28
31
|
try {
|
|
29
|
-
await
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
const { hasMigratableThemes, migratableThemesCount } = await getHasMigratableThemes(projectConfig);
|
|
33
|
+
if (hasMigratableThemes) {
|
|
34
|
+
const hasThemeMigrationAccess = await hasFeature(derivedAccountId, FEATURES.THEME_MIGRATION_2025_2);
|
|
35
|
+
if (!hasThemeMigrationAccess) {
|
|
36
|
+
uiLogger.error(commands.project.migrate.errors.noThemeMigrationAccess(derivedAccountId));
|
|
37
|
+
return process.exit(EXIT_CODES.ERROR);
|
|
38
|
+
}
|
|
39
|
+
await migrateThemes2025_2(derivedAccountId, {
|
|
40
|
+
...args,
|
|
41
|
+
platformVersion: unstable
|
|
42
|
+
? PLATFORM_VERSIONS.unstable
|
|
43
|
+
: platformVersion,
|
|
44
|
+
}, migratableThemesCount, projectConfig);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
await migrateApp2025_2(derivedAccountId, {
|
|
48
|
+
...args,
|
|
49
|
+
name: projectConfig?.projectConfig?.name,
|
|
50
|
+
platformVersion: unstable
|
|
51
|
+
? PLATFORM_VERSIONS.unstable
|
|
52
|
+
: platformVersion,
|
|
53
|
+
}, projectConfig);
|
|
54
|
+
}
|
|
36
55
|
}
|
|
37
56
|
catch (error) {
|
|
38
57
|
logError(error);
|
|
@@ -2,14 +2,14 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { logger } from '@hubspot/local-dev-lib/logger';
|
|
3
3
|
import { getAccountConfig } from '@hubspot/local-dev-lib/config';
|
|
4
4
|
import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
|
|
5
|
-
import { useV3Api } from '../../lib/projects/
|
|
5
|
+
import { useV3Api } from '../../lib/projects/platformVersion.js';
|
|
6
6
|
import { uiBetaTag, uiCommandReference } from '../../lib/ui/index.js';
|
|
7
7
|
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
8
8
|
import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/config.js';
|
|
9
9
|
import { logFeedbackMessage } from '../../lib/projects/ui.js';
|
|
10
10
|
import { handleProjectUpload } from '../../lib/projects/upload.js';
|
|
11
11
|
import { loadAndValidateProfile } from '../../lib/projectProfiles.js';
|
|
12
|
-
import { displayWarnLogs, pollProjectBuildAndDeploy, } from '../../lib/projects/
|
|
12
|
+
import { displayWarnLogs, pollProjectBuildAndDeploy, } from '../../lib/projects/pollProjectBuildAndDeploy.js';
|
|
13
13
|
import { i18n } from '../../lib/lang.js';
|
|
14
14
|
import { PROJECT_ERROR_TYPES } from '../../lib/constants.js';
|
|
15
15
|
import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { getAccountConfig } from '@hubspot/local-dev-lib/config';
|
|
3
|
-
import { useV3Api } from '../../lib/projects/
|
|
3
|
+
import { useV3Api } from '../../lib/projects/platformVersion.js';
|
|
4
4
|
import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
5
5
|
import { uiLogger } from '../../lib/ui/logger.js';
|
|
6
6
|
import { getProjectConfig, validateProjectConfig as validateProjectConfig, } from '../../lib/projects/config.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cancelStagedBuild, fetchProjectBuilds, } from '@hubspot/local-dev-lib/api/projects';
|
|
2
2
|
import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
|
|
3
|
-
import { useV3Api } from '../../lib/projects/
|
|
3
|
+
import { useV3Api } from '../../lib/projects/platformVersion.js';
|
|
4
4
|
import { uiCommandReference, uiLink, uiBetaTag } from '../../lib/ui/index.js';
|
|
5
5
|
import { i18n } from '../../lib/lang.js';
|
|
6
6
|
import { createWatcher } from '../../lib/projects/watch.js';
|
|
@@ -11,7 +11,7 @@ import { trackCommandUsage } from '../../lib/usageTracking.js';
|
|
|
11
11
|
import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/config.js';
|
|
12
12
|
import { logFeedbackMessage } from '../../lib/projects/ui.js';
|
|
13
13
|
import { handleProjectUpload } from '../../lib/projects/upload.js';
|
|
14
|
-
import { pollBuildStatus, pollDeployStatus, } from '../../lib/projects/
|
|
14
|
+
import { pollBuildStatus, pollDeployStatus, } from '../../lib/projects/pollProjectBuildAndDeploy.js';
|
|
15
15
|
import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
|
|
16
16
|
import { handleKeypress, handleExit } from '../../lib/process.js';
|
|
17
17
|
import { makeYargsBuilder } from '../../lib/yargsUtils.js';
|