@hubspot/cli 7.9.0 → 7.10.0-beta.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.
@@ -13,6 +13,7 @@ import migrateApp from '../project/migrateApp.js';
13
13
  import migrate from '../project/migrate.js';
14
14
  import cloneApp from '../project/cloneApp.js';
15
15
  import installDeps from '../project/installDeps.js';
16
+ import updateDeps from '../project/updateDeps.js';
16
17
  import validate from '../project/validate.js';
17
18
  import profileCommands from '../project/profile.js';
18
19
  import list from '../project/list.js';
@@ -72,6 +73,7 @@ describe('commands/project', () => {
72
73
  migrate,
73
74
  cloneApp,
74
75
  installDeps,
76
+ updateDeps,
75
77
  profileCommands,
76
78
  validate,
77
79
  list,
@@ -6,7 +6,7 @@ import { getCWDAccountOverride, getDefaultAccountOverrideFilePath, getConfigPath
6
6
  import { getGlobalConfig } from '@hubspot/local-dev-lib/config/migrate';
7
7
  import { promptUser } from '../../lib/prompts/promptUtils.js';
8
8
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
9
- import { trackCommandMetadataUsage } from '../../lib/usageTracking.js';
9
+ import { trackCommandUsage } from '../../lib/usageTracking.js';
10
10
  import { selectAccountFromConfig } from '../../lib/prompts/accountsPrompt.js';
11
11
  import { logError } from '../../lib/errorHandlers/index.js';
12
12
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
@@ -32,11 +32,6 @@ async function handler(args) {
32
32
  });
33
33
  uiLogger.log('');
34
34
  if (!replaceOverrideFile) {
35
- const accountId = getAccountId(accountOverride) || undefined;
36
- trackCommandMetadataUsage('account-createOverride', {
37
- command: 'hs account create-override',
38
- step: 'Reject overwriting an override via prompt',
39
- }, accountId);
40
35
  process.exit(EXIT_CODES.SUCCESS);
41
36
  }
42
37
  }
@@ -48,16 +43,11 @@ async function handler(args) {
48
43
  overrideDefaultAccount = await selectAccountFromConfig();
49
44
  }
50
45
  const accountId = getAccountId(overrideDefaultAccount);
46
+ trackCommandUsage('account-createOverride', undefined, accountId);
51
47
  try {
52
48
  const overrideFilePath = path.join(getCwd(), DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME);
53
49
  await fs.writeFile(overrideFilePath, accountId.toString(), 'utf8');
54
50
  uiLogger.success(commands.account.subcommands.createOverride.success(overrideFilePath));
55
- const trackingId = accountId || undefined;
56
- trackCommandMetadataUsage('config-migrate', {
57
- command: 'hs config migrate',
58
- step: 'Confirm overwriting an override via prompt',
59
- successful: true,
60
- }, trackingId);
61
51
  process.exit(EXIT_CODES.SUCCESS);
62
52
  }
63
53
  catch (e) {
@@ -3,7 +3,7 @@ import { getCWDAccountOverride, getDefaultAccountOverrideFilePath, getAccountId,
3
3
  import { DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME } from '@hubspot/local-dev-lib/constants/config';
4
4
  import { getGlobalConfig } from '@hubspot/local-dev-lib/config/migrate';
5
5
  import { promptUser } from '../../lib/prompts/promptUtils.js';
6
- import { trackCommandMetadataUsage } from '../../lib/usageTracking.js';
6
+ import { trackCommandUsage } from '../../lib/usageTracking.js';
7
7
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
8
8
  import { logError } from '../../lib/errorHandlers/index.js';
9
9
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
@@ -22,6 +22,7 @@ async function handler(args) {
22
22
  const overrideFilePath = getDefaultAccountOverrideFilePath();
23
23
  if (accountOverride && overrideFilePath) {
24
24
  const accountId = getAccountId(accountOverride) || undefined;
25
+ trackCommandUsage('account-removeOverride', undefined, accountId);
25
26
  if (!force) {
26
27
  uiLogger.log(commands.account.subcommands.removeOverride.accountOverride(overrideFilePath, accountOverride.toString()));
27
28
  const { deleteOverrideFile } = await promptUser({
@@ -32,21 +33,12 @@ async function handler(args) {
32
33
  });
33
34
  uiLogger.log('');
34
35
  if (!deleteOverrideFile) {
35
- trackCommandMetadataUsage('account-removeOverride', {
36
- command: 'hs account remove-override',
37
- step: 'Reject removing override via prompt',
38
- }, accountId);
39
36
  process.exit(EXIT_CODES.SUCCESS);
40
37
  }
41
38
  }
42
39
  try {
43
40
  fs.unlinkSync(overrideFilePath);
44
41
  uiLogger.success(commands.account.subcommands.removeOverride.success);
45
- trackCommandMetadataUsage('account-removeOverride', {
46
- command: 'hs account remove-override',
47
- step: 'Confirm removing override file (via prompt/force)',
48
- successful: true,
49
- }, accountId);
50
42
  process.exit(EXIT_CODES.SUCCESS);
51
43
  }
52
44
  catch (error) {
@@ -142,14 +142,11 @@ async function handler(args) {
142
142
  trackCommandUsage('preview', {}, derivedAccountId);
143
143
  let createUnifiedDevServer;
144
144
  try {
145
- // @ts-ignore TODO: Remove when we deprecate Node 18
146
- require.resolve('@hubspot/cms-dev-server');
147
- // @ts-ignore TODO: Remove when we deprecate Node 18
148
145
  const { createDevServer } = await import('@hubspot/cms-dev-server');
149
146
  createUnifiedDevServer = createDevServer;
150
147
  }
151
148
  catch (e) {
152
- uiLogger.warn('Unified dev server requires node 20 to run. Defaulting to legacy preview.');
149
+ uiLogger.warn('Error loading unified dev server. Defaulting to legacy preview.');
153
150
  }
154
151
  if (createUnifiedDevServer) {
155
152
  if (port) {
@@ -11,11 +11,10 @@ import { promptUser } from '../lib/prompts/promptUtils.js';
11
11
  import { projectNameAndDestPrompt } from '../lib/prompts/projectNameAndDestPrompt.js';
12
12
  import { uiAccountDescription, uiFeatureHighlight, uiInfoSection, } from '../lib/ui/index.js';
13
13
  import { uiLogger } from '../lib/ui/logger.js';
14
- import { debugError, logError } from '../lib/errorHandlers/index.js';
14
+ import { debugError } from '../lib/errorHandlers/index.js';
15
15
  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
- import { getProjectPackageJsonLocations, installPackages, } from '../lib/dependencyManagement.js';
19
18
  import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
20
19
  import { isV2Project } from '../lib/projects/platformVersion.js';
21
20
  import { openLink } from '../lib/links.js';
@@ -135,23 +134,7 @@ async function handler(args) {
135
134
  successful: true,
136
135
  step: 'project-creation',
137
136
  }, derivedAccountId);
138
- // 5. Install dependencies
139
- const installLocations = await getProjectPackageJsonLocations(projectDest);
140
- try {
141
- await installPackages({
142
- installLocations: installLocations,
143
- });
144
- uiLogger.log(' ');
145
- uiLogger.success(commands.getStarted.logs.dependenciesInstalled);
146
- uiLogger.log(' ');
147
- }
148
- catch (err) {
149
- uiLogger.log(' ');
150
- uiLogger.error(commands.getStarted.errors.installDepsFailed);
151
- logError(err);
152
- uiLogger.log(' ');
153
- }
154
- // 6. Ask user if they want to upload the project
137
+ // 5. Ask user if they want to upload the project
155
138
  const { shouldUpload } = await promptUser([
156
139
  {
157
140
  type: 'confirm',
@@ -256,6 +239,11 @@ async function handler(args) {
256
239
  process.exit(EXIT_CODES.ERROR);
257
240
  }
258
241
  }
242
+ else {
243
+ uiLogger.log(' ');
244
+ uiFeatureHighlight(['projectUploadCommand', 'projectDevCommand']);
245
+ process.exit(EXIT_CODES.SUCCESS);
246
+ }
259
247
  }
260
248
  // Track successful completion of get-started command
261
249
  await trackCommandMetadataUsage('get-started', {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,142 @@
1
+ import yargs from 'yargs';
2
+ import path from 'path';
3
+ import { uiLogger } from '../../../lib/ui/logger.js';
4
+ import * as projectUtils from '../../../lib/projects/config.js';
5
+ import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
6
+ import { trackCommandUsage } from '../../../lib/usageTracking.js';
7
+ import * as dependencyManagement from '../../../lib/dependencyManagement.js';
8
+ import * as promptUtils from '../../../lib/prompts/promptUtils.js';
9
+ import projectUpdateDepsCommand from '../updateDeps.js';
10
+ vi.mock('../../../lib/ui/logger.js');
11
+ vi.mock('../../../lib/projects/config');
12
+ vi.mock('../../../lib/dependencyManagement');
13
+ vi.mock('../../../lib/prompts/promptUtils');
14
+ vi.mock('../../../lib/usageTracking');
15
+ vi.mock('../../../lib/commonOpts');
16
+ const exampleSpy = vi.spyOn(yargs, 'example');
17
+ const processExitSpy = vi.spyOn(process, 'exit');
18
+ const getProjectConfigSpy = vi.spyOn(projectUtils, 'getProjectConfig');
19
+ const promptUserSpy = vi.spyOn(promptUtils, 'promptUser');
20
+ const getProjectPackageJsonLocationsSpy = vi.spyOn(dependencyManagement, 'getProjectPackageJsonLocations');
21
+ const updatePackagesSpy = vi.spyOn(dependencyManagement, 'updatePackages');
22
+ describe('commands/project/updateDeps', () => {
23
+ describe('command', () => {
24
+ it('should have the correct command structure', () => {
25
+ expect(projectUpdateDepsCommand.command).toEqual('update-deps [packages..]');
26
+ });
27
+ });
28
+ describe('describe', () => {
29
+ it('should not provide a description', () => {
30
+ expect(projectUpdateDepsCommand.describe).toEqual(expect.stringMatching(/Update the npm dependencies for your project, or update specific dependencies in a subcomponent of a project/));
31
+ });
32
+ });
33
+ describe('builder', () => {
34
+ it('should provide examples', () => {
35
+ projectUpdateDepsCommand.builder(yargs);
36
+ expect(exampleSpy).toHaveBeenCalledTimes(1);
37
+ });
38
+ });
39
+ describe('handler', () => {
40
+ let args;
41
+ beforeEach(() => {
42
+ args = {
43
+ derivedAccountId: 999999,
44
+ };
45
+ // @ts-expect-error Doesn't match the actual signature because then the linter complains about unused variables
46
+ processExitSpy.mockImplementation(() => { });
47
+ });
48
+ it('should track the command usage', async () => {
49
+ await projectUpdateDepsCommand.handler(args);
50
+ expect(trackCommandUsage).toHaveBeenCalledTimes(1);
51
+ expect(trackCommandUsage).toHaveBeenCalledWith('project-update-deps', undefined, args.derivedAccountId);
52
+ });
53
+ it('should handle exceptions', async () => {
54
+ const error = new Error('Something went super wrong');
55
+ getProjectConfigSpy.mockImplementationOnce(() => {
56
+ throw error;
57
+ });
58
+ await projectUpdateDepsCommand.handler(args);
59
+ expect(uiLogger.error).toHaveBeenCalledTimes(1);
60
+ expect(uiLogger.error).toHaveBeenCalledWith(error.message);
61
+ expect(processExitSpy).toHaveBeenCalledTimes(1);
62
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.ERROR);
63
+ });
64
+ it('should log an error and exit when the project config is not defined', async () => {
65
+ getProjectConfigSpy.mockResolvedValueOnce({
66
+ projectDir: null,
67
+ projectConfig: null,
68
+ });
69
+ await projectUpdateDepsCommand.handler(args);
70
+ expect(uiLogger.error).toHaveBeenCalledTimes(1);
71
+ expect(uiLogger.error).toHaveBeenCalledWith('No project detected. Run this command from a project directory.');
72
+ expect(processExitSpy).toHaveBeenCalledTimes(1);
73
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.ERROR);
74
+ });
75
+ it('should log an error and exit when the project config has no projectDir', async () => {
76
+ getProjectConfigSpy.mockResolvedValueOnce({
77
+ projectDir: null,
78
+ projectConfig: null,
79
+ });
80
+ await projectUpdateDepsCommand.handler(args);
81
+ expect(uiLogger.error).toHaveBeenCalledTimes(1);
82
+ expect(uiLogger.error).toHaveBeenCalledWith('No project detected. Run this command from a project directory.');
83
+ expect(processExitSpy).toHaveBeenCalledTimes(1);
84
+ expect(processExitSpy).toHaveBeenCalledWith(EXIT_CODES.ERROR);
85
+ });
86
+ it('should prompt for input when packages is defined', async () => {
87
+ const projectDir = 'src';
88
+ getProjectConfigSpy.mockResolvedValue({
89
+ projectDir,
90
+ projectConfig: null,
91
+ });
92
+ const packageJsonLocation = path.join(projectDir, 'directory1');
93
+ promptUserSpy.mockResolvedValueOnce({
94
+ selectedInstallLocations: packageJsonLocation,
95
+ });
96
+ getProjectPackageJsonLocationsSpy.mockResolvedValue([
97
+ packageJsonLocation,
98
+ ]);
99
+ await projectUpdateDepsCommand.handler({
100
+ ...args,
101
+ packages: ['@hubspot/local-dev-lib'],
102
+ });
103
+ expect(getProjectPackageJsonLocationsSpy).toHaveBeenCalledTimes(1);
104
+ expect(promptUserSpy).toHaveBeenCalledTimes(1);
105
+ expect(promptUserSpy).toHaveBeenCalledWith([
106
+ {
107
+ name: 'selectedInstallLocations',
108
+ type: 'checkbox',
109
+ when: expect.any(Function),
110
+ choices: [
111
+ {
112
+ name: 'directory1',
113
+ value: packageJsonLocation,
114
+ },
115
+ ],
116
+ message: 'Choose which project components you would like to update the dependencies for:',
117
+ validate: expect.any(Function),
118
+ },
119
+ ]);
120
+ });
121
+ it('should call updatePackages correctly', async () => {
122
+ const projectDir = 'src';
123
+ const packageJsonLocation = path.join(projectDir, 'directory1');
124
+ const installLocations = [packageJsonLocation];
125
+ const packages = ['@hubspot/local-dev-lib'];
126
+ getProjectConfigSpy.mockResolvedValue({
127
+ projectDir,
128
+ projectConfig: null,
129
+ });
130
+ promptUserSpy.mockResolvedValueOnce({
131
+ selectedInstallLocations: packageJsonLocation,
132
+ });
133
+ getProjectPackageJsonLocationsSpy.mockResolvedValue(installLocations);
134
+ await projectUpdateDepsCommand.handler({ ...args, packages });
135
+ expect(updatePackagesSpy).toHaveBeenCalledTimes(1);
136
+ expect(updatePackagesSpy).toHaveBeenCalledWith({
137
+ packages,
138
+ installLocations: packageJsonLocation,
139
+ });
140
+ });
141
+ });
142
+ });
@@ -94,7 +94,6 @@ async function handler(args) {
94
94
  'projectCommandTip',
95
95
  'projectUploadCommand',
96
96
  'projectDevCommand',
97
- 'projectInstallDepsCommand',
98
97
  'projectHelpCommand',
99
98
  'feedbackCommand',
100
99
  ]);
@@ -0,0 +1,6 @@
1
+ import { CommonArgs, ConfigArgs, YargsCommandModule } from '../../types/Yargs.js';
2
+ export type ProjectUpdateDepsArgs = CommonArgs & ConfigArgs & {
3
+ packages?: string[];
4
+ };
5
+ declare const projectUpdateDepsCommand: YargsCommandModule<unknown, ProjectUpdateDepsArgs>;
6
+ export default projectUpdateDepsCommand;
@@ -0,0 +1,80 @@
1
+ import { updatePackages, getProjectPackageJsonLocations, } from '../../lib/dependencyManagement.js';
2
+ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
3
+ import { getProjectConfig } from '../../lib/projects/config.js';
4
+ import { promptUser } from '../../lib/prompts/promptUtils.js';
5
+ import path from 'path';
6
+ import { commands } from '../../lang/en.js';
7
+ import { uiLogger } from '../../lib/ui/logger.js';
8
+ import { trackCommandUsage } from '../../lib/usageTracking.js';
9
+ import { logError } from '../../lib/errorHandlers/index.js';
10
+ import { makeYargsBuilder } from '../../lib/yargsUtils.js';
11
+ const command = 'update-deps [packages..]';
12
+ const describe = commands.project.updateDeps.help.describe;
13
+ async function handler(args) {
14
+ const { derivedAccountId, packages } = args;
15
+ try {
16
+ trackCommandUsage('project-update-deps', undefined, derivedAccountId);
17
+ const projectConfig = await getProjectConfig();
18
+ if (!projectConfig || !projectConfig.projectDir) {
19
+ uiLogger.error(commands.project.updateDeps.noProjectConfig);
20
+ return process.exit(EXIT_CODES.ERROR);
21
+ }
22
+ const { projectDir } = projectConfig;
23
+ let installLocations = await getProjectPackageJsonLocations();
24
+ if (packages) {
25
+ const { selectedInstallLocations } = await promptUser([
26
+ {
27
+ name: 'selectedInstallLocations',
28
+ type: 'checkbox',
29
+ when: () => packages && packages.length > 0,
30
+ message: commands.project.updateDeps.installLocationPrompt,
31
+ choices: installLocations.map(dir => ({
32
+ name: path.relative(projectDir, dir),
33
+ value: dir,
34
+ })),
35
+ validate: (choices) => {
36
+ if (choices === undefined || choices.length === 0) {
37
+ return commands.project.updateDeps.installLocationPromptRequired;
38
+ }
39
+ return true;
40
+ },
41
+ },
42
+ ]);
43
+ if (selectedInstallLocations) {
44
+ installLocations = selectedInstallLocations;
45
+ }
46
+ }
47
+ await updatePackages({
48
+ packages,
49
+ installLocations,
50
+ });
51
+ }
52
+ catch (e) {
53
+ logError(e);
54
+ return process.exit(EXIT_CODES.ERROR);
55
+ }
56
+ }
57
+ function projectUpdateDepsBuilder(yargs) {
58
+ yargs.example([
59
+ [
60
+ '$0 project update-deps',
61
+ commands.project.updateDeps.help.updateAppDepsExample,
62
+ ],
63
+ [
64
+ '$0 project update-deps dependency1 dependency2',
65
+ commands.project.updateDeps.help.updateDepToSubComponentExample,
66
+ ],
67
+ ]);
68
+ return yargs;
69
+ }
70
+ const builder = makeYargsBuilder(projectUpdateDepsBuilder, command, describe, {
71
+ useGlobalOptions: true,
72
+ useConfigOptions: true,
73
+ });
74
+ const projectUpdateDepsCommand = {
75
+ command,
76
+ describe,
77
+ handler,
78
+ builder,
79
+ };
80
+ export default projectUpdateDepsCommand;
@@ -13,6 +13,7 @@ import migrate from './project/migrate.js';
13
13
  import migrateApp from './project/migrateApp.js';
14
14
  import cloneApp from './project/cloneApp.js';
15
15
  import installDeps from './project/installDeps.js';
16
+ import updateDeps from './project/updateDeps.js';
16
17
  import profile from './project/profile.js';
17
18
  import projectValidate from './project/validate.js';
18
19
  import list from './project/list.js';
@@ -36,6 +37,7 @@ function projectBuilder(yargs) {
36
37
  .command(migrate)
37
38
  .command(cloneApp)
38
39
  .command(installDeps)
40
+ .command(updateDeps)
39
41
  .command(profile)
40
42
  .command(projectValidate)
41
43
  .demandCommand(1, '');
@@ -107,7 +107,7 @@ function createTestAccountBuilder(yargs) {
107
107
  });
108
108
  yargs.example([
109
109
  [
110
- '$0 create --config-path ./test-account-config.json',
110
+ '$0 test-account create --config-path ./test-account-config.json',
111
111
  commands.testAccount.create.example('./test-account-config.json'),
112
112
  ],
113
113
  ]);
package/lang/en.d.ts CHANGED
@@ -43,14 +43,13 @@ export declare const commands: {
43
43
  readonly projectCreated: {
44
44
  readonly title: string;
45
45
  readonly description: `Let's prepare and upload your project to HubSpot.
46
- You can use ${string} to ${string} and ${string} to ${string} your project.`;
46
+ You can use ${string} to ${string} your project.`;
47
47
  };
48
48
  };
49
49
  readonly logs: {
50
50
  readonly appSelected: `We'll create a new project with a sample app for you.
51
51
  Projects are what you can use to create apps with HubSpot.
52
52
  Usually you'll use the ${string} command, but we'll go ahead and make one now.`;
53
- readonly dependenciesInstalled: "Dependencies installed successfully.";
54
53
  readonly uploadingProject: "Uploading your project to HubSpot...";
55
54
  readonly uploadSuccess: "Project uploaded successfully!";
56
55
  readonly developerOverviewLink: "Open this link to navigate to your HubSpot developer portal";
@@ -58,7 +57,6 @@ Usually you'll use the ${string} command, but we'll go ahead and make one now.`;
58
57
  readonly errors: {
59
58
  readonly uploadFailed: "Failed to upload project to HubSpot.";
60
59
  readonly configFileNotFound: "Could not find project configuration for upload.";
61
- readonly installDepsFailed: "Failed to install dependencies.";
62
60
  };
63
61
  };
64
62
  readonly completion: {
@@ -1771,6 +1769,22 @@ ${string}`;
1771
1769
  readonly noPackageJsonInProject: (projectName: string) => string;
1772
1770
  readonly packageManagerNotInstalled: (packageManager: string) => string;
1773
1771
  };
1772
+ readonly updateDeps: {
1773
+ readonly help: {
1774
+ readonly describe: "Update the npm dependencies for your project, or update specific dependencies in a subcomponent of a project.";
1775
+ readonly updateAppDepsExample: "Update the dependencies for the project";
1776
+ readonly updateDepToSubComponentExample: "Update the npm dependencies in one or more project subcomponents";
1777
+ };
1778
+ readonly installLocationPrompt: "Choose which project components you would like to update the dependencies for:";
1779
+ readonly installLocationPromptRequired: "You must choose at least one subcomponent";
1780
+ readonly updatingDependencies: (directory: string) => string;
1781
+ readonly updateSuccessful: (directory: string) => string;
1782
+ readonly updatingDependenciesToLocation: (dependencies: string, directory: string) => string;
1783
+ readonly updatingDependenciesFailed: (directory: string) => string;
1784
+ readonly noProjectConfig: "No project detected. Run this command from a project directory.";
1785
+ readonly noPackageJsonInProject: (projectName: string) => string;
1786
+ readonly packageManagerNotInstalled: (packageManager: string) => string;
1787
+ };
1774
1788
  readonly validate: {
1775
1789
  readonly describe: "Validate the project before uploading";
1776
1790
  readonly mustBeRanWithinAProject: "This command must be run from within a project directory.";
@@ -2088,7 +2102,8 @@ ${string}`;
2088
2102
  };
2089
2103
  };
2090
2104
  readonly create: {
2091
- readonly describe: "Create a test account from a config file";
2105
+ readonly describe: `Create a test account from scratch or from a config file. Use ${string} to generate a config file.
2106
+ ${string}`;
2092
2107
  readonly configPathPrompt: "[--config-path] Enter the path to the test account config: ";
2093
2108
  readonly createTestAccountFromConfigPrompt: "How would you like to create your test account?";
2094
2109
  readonly createFromConfigOption: "Create test account from config file";
@@ -2971,7 +2986,7 @@ Run ${string} to upgrade to version ${string}`;
2971
2986
  };
2972
2987
  };
2973
2988
  readonly add: {
2974
- readonly nothingAdded: "No features added.";
2989
+ readonly nothingAdded: "No features were added to the project. Use the space bar to select features from the list.";
2975
2990
  };
2976
2991
  readonly updateHsMetaFilesWithAutoGeneratedFields: {
2977
2992
  readonly header: "Created the following components and features:";
package/lang/en.js CHANGED
@@ -51,12 +51,11 @@ export const commands = {
51
51
  uploadProject: (accountName) => `Would you like to upload this project to account "${accountName}" now?`,
52
52
  projectCreated: {
53
53
  title: chalk.bold('Next steps:'),
54
- description: `Let's prepare and upload your project to HubSpot.\nYou can use ${uiCommandReference('hs project install-deps')} to ${chalk.bold('install dependencies')} and ${uiCommandReference('hs project upload')} to ${chalk.bold('upload')} your project.`,
54
+ description: `Let's prepare and upload your project to HubSpot.\nYou can use ${uiCommandReference('hs project upload')} to ${chalk.bold('upload')} your project.`,
55
55
  },
56
56
  },
57
57
  logs: {
58
58
  appSelected: `We'll create a new project with a sample app for you.\nProjects are what you can use to create apps with HubSpot.\nUsually you'll use the ${uiCommandReference('hs project create')} command, but we'll go ahead and make one now.`,
59
- dependenciesInstalled: 'Dependencies installed successfully.',
60
59
  uploadingProject: 'Uploading your project to HubSpot...',
61
60
  uploadSuccess: 'Project uploaded successfully!',
62
61
  developerOverviewLink: 'Open this link to navigate to your HubSpot developer portal',
@@ -64,7 +63,6 @@ export const commands = {
64
63
  errors: {
65
64
  uploadFailed: 'Failed to upload project to HubSpot.',
66
65
  configFileNotFound: 'Could not find project configuration for upload.',
67
- installDepsFailed: 'Failed to install dependencies.',
68
66
  },
69
67
  },
70
68
  completion: {
@@ -1765,6 +1763,22 @@ export const commands = {
1765
1763
  noPackageJsonInProject: (projectName) => `No dependencies to install. The project ${projectName} folder might be missing component or subcomponent files. ${uiLink('Learn how to create a project from scratch', 'https://developers.hubspot.com/docs/apps/developer-platform/build-apps/create-an-app#customize-a-new-project-using-the-cli')}`,
1766
1764
  packageManagerNotInstalled: (packageManager) => `This command depends on ${packageManager}, install ${uiLink(packageManager, 'https://docs.npmjs.com/downloading-and-installing-node-js-and-npm')}`,
1767
1765
  },
1766
+ updateDeps: {
1767
+ help: {
1768
+ describe: 'Update the npm dependencies for your project, or update specific dependencies in a subcomponent of a project.',
1769
+ updateAppDepsExample: 'Update the dependencies for the project',
1770
+ updateDepToSubComponentExample: 'Update the npm dependencies in one or more project subcomponents',
1771
+ },
1772
+ installLocationPrompt: 'Choose which project components you would like to update the dependencies for:',
1773
+ installLocationPromptRequired: 'You must choose at least one subcomponent',
1774
+ updatingDependencies: (directory) => `Updating dependencies in ${directory}`,
1775
+ updateSuccessful: (directory) => `Updated dependencies in ${directory}`,
1776
+ updatingDependenciesToLocation: (dependencies, directory) => `Updating ${dependencies} in ${directory}`,
1777
+ updatingDependenciesFailed: (directory) => `Updating dependencies for ${directory} failed`,
1778
+ noProjectConfig: 'No project detected. Run this command from a project directory.',
1779
+ noPackageJsonInProject: (projectName) => `No dependencies to update. The project ${projectName} folder might be missing component or subcomponent files. ${uiLink('Learn how to create a project from scratch', 'https://developers.hubspot.com/docs/apps/developer-platform/build-apps/create-an-app#customize-a-new-project-using-the-cli')}`,
1780
+ packageManagerNotInstalled: (packageManager) => `This command depends on ${packageManager}, install ${uiLink(packageManager, 'https://docs.npmjs.com/downloading-and-installing-node-js-and-npm')}`,
1781
+ },
1768
1782
  validate: {
1769
1783
  describe: 'Validate the project before uploading',
1770
1784
  mustBeRanWithinAProject: 'This command must be run from within a project directory.',
@@ -2082,7 +2096,7 @@ export const commands = {
2082
2096
  },
2083
2097
  },
2084
2098
  create: {
2085
- describe: 'Create a test account from a config file',
2099
+ describe: `Create a test account from scratch or from a config file. Use ${uiCommandReference('hs test-account create-config')} to generate a config file. \n${uiLink('Learn more', 'https://developers.hubspot.com/docs/developer-tooling/local-development/configurable-test-accounts')}`,
2086
2100
  configPathPrompt: '[--config-path] Enter the path to the test account config: ',
2087
2101
  createTestAccountFromConfigPrompt: 'How would you like to create your test account?',
2088
2102
  createFromConfigOption: 'Create test account from config file',
@@ -2964,7 +2978,7 @@ export const lib = {
2964
2978
  },
2965
2979
  },
2966
2980
  add: {
2967
- nothingAdded: 'No features added.',
2981
+ nothingAdded: 'No features were added to the project. Use the space bar to select features from the list.',
2968
2982
  },
2969
2983
  updateHsMetaFilesWithAutoGeneratedFields: {
2970
2984
  header: 'Created the following components and features:',