@hubspot/cli 6.0.0 → 6.1.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.
@@ -20,6 +20,7 @@ const {
20
20
  } = require('../../lib/prompts/createProjectPrompt');
21
21
  const { poll } = require('../../lib/polling');
22
22
  const {
23
+ uiBetaTag,
23
24
  uiLine,
24
25
  uiCommandReference,
25
26
  uiAccountDescription,
@@ -46,7 +47,7 @@ const { extractZipArchive } = require('@hubspot/local-dev-lib/archive');
46
47
  const i18nKey = 'commands.project.subcommands.cloneApp';
47
48
 
48
49
  exports.command = 'clone-app';
49
- exports.describe = null; // uiBetaTag(i18n(`${i18nKey}.describe`), false);
50
+ exports.describe = uiBetaTag(i18n(`${i18nKey}.describe`), false);
50
51
 
51
52
  exports.handler = async options => {
52
53
  await loadAndValidateOptions(options);
@@ -21,12 +21,7 @@ const {
21
21
  validateProjectConfig,
22
22
  } = require('../../lib/projects');
23
23
  const { EXIT_CODES } = require('../../lib/enums/exitCodes');
24
- const {
25
- uiAccountDescription,
26
- uiBetaTag,
27
- uiCommandReference,
28
- uiLink,
29
- } = require('../../lib/ui');
24
+ const { uiBetaTag, uiCommandReference, uiLink } = require('../../lib/ui');
30
25
  const SpinniesManager = require('../../lib/ui/SpinniesManager');
31
26
  const LocalDevManager = require('../../lib/LocalDevManager');
32
27
  const {
@@ -52,6 +47,7 @@ const {
52
47
  createInitialBuildForNewProject,
53
48
  useExistingDevTestAccount,
54
49
  validateAccountOption,
50
+ checkIfParentAccountIsAuthed,
55
51
  } = require('../../lib/localDev');
56
52
 
57
53
  const i18nKey = 'commands.project.subcommands.dev';
@@ -130,19 +126,7 @@ exports.handler = async options => {
130
126
  await confirmDefaultAccountIsTarget(accountConfig, hasPublicApps);
131
127
 
132
128
  if (hasPublicApps) {
133
- // Exit if the user has not authed the parent account in the config
134
- if (!getAccountConfig(accountConfig.parentAccountId)) {
135
- logger.error(
136
- i18n(`${i18nKey}.errors.parentAccountNotConfigured`, {
137
- accountId: accountConfig.parentAccountId,
138
- accountIdentifier: uiAccountDescription(targetTestingAccountId),
139
- authCommand: uiCommandReference(
140
- `hs auth --account=${accountConfig.parentAccountId}`
141
- ),
142
- })
143
- );
144
- process.exit(EXIT_CODES.ERROR);
145
- }
129
+ checkIfParentAccountIsAuthed(accountConfig);
146
130
  targetProjectAccountId = accountConfig.parentAccountId;
147
131
  } else {
148
132
  targetProjectAccountId = accountId;
@@ -52,7 +52,7 @@ const {
52
52
  const i18nKey = 'commands.project.subcommands.migrateApp';
53
53
 
54
54
  exports.command = 'migrate-app';
55
- exports.describe = null; // uiBetaTag(i18n(`${i18nKey}.describe`), false);
55
+ exports.describe = uiBetaTag(i18n(`${i18nKey}.describe`), false);
56
56
 
57
57
  exports.handler = async options => {
58
58
  await loadAndValidateOptions(options);
@@ -63,6 +63,16 @@ exports.handler = async options => {
63
63
 
64
64
  trackCommandUsage('migrate-app', {}, accountId);
65
65
 
66
+ logger.log('');
67
+ logger.log(uiBetaTag(i18n(`${i18nKey}.header.text`), false));
68
+ logger.log(
69
+ uiLink(
70
+ i18n(`${i18nKey}.header.link`),
71
+ 'https://developers.hubspot.com/docs/platform/migrate-a-public-app-to-projects'
72
+ )
73
+ );
74
+ logger.log('');
75
+
66
76
  if (!isAppDeveloperAccount(accountConfig)) {
67
77
  uiLine();
68
78
  logger.error(i18n(`${i18nKey}.errors.invalidAccountTypeTitle`));
@@ -85,7 +95,6 @@ exports.handler = async options => {
85
95
  isMigratingApp: true,
86
96
  });
87
97
 
88
- let appName;
89
98
  try {
90
99
  const selectedApp = await fetchPublicAppMetadata(appId, accountId);
91
100
  // preventProjectMigrations returns true if we have not added app to allowlist config.
@@ -96,7 +105,6 @@ exports.handler = async options => {
96
105
  logger.error(i18n(`${i18nKey}.errors.invalidApp`, { appId }));
97
106
  process.exit(EXIT_CODES.ERROR);
98
107
  }
99
- appName = selectedApp.name;
100
108
  } catch (error) {
101
109
  logApiErrorInstance(error, new ApiErrorContext({ accountId }));
102
110
  process.exit(EXIT_CODES.ERROR);
@@ -134,7 +142,8 @@ exports.handler = async options => {
134
142
 
135
143
  logger.log('');
136
144
  uiLine();
137
- logger.log(uiBetaTag(i18n(`${i18nKey}.warning.title`, { appName }), false));
145
+ logger.warn(i18n(`${i18nKey}.warning.title`));
146
+ logger.log('');
138
147
  logger.log(i18n(`${i18nKey}.warning.projectConversion`));
139
148
  logger.log(i18n(`${i18nKey}.warning.appConfig`));
140
149
  logger.log('');
package/lang/en.lyaml CHANGED
@@ -484,7 +484,6 @@ en:
484
484
  noProjectConfig: "No project detected. Please run this command again from a project directory."
485
485
  invalidProjectComponents: "Projects cannot contain both private and public apps. Move your apps to separate projects before attempting local development."
486
486
  noRunnableComponents: "No supported components were found in this project. Run {{ command }} to see a list of available components and add one to your project."
487
- parentAccountNotConfigured: "To develop this project locally, run {{ authCommand }} to authenticate the App Developer Account {{ accountId }} associated with {{ accountIdentifier }}."
488
487
  examples:
489
488
  default: "Start local dev for the current project"
490
489
  create:
@@ -513,13 +512,16 @@ en:
513
512
  describe: "Directory where project should be created"
514
513
  name:
515
514
  describe: "Project name (cannot be changed)"
515
+ header:
516
+ text: "Migrate an app to the projects framework"
517
+ link: "Learn more about migrating apps to the projects framework"
516
518
  migrationStatus:
517
519
  inProgress: "Converting app configuration to {{#bold}}public-app.json{{/bold}} component definition ..."
518
520
  success: "{{#bold}}Your app was converted and build #1 is deployed{{/bold}}"
519
521
  done: "Converting app configuration to public-app.json component definition ... DONE"
520
522
  failure: "Converting app configuration to public-app.json component definition ... FAILED"
521
523
  warning:
522
- title: "{{#bold}}Migrate {{appName}} to the projects framework?{{/bold}}"
524
+ title: "{{#bold}}You are about to migrate an app to the projects framework{{/bold}}"
523
525
  projectConversion: "{{#bold}}The selected app will be converted to a project component.{{/bold}}"
524
526
  appConfig: "All supported app configuration will be moved to the {{#bold}}public-app.json{{/bold}} component definition file. Future updates to those features must be made through the project build and deploy pipeline, not the developer account UI."
525
527
  buildAndDeploy: "This will create a new project with a single app component and immediately build and deploy it to your developer account (build #1)."
@@ -1023,6 +1025,8 @@ en:
1023
1025
  createInitialBuildForNewProject:
1024
1026
  initialUploadMessage: "HubSpot Local Dev Server Startup"
1025
1027
  projectLockedError: "Your project is locked. This may mean that another user is running the {{#bold}}`hs project watch`{{/bold}} command for this project. If this is you, unlock the project in Projects UI."
1028
+ checkIfParentAccountIsAuthed:
1029
+ notAuthedError: "To develop this project locally, run {{ authCommand }} to authenticate the App Developer Account {{ accountId }} associated with {{ accountIdentifier }}."
1026
1030
  projects:
1027
1031
  config:
1028
1032
  srcOutsideProjectDir: "Invalid value for 'srcDir' in {{ projectConfig }}: {{#bold}}srcDir: \"{{ srcDir }}\"{{/bold}}\n\t'srcDir' must be a relative path to a folder under the project root, such as \".\" or \"./src\""
@@ -1218,7 +1222,7 @@ en:
1218
1222
  languageRequired: "Please select API sample app's language"
1219
1223
  createProjectPrompt:
1220
1224
  enterName: "[--name] Give your project a name: "
1221
- enterLocation: "[--location] Where should the project be created?"
1225
+ enterLocation: "[--location] Enter the folder to create the project in:"
1222
1226
  selectTemplate: "[--template] Choose a project template: "
1223
1227
  errors:
1224
1228
  nameRequired: "A project name is required"
@@ -28,6 +28,7 @@ describe('cli/lib/dependencyManagement', () => {
28
28
  const appFunctionsDir = path.join(appDir, 'app.functions');
29
29
  const extensionsDir = path.join(appDir, 'exensions');
30
30
  const projectName = 'super cool test project';
31
+ const installLocations = [appFunctionsDir, extensionsDir];
31
32
 
32
33
  beforeEach(() => {
33
34
  execMock = jest.fn();
@@ -64,7 +65,6 @@ describe('cli/lib/dependencyManagement', () => {
64
65
  describe('installPackages', () => {
65
66
  it('should setup a loading spinner', async () => {
66
67
  const packages = ['package1', 'package2'];
67
- const installLocations = ['src/app/app.functions', 'src/app/extensions'];
68
68
  await installPackages({ packages, installLocations });
69
69
  expect(SpinniesManager.init).toHaveBeenCalledTimes(
70
70
  installLocations.length
@@ -79,7 +79,6 @@ describe('cli/lib/dependencyManagement', () => {
79
79
 
80
80
  it('should install the provided packages in all the provided install locations', async () => {
81
81
  const packages = ['package1', 'package2'];
82
- const installLocations = ['src/app/app.functions', 'src/app/extensions'];
83
82
  await installPackages({ packages, installLocations });
84
83
 
85
84
  expect(execMock).toHaveBeenCalledTimes(installLocations.length);
@@ -91,9 +90,9 @@ describe('cli/lib/dependencyManagement', () => {
91
90
  );
92
91
 
93
92
  for (const location of installLocations) {
94
- expect(execMock).toHaveBeenCalledWith(
95
- `npm --prefix=${location} install package1 package2`
96
- );
93
+ expect(execMock).toHaveBeenCalledWith(`npm install package1 package2`, {
94
+ cwd: location,
95
+ });
97
96
  expect(SpinniesManager.add).toHaveBeenCalledWith(
98
97
  `installingDependencies-${location}`,
99
98
  {
@@ -110,15 +109,14 @@ describe('cli/lib/dependencyManagement', () => {
110
109
  });
111
110
 
112
111
  it('should use the provided install locations', async () => {
113
- const installLocations = ['src/app/app.functions', 'src/app/extensions'];
114
112
  await installPackages({ installLocations });
115
113
  expect(execMock).toHaveBeenCalledTimes(installLocations.length);
116
- expect(execMock).toHaveBeenCalledWith(
117
- `npm --prefix=${installLocations[0]} install`
118
- );
119
- expect(execMock).toHaveBeenCalledWith(
120
- `npm --prefix=${installLocations[1]} install`
121
- );
114
+ expect(execMock).toHaveBeenCalledWith(`npm install`, {
115
+ cwd: appFunctionsDir,
116
+ });
117
+ expect(execMock).toHaveBeenCalledWith(`npm install`, {
118
+ cwd: extensionsDir,
119
+ });
122
120
  });
123
121
 
124
122
  it('should locate the projects package.json files when install locations is not provided', async () => {
@@ -137,14 +135,14 @@ describe('cli/lib/dependencyManagement', () => {
137
135
  });
138
136
 
139
137
  await installPackages({});
140
- // Its called once per each install location, plus once to check if npm installed
138
+ // It's called once per each install location, plus once to check if npm installed
141
139
  expect(execMock).toHaveBeenCalledTimes(installLocations.length + 1);
142
- expect(execMock).toHaveBeenCalledWith(
143
- `npm --prefix=${appFunctionsDir} install`
144
- );
145
- expect(execMock).toHaveBeenCalledWith(
146
- `npm --prefix=${extensionsDir} install`
147
- );
140
+ expect(execMock).toHaveBeenCalledWith(`npm install`, {
141
+ cwd: appFunctionsDir,
142
+ });
143
+ expect(execMock).toHaveBeenCalledWith(`npm install`, {
144
+ cwd: extensionsDir,
145
+ });
148
146
  });
149
147
 
150
148
  it('should throw an error when installing the dependencies fails', async () => {
@@ -62,7 +62,7 @@ async function installPackagesInDirectory(packages, directory) {
62
62
  directory: relativeDir,
63
63
  }),
64
64
  });
65
- let installCommand = `${DEFAULT_PACKAGE_MANAGER} --prefix=${directory} install`;
65
+ let installCommand = `${DEFAULT_PACKAGE_MANAGER} install`;
66
66
 
67
67
  if (packages) {
68
68
  installCommand = `${installCommand} ${packages.join(' ')}`;
@@ -71,7 +71,7 @@ async function installPackagesInDirectory(packages, directory) {
71
71
  logger.debug(`Running ${installCommand}`);
72
72
  try {
73
73
  const exec = util.promisify(execAsync);
74
- await exec(installCommand);
74
+ await exec(installCommand, { cwd: directory });
75
75
  SpinniesManager.succeed(spinner, {
76
76
  text: i18n(`${i18nKey}.installationSuccessful`, {
77
77
  directory: relativeDir,
package/lib/localDev.js CHANGED
@@ -95,16 +95,34 @@ const checkIfAppDeveloperAccount = accountConfig => {
95
95
  }
96
96
  };
97
97
 
98
- // Confirm the default account is a developer account if developing public apps
99
- const validateAccountOption = (accountConfig, hasPublicApps) => {
100
- if (hasPublicApps && !isDeveloperTestAccount(accountConfig)) {
98
+ const checkIfParentAccountIsAuthed = accountConfig => {
99
+ if (!getAccountConfig(accountConfig.parentAccountId)) {
101
100
  logger.error(
102
- i18n(`${i18nKey}.validateAccountOption.invalidPublicAppAccount`, {
103
- useCommand: uiCommandReference('hs accounts use'),
104
- devCommand: uiCommandReference('hs project dev'),
101
+ i18n(`${i18nKey}.checkIfParentAccountIsAuthed.notAuthedError`, {
102
+ accountId: accountConfig.parentAccountId,
103
+ accountIdentifier: uiAccountDescription(accountConfig.portalId),
104
+ authCommand: uiCommandReference(
105
+ `hs auth --account=${accountConfig.parentAccountId}`
106
+ ),
105
107
  })
106
108
  );
107
109
  process.exit(EXIT_CODES.SUCCESS);
110
+ }
111
+ };
112
+
113
+ // Confirm the default account is a developer account if developing public apps
114
+ const validateAccountOption = (accountConfig, hasPublicApps) => {
115
+ if (hasPublicApps) {
116
+ if (!isDeveloperTestAccount) {
117
+ logger.error(
118
+ i18n(`${i18nKey}.validateAccountOption.invalidPublicAppAccount`, {
119
+ useCommand: uiCommandReference('hs accounts use'),
120
+ devCommand: uiCommandReference('hs project dev'),
121
+ })
122
+ );
123
+ process.exit(EXIT_CODES.SUCCESS);
124
+ }
125
+ checkIfParentAccountIsAuthed(accountConfig);
108
126
  } else if (isAppDeveloperAccount(accountConfig)) {
109
127
  logger.error(
110
128
  i18n(`${i18nKey}.validateAccountOption.invalidPrivateAppAccount`, {
@@ -456,4 +474,5 @@ module.exports = {
456
474
  createNewProjectForLocalDev,
457
475
  createInitialBuildForNewProject,
458
476
  getAccountHomeUrl,
477
+ checkIfParentAccountIsAuthed,
459
478
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "CLI for working with HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -46,5 +46,5 @@
46
46
  "publishConfig": {
47
47
  "access": "public"
48
48
  },
49
- "gitHead": "d01e7f7c6222133ffac7c6dd757fb95247a04b25"
49
+ "gitHead": "51f7638e491a999b6f64a9f3bda3c4d05fff0dbc"
50
50
  }